Merge "Try to find equivalent SuggestionsSpan when it has been updated." into nyc-dev
diff --git a/Android.mk b/Android.mk
index 6ec434c..3ac5889 100644
--- a/Android.mk
+++ b/Android.mk
@@ -150,14 +150,14 @@
core/java/android/content/pm/IPackageStatsObserver.aidl \
core/java/android/content/pm/IOnPermissionsChangeListener.aidl \
core/java/android/database/IContentObserver.aidl \
- core/java/android/hardware/ICameraService.aidl \
- core/java/android/hardware/ICameraServiceListener.aidl \
- core/java/android/hardware/ICameraServiceProxy.aidl \
- core/java/android/hardware/ICamera.aidl \
- core/java/android/hardware/ICameraClient.aidl \
+ ../av/camera/aidl/android/hardware/ICameraService.aidl \
+ ../av/camera/aidl/android/hardware/ICameraServiceListener.aidl \
+ ../av/camera/aidl/android/hardware/ICameraServiceProxy.aidl \
+ ../av/camera/aidl/android/hardware/ICamera.aidl \
+ ../av/camera/aidl/android/hardware/ICameraClient.aidl \
+ ../av/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl \
+ ../av/camera/aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl \
core/java/android/hardware/IConsumerIrService.aidl \
- core/java/android/hardware/camera2/ICameraDeviceUser.aidl \
- core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl \
core/java/android/hardware/ISerialManager.aidl \
core/java/android/hardware/display/IDisplayManager.aidl \
core/java/android/hardware/display/IDisplayManagerCallback.aidl \
@@ -194,6 +194,8 @@
core/java/android/hardware/usb/IUsbManager.aidl \
core/java/android/net/ICaptivePortal.aidl \
core/java/android/net/IConnectivityManager.aidl \
+ core/java/android/net/IConnectivityMetricsLogger.aidl \
+ core/java/android/net/IConnectivityMetricsLoggerSubscriber.aidl \
core/java/android/net/IEthernetManager.aidl \
core/java/android/net/IEthernetServiceListener.aidl \
core/java/android/net/INetworkManagementEventObserver.aidl \
@@ -215,6 +217,7 @@
core/java/android/os/IBatteryPropertiesRegistrar.aidl \
core/java/android/os/ICancellationSignal.aidl \
core/java/android/os/IDeviceIdleController.aidl \
+ core/java/android/os/IHardwarePropertiesManager.aidl \
core/java/android/os/IMaintenanceActivityListener.aidl \
core/java/android/os/IMessenger.aidl \
core/java/android/os/INetworkActivityListener.aidl \
@@ -222,6 +225,8 @@
core/java/android/os/IPermissionController.aidl \
core/java/android/os/IProcessInfoService.aidl \
core/java/android/os/IPowerManager.aidl \
+ core/java/android/os/IRecoverySystem.aidl \
+ core/java/android/os/IRecoverySystemProgressListener.aidl \
core/java/android/os/IRemoteCallback.aidl \
core/java/android/os/ISchedulingPolicyService.aidl \
core/java/android/os/IUpdateLock.aidl \
@@ -306,6 +311,7 @@
core/java/com/android/internal/policy/IKeyguardExitCallback.aidl \
core/java/com/android/internal/policy/IKeyguardService.aidl \
core/java/com/android/internal/policy/IKeyguardStateCallback.aidl \
+ core/java/com/android/internal/policy/IShortcutService.aidl \
core/java/com/android/internal/os/IDropBoxManagerService.aidl \
core/java/com/android/internal/os/IParcelFileDescriptorFactory.aidl \
core/java/com/android/internal/os/IResultReceiver.aidl \
@@ -449,13 +455,17 @@
$(FRAMEWORKS_BASE_JAVA_SRC_DIRS) \
frameworks/native/aidl/binder
+LOCAL_AIDL_INCLUDES += \
+ frameworks/av/camera/aidl \
+ frameworks/native/aidl/gui
+
LOCAL_INTERMEDIATE_SOURCES := \
$(framework_res_source_path)/android/R.java \
$(framework_res_source_path)/android/Manifest.java \
$(framework_res_source_path)/com/android/internal/R.java
LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core-oj core-libart conscrypt okhttp core-junit bouncycastle ext
+LOCAL_JAVA_LIBRARIES := core-oj core-libart core-lambda-stubs conscrypt okhttp core-junit bouncycastle ext
LOCAL_STATIC_JAVA_LIBRARIES := framework-protos
LOCAL_MODULE := framework
@@ -571,7 +581,7 @@
frameworks/base/core/java/android/view/Display.aidl \
frameworks/base/core/java/android/view/InputDevice.aidl \
frameworks/base/core/java/android/view/InputEvent.aidl \
- frameworks/base/core/java/android/view/Surface.aidl \
+ frameworks/native/aidl/gui/android/view/Surface.aidl \
frameworks/base/core/java/android/view/WindowContentFrameStats.aidl \
frameworks/base/core/java/android/view/inputmethod/InputMethodSubtype.aidl \
frameworks/base/core/java/android/view/inputmethod/CursorAnchorInfo.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 2fe5cbe..cee8fdb 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -240,6 +240,7 @@
$(call add-clean-step, rm -f $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/media/java/android/media/IRemoteControlDisplay.*)
$(call add-clean-step, rm -f $(OUT_DIR)/target/common/obj/APPS/FeatureSplit1_intermediates/src/com/android/test/split/feature/R.java)
$(call add-clean-step, rm -f $(OUT_DIR)/target/common/obj/APPS/FeatureSplit2_intermediates/src/com/android/test/split/feature/R.java)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/hardware)
# ******************************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
diff --git a/api/current.txt b/api/current.txt
index 1ebec4e..e5e1248 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -101,7 +101,6 @@
field public static final java.lang.String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS";
field public static final java.lang.String READ_SYNC_STATS = "android.permission.READ_SYNC_STATS";
field public static final java.lang.String READ_VOICEMAIL = "com.android.voicemail.permission.READ_VOICEMAIL";
- field public static final java.lang.String READ_WRITE_CONTACT_METADATA = "android.permission.READ_WRITE_CONTACT_METADATA";
field public static final java.lang.String REBOOT = "android.permission.REBOOT";
field public static final java.lang.String RECEIVE_BOOT_COMPLETED = "android.permission.RECEIVE_BOOT_COMPLETED";
field public static final java.lang.String RECEIVE_EMERGENCY_BROADCAST = "android.permission.RECEIVE_EMERGENCY_BROADCAST";
@@ -300,6 +299,7 @@
field public static final int backgroundTint = 16843883; // 0x101046b
field public static final int backgroundTintMode = 16843884; // 0x101046c
field public static final int backupAgent = 16843391; // 0x101027f
+ field public static final int backupInForeground = 16844059; // 0x101051b
field public static final int banner = 16843762; // 0x10103f2
field public static final int baseline = 16843548; // 0x101031c
field public static final int baselineAlignBottom = 16843042; // 0x1010122
@@ -337,6 +337,7 @@
field public static final int calendarViewStyle = 16843613; // 0x101035d
field public static final int canControlMagnification = 16844040; // 0x1010508
field public static final int canPerformGestures = 16844046; // 0x101050e
+ field public static final int canRecord = 16844061; // 0x101051d
field public static final int canRequestEnhancedWebAccessibility = 16843736; // 0x10103d8
field public static final int canRequestFilterKeyEvents = 16843737; // 0x10103d9
field public static final int canRequestTouchExplorationMode = 16843735; // 0x10103d7
@@ -422,6 +423,7 @@
field public static final int controlX2 = 16843774; // 0x10103fe
field public static final int controlY1 = 16843773; // 0x10103fd
field public static final int controlY2 = 16843775; // 0x10103ff
+ field public static final int countDown = 16844060; // 0x101051c
field public static final int country = 16843962; // 0x10104ba
field public static final int cropToPadding = 16843043; // 0x1010123
field public static final int cursorVisible = 16843090; // 0x1010152
@@ -1357,6 +1359,7 @@
field public static final int trimPathEnd = 16843785; // 0x1010409
field public static final int trimPathOffset = 16843786; // 0x101040a
field public static final int trimPathStart = 16843784; // 0x1010408
+ field public static final int tunerCount = 16844062; // 0x101051e
field public static final int type = 16843169; // 0x10101a1
field public static final int typeface = 16842902; // 0x1010096
field public static final int uiOptions = 16843672; // 0x1010398
@@ -2662,8 +2665,11 @@
field public static final int GLOBAL_ACTION_POWER_DIALOG = 6; // 0x6
field public static final int GLOBAL_ACTION_QUICK_SETTINGS = 5; // 0x5
field public static final int GLOBAL_ACTION_RECENTS = 3; // 0x3
+ field public static final int GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN = 7; // 0x7
field public static final java.lang.String SERVICE_INTERFACE = "android.accessibilityservice.AccessibilityService";
field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
+ field public static final int SHOW_MODE_AUTO = 0; // 0x0
+ field public static final int SHOW_MODE_HIDDEN = 1; // 0x1
}
public static abstract class AccessibilityService.GestureResultCallback {
@@ -4122,13 +4128,12 @@
field public java.lang.String serviceDetails;
}
- public class AutomaticZenRule implements android.os.Parcelable {
+ public final class AutomaticZenRule implements android.os.Parcelable {
ctor public AutomaticZenRule(java.lang.String, android.content.ComponentName, android.net.Uri, int, boolean);
ctor public AutomaticZenRule(android.os.Parcel);
method public int describeContents();
method public android.net.Uri getConditionId();
method public long getCreationTime();
- method public java.lang.String getId();
method public int getInterruptionFilter();
method public java.lang.String getName();
method public android.content.ComponentName getOwner();
@@ -4275,7 +4280,6 @@
public class DownloadManager {
method public long addCompletedDownload(java.lang.String, java.lang.String, boolean, java.lang.String, java.lang.String, long, boolean);
- method public long addCompletedDownload(java.lang.String, java.lang.String, boolean, java.lang.String, java.lang.String, long, boolean, android.net.Uri, android.net.Uri);
method public long enqueue(android.app.DownloadManager.Request);
method public static java.lang.Long getMaxBytesOverMobile(android.content.Context);
method public java.lang.String getMimeTypeForDownloadedFile(long);
@@ -4879,7 +4883,6 @@
method public android.graphics.drawable.Icon getLargeIcon();
method public android.graphics.drawable.Icon getSmallIcon();
method public java.lang.String getSortKey();
- method public android.app.Notification.Topic getTopic();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT;
field public static final java.lang.String CATEGORY_ALARM = "alarm";
@@ -4905,6 +4908,7 @@
field public static final int DEFAULT_VIBRATE = 2; // 0x2
field public static final java.lang.String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri";
field public static final java.lang.String EXTRA_BIG_TEXT = "android.bigText";
+ field public static final java.lang.String EXTRA_CHRONOMETER_COUNTS_DOWN = "android.chronometerCountsDown";
field public static final java.lang.String EXTRA_COMPACT_ACTIONS = "android.compactActions";
field public static final java.lang.String EXTRA_INFO_TEXT = "android.infoText";
field public static final java.lang.String EXTRA_LARGE_ICON = "android.largeIcon";
@@ -4943,7 +4947,6 @@
field public static final int PRIORITY_MAX = 2; // 0x2
field public static final int PRIORITY_MIN = -2; // 0xfffffffe
field public static final deprecated int STREAM_DEFAULT = -1; // 0xffffffff
- field public static final java.lang.String TOPIC_DEFAULT = "system_default_topic";
field public static final int VISIBILITY_PRIVATE = 0; // 0x0
field public static final int VISIBILITY_PUBLIC = 1; // 0x1
field public static final int VISIBILITY_SECRET = -1; // 0xffffffff
@@ -5047,16 +5050,17 @@
method public android.app.Notification.Builder addExtras(android.os.Bundle);
method public android.app.Notification.Builder addPerson(java.lang.String);
method public android.app.Notification build();
+ method public android.widget.RemoteViews createBigContentView();
+ method public android.widget.RemoteViews createContentView();
+ method public android.widget.RemoteViews createHeadsUpContentView();
method public android.app.Notification.Builder extend(android.app.Notification.Extender);
method public android.os.Bundle getExtras();
method public deprecated android.app.Notification getNotification();
- method public android.widget.RemoteViews makeBigContentView();
- method public android.widget.RemoteViews makeContentView();
- method public android.widget.RemoteViews makeHeadsUpContentView();
method public static android.app.Notification.Builder recoverBuilder(android.content.Context, android.app.Notification);
method public android.app.Notification.Builder setActions(android.app.Notification.Action...);
method public android.app.Notification.Builder setAutoCancel(boolean);
method public android.app.Notification.Builder setCategory(java.lang.String);
+ method public android.app.Notification.Builder setChronometerCountsDown(boolean);
method public android.app.Notification.Builder setColor(int);
method public deprecated android.app.Notification.Builder setContent(android.widget.RemoteViews);
method public android.app.Notification.Builder setContentInfo(java.lang.CharSequence);
@@ -5095,7 +5099,6 @@
method public android.app.Notification.Builder setSubText(java.lang.CharSequence);
method public android.app.Notification.Builder setTicker(java.lang.CharSequence);
method public deprecated android.app.Notification.Builder setTicker(java.lang.CharSequence, android.widget.RemoteViews);
- method public android.app.Notification.Builder setTopic(android.app.Notification.Topic);
method public android.app.Notification.Builder setUsesChronometer(boolean);
method public android.app.Notification.Builder setVibrate(long[]);
method public android.app.Notification.Builder setVisibility(int);
@@ -5133,6 +5136,16 @@
method public android.app.PendingIntent getReplyPendingIntent();
}
+ public static class Notification.DecoratedCustomViewStyle extends android.app.Notification.Style {
+ ctor public Notification.DecoratedCustomViewStyle();
+ ctor public Notification.DecoratedCustomViewStyle(android.app.Notification.Builder);
+ }
+
+ public static class Notification.DecoratedMediaCustomViewStyle extends android.app.Notification.MediaStyle {
+ ctor public Notification.DecoratedMediaCustomViewStyle();
+ ctor public Notification.DecoratedMediaCustomViewStyle(android.app.Notification.Builder);
+ }
+
public static abstract interface Notification.Extender {
method public abstract android.app.Notification.Builder extend(android.app.Notification.Builder);
}
@@ -5163,16 +5176,6 @@
field protected android.app.Notification.Builder mBuilder;
}
- public static class Notification.Topic implements android.os.Parcelable {
- ctor public Notification.Topic(java.lang.String, java.lang.CharSequence);
- method public android.app.Notification.Topic clone();
- method public int describeContents();
- method public java.lang.String getId();
- method public java.lang.CharSequence getLabel();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.app.Notification.Topic> CREATOR;
- }
-
public static final class Notification.WearableExtender implements android.app.Notification.Extender {
ctor public Notification.WearableExtender();
ctor public Notification.WearableExtender(android.app.Notification);
@@ -5226,16 +5229,16 @@
}
public class NotificationManager {
- method public android.app.AutomaticZenRule addAutomaticZenRule(android.app.AutomaticZenRule);
+ method public java.lang.String addAutomaticZenRule(android.app.AutomaticZenRule);
method public boolean areNotificationsEnabled();
method public void cancel(int);
method public void cancel(java.lang.String, int);
method public void cancelAll();
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String);
- method public java.util.List<android.app.AutomaticZenRule> getAutomaticZenRules();
+ method public java.util.Map<java.lang.String, android.app.AutomaticZenRule> getAutomaticZenRules();
method public final int getCurrentInterruptionFilter();
- method public int getImportance(java.lang.String);
+ method public int getImportance();
method public android.app.NotificationManager.Policy getNotificationPolicy();
method public boolean isNotificationPolicyAccessGranted();
method public void notify(int, android.app.Notification);
@@ -5243,7 +5246,7 @@
method public boolean removeAutomaticZenRule(java.lang.String);
method public final void setInterruptionFilter(int);
method public void setNotificationPolicy(android.app.NotificationManager.Policy);
- method public boolean updateAutomaticZenRule(android.app.AutomaticZenRule);
+ method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule);
field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
field public static final java.lang.String ACTION_NOTIFICATION_POLICY_CHANGED = "android.app.action.NOTIFICATION_POLICY_CHANGED";
@@ -5255,7 +5258,7 @@
}
public static class NotificationManager.Policy implements android.os.Parcelable {
- ctor public deprecated NotificationManager.Policy(int, int, int);
+ ctor public NotificationManager.Policy(int, int, int);
ctor public NotificationManager.Policy(int, int, int, int);
method public int describeContents();
method public static java.lang.String priorityCategoriesToString(int);
@@ -5607,8 +5610,6 @@
method public void enableCarMode(int);
method public int getCurrentModeType();
method public int getNightMode();
- method public boolean isNightModeLocked();
- method public boolean isUiModeLocked();
method public void setNightMode(int);
field public static java.lang.String ACTION_ENTER_CAR_MODE;
field public static java.lang.String ACTION_ENTER_DESK_MODE;
@@ -5710,6 +5711,7 @@
public class WallpaperManager {
method public void clear() throws java.io.IOException;
+ method public void clear(int) throws java.io.IOException;
method public void clearWallpaperOffsets(android.os.IBinder);
method public void forgetLoadedWallpaper();
method public android.graphics.drawable.Drawable getBuiltInDrawable();
@@ -5720,6 +5722,7 @@
method public android.graphics.drawable.Drawable getDrawable();
method public android.graphics.drawable.Drawable getFastDrawable();
method public static android.app.WallpaperManager getInstance(android.content.Context);
+ method public android.os.ParcelFileDescriptor getWallpaperFile(int);
method public android.app.WallpaperInfo getWallpaperInfo();
method public boolean hasResourceWallpaper(int);
method public boolean isWallpaperSettingAllowed();
@@ -5830,9 +5833,7 @@
method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
method public void clearProfileOwner(android.content.ComponentName);
method public void clearUserRestriction(android.content.ComponentName, java.lang.String);
- method public deprecated android.os.UserHandle createAndInitializeUser(android.content.ComponentName, java.lang.String, java.lang.String, android.content.ComponentName, android.os.Bundle);
method public android.os.UserHandle createAndManageUser(android.content.ComponentName, java.lang.String, android.content.ComponentName, android.os.PersistableBundle, int);
- method public deprecated android.os.UserHandle createUser(android.content.ComponentName, java.lang.String);
method public void enableSystemApp(android.content.ComponentName, java.lang.String);
method public int enableSystemApp(android.content.ComponentName, android.content.Intent);
method public java.lang.String[] getAccountTypesWithManagementDisabled();
@@ -5887,6 +5888,7 @@
method public boolean hasGrantedPolicy(android.content.ComponentName, int);
method public boolean installCaCert(android.content.ComponentName, byte[]);
method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate, java.lang.String);
+ method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate, java.lang.String, boolean);
method public boolean isActivePasswordSufficient();
method public boolean isAdminActive(android.content.ComponentName);
method public boolean isApplicationHidden(android.content.ComponentName, java.lang.String);
@@ -6589,7 +6591,7 @@
field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
}
- public static class SecurityLog.SecurityEvent implements android.os.Parcelable {
+ public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
method public int describeContents();
method public java.lang.Object getData();
method public int getTag();
@@ -7333,15 +7335,6 @@
field public static final int TYPE_SCO = 2; // 0x2
}
- public class OobData implements android.os.Parcelable {
- ctor public OobData();
- method public int describeContents();
- method public byte[] getSecurityManagerTk();
- method public void setSecurityManagerTk(byte[]);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.bluetooth.OobData> CREATOR;
- }
-
}
package android.bluetooth.le {
@@ -8471,6 +8464,7 @@
field public static final java.lang.String ACTION_AIRPLANE_MODE_CHANGED = "android.intent.action.AIRPLANE_MODE";
field public static final java.lang.String ACTION_ALL_APPS = "android.intent.action.ALL_APPS";
field public static final java.lang.String ACTION_ANSWER = "android.intent.action.ANSWER";
+ field public static final java.lang.String ACTION_APPLICATION_PREFERENCES = "android.intent.action.APPLICATION_PREFERENCES";
field public static final java.lang.String ACTION_APPLICATION_RESTRICTIONS_CHANGED = "android.intent.action.APPLICATION_RESTRICTIONS_CHANGED";
field public static final java.lang.String ACTION_APP_ERROR = "android.intent.action.APP_ERROR";
field public static final java.lang.String ACTION_ASSIST = "android.intent.action.ASSIST";
@@ -9786,6 +9780,8 @@
field public static final java.lang.String FEATURE_VERIFIED_BOOT = "android.software.verified_boot";
field public static final java.lang.String FEATURE_VR_MODE = "android.software.vr.mode";
field public static final java.lang.String FEATURE_VR_MODE_HIGH_PERFORMANCE = "android.hardware.vr.high_performance";
+ field public static final java.lang.String FEATURE_VULKAN_HARDWARE_LEVEL = "android.hardware.vulkan.level";
+ field public static final java.lang.String FEATURE_VULKAN_HARDWARE_VERSION = "android.hardware.vulkan.version";
field public static final java.lang.String FEATURE_WATCH = "android.hardware.type.watch";
field public static final java.lang.String FEATURE_WEBVIEW = "android.software.webview";
field public static final java.lang.String FEATURE_WIFI = "android.hardware.wifi";
@@ -10470,7 +10466,6 @@
method public boolean hasNext();
method public java.util.Iterator<android.database.CursorJoiner.Result> iterator();
method public android.database.CursorJoiner.Result next();
- method public void remove();
}
public static final class CursorJoiner.Result extends java.lang.Enum {
@@ -11947,6 +11942,8 @@
ctor public Outline(android.graphics.Outline);
method public boolean canClip();
method public float getAlpha();
+ method public float getRadius();
+ method public boolean getRect(android.graphics.Rect);
method public boolean isEmpty();
method public void offset(int, int);
method public void set(android.graphics.Outline);
@@ -12974,12 +12971,10 @@
ctor public deprecated NinePatchDrawable(android.graphics.NinePatch);
ctor public NinePatchDrawable(android.content.res.Resources, android.graphics.NinePatch);
method public void draw(android.graphics.Canvas);
- method public android.graphics.NinePatch getNinePatch();
method public int getOpacity();
method public android.graphics.Paint getPaint();
method public void setAlpha(int);
method public void setColorFilter(android.graphics.ColorFilter);
- method public void setNinePatch(android.graphics.NinePatch);
method public void setTargetDensity(android.graphics.Canvas);
method public void setTargetDensity(android.util.DisplayMetrics);
method public void setTargetDensity(int);
@@ -13202,8 +13197,8 @@
method public final void takePicture(android.hardware.Camera.ShutterCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback);
method public final void takePicture(android.hardware.Camera.ShutterCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback);
method public final void unlock();
- field public static final java.lang.String ACTION_NEW_PICTURE = "android.hardware.action.NEW_PICTURE";
- field public static final java.lang.String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO";
+ field public static final deprecated java.lang.String ACTION_NEW_PICTURE = "android.hardware.action.NEW_PICTURE";
+ field public static final deprecated java.lang.String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO";
field public static final int CAMERA_ERROR_EVICTED = 2; // 0x2
field public static final int CAMERA_ERROR_SERVER_DIED = 100; // 0x64
field public static final int CAMERA_ERROR_UNKNOWN = 1; // 0x1
@@ -19160,178 +19155,110 @@
public final class GnssClock implements android.os.Parcelable {
method public int describeContents();
- method public double getBiasInNs();
- method public double getBiasUncertaintyInNs();
- method public double getDriftInNsPerSec();
- method public double getDriftUncertaintyInNsPerSec();
- method public long getFullBiasInNs();
- method public short getLeapSecond();
- method public long getTimeInNs();
- method public long getTimeOfLastHwClockDiscontinuityInNs();
- method public double getTimeUncertaintyInNs();
- method public byte getType();
- method public boolean hasBiasInNs();
- method public boolean hasBiasUncertaintyInNs();
- method public boolean hasDriftInNsPerSec();
- method public boolean hasDriftUncertaintyInNsPerSec();
- method public boolean hasFullBiasInNs();
+ method public double getBiasNanos();
+ method public double getBiasUncertaintyNanos();
+ method public double getDriftNanosPerSecond();
+ method public double getDriftUncertaintyNanosPerSecond();
+ method public long getFullBiasNanos();
+ method public int getHardwareClockDiscontinuityCount();
+ method public int getLeapSecond();
+ method public long getTimeNanos();
+ method public double getTimeUncertaintyNanos();
+ method public boolean hasBiasNanos();
+ method public boolean hasBiasUncertaintyNanos();
+ method public boolean hasDriftNanosPerSecond();
+ method public boolean hasDriftUncertaintyNanosPerSecond();
+ method public boolean hasFullBiasNanos();
method public boolean hasLeapSecond();
- method public boolean hasTimeUncertaintyInNs();
+ method public boolean hasTimeUncertaintyNanos();
method public void reset();
- method public void resetBiasInNs();
- method public void resetBiasUncertaintyInNs();
- method public void resetDriftInNsPerSec();
- method public void resetDriftUncertaintyInNsPerSec();
- method public void resetFullBiasInNs();
+ method public void resetBiasNanos();
+ method public void resetBiasUncertaintyNanos();
+ method public void resetDriftNanosPerSecond();
+ method public void resetDriftUncertaintyNanosPerSecond();
+ method public void resetFullBiasNanos();
method public void resetLeapSecond();
- method public void resetTimeUncertaintyInNs();
+ method public void resetTimeUncertaintyNanos();
method public void set(android.location.GnssClock);
- method public void setBiasInNs(double);
- method public void setBiasUncertaintyInNs(double);
- method public void setDriftInNsPerSec(double);
- method public void setDriftUncertaintyInNsPerSec(double);
- method public void setFullBiasInNs(long);
- method public void setLeapSecond(short);
- method public void setTimeInNs(long);
- method public void setTimeOfLastHwClockDiscontinuityInNs(long);
- method public void setTimeUncertaintyInNs(double);
- method public void setType(byte);
+ method public void setBiasNanos(double);
+ method public void setBiasUncertaintyNanos(double);
+ method public void setDriftNanosPerSecond(double);
+ method public void setDriftUncertaintyNanosPerSecond(double);
+ method public void setFullBiasNanos(long);
+ method public void setHardwareClockDiscontinuityCount(int);
+ method public void setLeapSecond(int);
+ method public void setTimeNanos(long);
+ method public void setTimeUncertaintyNanos(double);
method public void writeToParcel(android.os.Parcel, int);
- field public static final byte CLOCK_TYPE_GPS_TIME = 2; // 0x2
- field public static final byte CLOCK_TYPE_LOCAL_HW_TIME = 1; // 0x1
- field public static final byte CLOCK_TYPE_UNKNOWN = 0; // 0x0
field public static final android.os.Parcelable.Creator<android.location.GnssClock> CREATOR;
}
- public static abstract class GnssClock.GnssClockType implements java.lang.annotation.Annotation {
- }
-
public final class GnssMeasurement implements android.os.Parcelable {
method public int describeContents();
- method public double getAccumulatedDeltaRangeInMeters();
- method public short getAccumulatedDeltaRangeState();
- method public double getAccumulatedDeltaRangeUncertaintyInMeters();
- method public double getAzimuthInDeg();
- method public double getAzimuthUncertaintyInDeg();
- method public int getBitNumber();
+ method public double getAccumulatedDeltaRangeMeters();
+ method public int getAccumulatedDeltaRangeState();
+ method public double getAccumulatedDeltaRangeUncertaintyMeters();
method public long getCarrierCycles();
- method public float getCarrierFrequencyInHz();
+ method public float getCarrierFrequencyHz();
method public double getCarrierPhase();
method public double getCarrierPhaseUncertainty();
- method public double getCn0InDbHz();
- method public double getCodePhaseInChips();
- method public double getCodePhaseUncertaintyInChips();
- method public double getDopplerShiftInHz();
- method public double getDopplerShiftUncertaintyInHz();
- method public double getElevationInDeg();
- method public double getElevationUncertaintyInDeg();
- method public byte getLossOfLock();
- method public byte getMultipathIndicator();
- method public double getPseudorangeInMeters();
- method public double getPseudorangeRateCarrierInMetersPerSec();
- method public double getPseudorangeRateCarrierUncertaintyInMetersPerSec();
- method public double getPseudorangeRateInMetersPerSec();
- method public double getPseudorangeRateUncertaintyInMetersPerSec();
- method public double getPseudorangeUncertaintyInMeters();
- method public long getReceivedGpsTowInNs();
- method public long getReceivedGpsTowUncertaintyInNs();
+ method public double getCn0DbHz();
+ method public int getConstellationType();
+ method public int getMultipathIndicator();
+ method public double getPseudorangeRateMetersPerSecond();
+ method public double getPseudorangeRateUncertaintyMetersPerSecond();
+ method public long getReceivedSvTimeNanos();
+ method public long getReceivedSvTimeUncertaintyNanos();
method public double getSnrInDb();
- method public short getState();
- method public short getSvid();
- method public short getTimeFromLastBitInMs();
- method public double getTimeOffsetInNs();
- method public boolean hasAzimuthInDeg();
- method public boolean hasAzimuthUncertaintyInDeg();
- method public boolean hasBitNumber();
+ method public int getState();
+ method public int getSvid();
+ method public double getTimeOffsetNanos();
method public boolean hasCarrierCycles();
- method public boolean hasCarrierFrequencyInHz();
+ method public boolean hasCarrierFrequencyHz();
method public boolean hasCarrierPhase();
method public boolean hasCarrierPhaseUncertainty();
- method public boolean hasCodePhaseInChips();
- method public boolean hasCodePhaseUncertaintyInChips();
- method public boolean hasDopplerShiftInHz();
- method public boolean hasDopplerShiftUncertaintyInHz();
- method public boolean hasElevationInDeg();
- method public boolean hasElevationUncertaintyInDeg();
- method public boolean hasPseudorangeInMeters();
- method public boolean hasPseudorangeUncertaintyInMeters();
method public boolean hasSnrInDb();
- method public boolean hasTimeFromLastBitInMs();
method public boolean isPseudorangeRateCorrected();
- method public boolean isUsedInFix();
method public void reset();
- method public void resetAzimuthInDeg();
- method public void resetAzimuthUncertaintyInDeg();
- method public void resetBitNumber();
method public void resetCarrierCycles();
- method public void resetCarrierFrequencyInHz();
+ method public void resetCarrierFrequencyHz();
method public void resetCarrierPhase();
method public void resetCarrierPhaseUncertainty();
- method public void resetCodePhaseInChips();
- method public void resetCodePhaseUncertaintyInChips();
- method public void resetDopplerShiftInHz();
- method public void resetDopplerShiftUncertaintyInHz();
- method public void resetElevationInDeg();
- method public void resetElevationUncertaintyInDeg();
- method public void resetPseudorangeInMeters();
- method public void resetPseudorangeUncertaintyInMeters();
method public void resetSnrInDb();
- method public void resetTimeFromLastBitInMs();
method public void set(android.location.GnssMeasurement);
- method public void setAccumulatedDeltaRangeInMeters(double);
- method public void setAccumulatedDeltaRangeState(short);
- method public void setAccumulatedDeltaRangeUncertaintyInMeters(double);
- method public void setAzimuthInDeg(double);
- method public void setAzimuthUncertaintyInDeg(double);
- method public void setBitNumber(int);
+ method public void setAccumulatedDeltaRangeMeters(double);
+ method public void setAccumulatedDeltaRangeState(int);
+ method public void setAccumulatedDeltaRangeUncertaintyMeters(double);
method public void setCarrierCycles(long);
- method public void setCarrierFrequencyInHz(float);
+ method public void setCarrierFrequencyHz(float);
method public void setCarrierPhase(double);
method public void setCarrierPhaseUncertainty(double);
- method public void setCn0InDbHz(double);
- method public void setCodePhaseInChips(double);
- method public void setCodePhaseUncertaintyInChips(double);
- method public void setDopplerShiftInHz(double);
- method public void setDopplerShiftUncertaintyInHz(double);
- method public void setElevationInDeg(double);
- method public void setElevationUncertaintyInDeg(double);
- method public void setLossOfLock(byte);
- method public void setMultipathIndicator(byte);
- method public void setPseudorangeInMeters(double);
- method public void setPseudorangeRateCarrierInMetersPerSec(double);
- method public void setPseudorangeRateCarrierUncertaintyInMetersPerSec(double);
- method public void setPseudorangeRateInMetersPerSec(double);
- method public void setPseudorangeRateUncertaintyInMetersPerSec(double);
- method public void setPseudorangeUncertaintyInMeters(double);
- method public void setReceivedGpsTowInNs(long);
- method public void setReceivedGpsTowUncertaintyInNs(long);
+ method public void setCn0DbHz(double);
+ method public void setConstellationType(int);
+ method public void setMultipathIndicator(int);
+ method public void setPseudorangeRateMetersPerSecond(double);
+ method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
+ method public void setReceivedSvTimeNanos(long);
+ method public void setReceivedSvTimeUncertaintyNanos(long);
method public void setSnrInDb(double);
- method public void setState(short);
- method public void setSvid(short);
- method public void setTimeFromLastBitInMs(short);
- method public void setTimeOffsetInNs(double);
- method public void setUsedInFix(boolean);
+ method public void setState(int);
+ method public void setSvid(int);
+ method public void setTimeOffsetNanos(double);
method public void writeToParcel(android.os.Parcel, int);
- field public static final short ADR_STATE_CYCLE_SLIP = 4; // 0x4
- field public static final short ADR_STATE_RESET = 2; // 0x2
- field public static final short ADR_STATE_UNKNOWN = 0; // 0x0
- field public static final short ADR_STATE_VALID = 1; // 0x1
+ field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
+ field public static final int ADR_STATE_RESET = 2; // 0x2
+ field public static final int ADR_STATE_UNKNOWN = 0; // 0x0
+ field public static final int ADR_STATE_VALID = 1; // 0x1
field public static final android.os.Parcelable.Creator<android.location.GnssMeasurement> CREATOR;
- field public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2; // 0x2
- field public static final byte LOSS_OF_LOCK_OK = 1; // 0x1
- field public static final byte LOSS_OF_LOCK_UNKNOWN = 0; // 0x0
- field public static final byte MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
- field public static final byte MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
- field public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
- field public static final short STATE_BIT_SYNC = 2; // 0x2
- field public static final short STATE_CODE_LOCK = 1; // 0x1
- field public static final short STATE_MSEC_AMBIGUOUS = 16; // 0x10
- field public static final short STATE_SUBFRAME_SYNC = 4; // 0x4
- field public static final short STATE_TOW_DECODED = 8; // 0x8
- field public static final short STATE_UNKNOWN = 0; // 0x0
- }
-
- public static abstract class GnssMeasurement.LossOfLockStatus implements java.lang.annotation.Annotation {
+ field public static final int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
+ field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+ field public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
+ field public static final int STATE_BIT_SYNC = 2; // 0x2
+ field public static final int STATE_CODE_LOCK = 1; // 0x1
+ field public static final int STATE_MSEC_AMBIGUOUS = 16; // 0x10
+ field public static final int STATE_SUBFRAME_SYNC = 4; // 0x4
+ field public static final int STATE_TOW_DECODED = 8; // 0x8
+ field public static final int STATE_UNKNOWN = 0; // 0x0
}
public static abstract class GnssMeasurement.MultipathIndicator implements java.lang.annotation.Annotation {
@@ -19344,7 +19271,7 @@
method public java.util.Collection<android.location.GnssMeasurement> getMeasurements();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementsEvent> CREATOR;
- field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+ field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
field public static final int STATUS_READY = 1; // 0x1
}
@@ -19361,29 +19288,34 @@
public final class GnssNavigationMessage implements android.os.Parcelable {
method public int describeContents();
method public byte[] getData();
- method public short getMessageId();
- method public short getStatus();
- method public short getSubmessageId();
- method public short getSvid();
- method public byte getType();
+ method public int getMessageId();
+ method public int getStatus();
+ method public int getSubmessageId();
+ method public int getSvid();
+ method public int getType();
method public void reset();
method public void set(android.location.GnssNavigationMessage);
method public void setData(byte[]);
- method public void setMessageId(short);
- method public void setStatus(short);
- method public void setSubmessageId(short);
- method public void setSvid(short);
- method public void setType(byte);
+ method public void setMessageId(int);
+ method public void setStatus(int);
+ method public void setSubmessageId(int);
+ method public void setSvid(int);
+ method public void setType(int);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
- field public static final byte MESSAGE_TYPE_CNAV2 = 4; // 0x4
- field public static final byte MESSAGE_TYPE_L1CA = 1; // 0x1
- field public static final byte MESSAGE_TYPE_L2CNAV = 2; // 0x2
- field public static final byte MESSAGE_TYPE_L5CNAV = 3; // 0x3
- field public static final byte MESSAGE_TYPE_UNKNOWN = 0; // 0x0
- field public static final short STATUS_PARITY_PASSED = 1; // 0x1
- field public static final short STATUS_PARITY_REBUILT = 2; // 0x2
- field public static final short STATUS_UNKNOWN = 0; // 0x0
+ field public static final int STATUS_PARITY_PASSED = 1; // 0x1
+ field public static final int STATUS_PARITY_REBUILT = 2; // 0x2
+ field public static final int STATUS_UNKNOWN = 0; // 0x0
+ field public static final int TYPE_BDS_D1 = 1281; // 0x501
+ field public static final int TYPE_BDS_D2 = 1282; // 0x502
+ field public static final int TYPE_GAL_F = 1538; // 0x602
+ field public static final int TYPE_GAL_I = 1537; // 0x601
+ field public static final int TYPE_GLO_L1CA = 769; // 0x301
+ field public static final int TYPE_GPS_CNAV2 = 260; // 0x104
+ field public static final int TYPE_GPS_L1CA = 257; // 0x101
+ field public static final int TYPE_GPS_L2CNAV = 258; // 0x102
+ field public static final int TYPE_GPS_L5CNAV = 259; // 0x103
+ field public static final int TYPE_UNKNOWN = 0; // 0x0
}
public static abstract class GnssNavigationMessage.GnssNavigationMessageType implements java.lang.annotation.Annotation {
@@ -19395,7 +19327,7 @@
method public android.location.GnssNavigationMessage getNavigationMessage();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessageEvent> CREATOR;
- field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+ field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
field public static final int STATUS_READY = 1; // 0x1
}
@@ -19414,11 +19346,11 @@
}
public final class GnssStatus {
- method public float getAzimuth(int);
+ method public float getAzimuthDegrees(int);
+ method public float getCn0DbHz(int);
method public int getConstellationType(int);
- method public float getElevation(int);
+ method public float getElevationDegrees(int);
method public int getNumSatellites();
- method public float getSnr(int);
method public int getSvid(int);
method public boolean hasAlmanac(int);
method public boolean hasEphemeris(int);
@@ -19432,6 +19364,9 @@
field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
}
+ public static abstract class GnssStatus.ConstellationType implements java.lang.annotation.Annotation {
+ }
+
public abstract class GnssStatusCallback {
ctor public GnssStatusCallback();
method public void onFirstFix(int);
@@ -19541,8 +19476,8 @@
method public java.util.List<java.lang.String> getProviders(boolean);
method public java.util.List<java.lang.String> getProviders(android.location.Criteria, boolean);
method public boolean isProviderEnabled(java.lang.String);
- method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
- method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
+ method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
+ method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback, android.os.Handler);
method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback);
@@ -19567,7 +19502,7 @@
method public void setTestProviderEnabled(java.lang.String, boolean);
method public void setTestProviderLocation(java.lang.String, android.location.Location);
method public void setTestProviderStatus(java.lang.String, int, android.os.Bundle, long);
- method public void unregisterGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
+ method public void unregisterGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
field public static final java.lang.String GPS_PROVIDER = "gps";
@@ -19687,6 +19622,7 @@
field public static final int TYPE_BUILTIN_EARPIECE = 1; // 0x1
field public static final int TYPE_BUILTIN_MIC = 15; // 0xf
field public static final int TYPE_BUILTIN_SPEAKER = 2; // 0x2
+ field public static final int TYPE_BUS = 21; // 0x15
field public static final int TYPE_DOCK = 13; // 0xd
field public static final int TYPE_FM = 14; // 0xe
field public static final int TYPE_FM_TUNER = 16; // 0x10
@@ -19704,12 +19640,14 @@
field public static final int TYPE_WIRED_HEADSET = 3; // 0x3
}
- public class AudioFormat {
+ public final class AudioFormat implements android.os.Parcelable {
+ method public int describeContents();
method public int getChannelCount();
method public int getChannelIndexMask();
method public int getChannelMask();
method public int getEncoding();
method public int getSampleRate();
+ method public void writeToParcel(android.os.Parcel, int);
field public static final deprecated int CHANNEL_CONFIGURATION_DEFAULT = 1; // 0x1
field public static final deprecated int CHANNEL_CONFIGURATION_INVALID = 0; // 0x0
field public static final deprecated int CHANNEL_CONFIGURATION_MONO = 2; // 0x2
@@ -19751,6 +19689,7 @@
field public static final int CHANNEL_OUT_SIDE_RIGHT = 4096; // 0x1000
field public static final int CHANNEL_OUT_STEREO = 12; // 0xc
field public static final int CHANNEL_OUT_SURROUND = 1052; // 0x41c
+ field public static final android.os.Parcelable.Creator<android.media.AudioFormat> CREATOR;
field public static final int ENCODING_AC3 = 5; // 0x5
field public static final int ENCODING_DEFAULT = 1; // 0x1
field public static final int ENCODING_DTS = 7; // 0x7
@@ -19761,6 +19700,7 @@
field public static final int ENCODING_PCM_16BIT = 2; // 0x2
field public static final int ENCODING_PCM_8BIT = 3; // 0x3
field public static final int ENCODING_PCM_FLOAT = 4; // 0x4
+ field public static final int SAMPLE_RATE_UNSPECIFIED = 0; // 0x0
}
public static class AudioFormat.Builder {
@@ -19926,7 +19866,7 @@
public static abstract class AudioManager.AudioRecordingCallback {
ctor public AudioManager.AudioRecordingCallback();
- method public void onRecordConfigChanged();
+ method public void onRecordConfigChanged(android.media.AudioRecordConfiguration[]);
}
public static abstract interface AudioManager.OnAudioFocusChangeListener {
@@ -20000,7 +19940,7 @@
method public abstract void onRoutingChanged(android.media.AudioRecord);
}
- public class AudioRecordConfiguration implements android.os.Parcelable {
+ public final class AudioRecordConfiguration implements android.os.Parcelable {
method public int describeContents();
method public android.media.AudioDeviceInfo getAudioDevice();
method public int getClientAudioSessionId();
@@ -20014,6 +19954,7 @@
public abstract interface AudioRouting {
method public abstract void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public abstract android.media.AudioDeviceInfo getPreferredDevice();
+ method public abstract android.media.AudioDeviceInfo getRoutedDevice();
method public abstract void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener);
method public abstract boolean setPreferredDevice(android.media.AudioDeviceInfo);
}
@@ -20194,6 +20135,8 @@
public class ExifInterface {
ctor public ExifInterface(java.lang.String) throws java.io.IOException;
+ ctor public ExifInterface(java.io.FileDescriptor) throws java.io.IOException;
+ ctor public ExifInterface(java.io.InputStream) throws java.io.IOException;
method public double getAltitude(double);
method public java.lang.String getAttribute(java.lang.String);
method public double getAttributeDouble(java.lang.String, double);
@@ -20215,6 +20158,10 @@
field public static final java.lang.String TAG_APERTURE = "FNumber";
field public static final java.lang.String TAG_DATETIME = "DateTime";
field public static final java.lang.String TAG_DATETIME_DIGITIZED = "DateTimeDigitized";
+ field public static final java.lang.String TAG_DIGITAL_ZOOM_RATIO = "DigitalZoomRatio";
+ field public static final java.lang.String TAG_EXPOSURE_BIAS_VALUE = "ExposureBiasValue";
+ field public static final java.lang.String TAG_EXPOSURE_MODE = "ExposureMode";
+ field public static final java.lang.String TAG_EXPOSURE_PROGRAM = "ExposureProgram";
field public static final java.lang.String TAG_EXPOSURE_TIME = "ExposureTime";
field public static final java.lang.String TAG_FLASH = "Flash";
field public static final java.lang.String TAG_FOCAL_LENGTH = "FocalLength";
@@ -20230,9 +20177,12 @@
field public static final java.lang.String TAG_IMAGE_LENGTH = "ImageLength";
field public static final java.lang.String TAG_IMAGE_WIDTH = "ImageWidth";
field public static final java.lang.String TAG_ISO = "ISOSpeedRatings";
+ field public static final java.lang.String TAG_LIGHT_SOURCE = "LightSource";
field public static final java.lang.String TAG_MAKE = "Make";
+ field public static final java.lang.String TAG_METERING_MODE = "MeteringMode";
field public static final java.lang.String TAG_MODEL = "Model";
field public static final java.lang.String TAG_ORIENTATION = "Orientation";
+ field public static final java.lang.String TAG_SUBJECT_DISTANCE = "SubjectDistance";
field public static final java.lang.String TAG_SUBSEC_TIME = "SubSecTime";
field public static final java.lang.String TAG_SUBSEC_TIME_DIG = "SubSecTimeDigitized";
field public static final java.lang.String TAG_SUBSEC_TIME_ORIG = "SubSecTimeOriginal";
@@ -20642,6 +20592,7 @@
field public static final int HEVCMainTierLevel62 = 16777216; // 0x1000000
field public static final int HEVCProfileMain = 1; // 0x1
field public static final int HEVCProfileMain10 = 2; // 0x2
+ field public static final int HEVCProfileMain10HDR10 = 4096; // 0x1000
field public static final int MPEG2LevelH14 = 2; // 0x2
field public static final int MPEG2LevelHL = 3; // 0x3
field public static final int MPEG2LevelLL = 0; // 0x0
@@ -20899,6 +20850,7 @@
method public final void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
method public final void setDataSource(java.lang.String, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
method public final void setDataSource(java.lang.String) throws java.io.IOException;
+ method public final void setDataSource(android.content.res.AssetFileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public final void setDataSource(java.io.FileDescriptor) throws java.io.IOException;
method public final void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException;
method public void unselectTrack(int);
@@ -20973,6 +20925,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_PCM_ENCODING = "pcm-encoding";
field public static final java.lang.String KEY_PRIORITY = "priority";
field public static final java.lang.String KEY_PROFILE = "profile";
field public static final java.lang.String KEY_PUSH_BLANK_BUFFERS_ON_STOP = "push-blank-buffers-on-shutdown";
@@ -20982,6 +20935,7 @@
field public static final java.lang.String KEY_SLICE_HEIGHT = "slice-height";
field public static final java.lang.String KEY_STRIDE = "stride";
field public static final java.lang.String KEY_TEMPORAL_LAYERING = "ts-schema";
+ field public static final java.lang.String KEY_TRACK_ID = "track-id";
field public static final java.lang.String KEY_WIDTH = "width";
field public static final java.lang.String MIMETYPE_AUDIO_AAC = "audio/mp4a-latm";
field public static final java.lang.String MIMETYPE_AUDIO_AC3 = "audio/ac3";
@@ -21181,6 +21135,7 @@
method public void setDataSource(android.content.Context, android.net.Uri) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
method public void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
method public void setDataSource(java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
+ method public void setDataSource(android.content.res.AssetFileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public void setDataSource(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public void setDataSource(android.media.MediaDataSource) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
@@ -22547,6 +22502,10 @@
method public void playFromMediaId(java.lang.String, android.os.Bundle);
method public void playFromSearch(java.lang.String, android.os.Bundle);
method public void playFromUri(android.net.Uri, android.os.Bundle);
+ method public void prepare();
+ method public void prepareFromMediaId(java.lang.String, android.os.Bundle);
+ method public void prepareFromSearch(java.lang.String, android.os.Bundle);
+ method public void prepareFromUri(android.net.Uri, android.os.Bundle);
method public void rewind();
method public void seekTo(long);
method public void sendCustomAction(android.media.session.PlaybackState.CustomAction, android.os.Bundle);
@@ -22580,7 +22539,6 @@
method public void setRatingType(int);
method public void setSessionActivity(android.app.PendingIntent);
field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
- field public static final int FLAG_HANDLES_PREPARE_ONLY = 4; // 0x4
field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
}
@@ -22595,6 +22553,10 @@
method public void onPlayFromMediaId(java.lang.String, android.os.Bundle);
method public void onPlayFromSearch(java.lang.String, android.os.Bundle);
method public void onPlayFromUri(android.net.Uri, android.os.Bundle);
+ method public void onPrepare();
+ method public void onPrepareFromMediaId(java.lang.String, android.os.Bundle);
+ method public void onPrepareFromSearch(java.lang.String, android.os.Bundle);
+ method public void onPrepareFromUri(android.net.Uri, android.os.Bundle);
method public void onRewind();
method public void onSeekTo(long);
method public void onSetRating(android.media.Rating);
@@ -22651,6 +22613,10 @@
field public static final long ACTION_PLAY_FROM_SEARCH = 2048L; // 0x800L
field public static final long ACTION_PLAY_FROM_URI = 8192L; // 0x2000L
field public static final long ACTION_PLAY_PAUSE = 512L; // 0x200L
+ field public static final long ACTION_PREPARE = 16384L; // 0x4000L
+ field public static final long ACTION_PREPARE_FROM_MEDIA_ID = 32768L; // 0x8000L
+ field public static final long ACTION_PREPARE_FROM_SEARCH = 65536L; // 0x10000L
+ field public static final long ACTION_PREPARE_FROM_URI = 131072L; // 0x20000L
field public static final long ACTION_REWIND = 8L; // 0x8L
field public static final long ACTION_SEEK_TO = 256L; // 0x100L
field public static final long ACTION_SET_RATING = 128L; // 0x80L
@@ -22659,7 +22625,6 @@
field public static final long ACTION_SKIP_TO_QUEUE_ITEM = 4096L; // 0x1000L
field public static final long ACTION_STOP = 1L; // 0x1L
field public static final android.os.Parcelable.Creator<android.media.session.PlaybackState> CREATOR;
- field public static final java.lang.String EXTRA_PREPARE_ONLY = "android.media.session.extra.PREPARE_ONLY";
field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL
field public static final int STATE_BUFFERING = 6; // 0x6
field public static final int STATE_CONNECTING = 8; // 0x8
@@ -22735,6 +22700,10 @@
method public static final android.net.Uri buildProgramsUriForChannel(long, long, long);
method public static final android.net.Uri buildProgramsUriForChannel(android.net.Uri, long, long);
method public static final android.net.Uri buildRecordedProgramUri(long);
+ method public static final boolean isChannelUri(android.net.Uri);
+ method public static final boolean isChannelUriForPassthroughInput(android.net.Uri);
+ method public static final boolean isChannelUriForTunerInput(android.net.Uri);
+ method public static final boolean isProgramUri(android.net.Uri);
field public static final java.lang.String AUTHORITY = "android.media.tv";
}
@@ -22826,7 +22795,8 @@
field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
- field public static final java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
+ field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
+ field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
@@ -22836,7 +22806,9 @@
field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
- field public static final java.lang.String COLUMN_SEASON_NUMBER = "season_number";
+ field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
+ field public static final deprecated java.lang.String COLUMN_SEASON_NUMBER = "season_number";
+ field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
@@ -22852,6 +22824,7 @@
public static final class TvContract.Programs.Genres {
method public static java.lang.String[] decode(java.lang.String);
method public static java.lang.String encode(java.lang.String...);
+ method public static boolean isCanonical(java.lang.String);
field public static final java.lang.String ANIMAL_WILDLIFE = "ANIMAL_WILDLIFE";
field public static final java.lang.String ARTS = "ARTS";
field public static final java.lang.String COMEDY = "COMEDY";
@@ -22878,7 +22851,7 @@
field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
- field public static final java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
+ field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
field public static final java.lang.String COLUMN_INPUT_ID = "input_id";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
@@ -22893,7 +22866,8 @@
field public static final java.lang.String COLUMN_RECORDING_DURATION_MILLIS = "recording_duration_millis";
field public static final java.lang.String COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS = "recording_expire_time_utc_millis";
field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
- field public static final java.lang.String COLUMN_SEASON_NUMBER = "season_number";
+ field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
+ field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
@@ -22937,7 +22911,7 @@
}
public static final class TvInputInfo.Builder {
- ctor public TvInputInfo.Builder(android.content.Context, java.lang.Class<?>);
+ ctor public TvInputInfo.Builder(android.content.Context, android.content.ComponentName);
method public android.media.tv.TvInputInfo build() throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public android.media.tv.TvInputInfo.Builder setCanRecord(boolean);
method public android.media.tv.TvInputInfo.Builder setTunerCount(int);
@@ -22954,6 +22928,7 @@
field public static final java.lang.String ACTION_BLOCKED_RATINGS_CHANGED = "android.media.tv.action.BLOCKED_RATINGS_CHANGED";
field public static final java.lang.String ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED = "android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED";
field public static final java.lang.String ACTION_QUERY_CONTENT_RATING_SYSTEMS = "android.media.tv.action.QUERY_CONTENT_RATING_SYSTEMS";
+ field public static final java.lang.String ACTION_SETUP_INPUTS = "android.media.tv.action.SETUP_INPUTS";
field public static final int INPUT_STATE_CONNECTED = 0; // 0x0
field public static final int INPUT_STATE_CONNECTED_STANDBY = 1; // 0x1
field public static final int INPUT_STATE_DISCONNECTED = 2; // 0x2
@@ -23004,7 +22979,7 @@
ctor public TvInputService.RecordingSession(android.content.Context);
method public void notifyError(int);
method public void notifyRecordingStopped(android.net.Uri);
- method public void notifyTuned();
+ method public void notifyTuned(android.net.Uri);
method public abstract void onRelease();
method public abstract void onStartRecording(android.net.Uri);
method public abstract void onStopRecording();
@@ -23063,7 +23038,7 @@
method public void onDisconnected(java.lang.String);
method public void onError(int);
method public void onRecordingStopped(android.net.Uri);
- method public void onTuned();
+ method public void onTuned(android.net.Uri);
}
public final class TvTrackInfo implements android.os.Parcelable {
@@ -23490,7 +23465,7 @@
method public int getUid();
}
- public class DataUsageRequest implements android.os.Parcelable {
+ public final class DataUsageRequest 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.net.DataUsageRequest> CREATOR;
@@ -26808,7 +26783,8 @@
method public static void glGetSynciv(long, int, int, int[], int, int[], int);
method public static void glGetSynciv(long, int, int, java.nio.IntBuffer, java.nio.IntBuffer);
method public static void glGetTransformFeedbackVarying(int, int, int, int[], int, int[], int, int[], int, byte[], int);
- method public static void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte);
+ method public static deprecated void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte);
+ method public static void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.ByteBuffer);
method public static java.lang.String glGetTransformFeedbackVarying(int, int, int[], int, int[], int);
method public static java.lang.String glGetTransformFeedbackVarying(int, int, java.nio.IntBuffer, java.nio.IntBuffer);
method public static int glGetUniformBlockIndex(int, java.lang.String);
@@ -26834,6 +26810,7 @@
method public static void glProgramBinary(int, int, java.nio.Buffer, int);
method public static void glProgramParameteri(int, int, int);
method public static void glReadBuffer(int);
+ method public static void glReadPixels(int, int, int, int, int, int, int);
method public static void glRenderbufferStorageMultisample(int, int, int, int, int);
method public static void glResumeTransformFeedback();
method public static void glSamplerParameterf(int, int, float);
@@ -28419,6 +28396,10 @@
ctor public DeadObjectException(java.lang.String);
}
+ public class DeadSystemException extends android.os.DeadObjectException {
+ ctor public DeadSystemException();
+ }
+
public final class Debug {
method public static deprecated void changeDebugPort(int);
method public static void dumpHprofData(java.lang.String) throws java.io.IOException;
@@ -29051,7 +29032,6 @@
field public static final int RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY = 1; // 0x1
field public static final deprecated int SCREEN_BRIGHT_WAKE_LOCK = 10; // 0xa
field public static final deprecated int SCREEN_DIM_WAKE_LOCK = 6; // 0x6
- field public static final int SUSTAINED_PERFORMANCE_WAKE_LOCK = 256; // 0x100
}
public final class PowerManager.WakeLock {
@@ -29068,6 +29048,8 @@
ctor public Process();
method public static final long getElapsedCpuTime();
method public static final int getGidForName(java.lang.String);
+ method public static final long getStartElapsedRealtime();
+ method public static final long getStartUptimeMillis();
method public static final int getThreadPriority(int) throws java.lang.IllegalArgumentException;
method public static final int getUidForName(java.lang.String);
method public static final boolean is64Bit();
@@ -29373,7 +29355,7 @@
method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener);
}
- public class StorageVolume implements android.os.Parcelable {
+ public final class StorageVolume implements android.os.Parcelable {
method public android.content.Intent createAccessIntent(java.lang.String);
method public int describeContents();
method public java.lang.String getDescription(android.content.Context);
@@ -29501,6 +29483,7 @@
method protected int getPersistedInt(int);
method protected long getPersistedLong(long);
method protected java.lang.String getPersistedString(java.lang.String);
+ method public java.util.Set<java.lang.String> getPersistedStringSet(java.util.Set<java.lang.String>);
method public android.preference.PreferenceManager getPreferenceManager();
method public android.content.SharedPreferences getSharedPreferences();
method public boolean getShouldDisableView();
@@ -29535,6 +29518,7 @@
method protected boolean persistInt(int);
method protected boolean persistLong(long);
method protected boolean persistString(java.lang.String);
+ method public boolean persistStringSet(java.util.Set<java.lang.String>);
method public void restoreHierarchyState(android.os.Bundle);
method public void saveHierarchyState(android.os.Bundle);
method public void setDefaultValue(java.lang.Object);
@@ -30204,7 +30188,7 @@
field public static final java.lang.String COLUMN_ID = "_id";
field public static final java.lang.String COLUMN_ORIGINAL_NUMBER = "original_number";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/blocked_number";
- field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_numbers";
+ field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_number";
field public static final android.net.Uri CONTENT_URI;
}
@@ -31731,6 +31715,7 @@
public static final class DocumentsContract.Root {
field public static final java.lang.String COLUMN_AVAILABLE_BYTES = "available_bytes";
+ field public static final java.lang.String COLUMN_CAPACITY_BYTES = "capacity_bytes";
field public static final java.lang.String COLUMN_DOCUMENT_ID = "document_id";
field public static final java.lang.String COLUMN_FLAGS = "flags";
field public static final java.lang.String COLUMN_ICON = "icon";
@@ -34093,6 +34078,7 @@
method public java.lang.String[] getSignaturePaddings();
method public int getUserAuthenticationValidityDurationSeconds();
method public boolean isDigestsSpecified();
+ method public boolean isInvalidatedByBiometricEnrollment();
method public boolean isRandomizedEncryptionRequired();
method public boolean isUserAuthenticationRequired();
method public boolean isUserAuthenticationValidWhileOnBody();
@@ -34110,6 +34096,7 @@
method public android.security.keystore.KeyGenParameterSpec.Builder setCertificateSubject(javax.security.auth.x500.X500Principal);
method public android.security.keystore.KeyGenParameterSpec.Builder setDigests(java.lang.String...);
method public android.security.keystore.KeyGenParameterSpec.Builder setEncryptionPaddings(java.lang.String...);
+ method public android.security.keystore.KeyGenParameterSpec.Builder setInvalidatedByBiometricEnrollment(boolean);
method public android.security.keystore.KeyGenParameterSpec.Builder setKeySize(int);
method public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityEnd(java.util.Date);
method public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityForConsumptionEnd(java.util.Date);
@@ -34136,6 +34123,7 @@
method public java.lang.String[] getSignaturePaddings();
method public int getUserAuthenticationValidityDurationSeconds();
method public boolean isInsideSecureHardware();
+ method public boolean isInvalidatedByBiometricEnrollment();
method public boolean isUserAuthenticationRequired();
method public boolean isUserAuthenticationRequirementEnforcedBySecureHardware();
method public boolean isUserAuthenticationValidWhileOnBody();
@@ -34199,6 +34187,7 @@
method public java.lang.String[] getSignaturePaddings();
method public int getUserAuthenticationValidityDurationSeconds();
method public boolean isDigestsSpecified();
+ method public boolean isInvalidatedByBiometricEnrollment();
method public boolean isRandomizedEncryptionRequired();
method public boolean isUserAuthenticationRequired();
method public boolean isUserAuthenticationValidWhileOnBody();
@@ -34210,6 +34199,7 @@
method public android.security.keystore.KeyProtection.Builder setBlockModes(java.lang.String...);
method public android.security.keystore.KeyProtection.Builder setDigests(java.lang.String...);
method public android.security.keystore.KeyProtection.Builder setEncryptionPaddings(java.lang.String...);
+ method public android.security.keystore.KeyProtection.Builder setInvalidatedByBiometricEnrollment(boolean);
method public android.security.keystore.KeyProtection.Builder setKeyValidityEnd(java.util.Date);
method public android.security.keystore.KeyProtection.Builder setKeyValidityForConsumptionEnd(java.util.Date);
method public android.security.keystore.KeyProtection.Builder setKeyValidityForOriginationEnd(java.util.Date);
@@ -34248,7 +34238,8 @@
ctor public CarrierMessagingService();
method public android.os.IBinder onBind(android.content.Intent);
method public void onDownloadMms(android.net.Uri, int, android.net.Uri, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Integer>);
- method public void onFilterSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Boolean>);
+ method public deprecated void onFilterSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Boolean>);
+ method public void onReceiveTextSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Integer>);
method public deprecated void onSendDataSms(byte[], int, java.lang.String, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
method public void onSendDataSms(byte[], int, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
method public void onSendMms(android.net.Uri, int, android.net.Uri, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendMmsResult>);
@@ -34259,6 +34250,9 @@
field public static final int DOWNLOAD_STATUS_ERROR = 2; // 0x2
field public static final int DOWNLOAD_STATUS_OK = 0; // 0x0
field public static final int DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK = 1; // 0x1
+ field public static final int RECEIVE_OPTIONS_DEFAULT = 0; // 0x0
+ field public static final int RECEIVE_OPTIONS_DROP = 1; // 0x1
+ field public static final int RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE = 2; // 0x2
field public static final int SEND_FLAG_REQUEST_DELIVERY_STATUS = 1; // 0x1
field public static final int SEND_STATUS_ERROR = 2; // 0x2
field public static final int SEND_STATUS_OK = 0; // 0x0
@@ -34490,7 +34484,7 @@
method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
method public final void requestInterruptionFilter(int);
method public final void requestListenerHints(int);
- method public static final void requestRebind(android.content.ComponentName) throws android.os.RemoteException;
+ method public static void requestRebind(android.content.ComponentName) throws android.os.RemoteException;
method public final void requestUnbind() throws android.os.RemoteException;
method public final void setNotificationsShown(java.lang.String[]);
field public static final java.lang.String CATEGORY_VR_NOTIFICATIONS = "android.intent.category.vr.notifications";
@@ -34514,10 +34508,11 @@
method public int getSuppressedVisualEffects();
method public boolean isAmbient();
method public boolean matchesInterruptionFilter();
- field public static final int IMPORTANCE_DEFAULT = 2; // 0x2
- field public static final int IMPORTANCE_HIGH = 3; // 0x3
- field public static final int IMPORTANCE_LOW = 1; // 0x1
- field public static final int IMPORTANCE_MAX = 4; // 0x4
+ field public static final int IMPORTANCE_DEFAULT = 3; // 0x3
+ field public static final int IMPORTANCE_HIGH = 4; // 0x4
+ field public static final int IMPORTANCE_LOW = 2; // 0x2
+ field public static final int IMPORTANCE_MAX = 5; // 0x5
+ field public static final int IMPORTANCE_MIN = 1; // 0x1
field public static final int IMPORTANCE_NONE = 0; // 0x0
field public static final int IMPORTANCE_UNSPECIFIED = -1000; // 0xfffffc18
}
@@ -34588,6 +34583,7 @@
method public final void startActivityAndCollapse(android.content.Intent);
method public final void unlockAndRun(java.lang.Runnable);
field public static final java.lang.String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE";
+ field public static final java.lang.String ACTION_QS_TILE_PREFERENCES = "android.service.quicksettings.action.QS_TILE_PREFERENCES";
field public static final int TILE_MODE_ACTIVE = 2; // 0x2
field public static final int TILE_MODE_PASSIVE = 1; // 0x1
}
@@ -36078,6 +36074,7 @@
method public final void conferenceRemoteConnections(android.telecom.RemoteConnection, android.telecom.RemoteConnection);
method public final android.telecom.RemoteConnection createRemoteIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public final android.telecom.RemoteConnection createRemoteOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
+ method public final java.util.Collection<android.telecom.Conference> getAllConferences();
method public final java.util.Collection<android.telecom.Connection> getAllConnections();
method public final android.os.IBinder onBind(android.content.Intent);
method public void onConference(android.telecom.Connection, android.telecom.Connection);
@@ -36354,6 +36351,7 @@
public class TelecomManager {
method public void addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle);
method public void cancelMissedCallsNotification();
+ method public android.content.Intent createManageBlockedNumbersIntent();
method public android.net.Uri getAdnUriForPhoneAccount(android.telecom.PhoneAccountHandle);
method public java.util.List<android.telecom.PhoneAccountHandle> getCallCapablePhoneAccounts();
method public java.lang.String getDefaultDialerPackage();
@@ -36366,7 +36364,7 @@
method public boolean handleMmi(java.lang.String, android.telecom.PhoneAccountHandle);
method public boolean isInCall();
method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String);
- method public void launchManageBlockedNumbersActivity();
+ method public deprecated void launchManageBlockedNumbersActivity();
method public void placeCall(android.net.Uri, android.os.Bundle);
method public void registerPhoneAccount(android.telecom.PhoneAccount);
method public void showInCallScreen(boolean);
@@ -36446,9 +36444,11 @@
package android.telephony {
public class CarrierConfigManager {
+ method public android.os.PersistableBundle getConfig(int);
method public android.os.PersistableBundle getConfig();
- method public android.os.PersistableBundle getConfigForSubId(int);
- method public void notifyConfigChangedForSubId(int);
+ method public deprecated android.os.PersistableBundle getConfigForSubId(int);
+ method public void notifyConfigChanged(int);
+ method public deprecated void notifyConfigChangedForSubId(int);
field public static final java.lang.String ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED";
field public static final java.lang.String BOOL_ALLOW_EMERGENCY_VIDEO_CALLS = "bool_allow_emergency_video_calls";
field public static final java.lang.String BOOL_ALLOW_VIDEO_PAUSE = "bool_allow_video_pause";
@@ -37086,12 +37086,18 @@
method public int getVoiceNetworkType(int);
method public android.net.Uri getVoicemailRingtoneUri(android.telecom.PhoneAccountHandle);
method public boolean hasCarrierPrivileges();
+ method public boolean hasCarrierPrivileges(int);
method public boolean hasIccCard();
method public boolean iccCloseLogicalChannel(int);
+ method public boolean iccCloseLogicalChannel(int, int);
method public byte[] iccExchangeSimIO(int, int, int, int, int, java.lang.String);
+ method public byte[] iccExchangeSimIO(int, int, int, int, int, int, java.lang.String);
method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String);
+ method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(int, java.lang.String);
method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, java.lang.String);
+ method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, int, java.lang.String);
method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
+ method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, int, java.lang.String);
method public boolean isHearingAidCompatibilitySupported();
method public boolean isNetworkRoaming();
method public boolean isNetworkRoaming(int);
@@ -37102,10 +37108,13 @@
method public boolean isWorldPhone();
method public void listen(android.telephony.PhoneStateListener, int);
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
+ method public java.lang.String sendEnvelopeWithStatus(int, java.lang.String);
method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
method public boolean setLine1NumberForDisplay(int, java.lang.String, java.lang.String);
method public boolean setOperatorBrandOverride(java.lang.String);
+ method public boolean setOperatorBrandOverride(int, java.lang.String);
method public boolean setPreferredNetworkTypeToGlobal();
+ method public boolean setPreferredNetworkTypeToGlobal(int);
method public boolean setVoiceMailNumber(java.lang.String, java.lang.String);
method public boolean setVoiceMailNumber(int, java.lang.String, java.lang.String);
field public static final java.lang.String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL";
@@ -38470,7 +38479,6 @@
method public boolean hasNext();
method public java.util.Iterator<java.lang.String> iterator();
method public java.lang.String next();
- method public void remove();
method public void setString(java.lang.String);
}
@@ -40082,6 +40090,7 @@
method public int describeContents();
method public static android.util.LocaleList forLanguageTags(java.lang.String);
method public java.util.Locale get(int);
+ method public static android.util.LocaleList getAdjustedDefault();
method public static android.util.LocaleList getDefault();
method public static android.util.LocaleList getEmptyLocaleList();
method public java.util.Locale getFirstMatch(java.lang.String[]);
@@ -44009,6 +44018,7 @@
field public static final int TYPE_ACCESSIBILITY_OVERLAY = 4; // 0x4
field public static final int TYPE_APPLICATION = 1; // 0x1
field public static final int TYPE_INPUT_METHOD = 2; // 0x2
+ field public static final int TYPE_SPLIT_SCREEN_DIVIDER = 5; // 0x5
field public static final int TYPE_SYSTEM = 3; // 0x3
}
@@ -44348,6 +44358,7 @@
method public int getCursorCapsMode(int);
method public android.text.Editable getEditable();
method public android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int);
+ method public android.os.Handler getHandler();
method public java.lang.CharSequence getSelectedText(int);
method public java.lang.CharSequence getTextAfterCursor(int, int);
method public java.lang.CharSequence getTextBeforeCursor(int, int);
@@ -44511,6 +44522,7 @@
method public abstract boolean finishComposingText();
method public abstract int getCursorCapsMode(int);
method public abstract android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int);
+ method public abstract android.os.Handler getHandler();
method public abstract java.lang.CharSequence getSelectedText(int);
method public abstract java.lang.CharSequence getTextAfterCursor(int, int);
method public abstract java.lang.CharSequence getTextBeforeCursor(int, int);
@@ -44542,6 +44554,7 @@
method public boolean finishComposingText();
method public int getCursorCapsMode(int);
method public android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int);
+ method public android.os.Handler getHandler();
method public java.lang.CharSequence getSelectedText(int);
method public java.lang.CharSequence getTextAfterCursor(int, int);
method public java.lang.CharSequence getTextBeforeCursor(int, int);
@@ -46048,7 +46061,9 @@
method public long getBase();
method public java.lang.String getFormat();
method public android.widget.Chronometer.OnChronometerTickListener getOnChronometerTickListener();
+ method public boolean isCountDown();
method public void setBase(long);
+ method public void setCountDown(boolean);
method public void setFormat(java.lang.String);
method public void setOnChronometerTickListener(android.widget.Chronometer.OnChronometerTickListener);
method public void start();
@@ -47140,6 +47155,7 @@
method public void setChar(int, java.lang.String, char);
method public void setCharSequence(int, java.lang.String, java.lang.CharSequence);
method public void setChronometer(int, long, java.lang.String, boolean);
+ method public void setChronometerCountsDown(int, boolean);
method public void setContentDescription(int, java.lang.CharSequence);
method public void setDisplayedChild(int, int);
method public void setDouble(int, java.lang.String, double);
@@ -50386,6 +50402,7 @@
method public static long doubleToRawLongBits(double);
method public double doubleValue();
method public float floatValue();
+ method public static int hashCode(double);
method public int intValue();
method public static boolean isInfinite(double);
method public boolean isInfinite();
@@ -50393,11 +50410,15 @@
method public boolean isNaN();
method public static double longBitsToDouble(long);
method public long longValue();
+ method public static double max(double, double);
+ method public static double min(double, double);
method public static double parseDouble(java.lang.String) throws java.lang.NumberFormatException;
+ method public static double sum(double, double);
method public static java.lang.String toHexString(double);
method public static java.lang.String toString(double);
method public static java.lang.Double valueOf(java.lang.String) throws java.lang.NumberFormatException;
method public static java.lang.Double valueOf(double);
+ field public static final int BYTES = 8; // 0x8
field public static final int MAX_EXPONENT = 1023; // 0x3ff
field public static final double MAX_VALUE = 1.7976931348623157E308;
field public static final int MIN_EXPONENT = -1022; // 0xfffffc02
@@ -50560,10 +50581,13 @@
method public static java.lang.Integer getInteger(java.lang.String);
method public static java.lang.Integer getInteger(java.lang.String, int);
method public static java.lang.Integer getInteger(java.lang.String, java.lang.Integer);
+ method public static int hashCode(int);
method public static int highestOneBit(int);
method public int intValue();
method public long longValue();
method public static int lowestOneBit(int);
+ method public static int max(int, int);
+ method public static int min(int, int);
method public static int numberOfLeadingZeros(int);
method public static int numberOfTrailingZeros(int);
method public static int parseInt(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -50573,6 +50597,7 @@
method public static int rotateLeft(int, int);
method public static int rotateRight(int, int);
method public static int signum(int);
+ method public static int sum(int, int);
method public static java.lang.String toBinaryString(int);
method public static java.lang.String toHexString(int);
method public static java.lang.String toOctalString(int);
@@ -50581,6 +50606,7 @@
method public static java.lang.Integer valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
method public static java.lang.Integer valueOf(java.lang.String) throws java.lang.NumberFormatException;
method public static java.lang.Integer valueOf(int);
+ field public static final int BYTES = 4; // 0x4
field public static final int MAX_VALUE = 2147483647; // 0x7fffffff
field public static final int MIN_VALUE = -2147483648; // 0x80000000
field public static final int SIZE = 32; // 0x20
@@ -50600,6 +50626,7 @@
}
public abstract interface Iterable {
+ method public default void forEach(java.util.function.Consumer<? super T>);
method public abstract java.util.Iterator<T> iterator();
}
@@ -50621,10 +50648,13 @@
method public static java.lang.Long getLong(java.lang.String);
method public static java.lang.Long getLong(java.lang.String, long);
method public static java.lang.Long getLong(java.lang.String, java.lang.Long);
+ method public static int hashCode(long);
method public static long highestOneBit(long);
method public int intValue();
method public long longValue();
method public static long lowestOneBit(long);
+ method public static long max(long, long);
+ method public static long min(long, long);
method public static int numberOfLeadingZeros(long);
method public static int numberOfTrailingZeros(long);
method public static long parseLong(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -50634,6 +50664,7 @@
method public static long rotateLeft(long, int);
method public static long rotateRight(long, int);
method public static int signum(long);
+ method public static long sum(long, long);
method public static java.lang.String toBinaryString(long);
method public static java.lang.String toHexString(long);
method public static java.lang.String toOctalString(long);
@@ -53052,7 +53083,7 @@
ctor public ConnectionPendingException();
}
- public abstract class DatagramChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.ByteChannel java.nio.channels.GatheringByteChannel java.nio.channels.ScatteringByteChannel {
+ public abstract class DatagramChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.ByteChannel java.nio.channels.GatheringByteChannel java.nio.channels.NetworkChannel java.nio.channels.ScatteringByteChannel {
ctor protected DatagramChannel(java.nio.channels.spi.SelectorProvider);
method public abstract java.nio.channels.DatagramChannel bind(java.net.SocketAddress) throws java.io.IOException;
method public abstract java.nio.channels.DatagramChannel connect(java.net.SocketAddress) throws java.io.IOException;
@@ -54075,6 +54106,7 @@
public abstract class Provider extends java.util.Properties {
ctor protected Provider(java.lang.String, double, java.lang.String);
+ method public synchronized void forEach(java.util.function.BiConsumer<? super java.lang.Object, ? super java.lang.Object>);
method public java.lang.String getInfo();
method public java.lang.String getName();
method public synchronized java.security.Provider.Service getService(java.lang.String, java.lang.String);
@@ -57024,6 +57056,7 @@
ctor public ArrayList(java.util.Collection<? extends E>);
method public java.lang.Object clone();
method public void ensureCapacity(int);
+ method public void forEach(java.util.function.Consumer<? super E>);
method public E get(int);
method public int size();
method public void trimToSize();
@@ -57587,6 +57620,7 @@
ctor public HashMap(java.util.Map<? extends K, ? extends V>);
method public java.lang.Object clone();
method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+ method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
}
public class HashSet extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
@@ -57611,6 +57645,7 @@
method public boolean containsValue(java.lang.Object);
method public synchronized java.util.Enumeration<V> elements();
method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+ method public synchronized void forEach(java.util.function.BiConsumer<? super K, ? super V>);
method public synchronized V get(java.lang.Object);
method public synchronized boolean isEmpty();
method public java.util.Set<K> keySet();
@@ -57629,6 +57664,7 @@
ctor public IdentityHashMap(java.util.Map<? extends K, ? extends V>);
method public java.lang.Object clone();
method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+ method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
}
public class IllegalFormatCodePointException extends java.util.IllegalFormatException {
@@ -57678,9 +57714,10 @@
}
public abstract interface Iterator {
+ method public default void forEachRemaining(java.util.function.Consumer<? super E>);
method public abstract boolean hasNext();
method public abstract E next();
- method public abstract void remove();
+ method public default void remove();
}
public class LinkedHashMap extends java.util.HashMap implements java.util.Map {
@@ -57868,6 +57905,7 @@
method public abstract boolean containsValue(java.lang.Object);
method public abstract java.util.Set<java.util.Map.Entry<K, V>> entrySet();
method public abstract boolean equals(java.lang.Object);
+ method public default void forEach(java.util.function.BiConsumer<? super K, ? super V>);
method public abstract V get(java.lang.Object);
method public abstract int hashCode();
method public abstract boolean isEmpty();
@@ -57982,6 +58020,79 @@
method public abstract void update(java.util.Observable, java.lang.Object);
}
+ public final class Optional {
+ method public static java.util.Optional<T> empty();
+ method public java.util.Optional<T> filter(java.util.function.Predicate<? super T>);
+ method public java.util.Optional<U> flatMap(java.util.function.Function<? super T, java.util.Optional<U>>);
+ method public T get();
+ method public void ifPresent(java.util.function.Consumer<? super T>);
+ method public boolean isPresent();
+ method public java.util.Optional<U> map(java.util.function.Function<? super T, ? extends U>);
+ method public static java.util.Optional<T> of(T);
+ method public static java.util.Optional<T> ofNullable(T);
+ method public T orElse(T);
+ method public T orElseGet(java.util.function.Supplier<? extends T>);
+ method public T orElseThrow(java.util.function.Supplier<? extends X>) throws java.lang.Throwable;
+ }
+
+ public final class OptionalDouble {
+ method public static java.util.OptionalDouble empty();
+ method public double getAsDouble();
+ method public void ifPresent(java.util.function.DoubleConsumer);
+ method public boolean isPresent();
+ method public static java.util.OptionalDouble of(double);
+ method public double orElse(double);
+ method public double orElseGet(java.util.function.DoubleSupplier);
+ method public double orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+ }
+
+ public final class OptionalInt {
+ method public static java.util.OptionalInt empty();
+ method public int getAsInt();
+ method public void ifPresent(java.util.function.IntConsumer);
+ method public boolean isPresent();
+ method public static java.util.OptionalInt of(int);
+ method public int orElse(int);
+ method public int orElseGet(java.util.function.IntSupplier);
+ method public int orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+ }
+
+ public final class OptionalLong {
+ method public static java.util.OptionalLong empty();
+ method public long getAsLong();
+ method public void ifPresent(java.util.function.LongConsumer);
+ method public boolean isPresent();
+ method public static java.util.OptionalLong of(long);
+ method public long orElse(long);
+ method public long orElseGet(java.util.function.LongSupplier);
+ method public long orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+ }
+
+ public abstract interface PrimitiveIterator implements java.util.Iterator {
+ method public abstract void forEachRemaining(T_CONS);
+ }
+
+ public static abstract interface PrimitiveIterator.OfDouble implements java.util.PrimitiveIterator {
+ method public default void forEachRemaining(java.util.function.DoubleConsumer);
+ method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Double>);
+ method public default java.lang.Double next();
+ method public abstract double nextDouble();
+ }
+
+ public static abstract interface PrimitiveIterator.OfInt implements java.util.PrimitiveIterator {
+ method public default void forEachRemaining(java.util.function.IntConsumer);
+ method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Integer>);
+ method public default java.lang.Integer next();
+ method public abstract int nextInt();
+ }
+
+ public static abstract interface PrimitiveIterator.OfLong implements java.util.PrimitiveIterator {
+ method public default void forEachRemaining(java.util.function.LongConsumer);
+ method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Long>);
+ method public default java.lang.Long next();
+ method public abstract long nextLong();
+ }
+
public class PriorityQueue extends java.util.AbstractQueue implements java.io.Serializable {
ctor public PriorityQueue();
ctor public PriorityQueue(int);
@@ -58153,7 +58264,6 @@
method public short nextShort();
method public short nextShort(int);
method public int radix();
- method public void remove();
method public java.util.Scanner reset();
method public java.util.Scanner skip(java.util.regex.Pattern);
method public java.util.Scanner skip(java.lang.String);
@@ -58329,6 +58439,7 @@
method public K firstKey();
method public java.util.Map.Entry<K, V> floorEntry(K);
method public K floorKey(K);
+ method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
method public java.util.NavigableMap<K, V> headMap(K, boolean);
method public java.util.SortedMap<K, V> headMap(K);
method public java.util.Map.Entry<K, V> higherEntry(K);
@@ -58411,6 +58522,7 @@
method public java.util.Enumeration<E> elements();
method public synchronized void ensureCapacity(int);
method public synchronized E firstElement();
+ method public synchronized void forEach(java.util.function.Consumer<? super E>);
method public synchronized E get(int);
method public synchronized int indexOf(java.lang.Object, int);
method public synchronized void insertElementAt(E, int);
@@ -58434,6 +58546,7 @@
ctor public WeakHashMap();
ctor public WeakHashMap(java.util.Map<? extends K, ? extends V>);
method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+ method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
}
}
diff --git a/api/removed.txt b/api/removed.txt
index 0bf6594..115224c 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -9,6 +9,8 @@
package android.app.admin {
public class DevicePolicyManager {
+ method public deprecated android.os.UserHandle createAndInitializeUser(android.content.ComponentName, java.lang.String, java.lang.String, android.content.ComponentName, android.os.Bundle);
+ method public deprecated android.os.UserHandle createUser(android.content.ComponentName, java.lang.String);
method public deprecated java.lang.String getDeviceInitializerApp();
method public deprecated android.content.ComponentName getDeviceInitializerComponent();
}
@@ -35,7 +37,7 @@
package android.media {
- public class AudioFormat {
+ public final class AudioFormat implements android.os.Parcelable {
ctor public AudioFormat();
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 55df364..7d94199 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -169,7 +169,6 @@
field public static final java.lang.String READ_SYNC_STATS = "android.permission.READ_SYNC_STATS";
field public static final java.lang.String READ_VOICEMAIL = "com.android.voicemail.permission.READ_VOICEMAIL";
field public static final java.lang.String READ_WIFI_CREDENTIAL = "android.permission.READ_WIFI_CREDENTIAL";
- field public static final java.lang.String READ_WRITE_CONTACT_METADATA = "android.permission.READ_WRITE_CONTACT_METADATA";
field public static final java.lang.String REAL_GET_TASKS = "android.permission.REAL_GET_TASKS";
field public static final java.lang.String REBOOT = "android.permission.REBOOT";
field public static final java.lang.String RECEIVE_BOOT_COMPLETED = "android.permission.RECEIVE_BOOT_COMPLETED";
@@ -395,6 +394,7 @@
field public static final int backgroundTint = 16843883; // 0x101046b
field public static final int backgroundTintMode = 16843884; // 0x101046c
field public static final int backupAgent = 16843391; // 0x101027f
+ field public static final int backupInForeground = 16844059; // 0x101051b
field public static final int banner = 16843762; // 0x10103f2
field public static final int baseline = 16843548; // 0x101031c
field public static final int baselineAlignBottom = 16843042; // 0x1010122
@@ -432,6 +432,7 @@
field public static final int calendarViewStyle = 16843613; // 0x101035d
field public static final int canControlMagnification = 16844040; // 0x1010508
field public static final int canPerformGestures = 16844046; // 0x101050e
+ field public static final int canRecord = 16844061; // 0x101051d
field public static final int canRequestEnhancedWebAccessibility = 16843736; // 0x10103d8
field public static final int canRequestFilterKeyEvents = 16843737; // 0x10103d9
field public static final int canRequestTouchExplorationMode = 16843735; // 0x10103d7
@@ -517,6 +518,7 @@
field public static final int controlX2 = 16843774; // 0x10103fe
field public static final int controlY1 = 16843773; // 0x10103fd
field public static final int controlY2 = 16843775; // 0x10103ff
+ field public static final int countDown = 16844060; // 0x101051c
field public static final int country = 16843962; // 0x10104ba
field public static final int cropToPadding = 16843043; // 0x1010123
field public static final int cursorVisible = 16843090; // 0x1010152
@@ -1456,6 +1458,7 @@
field public static final int trimPathEnd = 16843785; // 0x1010409
field public static final int trimPathOffset = 16843786; // 0x101040a
field public static final int trimPathStart = 16843784; // 0x1010408
+ field public static final int tunerCount = 16844062; // 0x101051e
field public static final int type = 16843169; // 0x10101a1
field public static final int typeface = 16842902; // 0x1010096
field public static final int uiOptions = 16843672; // 0x1010398
@@ -2764,8 +2767,11 @@
field public static final int GLOBAL_ACTION_POWER_DIALOG = 6; // 0x6
field public static final int GLOBAL_ACTION_QUICK_SETTINGS = 5; // 0x5
field public static final int GLOBAL_ACTION_RECENTS = 3; // 0x3
+ field public static final int GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN = 7; // 0x7
field public static final java.lang.String SERVICE_INTERFACE = "android.accessibilityservice.AccessibilityService";
field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
+ field public static final int SHOW_MODE_AUTO = 0; // 0x0
+ field public static final int SHOW_MODE_HIDDEN = 1; // 0x1
}
public static abstract class AccessibilityService.GestureResultCallback {
@@ -4248,13 +4254,12 @@
field public java.lang.String serviceDetails;
}
- public class AutomaticZenRule implements android.os.Parcelable {
+ public final class AutomaticZenRule implements android.os.Parcelable {
ctor public AutomaticZenRule(java.lang.String, android.content.ComponentName, android.net.Uri, int, boolean);
ctor public AutomaticZenRule(android.os.Parcel);
method public int describeContents();
method public android.net.Uri getConditionId();
method public long getCreationTime();
- method public java.lang.String getId();
method public int getInterruptionFilter();
method public java.lang.String getName();
method public android.content.ComponentName getOwner();
@@ -4407,7 +4412,6 @@
public class DownloadManager {
method public long addCompletedDownload(java.lang.String, java.lang.String, boolean, java.lang.String, java.lang.String, long, boolean);
- method public long addCompletedDownload(java.lang.String, java.lang.String, boolean, java.lang.String, java.lang.String, long, boolean, android.net.Uri, android.net.Uri);
method public long enqueue(android.app.DownloadManager.Request);
method public static java.lang.Long getMaxBytesOverMobile(android.content.Context);
method public java.lang.String getMimeTypeForDownloadedFile(long);
@@ -5011,7 +5015,6 @@
method public android.graphics.drawable.Icon getLargeIcon();
method public android.graphics.drawable.Icon getSmallIcon();
method public java.lang.String getSortKey();
- method public android.app.Notification.Topic getTopic();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT;
field public static final java.lang.String CATEGORY_ALARM = "alarm";
@@ -5037,6 +5040,7 @@
field public static final int DEFAULT_VIBRATE = 2; // 0x2
field public static final java.lang.String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri";
field public static final java.lang.String EXTRA_BIG_TEXT = "android.bigText";
+ field public static final java.lang.String EXTRA_CHRONOMETER_COUNTS_DOWN = "android.chronometerCountsDown";
field public static final java.lang.String EXTRA_COMPACT_ACTIONS = "android.compactActions";
field public static final java.lang.String EXTRA_INFO_TEXT = "android.infoText";
field public static final java.lang.String EXTRA_LARGE_ICON = "android.largeIcon";
@@ -5075,7 +5079,6 @@
field public static final int PRIORITY_MAX = 2; // 0x2
field public static final int PRIORITY_MIN = -2; // 0xfffffffe
field public static final deprecated int STREAM_DEFAULT = -1; // 0xffffffff
- field public static final java.lang.String TOPIC_DEFAULT = "system_default_topic";
field public static final int VISIBILITY_PRIVATE = 0; // 0x0
field public static final int VISIBILITY_PUBLIC = 1; // 0x1
field public static final int VISIBILITY_SECRET = -1; // 0xffffffff
@@ -5179,16 +5182,17 @@
method public android.app.Notification.Builder addExtras(android.os.Bundle);
method public android.app.Notification.Builder addPerson(java.lang.String);
method public android.app.Notification build();
+ method public android.widget.RemoteViews createBigContentView();
+ method public android.widget.RemoteViews createContentView();
+ method public android.widget.RemoteViews createHeadsUpContentView();
method public android.app.Notification.Builder extend(android.app.Notification.Extender);
method public android.os.Bundle getExtras();
method public deprecated android.app.Notification getNotification();
- method public android.widget.RemoteViews makeBigContentView();
- method public android.widget.RemoteViews makeContentView();
- method public android.widget.RemoteViews makeHeadsUpContentView();
method public static android.app.Notification.Builder recoverBuilder(android.content.Context, android.app.Notification);
method public android.app.Notification.Builder setActions(android.app.Notification.Action...);
method public android.app.Notification.Builder setAutoCancel(boolean);
method public android.app.Notification.Builder setCategory(java.lang.String);
+ method public android.app.Notification.Builder setChronometerCountsDown(boolean);
method public android.app.Notification.Builder setColor(int);
method public deprecated android.app.Notification.Builder setContent(android.widget.RemoteViews);
method public android.app.Notification.Builder setContentInfo(java.lang.CharSequence);
@@ -5227,7 +5231,6 @@
method public android.app.Notification.Builder setSubText(java.lang.CharSequence);
method public android.app.Notification.Builder setTicker(java.lang.CharSequence);
method public deprecated android.app.Notification.Builder setTicker(java.lang.CharSequence, android.widget.RemoteViews);
- method public android.app.Notification.Builder setTopic(android.app.Notification.Topic);
method public android.app.Notification.Builder setUsesChronometer(boolean);
method public android.app.Notification.Builder setVibrate(long[]);
method public android.app.Notification.Builder setVisibility(int);
@@ -5265,6 +5268,16 @@
method public android.app.PendingIntent getReplyPendingIntent();
}
+ public static class Notification.DecoratedCustomViewStyle extends android.app.Notification.Style {
+ ctor public Notification.DecoratedCustomViewStyle();
+ ctor public Notification.DecoratedCustomViewStyle(android.app.Notification.Builder);
+ }
+
+ public static class Notification.DecoratedMediaCustomViewStyle extends android.app.Notification.MediaStyle {
+ ctor public Notification.DecoratedMediaCustomViewStyle();
+ ctor public Notification.DecoratedMediaCustomViewStyle(android.app.Notification.Builder);
+ }
+
public static abstract interface Notification.Extender {
method public abstract android.app.Notification.Builder extend(android.app.Notification.Builder);
}
@@ -5295,16 +5308,6 @@
field protected android.app.Notification.Builder mBuilder;
}
- public static class Notification.Topic implements android.os.Parcelable {
- ctor public Notification.Topic(java.lang.String, java.lang.CharSequence);
- method public android.app.Notification.Topic clone();
- method public int describeContents();
- method public java.lang.String getId();
- method public java.lang.CharSequence getLabel();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.app.Notification.Topic> CREATOR;
- }
-
public static final class Notification.WearableExtender implements android.app.Notification.Extender {
ctor public Notification.WearableExtender();
ctor public Notification.WearableExtender(android.app.Notification);
@@ -5358,16 +5361,16 @@
}
public class NotificationManager {
- method public android.app.AutomaticZenRule addAutomaticZenRule(android.app.AutomaticZenRule);
+ method public java.lang.String addAutomaticZenRule(android.app.AutomaticZenRule);
method public boolean areNotificationsEnabled();
method public void cancel(int);
method public void cancel(java.lang.String, int);
method public void cancelAll();
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String);
- method public java.util.List<android.app.AutomaticZenRule> getAutomaticZenRules();
+ method public java.util.Map<java.lang.String, android.app.AutomaticZenRule> getAutomaticZenRules();
method public final int getCurrentInterruptionFilter();
- method public int getImportance(java.lang.String);
+ method public int getImportance();
method public android.app.NotificationManager.Policy getNotificationPolicy();
method public boolean isNotificationPolicyAccessGranted();
method public void notify(int, android.app.Notification);
@@ -5375,7 +5378,7 @@
method public boolean removeAutomaticZenRule(java.lang.String);
method public final void setInterruptionFilter(int);
method public void setNotificationPolicy(android.app.NotificationManager.Policy);
- method public boolean updateAutomaticZenRule(android.app.AutomaticZenRule);
+ method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule);
field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
field public static final java.lang.String ACTION_NOTIFICATION_POLICY_CHANGED = "android.app.action.NOTIFICATION_POLICY_CHANGED";
@@ -5387,7 +5390,7 @@
}
public static class NotificationManager.Policy implements android.os.Parcelable {
- ctor public deprecated NotificationManager.Policy(int, int, int);
+ ctor public NotificationManager.Policy(int, int, int);
ctor public NotificationManager.Policy(int, int, int, int);
method public int describeContents();
method public static java.lang.String priorityCategoriesToString(int);
@@ -5739,8 +5742,6 @@
method public void enableCarMode(int);
method public int getCurrentModeType();
method public int getNightMode();
- method public boolean isNightModeLocked();
- method public boolean isUiModeLocked();
method public void setNightMode(int);
field public static java.lang.String ACTION_ENTER_CAR_MODE;
field public static java.lang.String ACTION_ENTER_DESK_MODE;
@@ -5842,7 +5843,9 @@
public class WallpaperManager {
method public void clear() throws java.io.IOException;
+ method public void clear(int) throws java.io.IOException;
method public void clearWallpaper();
+ method public void clearWallpaper(int, int);
method public void clearWallpaperOffsets(android.os.IBinder);
method public void forgetLoadedWallpaper();
method public android.graphics.drawable.Drawable getBuiltInDrawable();
@@ -5853,6 +5856,7 @@
method public android.graphics.drawable.Drawable getDrawable();
method public android.graphics.drawable.Drawable getFastDrawable();
method public static android.app.WallpaperManager getInstance(android.content.Context);
+ method public android.os.ParcelFileDescriptor getWallpaperFile(int);
method public android.app.WallpaperInfo getWallpaperInfo();
method public boolean hasResourceWallpaper(int);
method public boolean isWallpaperSettingAllowed();
@@ -5966,9 +5970,7 @@
method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
method public void clearProfileOwner(android.content.ComponentName);
method public void clearUserRestriction(android.content.ComponentName, java.lang.String);
- method public deprecated android.os.UserHandle createAndInitializeUser(android.content.ComponentName, java.lang.String, java.lang.String, android.content.ComponentName, android.os.Bundle);
method public android.os.UserHandle createAndManageUser(android.content.ComponentName, java.lang.String, android.content.ComponentName, android.os.PersistableBundle, int);
- method public deprecated android.os.UserHandle createUser(android.content.ComponentName, java.lang.String);
method public void enableSystemApp(android.content.ComponentName, java.lang.String);
method public int enableSystemApp(android.content.ComponentName, android.content.Intent);
method public java.lang.String[] getAccountTypesWithManagementDisabled();
@@ -6025,12 +6027,14 @@
method public int getStorageEncryptionStatus();
method public android.app.admin.SystemUpdatePolicy getSystemUpdatePolicy();
method public java.util.List<android.os.PersistableBundle> getTrustAgentConfiguration(android.content.ComponentName, android.content.ComponentName);
+ method public int getUserProvisioningState();
method public android.os.Bundle getUserRestrictions(android.content.ComponentName);
method public java.lang.String getWifiMacAddress();
method public boolean hasCaCertInstalled(android.content.ComponentName, byte[]);
method public boolean hasGrantedPolicy(android.content.ComponentName, int);
method public boolean installCaCert(android.content.ComponentName, byte[]);
method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate, java.lang.String);
+ method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate, java.lang.String, boolean);
method public boolean isActivePasswordSufficient();
method public boolean isAdminActive(android.content.ComponentName);
method public boolean isApplicationHidden(android.content.ComponentName, java.lang.String);
@@ -6111,6 +6115,7 @@
field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
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_PROVISION_FINALIZATION = "android.app.action.PROVISION_FINALIZATION";
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_DEVICE_FROM_TRUSTED_SOURCE = "android.app.action.PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE";
field public static final java.lang.String ACTION_PROVISION_MANAGED_PROFILE = "android.app.action.PROVISION_MANAGED_PROFILE";
@@ -6180,6 +6185,11 @@
field public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 2; // 0x2
field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1
field public static final int SKIP_SETUP_WIZARD = 1; // 0x1
+ field public static final int STATE_USER_PROFILE_COMPLETE = 4; // 0x4
+ field public static final int STATE_USER_SETUP_COMPLETE = 2; // 0x2
+ field public static final int STATE_USER_SETUP_FINALIZED = 3; // 0x3
+ field public static final int STATE_USER_SETUP_INCOMPLETE = 1; // 0x1
+ field public static final int STATE_USER_UNMANAGED = 0; // 0x0
field public static final int WIPE_EXTERNAL_STORAGE = 1; // 0x1
field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
}
@@ -6848,7 +6858,7 @@
field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
}
- public static class SecurityLog.SecurityEvent implements android.os.Parcelable {
+ public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
method public int describeContents();
method public java.lang.Object getData();
method public int getTag();
@@ -7600,15 +7610,6 @@
field public static final int TYPE_SCO = 2; // 0x2
}
- public class OobData implements android.os.Parcelable {
- ctor public OobData();
- method public int describeContents();
- method public byte[] getSecurityManagerTk();
- method public void setSecurityManagerTk(byte[]);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.bluetooth.OobData> CREATOR;
- }
-
}
package android.bluetooth.le {
@@ -8775,6 +8776,7 @@
field public static final java.lang.String ACTION_AIRPLANE_MODE_CHANGED = "android.intent.action.AIRPLANE_MODE";
field public static final java.lang.String ACTION_ALL_APPS = "android.intent.action.ALL_APPS";
field public static final java.lang.String ACTION_ANSWER = "android.intent.action.ANSWER";
+ field public static final java.lang.String ACTION_APPLICATION_PREFERENCES = "android.intent.action.APPLICATION_PREFERENCES";
field public static final java.lang.String ACTION_APPLICATION_RESTRICTIONS_CHANGED = "android.intent.action.APPLICATION_RESTRICTIONS_CHANGED";
field public static final java.lang.String ACTION_APP_ERROR = "android.intent.action.APP_ERROR";
field public static final java.lang.String ACTION_ASSIST = "android.intent.action.ASSIST";
@@ -9696,25 +9698,6 @@
field public int reqTouchScreen;
}
- public deprecated class ContainerEncryptionParams implements android.os.Parcelable {
- ctor public ContainerEncryptionParams(java.lang.String, java.security.spec.AlgorithmParameterSpec, javax.crypto.SecretKey) throws java.security.InvalidAlgorithmParameterException;
- ctor public ContainerEncryptionParams(java.lang.String, java.security.spec.AlgorithmParameterSpec, javax.crypto.SecretKey, java.lang.String, java.security.spec.AlgorithmParameterSpec, javax.crypto.SecretKey, byte[], long, long, long) throws java.security.InvalidAlgorithmParameterException;
- method public int describeContents();
- method public long getAuthenticatedDataStart();
- method public long getDataEnd();
- method public long getEncryptedDataStart();
- method public java.lang.String getEncryptionAlgorithm();
- method public javax.crypto.SecretKey getEncryptionKey();
- method public java.security.spec.AlgorithmParameterSpec getEncryptionSpec();
- method public java.lang.String getMacAlgorithm();
- method public javax.crypto.SecretKey getMacKey();
- method public java.security.spec.AlgorithmParameterSpec getMacSpec();
- method public byte[] getMacTag();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.content.pm.ContainerEncryptionParams> CREATOR;
- field protected static final java.lang.String TAG = "ContainerEncryptionParams";
- }
-
public final class EphemeralResolveInfo implements android.os.Parcelable {
ctor public EphemeralResolveInfo(android.net.Uri, java.lang.String, java.util.List<android.content.IntentFilter>);
method public int describeContents();
@@ -9944,6 +9927,7 @@
method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
method public android.graphics.drawable.Drawable loadLogo(android.content.pm.PackageManager);
+ method public java.lang.CharSequence loadSafeLabel(android.content.pm.PackageManager);
method public android.graphics.drawable.Drawable loadUnbadgedIcon(android.content.pm.PackageManager);
method public android.content.res.XmlResourceParser loadXmlMetaData(android.content.pm.PackageManager, java.lang.String);
method public void writeToParcel(android.os.Parcel, int);
@@ -10143,6 +10127,8 @@
field public static final java.lang.String FEATURE_VERIFIED_BOOT = "android.software.verified_boot";
field public static final java.lang.String FEATURE_VR_MODE = "android.software.vr.mode";
field public static final java.lang.String FEATURE_VR_MODE_HIGH_PERFORMANCE = "android.hardware.vr.high_performance";
+ field public static final java.lang.String FEATURE_VULKAN_HARDWARE_LEVEL = "android.hardware.vulkan.level";
+ field public static final java.lang.String FEATURE_VULKAN_HARDWARE_VERSION = "android.hardware.vulkan.version";
field public static final java.lang.String FEATURE_WATCH = "android.hardware.type.watch";
field public static final java.lang.String FEATURE_WEBVIEW = "android.software.webview";
field public static final java.lang.String FEATURE_WIFI = "android.hardware.wifi";
@@ -10200,6 +10186,8 @@
field public static final int INSTALL_PARSE_FAILED_NO_CERTIFICATES = -103; // 0xffffff99
field public static final int INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION = -102; // 0xffffff9a
field public static final int INSTALL_SUCCEEDED = 1; // 0x1
+ field public static final int INTENT_FILTER_VERIFICATION_FAILURE = -1; // 0xffffffff
+ field public static final int INTENT_FILTER_VERIFICATION_SUCCESS = 1; // 0x1
field public static final int MASK_PERMISSION_FLAGS = 255; // 0xff
field public static final int MATCH_ALL = 131072; // 0x20000
field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000
@@ -10282,6 +10270,7 @@
field public static final android.os.Parcelable.Creator<android.content.pm.PermissionInfo> CREATOR;
field public static final int FLAG_COSTS_MONEY = 1; // 0x1
field public static final int FLAG_INSTALLED = 1073741824; // 0x40000000
+ field public static final int FLAG_REMOVED = 2; // 0x2
field public static final int PROTECTION_DANGEROUS = 1; // 0x1
field public static final int PROTECTION_FLAG_APPOP = 64; // 0x40
field public static final int PROTECTION_FLAG_DEVELOPMENT = 32; // 0x20
@@ -10871,7 +10860,6 @@
method public boolean hasNext();
method public java.util.Iterator<android.database.CursorJoiner.Result> iterator();
method public android.database.CursorJoiner.Result next();
- method public void remove();
}
public static final class CursorJoiner.Result extends java.lang.Enum {
@@ -12348,6 +12336,8 @@
ctor public Outline(android.graphics.Outline);
method public boolean canClip();
method public float getAlpha();
+ method public float getRadius();
+ method public boolean getRect(android.graphics.Rect);
method public boolean isEmpty();
method public void offset(int, int);
method public void set(android.graphics.Outline);
@@ -13375,12 +13365,10 @@
ctor public deprecated NinePatchDrawable(android.graphics.NinePatch);
ctor public NinePatchDrawable(android.content.res.Resources, android.graphics.NinePatch);
method public void draw(android.graphics.Canvas);
- method public android.graphics.NinePatch getNinePatch();
method public int getOpacity();
method public android.graphics.Paint getPaint();
method public void setAlpha(int);
method public void setColorFilter(android.graphics.ColorFilter);
- method public void setNinePatch(android.graphics.NinePatch);
method public void setTargetDensity(android.graphics.Canvas);
method public void setTargetDensity(android.util.DisplayMetrics);
method public void setTargetDensity(int);
@@ -13603,8 +13591,8 @@
method public final void takePicture(android.hardware.Camera.ShutterCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback);
method public final void takePicture(android.hardware.Camera.ShutterCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback);
method public final void unlock();
- field public static final java.lang.String ACTION_NEW_PICTURE = "android.hardware.action.NEW_PICTURE";
- field public static final java.lang.String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO";
+ field public static final deprecated java.lang.String ACTION_NEW_PICTURE = "android.hardware.action.NEW_PICTURE";
+ field public static final deprecated java.lang.String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO";
field public static final int CAMERA_ERROR_EVICTED = 2; // 0x2
field public static final int CAMERA_ERROR_SERVER_DIED = 100; // 0x64
field public static final int CAMERA_ERROR_UNKNOWN = 1; // 0x1
@@ -20340,178 +20328,110 @@
public final class GnssClock implements android.os.Parcelable {
method public int describeContents();
- method public double getBiasInNs();
- method public double getBiasUncertaintyInNs();
- method public double getDriftInNsPerSec();
- method public double getDriftUncertaintyInNsPerSec();
- method public long getFullBiasInNs();
- method public short getLeapSecond();
- method public long getTimeInNs();
- method public long getTimeOfLastHwClockDiscontinuityInNs();
- method public double getTimeUncertaintyInNs();
- method public byte getType();
- method public boolean hasBiasInNs();
- method public boolean hasBiasUncertaintyInNs();
- method public boolean hasDriftInNsPerSec();
- method public boolean hasDriftUncertaintyInNsPerSec();
- method public boolean hasFullBiasInNs();
+ method public double getBiasNanos();
+ method public double getBiasUncertaintyNanos();
+ method public double getDriftNanosPerSecond();
+ method public double getDriftUncertaintyNanosPerSecond();
+ method public long getFullBiasNanos();
+ method public int getHardwareClockDiscontinuityCount();
+ method public int getLeapSecond();
+ method public long getTimeNanos();
+ method public double getTimeUncertaintyNanos();
+ method public boolean hasBiasNanos();
+ method public boolean hasBiasUncertaintyNanos();
+ method public boolean hasDriftNanosPerSecond();
+ method public boolean hasDriftUncertaintyNanosPerSecond();
+ method public boolean hasFullBiasNanos();
method public boolean hasLeapSecond();
- method public boolean hasTimeUncertaintyInNs();
+ method public boolean hasTimeUncertaintyNanos();
method public void reset();
- method public void resetBiasInNs();
- method public void resetBiasUncertaintyInNs();
- method public void resetDriftInNsPerSec();
- method public void resetDriftUncertaintyInNsPerSec();
- method public void resetFullBiasInNs();
+ method public void resetBiasNanos();
+ method public void resetBiasUncertaintyNanos();
+ method public void resetDriftNanosPerSecond();
+ method public void resetDriftUncertaintyNanosPerSecond();
+ method public void resetFullBiasNanos();
method public void resetLeapSecond();
- method public void resetTimeUncertaintyInNs();
+ method public void resetTimeUncertaintyNanos();
method public void set(android.location.GnssClock);
- method public void setBiasInNs(double);
- method public void setBiasUncertaintyInNs(double);
- method public void setDriftInNsPerSec(double);
- method public void setDriftUncertaintyInNsPerSec(double);
- method public void setFullBiasInNs(long);
- method public void setLeapSecond(short);
- method public void setTimeInNs(long);
- method public void setTimeOfLastHwClockDiscontinuityInNs(long);
- method public void setTimeUncertaintyInNs(double);
- method public void setType(byte);
+ method public void setBiasNanos(double);
+ method public void setBiasUncertaintyNanos(double);
+ method public void setDriftNanosPerSecond(double);
+ method public void setDriftUncertaintyNanosPerSecond(double);
+ method public void setFullBiasNanos(long);
+ method public void setHardwareClockDiscontinuityCount(int);
+ method public void setLeapSecond(int);
+ method public void setTimeNanos(long);
+ method public void setTimeUncertaintyNanos(double);
method public void writeToParcel(android.os.Parcel, int);
- field public static final byte CLOCK_TYPE_GPS_TIME = 2; // 0x2
- field public static final byte CLOCK_TYPE_LOCAL_HW_TIME = 1; // 0x1
- field public static final byte CLOCK_TYPE_UNKNOWN = 0; // 0x0
field public static final android.os.Parcelable.Creator<android.location.GnssClock> CREATOR;
}
- public static abstract class GnssClock.GnssClockType implements java.lang.annotation.Annotation {
- }
-
public final class GnssMeasurement implements android.os.Parcelable {
method public int describeContents();
- method public double getAccumulatedDeltaRangeInMeters();
- method public short getAccumulatedDeltaRangeState();
- method public double getAccumulatedDeltaRangeUncertaintyInMeters();
- method public double getAzimuthInDeg();
- method public double getAzimuthUncertaintyInDeg();
- method public int getBitNumber();
+ method public double getAccumulatedDeltaRangeMeters();
+ method public int getAccumulatedDeltaRangeState();
+ method public double getAccumulatedDeltaRangeUncertaintyMeters();
method public long getCarrierCycles();
- method public float getCarrierFrequencyInHz();
+ method public float getCarrierFrequencyHz();
method public double getCarrierPhase();
method public double getCarrierPhaseUncertainty();
- method public double getCn0InDbHz();
- method public double getCodePhaseInChips();
- method public double getCodePhaseUncertaintyInChips();
- method public double getDopplerShiftInHz();
- method public double getDopplerShiftUncertaintyInHz();
- method public double getElevationInDeg();
- method public double getElevationUncertaintyInDeg();
- method public byte getLossOfLock();
- method public byte getMultipathIndicator();
- method public double getPseudorangeInMeters();
- method public double getPseudorangeRateCarrierInMetersPerSec();
- method public double getPseudorangeRateCarrierUncertaintyInMetersPerSec();
- method public double getPseudorangeRateInMetersPerSec();
- method public double getPseudorangeRateUncertaintyInMetersPerSec();
- method public double getPseudorangeUncertaintyInMeters();
- method public long getReceivedGpsTowInNs();
- method public long getReceivedGpsTowUncertaintyInNs();
+ method public double getCn0DbHz();
+ method public int getConstellationType();
+ method public int getMultipathIndicator();
+ method public double getPseudorangeRateMetersPerSecond();
+ method public double getPseudorangeRateUncertaintyMetersPerSecond();
+ method public long getReceivedSvTimeNanos();
+ method public long getReceivedSvTimeUncertaintyNanos();
method public double getSnrInDb();
- method public short getState();
- method public short getSvid();
- method public short getTimeFromLastBitInMs();
- method public double getTimeOffsetInNs();
- method public boolean hasAzimuthInDeg();
- method public boolean hasAzimuthUncertaintyInDeg();
- method public boolean hasBitNumber();
+ method public int getState();
+ method public int getSvid();
+ method public double getTimeOffsetNanos();
method public boolean hasCarrierCycles();
- method public boolean hasCarrierFrequencyInHz();
+ method public boolean hasCarrierFrequencyHz();
method public boolean hasCarrierPhase();
method public boolean hasCarrierPhaseUncertainty();
- method public boolean hasCodePhaseInChips();
- method public boolean hasCodePhaseUncertaintyInChips();
- method public boolean hasDopplerShiftInHz();
- method public boolean hasDopplerShiftUncertaintyInHz();
- method public boolean hasElevationInDeg();
- method public boolean hasElevationUncertaintyInDeg();
- method public boolean hasPseudorangeInMeters();
- method public boolean hasPseudorangeUncertaintyInMeters();
method public boolean hasSnrInDb();
- method public boolean hasTimeFromLastBitInMs();
method public boolean isPseudorangeRateCorrected();
- method public boolean isUsedInFix();
method public void reset();
- method public void resetAzimuthInDeg();
- method public void resetAzimuthUncertaintyInDeg();
- method public void resetBitNumber();
method public void resetCarrierCycles();
- method public void resetCarrierFrequencyInHz();
+ method public void resetCarrierFrequencyHz();
method public void resetCarrierPhase();
method public void resetCarrierPhaseUncertainty();
- method public void resetCodePhaseInChips();
- method public void resetCodePhaseUncertaintyInChips();
- method public void resetDopplerShiftInHz();
- method public void resetDopplerShiftUncertaintyInHz();
- method public void resetElevationInDeg();
- method public void resetElevationUncertaintyInDeg();
- method public void resetPseudorangeInMeters();
- method public void resetPseudorangeUncertaintyInMeters();
method public void resetSnrInDb();
- method public void resetTimeFromLastBitInMs();
method public void set(android.location.GnssMeasurement);
- method public void setAccumulatedDeltaRangeInMeters(double);
- method public void setAccumulatedDeltaRangeState(short);
- method public void setAccumulatedDeltaRangeUncertaintyInMeters(double);
- method public void setAzimuthInDeg(double);
- method public void setAzimuthUncertaintyInDeg(double);
- method public void setBitNumber(int);
+ method public void setAccumulatedDeltaRangeMeters(double);
+ method public void setAccumulatedDeltaRangeState(int);
+ method public void setAccumulatedDeltaRangeUncertaintyMeters(double);
method public void setCarrierCycles(long);
- method public void setCarrierFrequencyInHz(float);
+ method public void setCarrierFrequencyHz(float);
method public void setCarrierPhase(double);
method public void setCarrierPhaseUncertainty(double);
- method public void setCn0InDbHz(double);
- method public void setCodePhaseInChips(double);
- method public void setCodePhaseUncertaintyInChips(double);
- method public void setDopplerShiftInHz(double);
- method public void setDopplerShiftUncertaintyInHz(double);
- method public void setElevationInDeg(double);
- method public void setElevationUncertaintyInDeg(double);
- method public void setLossOfLock(byte);
- method public void setMultipathIndicator(byte);
- method public void setPseudorangeInMeters(double);
- method public void setPseudorangeRateCarrierInMetersPerSec(double);
- method public void setPseudorangeRateCarrierUncertaintyInMetersPerSec(double);
- method public void setPseudorangeRateInMetersPerSec(double);
- method public void setPseudorangeRateUncertaintyInMetersPerSec(double);
- method public void setPseudorangeUncertaintyInMeters(double);
- method public void setReceivedGpsTowInNs(long);
- method public void setReceivedGpsTowUncertaintyInNs(long);
+ method public void setCn0DbHz(double);
+ method public void setConstellationType(int);
+ method public void setMultipathIndicator(int);
+ method public void setPseudorangeRateMetersPerSecond(double);
+ method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
+ method public void setReceivedSvTimeNanos(long);
+ method public void setReceivedSvTimeUncertaintyNanos(long);
method public void setSnrInDb(double);
- method public void setState(short);
- method public void setSvid(short);
- method public void setTimeFromLastBitInMs(short);
- method public void setTimeOffsetInNs(double);
- method public void setUsedInFix(boolean);
+ method public void setState(int);
+ method public void setSvid(int);
+ method public void setTimeOffsetNanos(double);
method public void writeToParcel(android.os.Parcel, int);
- field public static final short ADR_STATE_CYCLE_SLIP = 4; // 0x4
- field public static final short ADR_STATE_RESET = 2; // 0x2
- field public static final short ADR_STATE_UNKNOWN = 0; // 0x0
- field public static final short ADR_STATE_VALID = 1; // 0x1
+ field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
+ field public static final int ADR_STATE_RESET = 2; // 0x2
+ field public static final int ADR_STATE_UNKNOWN = 0; // 0x0
+ field public static final int ADR_STATE_VALID = 1; // 0x1
field public static final android.os.Parcelable.Creator<android.location.GnssMeasurement> CREATOR;
- field public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2; // 0x2
- field public static final byte LOSS_OF_LOCK_OK = 1; // 0x1
- field public static final byte LOSS_OF_LOCK_UNKNOWN = 0; // 0x0
- field public static final byte MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
- field public static final byte MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
- field public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
- field public static final short STATE_BIT_SYNC = 2; // 0x2
- field public static final short STATE_CODE_LOCK = 1; // 0x1
- field public static final short STATE_MSEC_AMBIGUOUS = 16; // 0x10
- field public static final short STATE_SUBFRAME_SYNC = 4; // 0x4
- field public static final short STATE_TOW_DECODED = 8; // 0x8
- field public static final short STATE_UNKNOWN = 0; // 0x0
- }
-
- public static abstract class GnssMeasurement.LossOfLockStatus implements java.lang.annotation.Annotation {
+ field public static final int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
+ field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+ field public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
+ field public static final int STATE_BIT_SYNC = 2; // 0x2
+ field public static final int STATE_CODE_LOCK = 1; // 0x1
+ field public static final int STATE_MSEC_AMBIGUOUS = 16; // 0x10
+ field public static final int STATE_SUBFRAME_SYNC = 4; // 0x4
+ field public static final int STATE_TOW_DECODED = 8; // 0x8
+ field public static final int STATE_UNKNOWN = 0; // 0x0
}
public static abstract class GnssMeasurement.MultipathIndicator implements java.lang.annotation.Annotation {
@@ -20524,7 +20444,7 @@
method public java.util.Collection<android.location.GnssMeasurement> getMeasurements();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementsEvent> CREATOR;
- field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+ field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
field public static final int STATUS_READY = 1; // 0x1
}
@@ -20541,29 +20461,34 @@
public final class GnssNavigationMessage implements android.os.Parcelable {
method public int describeContents();
method public byte[] getData();
- method public short getMessageId();
- method public short getStatus();
- method public short getSubmessageId();
- method public short getSvid();
- method public byte getType();
+ method public int getMessageId();
+ method public int getStatus();
+ method public int getSubmessageId();
+ method public int getSvid();
+ method public int getType();
method public void reset();
method public void set(android.location.GnssNavigationMessage);
method public void setData(byte[]);
- method public void setMessageId(short);
- method public void setStatus(short);
- method public void setSubmessageId(short);
- method public void setSvid(short);
- method public void setType(byte);
+ method public void setMessageId(int);
+ method public void setStatus(int);
+ method public void setSubmessageId(int);
+ method public void setSvid(int);
+ method public void setType(int);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
- field public static final byte MESSAGE_TYPE_CNAV2 = 4; // 0x4
- field public static final byte MESSAGE_TYPE_L1CA = 1; // 0x1
- field public static final byte MESSAGE_TYPE_L2CNAV = 2; // 0x2
- field public static final byte MESSAGE_TYPE_L5CNAV = 3; // 0x3
- field public static final byte MESSAGE_TYPE_UNKNOWN = 0; // 0x0
- field public static final short STATUS_PARITY_PASSED = 1; // 0x1
- field public static final short STATUS_PARITY_REBUILT = 2; // 0x2
- field public static final short STATUS_UNKNOWN = 0; // 0x0
+ field public static final int STATUS_PARITY_PASSED = 1; // 0x1
+ field public static final int STATUS_PARITY_REBUILT = 2; // 0x2
+ field public static final int STATUS_UNKNOWN = 0; // 0x0
+ field public static final int TYPE_BDS_D1 = 1281; // 0x501
+ field public static final int TYPE_BDS_D2 = 1282; // 0x502
+ field public static final int TYPE_GAL_F = 1538; // 0x602
+ field public static final int TYPE_GAL_I = 1537; // 0x601
+ field public static final int TYPE_GLO_L1CA = 769; // 0x301
+ field public static final int TYPE_GPS_CNAV2 = 260; // 0x104
+ field public static final int TYPE_GPS_L1CA = 257; // 0x101
+ field public static final int TYPE_GPS_L2CNAV = 258; // 0x102
+ field public static final int TYPE_GPS_L5CNAV = 259; // 0x103
+ field public static final int TYPE_UNKNOWN = 0; // 0x0
}
public static abstract class GnssNavigationMessage.GnssNavigationMessageType implements java.lang.annotation.Annotation {
@@ -20575,7 +20500,7 @@
method public android.location.GnssNavigationMessage getNavigationMessage();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessageEvent> CREATOR;
- field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+ field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
field public static final int STATUS_READY = 1; // 0x1
}
@@ -20594,11 +20519,11 @@
}
public final class GnssStatus {
- method public float getAzimuth(int);
+ method public float getAzimuthDegrees(int);
+ method public float getCn0DbHz(int);
method public int getConstellationType(int);
- method public float getElevation(int);
+ method public float getElevationDegrees(int);
method public int getNumSatellites();
- method public float getSnr(int);
method public int getSvid(int);
method public boolean hasAlmanac(int);
method public boolean hasEphemeris(int);
@@ -20612,6 +20537,9 @@
field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
}
+ public static abstract class GnssStatus.ConstellationType implements java.lang.annotation.Annotation {
+ }
+
public abstract class GnssStatusCallback {
ctor public GnssStatusCallback();
method public void onFirstFix(int);
@@ -20968,8 +20896,8 @@
method public java.util.List<java.lang.String> getProviders(boolean);
method public java.util.List<java.lang.String> getProviders(android.location.Criteria, boolean);
method public boolean isProviderEnabled(java.lang.String);
- method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
- method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
+ method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
+ method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback, android.os.Handler);
method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback);
@@ -20998,7 +20926,7 @@
method public void setTestProviderEnabled(java.lang.String, boolean);
method public void setTestProviderLocation(java.lang.String, android.location.Location);
method public void setTestProviderStatus(java.lang.String, int, android.os.Bundle, long);
- method public void unregisterGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
+ method public void unregisterGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
field public static final java.lang.String GPS_PROVIDER = "gps";
@@ -21162,6 +21090,7 @@
field public static final int TYPE_BUILTIN_EARPIECE = 1; // 0x1
field public static final int TYPE_BUILTIN_MIC = 15; // 0xf
field public static final int TYPE_BUILTIN_SPEAKER = 2; // 0x2
+ field public static final int TYPE_BUS = 21; // 0x15
field public static final int TYPE_DOCK = 13; // 0xd
field public static final int TYPE_FM = 14; // 0xe
field public static final int TYPE_FM_TUNER = 16; // 0x10
@@ -21191,12 +21120,14 @@
field public static final android.os.Parcelable.Creator<android.media.AudioFocusInfo> CREATOR;
}
- public class AudioFormat {
+ public final class AudioFormat implements android.os.Parcelable {
+ method public int describeContents();
method public int getChannelCount();
method public int getChannelIndexMask();
method public int getChannelMask();
method public int getEncoding();
method public int getSampleRate();
+ method public void writeToParcel(android.os.Parcel, int);
field public static final deprecated int CHANNEL_CONFIGURATION_DEFAULT = 1; // 0x1
field public static final deprecated int CHANNEL_CONFIGURATION_INVALID = 0; // 0x0
field public static final deprecated int CHANNEL_CONFIGURATION_MONO = 2; // 0x2
@@ -21238,6 +21169,7 @@
field public static final int CHANNEL_OUT_SIDE_RIGHT = 4096; // 0x1000
field public static final int CHANNEL_OUT_STEREO = 12; // 0xc
field public static final int CHANNEL_OUT_SURROUND = 1052; // 0x41c
+ field public static final android.os.Parcelable.Creator<android.media.AudioFormat> CREATOR;
field public static final int ENCODING_AC3 = 5; // 0x5
field public static final int ENCODING_DEFAULT = 1; // 0x1
field public static final int ENCODING_DTS = 7; // 0x7
@@ -21248,6 +21180,7 @@
field public static final int ENCODING_PCM_16BIT = 2; // 0x2
field public static final int ENCODING_PCM_8BIT = 3; // 0x3
field public static final int ENCODING_PCM_FLOAT = 4; // 0x4
+ field public static final int SAMPLE_RATE_UNSPECIFIED = 0; // 0x0
}
public static class AudioFormat.Builder {
@@ -21422,7 +21355,7 @@
public static abstract class AudioManager.AudioRecordingCallback {
ctor public AudioManager.AudioRecordingCallback();
- method public void onRecordConfigChanged();
+ method public void onRecordConfigChanged(android.media.AudioRecordConfiguration[]);
}
public static abstract interface AudioManager.OnAudioFocusChangeListener {
@@ -21499,7 +21432,7 @@
method public abstract void onRoutingChanged(android.media.AudioRecord);
}
- public class AudioRecordConfiguration implements android.os.Parcelable {
+ public final class AudioRecordConfiguration implements android.os.Parcelable {
method public int describeContents();
method public android.media.AudioDeviceInfo getAudioDevice();
method public int getClientAudioSessionId();
@@ -21513,6 +21446,7 @@
public abstract interface AudioRouting {
method public abstract void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public abstract android.media.AudioDeviceInfo getPreferredDevice();
+ method public abstract android.media.AudioDeviceInfo getRoutedDevice();
method public abstract void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener);
method public abstract boolean setPreferredDevice(android.media.AudioDeviceInfo);
}
@@ -21693,6 +21627,8 @@
public class ExifInterface {
ctor public ExifInterface(java.lang.String) throws java.io.IOException;
+ ctor public ExifInterface(java.io.FileDescriptor) throws java.io.IOException;
+ ctor public ExifInterface(java.io.InputStream) throws java.io.IOException;
method public double getAltitude(double);
method public java.lang.String getAttribute(java.lang.String);
method public double getAttributeDouble(java.lang.String, double);
@@ -21714,6 +21650,10 @@
field public static final java.lang.String TAG_APERTURE = "FNumber";
field public static final java.lang.String TAG_DATETIME = "DateTime";
field public static final java.lang.String TAG_DATETIME_DIGITIZED = "DateTimeDigitized";
+ field public static final java.lang.String TAG_DIGITAL_ZOOM_RATIO = "DigitalZoomRatio";
+ field public static final java.lang.String TAG_EXPOSURE_BIAS_VALUE = "ExposureBiasValue";
+ field public static final java.lang.String TAG_EXPOSURE_MODE = "ExposureMode";
+ field public static final java.lang.String TAG_EXPOSURE_PROGRAM = "ExposureProgram";
field public static final java.lang.String TAG_EXPOSURE_TIME = "ExposureTime";
field public static final java.lang.String TAG_FLASH = "Flash";
field public static final java.lang.String TAG_FOCAL_LENGTH = "FocalLength";
@@ -21729,9 +21669,12 @@
field public static final java.lang.String TAG_IMAGE_LENGTH = "ImageLength";
field public static final java.lang.String TAG_IMAGE_WIDTH = "ImageWidth";
field public static final java.lang.String TAG_ISO = "ISOSpeedRatings";
+ field public static final java.lang.String TAG_LIGHT_SOURCE = "LightSource";
field public static final java.lang.String TAG_MAKE = "Make";
+ field public static final java.lang.String TAG_METERING_MODE = "MeteringMode";
field public static final java.lang.String TAG_MODEL = "Model";
field public static final java.lang.String TAG_ORIENTATION = "Orientation";
+ field public static final java.lang.String TAG_SUBJECT_DISTANCE = "SubjectDistance";
field public static final java.lang.String TAG_SUBSEC_TIME = "SubSecTime";
field public static final java.lang.String TAG_SUBSEC_TIME_DIG = "SubSecTimeDigitized";
field public static final java.lang.String TAG_SUBSEC_TIME_ORIG = "SubSecTimeOriginal";
@@ -22141,6 +22084,7 @@
field public static final int HEVCMainTierLevel62 = 16777216; // 0x1000000
field public static final int HEVCProfileMain = 1; // 0x1
field public static final int HEVCProfileMain10 = 2; // 0x2
+ field public static final int HEVCProfileMain10HDR10 = 4096; // 0x1000
field public static final int MPEG2LevelH14 = 2; // 0x2
field public static final int MPEG2LevelHL = 3; // 0x3
field public static final int MPEG2LevelLL = 0; // 0x0
@@ -22398,6 +22342,7 @@
method public final void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
method public final void setDataSource(java.lang.String, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
method public final void setDataSource(java.lang.String) throws java.io.IOException;
+ method public final void setDataSource(android.content.res.AssetFileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public final void setDataSource(java.io.FileDescriptor) throws java.io.IOException;
method public final void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException;
method public void unselectTrack(int);
@@ -22472,6 +22417,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_PCM_ENCODING = "pcm-encoding";
field public static final java.lang.String KEY_PRIORITY = "priority";
field public static final java.lang.String KEY_PROFILE = "profile";
field public static final java.lang.String KEY_PUSH_BLANK_BUFFERS_ON_STOP = "push-blank-buffers-on-shutdown";
@@ -22481,6 +22427,7 @@
field public static final java.lang.String KEY_SLICE_HEIGHT = "slice-height";
field public static final java.lang.String KEY_STRIDE = "stride";
field public static final java.lang.String KEY_TEMPORAL_LAYERING = "ts-schema";
+ field public static final java.lang.String KEY_TRACK_ID = "track-id";
field public static final java.lang.String KEY_WIDTH = "width";
field public static final java.lang.String MIMETYPE_AUDIO_AAC = "audio/mp4a-latm";
field public static final java.lang.String MIMETYPE_AUDIO_AC3 = "audio/ac3";
@@ -22680,6 +22627,7 @@
method public void setDataSource(android.content.Context, android.net.Uri) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
method public void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
method public void setDataSource(java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
+ method public void setDataSource(android.content.res.AssetFileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public void setDataSource(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public void setDataSource(android.media.MediaDataSource) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
@@ -24119,6 +24067,10 @@
method public void playFromMediaId(java.lang.String, android.os.Bundle);
method public void playFromSearch(java.lang.String, android.os.Bundle);
method public void playFromUri(android.net.Uri, android.os.Bundle);
+ method public void prepare();
+ method public void prepareFromMediaId(java.lang.String, android.os.Bundle);
+ method public void prepareFromSearch(java.lang.String, android.os.Bundle);
+ method public void prepareFromUri(android.net.Uri, android.os.Bundle);
method public void rewind();
method public void seekTo(long);
method public void sendCustomAction(android.media.session.PlaybackState.CustomAction, android.os.Bundle);
@@ -24152,7 +24104,6 @@
method public void setRatingType(int);
method public void setSessionActivity(android.app.PendingIntent);
field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
- field public static final int FLAG_HANDLES_PREPARE_ONLY = 4; // 0x4
field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
}
@@ -24167,6 +24118,10 @@
method public void onPlayFromMediaId(java.lang.String, android.os.Bundle);
method public void onPlayFromSearch(java.lang.String, android.os.Bundle);
method public void onPlayFromUri(android.net.Uri, android.os.Bundle);
+ method public void onPrepare();
+ method public void onPrepareFromMediaId(java.lang.String, android.os.Bundle);
+ method public void onPrepareFromSearch(java.lang.String, android.os.Bundle);
+ method public void onPrepareFromUri(android.net.Uri, android.os.Bundle);
method public void onRewind();
method public void onSeekTo(long);
method public void onSetRating(android.media.Rating);
@@ -24223,6 +24178,10 @@
field public static final long ACTION_PLAY_FROM_SEARCH = 2048L; // 0x800L
field public static final long ACTION_PLAY_FROM_URI = 8192L; // 0x2000L
field public static final long ACTION_PLAY_PAUSE = 512L; // 0x200L
+ field public static final long ACTION_PREPARE = 16384L; // 0x4000L
+ field public static final long ACTION_PREPARE_FROM_MEDIA_ID = 32768L; // 0x8000L
+ field public static final long ACTION_PREPARE_FROM_SEARCH = 65536L; // 0x10000L
+ field public static final long ACTION_PREPARE_FROM_URI = 131072L; // 0x20000L
field public static final long ACTION_REWIND = 8L; // 0x8L
field public static final long ACTION_SEEK_TO = 256L; // 0x100L
field public static final long ACTION_SET_RATING = 128L; // 0x80L
@@ -24231,7 +24190,6 @@
field public static final long ACTION_SKIP_TO_QUEUE_ITEM = 4096L; // 0x1000L
field public static final long ACTION_STOP = 1L; // 0x1L
field public static final android.os.Parcelable.Creator<android.media.session.PlaybackState> CREATOR;
- field public static final java.lang.String EXTRA_PREPARE_ONLY = "android.media.session.extra.PREPARE_ONLY";
field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL
field public static final int STATE_BUFFERING = 6; // 0x6
field public static final int STATE_CONNECTING = 8; // 0x8
@@ -24356,7 +24314,10 @@
method public static final android.net.Uri buildProgramsUriForChannel(long, long, long);
method public static final android.net.Uri buildProgramsUriForChannel(android.net.Uri, long, long);
method public static final android.net.Uri buildRecordedProgramUri(long);
+ method public static final boolean isChannelUri(android.net.Uri);
method public static final boolean isChannelUriForPassthroughInput(android.net.Uri);
+ method public static final boolean isChannelUriForTunerInput(android.net.Uri);
+ method public static final boolean isProgramUri(android.net.Uri);
field public static final java.lang.String AUTHORITY = "android.media.tv";
}
@@ -24450,7 +24411,8 @@
field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
- field public static final java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
+ field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
+ field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
@@ -24460,7 +24422,9 @@
field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
- field public static final java.lang.String COLUMN_SEASON_NUMBER = "season_number";
+ field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
+ field public static final deprecated java.lang.String COLUMN_SEASON_NUMBER = "season_number";
+ field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
@@ -24503,7 +24467,7 @@
field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
- field public static final java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
+ field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
field public static final java.lang.String COLUMN_INPUT_ID = "input_id";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
@@ -24518,7 +24482,8 @@
field public static final java.lang.String COLUMN_RECORDING_DURATION_MILLIS = "recording_duration_millis";
field public static final java.lang.String COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS = "recording_expire_time_utc_millis";
field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
- field public static final java.lang.String COLUMN_SEASON_NUMBER = "season_number";
+ field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
+ field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
@@ -24599,6 +24564,7 @@
method public boolean isPassthroughInput();
method public java.lang.CharSequence loadCustomLabel(android.content.Context);
method public android.graphics.drawable.Drawable loadIcon(android.content.Context);
+ method public android.graphics.drawable.Drawable loadIcon(android.content.Context, int);
method public java.lang.CharSequence loadLabel(android.content.Context);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.media.tv.TvInputInfo> CREATOR;
@@ -24616,11 +24582,12 @@
}
public static final class TvInputInfo.Builder {
- ctor public TvInputInfo.Builder(android.content.Context, java.lang.Class<?>);
+ ctor public TvInputInfo.Builder(android.content.Context, android.content.ComponentName);
method public android.media.tv.TvInputInfo build() throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public android.media.tv.TvInputInfo.Builder setCanRecord(boolean);
method public android.media.tv.TvInputInfo.Builder setHdmiDeviceInfo(android.hardware.hdmi.HdmiDeviceInfo);
method public android.media.tv.TvInputInfo.Builder setIcon(android.graphics.drawable.Icon);
+ method public android.media.tv.TvInputInfo.Builder setIcon(android.graphics.drawable.Icon, int);
method public android.media.tv.TvInputInfo.Builder setLabel(int);
method public android.media.tv.TvInputInfo.Builder setParentId(java.lang.String);
method public android.media.tv.TvInputInfo.Builder setTunerCount(int);
@@ -24658,6 +24625,7 @@
field public static final java.lang.String ACTION_BLOCKED_RATINGS_CHANGED = "android.media.tv.action.BLOCKED_RATINGS_CHANGED";
field public static final java.lang.String ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED = "android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED";
field public static final java.lang.String ACTION_QUERY_CONTENT_RATING_SYSTEMS = "android.media.tv.action.QUERY_CONTENT_RATING_SYSTEMS";
+ field public static final java.lang.String ACTION_SETUP_INPUTS = "android.media.tv.action.SETUP_INPUTS";
field public static final int INPUT_STATE_CONNECTED = 0; // 0x0
field public static final int INPUT_STATE_CONNECTED_STANDBY = 1; // 0x1
field public static final int INPUT_STATE_DISCONNECTED = 2; // 0x2
@@ -24759,7 +24727,7 @@
method public void notifyError(int);
method public void notifyRecordingStopped(android.net.Uri);
method public void notifySessionEvent(java.lang.String, android.os.Bundle);
- method public void notifyTuned();
+ method public void notifyTuned(android.net.Uri);
method public void onAppPrivateCommand(java.lang.String, android.os.Bundle);
method public abstract void onRelease();
method public abstract void onStartRecording(android.net.Uri);
@@ -24827,7 +24795,7 @@
method public void onError(int);
method public void onEvent(java.lang.String, java.lang.String, android.os.Bundle);
method public void onRecordingStopped(android.net.Uri);
- method public void onTuned();
+ method public void onTuned(android.net.Uri);
}
public class TvStreamConfig implements android.os.Parcelable {
@@ -25302,7 +25270,7 @@
method public int getUid();
}
- public class DataUsageRequest implements android.os.Parcelable {
+ public final class DataUsageRequest 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.net.DataUsageRequest> CREATOR;
@@ -26400,6 +26368,7 @@
field public int numberBurst;
field public int preamble;
field public int requestType;
+ field public boolean secure;
}
public static class RttManager.RttResult {
@@ -26431,6 +26400,7 @@
field public deprecated long rtt_sd_ns;
field public deprecated long rtt_spread_ns;
field public int rxRate;
+ field public boolean secure;
field public int status;
field public int successMeasurementFrameNumber;
field public long ts;
@@ -26695,7 +26665,6 @@
method public boolean reconnect();
method public boolean removeNetwork(int);
method public boolean saveConfiguration();
- method public boolean setMetered(int, boolean);
method public void setTdlsEnabled(java.net.InetAddress, boolean);
method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
method public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
@@ -26808,6 +26777,7 @@
method public void stopTrackingWifiChange(android.net.wifi.WifiScanner.WifiChangeListener);
field public static final int MAX_SCAN_PERIOD_MS = 1024000; // 0xfa000
field public static final int MIN_SCAN_PERIOD_MS = 1000; // 0x3e8
+ field public static final int REASON_DUPLICATE_REQEUST = -5; // 0xfffffffb
field public static final int REASON_INVALID_LISTENER = -2; // 0xfffffffe
field public static final int REASON_INVALID_REQUEST = -3; // 0xfffffffd
field public static final int REASON_NOT_AUTHORIZED = -4; // 0xfffffffc
@@ -29098,7 +29068,8 @@
method public static void glGetSynciv(long, int, int, int[], int, int[], int);
method public static void glGetSynciv(long, int, int, java.nio.IntBuffer, java.nio.IntBuffer);
method public static void glGetTransformFeedbackVarying(int, int, int, int[], int, int[], int, int[], int, byte[], int);
- method public static void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte);
+ method public static deprecated void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte);
+ method public static void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.ByteBuffer);
method public static java.lang.String glGetTransformFeedbackVarying(int, int, int[], int, int[], int);
method public static java.lang.String glGetTransformFeedbackVarying(int, int, java.nio.IntBuffer, java.nio.IntBuffer);
method public static int glGetUniformBlockIndex(int, java.lang.String);
@@ -29124,6 +29095,7 @@
method public static void glProgramBinary(int, int, java.nio.Buffer, int);
method public static void glProgramParameteri(int, int, int);
method public static void glReadBuffer(int);
+ method public static void glReadPixels(int, int, int, int, int, int, int);
method public static void glRenderbufferStorageMultisample(int, int, int, int, int);
method public static void glResumeTransformFeedback();
method public static void glSamplerParameterf(int, int, float);
@@ -30709,6 +30681,10 @@
ctor public DeadObjectException(java.lang.String);
}
+ public class DeadSystemException extends android.os.DeadObjectException {
+ ctor public DeadSystemException();
+ }
+
public final class Debug {
method public static deprecated void changeDebugPort(int);
method public static void dumpHprofData(java.lang.String) throws java.io.IOException;
@@ -31344,7 +31320,6 @@
field public static final int RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY = 1; // 0x1
field public static final deprecated int SCREEN_BRIGHT_WAKE_LOCK = 10; // 0xa
field public static final deprecated int SCREEN_DIM_WAKE_LOCK = 6; // 0x6
- field public static final int SUSTAINED_PERFORMANCE_WAKE_LOCK = 256; // 0x100
field public static final int USER_ACTIVITY_EVENT_BUTTON = 1; // 0x1
field public static final int USER_ACTIVITY_EVENT_OTHER = 0; // 0x0
field public static final int USER_ACTIVITY_EVENT_TOUCH = 2; // 0x2
@@ -31366,6 +31341,8 @@
ctor public Process();
method public static final long getElapsedCpuTime();
method public static final int getGidForName(java.lang.String);
+ method public static final long getStartElapsedRealtime();
+ method public static final long getStartUptimeMillis();
method public static final int getThreadPriority(int) throws java.lang.IllegalArgumentException;
method public static final int getUidForName(java.lang.String);
method public static final boolean is64Bit();
@@ -31399,9 +31376,14 @@
}
public class RecoverySystem {
+ method public static void cancelScheduledUpdate(android.content.Context) throws java.io.IOException;
method public static void installPackage(android.content.Context, java.io.File) throws java.io.IOException;
+ method public static void installPackage(android.content.Context, java.io.File, boolean) throws java.io.IOException;
+ method public static void processPackage(android.content.Context, java.io.File, android.os.RecoverySystem.ProgressListener, android.os.Handler) throws java.io.IOException;
+ method public static void processPackage(android.content.Context, java.io.File, android.os.RecoverySystem.ProgressListener) throws java.io.IOException;
method public static void rebootWipeCache(android.content.Context) throws java.io.IOException;
method public static void rebootWipeUserData(android.content.Context) throws java.io.IOException;
+ method public static void scheduleUpdateOnBoot(android.content.Context, java.io.File) throws java.io.IOException;
method public static void verifyPackage(java.io.File, android.os.RecoverySystem.ProgressListener, java.io.File) throws java.security.GeneralSecurityException, java.io.IOException;
}
@@ -31727,7 +31709,7 @@
method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener);
}
- public class StorageVolume implements android.os.Parcelable {
+ public final class StorageVolume implements android.os.Parcelable {
method public android.content.Intent createAccessIntent(java.lang.String);
method public int describeContents();
method public java.lang.String getDescription(android.content.Context);
@@ -31855,6 +31837,7 @@
method protected int getPersistedInt(int);
method protected long getPersistedLong(long);
method protected java.lang.String getPersistedString(java.lang.String);
+ method public java.util.Set<java.lang.String> getPersistedStringSet(java.util.Set<java.lang.String>);
method public android.preference.PreferenceManager getPreferenceManager();
method public android.content.SharedPreferences getSharedPreferences();
method public boolean getShouldDisableView();
@@ -31889,6 +31872,7 @@
method protected boolean persistInt(int);
method protected boolean persistLong(long);
method protected boolean persistString(java.lang.String);
+ method public boolean persistStringSet(java.util.Set<java.lang.String>);
method public void restoreHierarchyState(android.os.Bundle);
method public void saveHierarchyState(android.os.Bundle);
method public void setDefaultValue(java.lang.Object);
@@ -32559,7 +32543,7 @@
field public static final java.lang.String COLUMN_ID = "_id";
field public static final java.lang.String COLUMN_ORIGINAL_NUMBER = "original_number";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/blocked_number";
- field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_numbers";
+ field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_number";
field public static final android.net.Uri CONTENT_URI;
}
@@ -34116,6 +34100,7 @@
public static final class DocumentsContract.Root {
field public static final java.lang.String COLUMN_AVAILABLE_BYTES = "available_bytes";
+ field public static final java.lang.String COLUMN_CAPACITY_BYTES = "capacity_bytes";
field public static final java.lang.String COLUMN_DOCUMENT_ID = "document_id";
field public static final java.lang.String COLUMN_FLAGS = "flags";
field public static final java.lang.String COLUMN_ICON = "icon";
@@ -34732,6 +34717,7 @@
field public static final java.lang.String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
field public static final java.lang.String USE_GOOGLE_MAIL = "use_google_mail";
field public static final java.lang.String WAIT_FOR_DEBUGGER = "wait_for_debugger";
+ field public static final java.lang.String WEBVIEW_MULTIPROCESS = "webview_multiprocess";
field public static final java.lang.String WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN = "wifi_device_owner_configs_lockdown";
field public static final java.lang.String WIFI_MAX_DHCP_RETRY_COUNT = "wifi_max_dhcp_retry_count";
field public static final java.lang.String WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS = "wifi_mobile_data_transition_wakelock_timeout_ms";
@@ -36582,6 +36568,7 @@
method public java.lang.String[] getSignaturePaddings();
method public int getUserAuthenticationValidityDurationSeconds();
method public boolean isDigestsSpecified();
+ method public boolean isInvalidatedByBiometricEnrollment();
method public boolean isRandomizedEncryptionRequired();
method public boolean isUserAuthenticationRequired();
method public boolean isUserAuthenticationValidWhileOnBody();
@@ -36599,6 +36586,7 @@
method public android.security.keystore.KeyGenParameterSpec.Builder setCertificateSubject(javax.security.auth.x500.X500Principal);
method public android.security.keystore.KeyGenParameterSpec.Builder setDigests(java.lang.String...);
method public android.security.keystore.KeyGenParameterSpec.Builder setEncryptionPaddings(java.lang.String...);
+ method public android.security.keystore.KeyGenParameterSpec.Builder setInvalidatedByBiometricEnrollment(boolean);
method public android.security.keystore.KeyGenParameterSpec.Builder setKeySize(int);
method public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityEnd(java.util.Date);
method public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityForConsumptionEnd(java.util.Date);
@@ -36625,6 +36613,7 @@
method public java.lang.String[] getSignaturePaddings();
method public int getUserAuthenticationValidityDurationSeconds();
method public boolean isInsideSecureHardware();
+ method public boolean isInvalidatedByBiometricEnrollment();
method public boolean isUserAuthenticationRequired();
method public boolean isUserAuthenticationRequirementEnforcedBySecureHardware();
method public boolean isUserAuthenticationValidWhileOnBody();
@@ -36688,6 +36677,7 @@
method public java.lang.String[] getSignaturePaddings();
method public int getUserAuthenticationValidityDurationSeconds();
method public boolean isDigestsSpecified();
+ method public boolean isInvalidatedByBiometricEnrollment();
method public boolean isRandomizedEncryptionRequired();
method public boolean isUserAuthenticationRequired();
method public boolean isUserAuthenticationValidWhileOnBody();
@@ -36699,6 +36689,7 @@
method public android.security.keystore.KeyProtection.Builder setBlockModes(java.lang.String...);
method public android.security.keystore.KeyProtection.Builder setDigests(java.lang.String...);
method public android.security.keystore.KeyProtection.Builder setEncryptionPaddings(java.lang.String...);
+ method public android.security.keystore.KeyProtection.Builder setInvalidatedByBiometricEnrollment(boolean);
method public android.security.keystore.KeyProtection.Builder setKeyValidityEnd(java.util.Date);
method public android.security.keystore.KeyProtection.Builder setKeyValidityForConsumptionEnd(java.util.Date);
method public android.security.keystore.KeyProtection.Builder setKeyValidityForOriginationEnd(java.util.Date);
@@ -36737,7 +36728,8 @@
ctor public CarrierMessagingService();
method public android.os.IBinder onBind(android.content.Intent);
method public void onDownloadMms(android.net.Uri, int, android.net.Uri, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Integer>);
- method public void onFilterSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Boolean>);
+ method public deprecated void onFilterSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Boolean>);
+ method public void onReceiveTextSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Integer>);
method public deprecated void onSendDataSms(byte[], int, java.lang.String, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
method public void onSendDataSms(byte[], int, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
method public void onSendMms(android.net.Uri, int, android.net.Uri, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendMmsResult>);
@@ -36748,6 +36740,9 @@
field public static final int DOWNLOAD_STATUS_ERROR = 2; // 0x2
field public static final int DOWNLOAD_STATUS_OK = 0; // 0x0
field public static final int DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK = 1; // 0x1
+ field public static final int RECEIVE_OPTIONS_DEFAULT = 0; // 0x0
+ field public static final int RECEIVE_OPTIONS_DROP = 1; // 0x1
+ field public static final int RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE = 2; // 0x2
field public static final int SEND_FLAG_REQUEST_DELIVERY_STATUS = 1; // 0x1
field public static final int SEND_STATUS_ERROR = 2; // 0x2
field public static final int SEND_STATUS_OK = 0; // 0x0
@@ -36961,6 +36956,7 @@
public abstract class NotificationAssistantService extends android.service.notification.NotificationListenerService {
ctor public NotificationAssistantService();
method public final void adjustImportance(java.lang.String, android.service.notification.NotificationAssistantService.Adjustment);
+ method public final android.os.IBinder onBind(android.content.Intent);
method public void onNotificationActionClick(java.lang.String, long, int);
method public void onNotificationClick(java.lang.String, long);
method public abstract android.service.notification.NotificationAssistantService.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
@@ -36978,9 +36974,8 @@
field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb
field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
- field public static final int REASON_PACKAGE_SUSPENDED = 15; // 0xf
- field public static final int REASON_PROFILE_TURNED_OFF = 16; // 0x10
- field public static final int REASON_TOPIC_BANNED = 14; // 0xe
+ field public static final int REASON_PACKAGE_SUSPENDED = 14; // 0xe
+ field public static final int REASON_PROFILE_TURNED_OFF = 15; // 0xf
field public static final int REASON_USER_STOPPED = 6; // 0x6
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
}
@@ -37014,7 +37009,7 @@
method public void registerAsSystemService(android.content.Context, android.content.ComponentName, int) throws android.os.RemoteException;
method public final void requestInterruptionFilter(int);
method public final void requestListenerHints(int);
- method public static final void requestRebind(android.content.ComponentName) throws android.os.RemoteException;
+ method public static void requestRebind(android.content.ComponentName) throws android.os.RemoteException;
method public final void requestUnbind() throws android.os.RemoteException;
method public final void setNotificationsShown(java.lang.String[]);
method public final void setOnNotificationPostedTrim(int);
@@ -37042,10 +37037,11 @@
method public int getSuppressedVisualEffects();
method public boolean isAmbient();
method public boolean matchesInterruptionFilter();
- field public static final int IMPORTANCE_DEFAULT = 2; // 0x2
- field public static final int IMPORTANCE_HIGH = 3; // 0x3
- field public static final int IMPORTANCE_LOW = 1; // 0x1
- field public static final int IMPORTANCE_MAX = 4; // 0x4
+ field public static final int IMPORTANCE_DEFAULT = 3; // 0x3
+ field public static final int IMPORTANCE_HIGH = 4; // 0x4
+ field public static final int IMPORTANCE_LOW = 2; // 0x2
+ field public static final int IMPORTANCE_MAX = 5; // 0x5
+ field public static final int IMPORTANCE_MIN = 1; // 0x1
field public static final int IMPORTANCE_NONE = 0; // 0x0
field public static final int IMPORTANCE_UNSPECIFIED = -1000; // 0xfffffc18
}
@@ -37084,6 +37080,7 @@
public abstract interface IPersistentDataBlockService implements android.os.IInterface {
method public abstract int getDataBlockSize() throws android.os.RemoteException;
+ method public abstract int getFlashLockState() throws android.os.RemoteException;
method public abstract long getMaximumDataBlockSize() throws android.os.RemoteException;
method public abstract boolean getOemUnlockEnabled() throws android.os.RemoteException;
method public abstract byte[] read() throws android.os.RemoteException;
@@ -37095,12 +37092,19 @@
public class PersistentDataBlockManager {
ctor public PersistentDataBlockManager(android.service.persistentdata.IPersistentDataBlockService);
method public int getDataBlockSize();
+ method public int getFlashLockState();
method public long getMaximumDataBlockSize();
method public boolean getOemUnlockEnabled();
method public byte[] read();
method public void setOemUnlockEnabled(boolean);
method public void wipe();
method public int write(byte[]);
+ field public static final int FLASH_LOCK_LOCKED = 1; // 0x1
+ field public static final int FLASH_LOCK_UNKNOWN = -1; // 0xffffffff
+ field public static final int FLASH_LOCK_UNLOCKED = 0; // 0x0
+ }
+
+ public static abstract class PersistentDataBlockManager.FlashLockState implements java.lang.annotation.Annotation {
}
}
@@ -37142,6 +37146,7 @@
method public final void startActivityAndCollapse(android.content.Intent);
method public final void unlockAndRun(java.lang.Runnable);
field public static final java.lang.String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE";
+ field public static final java.lang.String ACTION_QS_TILE_PREFERENCES = "android.service.quicksettings.action.QS_TILE_PREFERENCES";
field public static final int TILE_MODE_ACTIVE = 2; // 0x2
field public static final int TILE_MODE_PASSIVE = 1; // 0x1
}
@@ -38686,6 +38691,7 @@
method public final void conferenceRemoteConnections(android.telecom.RemoteConnection, android.telecom.RemoteConnection);
method public final android.telecom.RemoteConnection createRemoteIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public final android.telecom.RemoteConnection createRemoteOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
+ method public final java.util.Collection<android.telecom.Conference> getAllConferences();
method public final java.util.Collection<android.telecom.Connection> getAllConnections();
method public final android.os.IBinder onBind(android.content.Intent);
method public void onConference(android.telecom.Connection, android.telecom.Connection);
@@ -39028,6 +39034,7 @@
method public void cancelMissedCallsNotification();
method public deprecated void clearAccounts();
method public void clearPhoneAccounts();
+ method public android.content.Intent createManageBlockedNumbersIntent();
method public java.util.List<android.telecom.ParcelableCallAnalytics> dumpAnalytics();
method public void enablePhoneAccount(android.telecom.PhoneAccountHandle, boolean);
method public boolean endCall();
@@ -39053,7 +39060,7 @@
method public boolean isRinging();
method public boolean isTtySupported();
method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String);
- method public void launchManageBlockedNumbersActivity();
+ method public deprecated void launchManageBlockedNumbersActivity();
method public void placeCall(android.net.Uri, android.os.Bundle);
method public void registerPhoneAccount(android.telecom.PhoneAccount);
method public void showInCallScreen(boolean);
@@ -39138,10 +39145,12 @@
package android.telephony {
public class CarrierConfigManager {
+ method public android.os.PersistableBundle getConfig(int);
method public android.os.PersistableBundle getConfig();
- method public android.os.PersistableBundle getConfigForSubId(int);
+ method public deprecated android.os.PersistableBundle getConfigForSubId(int);
method public static android.os.PersistableBundle getDefaultConfig();
- method public void notifyConfigChangedForSubId(int);
+ method public void notifyConfigChanged(int);
+ method public deprecated void notifyConfigChangedForSubId(int);
method public void updateConfigForPhoneId(int, java.lang.String);
field public static final java.lang.String ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED";
field public static final java.lang.String BOOL_ALLOW_EMERGENCY_VIDEO_CALLS = "bool_allow_emergency_video_calls";
@@ -39801,12 +39810,18 @@
method public boolean handlePinMmi(java.lang.String);
method public boolean handlePinMmiForSubscriber(int, java.lang.String);
method public boolean hasCarrierPrivileges();
+ method public boolean hasCarrierPrivileges(int);
method public boolean hasIccCard();
method public boolean iccCloseLogicalChannel(int);
+ method public boolean iccCloseLogicalChannel(int, int);
method public byte[] iccExchangeSimIO(int, int, int, int, int, java.lang.String);
+ method public byte[] iccExchangeSimIO(int, int, int, int, int, int, java.lang.String);
method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String);
+ method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(int, java.lang.String);
method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, java.lang.String);
+ method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, int, java.lang.String);
method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
+ method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, int, java.lang.String);
method public boolean isDataConnectivityPossible();
method public boolean isHearingAidCompatibilitySupported();
method public boolean isIdle();
@@ -39824,12 +39839,15 @@
method public void listen(android.telephony.PhoneStateListener, int);
method public boolean needsOtaServiceProvisioning();
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
+ method public java.lang.String sendEnvelopeWithStatus(int, java.lang.String);
method public void setDataEnabled(boolean);
method public void setDataEnabled(int, boolean);
method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
method public boolean setLine1NumberForDisplay(int, java.lang.String, java.lang.String);
method public boolean setOperatorBrandOverride(java.lang.String);
+ method public boolean setOperatorBrandOverride(int, java.lang.String);
method public boolean setPreferredNetworkTypeToGlobal();
+ method public boolean setPreferredNetworkTypeToGlobal(int);
method public boolean setRadio(boolean);
method public boolean setRadioPower(boolean);
method public boolean setVoiceMailNumber(java.lang.String, java.lang.String);
@@ -41228,7 +41246,6 @@
method public boolean hasNext();
method public java.util.Iterator<java.lang.String> iterator();
method public java.lang.String next();
- method public void remove();
method public void setString(java.lang.String);
}
@@ -42840,6 +42857,7 @@
method public int describeContents();
method public static android.util.LocaleList forLanguageTags(java.lang.String);
method public java.util.Locale get(int);
+ method public static android.util.LocaleList getAdjustedDefault();
method public static android.util.LocaleList getDefault();
method public static android.util.LocaleList getEmptyLocaleList();
method public java.util.Locale getFirstMatch(java.lang.String[]);
@@ -46770,6 +46788,7 @@
field public static final int TYPE_ACCESSIBILITY_OVERLAY = 4; // 0x4
field public static final int TYPE_APPLICATION = 1; // 0x1
field public static final int TYPE_INPUT_METHOD = 2; // 0x2
+ field public static final int TYPE_SPLIT_SCREEN_DIVIDER = 5; // 0x5
field public static final int TYPE_SYSTEM = 3; // 0x3
}
@@ -47109,6 +47128,7 @@
method public int getCursorCapsMode(int);
method public android.text.Editable getEditable();
method public android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int);
+ method public android.os.Handler getHandler();
method public java.lang.CharSequence getSelectedText(int);
method public java.lang.CharSequence getTextAfterCursor(int, int);
method public java.lang.CharSequence getTextBeforeCursor(int, int);
@@ -47272,6 +47292,7 @@
method public abstract boolean finishComposingText();
method public abstract int getCursorCapsMode(int);
method public abstract android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int);
+ method public abstract android.os.Handler getHandler();
method public abstract java.lang.CharSequence getSelectedText(int);
method public abstract java.lang.CharSequence getTextAfterCursor(int, int);
method public abstract java.lang.CharSequence getTextBeforeCursor(int, int);
@@ -47303,6 +47324,7 @@
method public boolean finishComposingText();
method public int getCursorCapsMode(int);
method public android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int);
+ method public android.os.Handler getHandler();
method public java.lang.CharSequence getSelectedText(int);
method public java.lang.CharSequence getTextAfterCursor(int, int);
method public java.lang.CharSequence getTextBeforeCursor(int, int);
@@ -48553,6 +48575,7 @@
method public abstract void onConfigurationChanged(android.content.res.Configuration);
method public abstract android.view.inputmethod.InputConnection onCreateInputConnection(android.view.inputmethod.EditorInfo);
method public abstract void onDetachedFromWindow();
+ method public abstract boolean onDragEvent(android.view.DragEvent);
method public abstract void onDraw(android.graphics.Canvas);
method public abstract void onDrawVerticalScrollBar(android.graphics.Canvas, android.graphics.drawable.Drawable, int, int, int, int);
method public abstract void onFinishTemporaryDetach();
@@ -49142,7 +49165,9 @@
method public long getBase();
method public java.lang.String getFormat();
method public android.widget.Chronometer.OnChronometerTickListener getOnChronometerTickListener();
+ method public boolean isCountDown();
method public void setBase(long);
+ method public void setCountDown(boolean);
method public void setFormat(java.lang.String);
method public void setOnChronometerTickListener(android.widget.Chronometer.OnChronometerTickListener);
method public void start();
@@ -50234,6 +50259,7 @@
method public void setChar(int, java.lang.String, char);
method public void setCharSequence(int, java.lang.String, java.lang.CharSequence);
method public void setChronometer(int, long, java.lang.String, boolean);
+ method public void setChronometerCountsDown(int, boolean);
method public void setContentDescription(int, java.lang.CharSequence);
method public void setDisplayedChild(int, int);
method public void setDouble(int, java.lang.String, double);
@@ -53480,6 +53506,7 @@
method public static long doubleToRawLongBits(double);
method public double doubleValue();
method public float floatValue();
+ method public static int hashCode(double);
method public int intValue();
method public static boolean isInfinite(double);
method public boolean isInfinite();
@@ -53487,11 +53514,15 @@
method public boolean isNaN();
method public static double longBitsToDouble(long);
method public long longValue();
+ method public static double max(double, double);
+ method public static double min(double, double);
method public static double parseDouble(java.lang.String) throws java.lang.NumberFormatException;
+ method public static double sum(double, double);
method public static java.lang.String toHexString(double);
method public static java.lang.String toString(double);
method public static java.lang.Double valueOf(java.lang.String) throws java.lang.NumberFormatException;
method public static java.lang.Double valueOf(double);
+ field public static final int BYTES = 8; // 0x8
field public static final int MAX_EXPONENT = 1023; // 0x3ff
field public static final double MAX_VALUE = 1.7976931348623157E308;
field public static final int MIN_EXPONENT = -1022; // 0xfffffc02
@@ -53654,10 +53685,13 @@
method public static java.lang.Integer getInteger(java.lang.String);
method public static java.lang.Integer getInteger(java.lang.String, int);
method public static java.lang.Integer getInteger(java.lang.String, java.lang.Integer);
+ method public static int hashCode(int);
method public static int highestOneBit(int);
method public int intValue();
method public long longValue();
method public static int lowestOneBit(int);
+ method public static int max(int, int);
+ method public static int min(int, int);
method public static int numberOfLeadingZeros(int);
method public static int numberOfTrailingZeros(int);
method public static int parseInt(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -53667,6 +53701,7 @@
method public static int rotateLeft(int, int);
method public static int rotateRight(int, int);
method public static int signum(int);
+ method public static int sum(int, int);
method public static java.lang.String toBinaryString(int);
method public static java.lang.String toHexString(int);
method public static java.lang.String toOctalString(int);
@@ -53675,6 +53710,7 @@
method public static java.lang.Integer valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
method public static java.lang.Integer valueOf(java.lang.String) throws java.lang.NumberFormatException;
method public static java.lang.Integer valueOf(int);
+ field public static final int BYTES = 4; // 0x4
field public static final int MAX_VALUE = 2147483647; // 0x7fffffff
field public static final int MIN_VALUE = -2147483648; // 0x80000000
field public static final int SIZE = 32; // 0x20
@@ -53694,6 +53730,7 @@
}
public abstract interface Iterable {
+ method public default void forEach(java.util.function.Consumer<? super T>);
method public abstract java.util.Iterator<T> iterator();
}
@@ -53715,10 +53752,13 @@
method public static java.lang.Long getLong(java.lang.String);
method public static java.lang.Long getLong(java.lang.String, long);
method public static java.lang.Long getLong(java.lang.String, java.lang.Long);
+ method public static int hashCode(long);
method public static long highestOneBit(long);
method public int intValue();
method public long longValue();
method public static long lowestOneBit(long);
+ method public static long max(long, long);
+ method public static long min(long, long);
method public static int numberOfLeadingZeros(long);
method public static int numberOfTrailingZeros(long);
method public static long parseLong(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -53728,6 +53768,7 @@
method public static long rotateLeft(long, int);
method public static long rotateRight(long, int);
method public static int signum(long);
+ method public static long sum(long, long);
method public static java.lang.String toBinaryString(long);
method public static java.lang.String toHexString(long);
method public static java.lang.String toOctalString(long);
@@ -56146,7 +56187,7 @@
ctor public ConnectionPendingException();
}
- public abstract class DatagramChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.ByteChannel java.nio.channels.GatheringByteChannel java.nio.channels.ScatteringByteChannel {
+ public abstract class DatagramChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.ByteChannel java.nio.channels.GatheringByteChannel java.nio.channels.NetworkChannel java.nio.channels.ScatteringByteChannel {
ctor protected DatagramChannel(java.nio.channels.spi.SelectorProvider);
method public abstract java.nio.channels.DatagramChannel bind(java.net.SocketAddress) throws java.io.IOException;
method public abstract java.nio.channels.DatagramChannel connect(java.net.SocketAddress) throws java.io.IOException;
@@ -57169,6 +57210,7 @@
public abstract class Provider extends java.util.Properties {
ctor protected Provider(java.lang.String, double, java.lang.String);
+ method public synchronized void forEach(java.util.function.BiConsumer<? super java.lang.Object, ? super java.lang.Object>);
method public java.lang.String getInfo();
method public java.lang.String getName();
method public synchronized java.security.Provider.Service getService(java.lang.String, java.lang.String);
@@ -60118,6 +60160,7 @@
ctor public ArrayList(java.util.Collection<? extends E>);
method public java.lang.Object clone();
method public void ensureCapacity(int);
+ method public void forEach(java.util.function.Consumer<? super E>);
method public E get(int);
method public int size();
method public void trimToSize();
@@ -60681,6 +60724,7 @@
ctor public HashMap(java.util.Map<? extends K, ? extends V>);
method public java.lang.Object clone();
method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+ method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
}
public class HashSet extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
@@ -60705,6 +60749,7 @@
method public boolean containsValue(java.lang.Object);
method public synchronized java.util.Enumeration<V> elements();
method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+ method public synchronized void forEach(java.util.function.BiConsumer<? super K, ? super V>);
method public synchronized V get(java.lang.Object);
method public synchronized boolean isEmpty();
method public java.util.Set<K> keySet();
@@ -60723,6 +60768,7 @@
ctor public IdentityHashMap(java.util.Map<? extends K, ? extends V>);
method public java.lang.Object clone();
method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+ method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
}
public class IllegalFormatCodePointException extends java.util.IllegalFormatException {
@@ -60772,9 +60818,10 @@
}
public abstract interface Iterator {
+ method public default void forEachRemaining(java.util.function.Consumer<? super E>);
method public abstract boolean hasNext();
method public abstract E next();
- method public abstract void remove();
+ method public default void remove();
}
public class LinkedHashMap extends java.util.HashMap implements java.util.Map {
@@ -60962,6 +61009,7 @@
method public abstract boolean containsValue(java.lang.Object);
method public abstract java.util.Set<java.util.Map.Entry<K, V>> entrySet();
method public abstract boolean equals(java.lang.Object);
+ method public default void forEach(java.util.function.BiConsumer<? super K, ? super V>);
method public abstract V get(java.lang.Object);
method public abstract int hashCode();
method public abstract boolean isEmpty();
@@ -61076,6 +61124,79 @@
method public abstract void update(java.util.Observable, java.lang.Object);
}
+ public final class Optional {
+ method public static java.util.Optional<T> empty();
+ method public java.util.Optional<T> filter(java.util.function.Predicate<? super T>);
+ method public java.util.Optional<U> flatMap(java.util.function.Function<? super T, java.util.Optional<U>>);
+ method public T get();
+ method public void ifPresent(java.util.function.Consumer<? super T>);
+ method public boolean isPresent();
+ method public java.util.Optional<U> map(java.util.function.Function<? super T, ? extends U>);
+ method public static java.util.Optional<T> of(T);
+ method public static java.util.Optional<T> ofNullable(T);
+ method public T orElse(T);
+ method public T orElseGet(java.util.function.Supplier<? extends T>);
+ method public T orElseThrow(java.util.function.Supplier<? extends X>) throws java.lang.Throwable;
+ }
+
+ public final class OptionalDouble {
+ method public static java.util.OptionalDouble empty();
+ method public double getAsDouble();
+ method public void ifPresent(java.util.function.DoubleConsumer);
+ method public boolean isPresent();
+ method public static java.util.OptionalDouble of(double);
+ method public double orElse(double);
+ method public double orElseGet(java.util.function.DoubleSupplier);
+ method public double orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+ }
+
+ public final class OptionalInt {
+ method public static java.util.OptionalInt empty();
+ method public int getAsInt();
+ method public void ifPresent(java.util.function.IntConsumer);
+ method public boolean isPresent();
+ method public static java.util.OptionalInt of(int);
+ method public int orElse(int);
+ method public int orElseGet(java.util.function.IntSupplier);
+ method public int orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+ }
+
+ public final class OptionalLong {
+ method public static java.util.OptionalLong empty();
+ method public long getAsLong();
+ method public void ifPresent(java.util.function.LongConsumer);
+ method public boolean isPresent();
+ method public static java.util.OptionalLong of(long);
+ method public long orElse(long);
+ method public long orElseGet(java.util.function.LongSupplier);
+ method public long orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+ }
+
+ public abstract interface PrimitiveIterator implements java.util.Iterator {
+ method public abstract void forEachRemaining(T_CONS);
+ }
+
+ public static abstract interface PrimitiveIterator.OfDouble implements java.util.PrimitiveIterator {
+ method public default void forEachRemaining(java.util.function.DoubleConsumer);
+ method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Double>);
+ method public default java.lang.Double next();
+ method public abstract double nextDouble();
+ }
+
+ public static abstract interface PrimitiveIterator.OfInt implements java.util.PrimitiveIterator {
+ method public default void forEachRemaining(java.util.function.IntConsumer);
+ method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Integer>);
+ method public default java.lang.Integer next();
+ method public abstract int nextInt();
+ }
+
+ public static abstract interface PrimitiveIterator.OfLong implements java.util.PrimitiveIterator {
+ method public default void forEachRemaining(java.util.function.LongConsumer);
+ method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Long>);
+ method public default java.lang.Long next();
+ method public abstract long nextLong();
+ }
+
public class PriorityQueue extends java.util.AbstractQueue implements java.io.Serializable {
ctor public PriorityQueue();
ctor public PriorityQueue(int);
@@ -61247,7 +61368,6 @@
method public short nextShort();
method public short nextShort(int);
method public int radix();
- method public void remove();
method public java.util.Scanner reset();
method public java.util.Scanner skip(java.util.regex.Pattern);
method public java.util.Scanner skip(java.lang.String);
@@ -61423,6 +61543,7 @@
method public K firstKey();
method public java.util.Map.Entry<K, V> floorEntry(K);
method public K floorKey(K);
+ method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
method public java.util.NavigableMap<K, V> headMap(K, boolean);
method public java.util.SortedMap<K, V> headMap(K);
method public java.util.Map.Entry<K, V> higherEntry(K);
@@ -61505,6 +61626,7 @@
method public java.util.Enumeration<E> elements();
method public synchronized void ensureCapacity(int);
method public synchronized E firstElement();
+ method public synchronized void forEach(java.util.function.Consumer<? super E>);
method public synchronized E get(int);
method public synchronized int indexOf(java.lang.Object, int);
method public synchronized void insertElementAt(E, int);
@@ -61528,6 +61650,7 @@
ctor public WeakHashMap();
ctor public WeakHashMap(java.util.Map<? extends K, ? extends V>);
method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+ method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
}
}
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 27de913..9ebc484 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -6,6 +6,15 @@
}
+package android.app.admin {
+
+ public class DevicePolicyManager {
+ method public deprecated android.os.UserHandle createAndInitializeUser(android.content.ComponentName, java.lang.String, java.lang.String, android.content.ComponentName, android.os.Bundle);
+ method public deprecated android.os.UserHandle createUser(android.content.ComponentName, java.lang.String);
+ }
+
+}
+
package android.content.pm {
public class PackageInfo implements android.os.Parcelable {
@@ -26,7 +35,7 @@
package android.media {
- public class AudioFormat {
+ public final class AudioFormat implements android.os.Parcelable {
ctor public AudioFormat();
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 8fcb9bd..d1ed20c 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -101,7 +101,6 @@
field public static final java.lang.String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS";
field public static final java.lang.String READ_SYNC_STATS = "android.permission.READ_SYNC_STATS";
field public static final java.lang.String READ_VOICEMAIL = "com.android.voicemail.permission.READ_VOICEMAIL";
- field public static final java.lang.String READ_WRITE_CONTACT_METADATA = "android.permission.READ_WRITE_CONTACT_METADATA";
field public static final java.lang.String REBOOT = "android.permission.REBOOT";
field public static final java.lang.String RECEIVE_BOOT_COMPLETED = "android.permission.RECEIVE_BOOT_COMPLETED";
field public static final java.lang.String RECEIVE_EMERGENCY_BROADCAST = "android.permission.RECEIVE_EMERGENCY_BROADCAST";
@@ -300,6 +299,7 @@
field public static final int backgroundTint = 16843883; // 0x101046b
field public static final int backgroundTintMode = 16843884; // 0x101046c
field public static final int backupAgent = 16843391; // 0x101027f
+ field public static final int backupInForeground = 16844059; // 0x101051b
field public static final int banner = 16843762; // 0x10103f2
field public static final int baseline = 16843548; // 0x101031c
field public static final int baselineAlignBottom = 16843042; // 0x1010122
@@ -337,6 +337,7 @@
field public static final int calendarViewStyle = 16843613; // 0x101035d
field public static final int canControlMagnification = 16844040; // 0x1010508
field public static final int canPerformGestures = 16844046; // 0x101050e
+ field public static final int canRecord = 16844061; // 0x101051d
field public static final int canRequestEnhancedWebAccessibility = 16843736; // 0x10103d8
field public static final int canRequestFilterKeyEvents = 16843737; // 0x10103d9
field public static final int canRequestTouchExplorationMode = 16843735; // 0x10103d7
@@ -422,6 +423,7 @@
field public static final int controlX2 = 16843774; // 0x10103fe
field public static final int controlY1 = 16843773; // 0x10103fd
field public static final int controlY2 = 16843775; // 0x10103ff
+ field public static final int countDown = 16844060; // 0x101051c
field public static final int country = 16843962; // 0x10104ba
field public static final int cropToPadding = 16843043; // 0x1010123
field public static final int cursorVisible = 16843090; // 0x1010152
@@ -1357,6 +1359,7 @@
field public static final int trimPathEnd = 16843785; // 0x1010409
field public static final int trimPathOffset = 16843786; // 0x101040a
field public static final int trimPathStart = 16843784; // 0x1010408
+ field public static final int tunerCount = 16844062; // 0x101051e
field public static final int type = 16843169; // 0x10101a1
field public static final int typeface = 16842902; // 0x1010096
field public static final int uiOptions = 16843672; // 0x1010398
@@ -2662,8 +2665,11 @@
field public static final int GLOBAL_ACTION_POWER_DIALOG = 6; // 0x6
field public static final int GLOBAL_ACTION_QUICK_SETTINGS = 5; // 0x5
field public static final int GLOBAL_ACTION_RECENTS = 3; // 0x3
+ field public static final int GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN = 7; // 0x7
field public static final java.lang.String SERVICE_INTERFACE = "android.accessibilityservice.AccessibilityService";
field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
+ field public static final int SHOW_MODE_AUTO = 0; // 0x0
+ field public static final int SHOW_MODE_HIDDEN = 1; // 0x1
}
public static abstract class AccessibilityService.GestureResultCallback {
@@ -4122,13 +4128,12 @@
field public java.lang.String serviceDetails;
}
- public class AutomaticZenRule implements android.os.Parcelable {
+ public final class AutomaticZenRule implements android.os.Parcelable {
ctor public AutomaticZenRule(java.lang.String, android.content.ComponentName, android.net.Uri, int, boolean);
ctor public AutomaticZenRule(android.os.Parcel);
method public int describeContents();
method public android.net.Uri getConditionId();
method public long getCreationTime();
- method public java.lang.String getId();
method public int getInterruptionFilter();
method public java.lang.String getName();
method public android.content.ComponentName getOwner();
@@ -4275,7 +4280,6 @@
public class DownloadManager {
method public long addCompletedDownload(java.lang.String, java.lang.String, boolean, java.lang.String, java.lang.String, long, boolean);
- method public long addCompletedDownload(java.lang.String, java.lang.String, boolean, java.lang.String, java.lang.String, long, boolean, android.net.Uri, android.net.Uri);
method public long enqueue(android.app.DownloadManager.Request);
method public static java.lang.Long getMaxBytesOverMobile(android.content.Context);
method public java.lang.String getMimeTypeForDownloadedFile(long);
@@ -4879,7 +4883,6 @@
method public android.graphics.drawable.Icon getLargeIcon();
method public android.graphics.drawable.Icon getSmallIcon();
method public java.lang.String getSortKey();
- method public android.app.Notification.Topic getTopic();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT;
field public static final java.lang.String CATEGORY_ALARM = "alarm";
@@ -4905,6 +4908,7 @@
field public static final int DEFAULT_VIBRATE = 2; // 0x2
field public static final java.lang.String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri";
field public static final java.lang.String EXTRA_BIG_TEXT = "android.bigText";
+ field public static final java.lang.String EXTRA_CHRONOMETER_COUNTS_DOWN = "android.chronometerCountsDown";
field public static final java.lang.String EXTRA_COMPACT_ACTIONS = "android.compactActions";
field public static final java.lang.String EXTRA_INFO_TEXT = "android.infoText";
field public static final java.lang.String EXTRA_LARGE_ICON = "android.largeIcon";
@@ -4943,7 +4947,6 @@
field public static final int PRIORITY_MAX = 2; // 0x2
field public static final int PRIORITY_MIN = -2; // 0xfffffffe
field public static final deprecated int STREAM_DEFAULT = -1; // 0xffffffff
- field public static final java.lang.String TOPIC_DEFAULT = "system_default_topic";
field public static final int VISIBILITY_PRIVATE = 0; // 0x0
field public static final int VISIBILITY_PUBLIC = 1; // 0x1
field public static final int VISIBILITY_SECRET = -1; // 0xffffffff
@@ -5047,16 +5050,17 @@
method public android.app.Notification.Builder addExtras(android.os.Bundle);
method public android.app.Notification.Builder addPerson(java.lang.String);
method public android.app.Notification build();
+ method public android.widget.RemoteViews createBigContentView();
+ method public android.widget.RemoteViews createContentView();
+ method public android.widget.RemoteViews createHeadsUpContentView();
method public android.app.Notification.Builder extend(android.app.Notification.Extender);
method public android.os.Bundle getExtras();
method public deprecated android.app.Notification getNotification();
- method public android.widget.RemoteViews makeBigContentView();
- method public android.widget.RemoteViews makeContentView();
- method public android.widget.RemoteViews makeHeadsUpContentView();
method public static android.app.Notification.Builder recoverBuilder(android.content.Context, android.app.Notification);
method public android.app.Notification.Builder setActions(android.app.Notification.Action...);
method public android.app.Notification.Builder setAutoCancel(boolean);
method public android.app.Notification.Builder setCategory(java.lang.String);
+ method public android.app.Notification.Builder setChronometerCountsDown(boolean);
method public android.app.Notification.Builder setColor(int);
method public deprecated android.app.Notification.Builder setContent(android.widget.RemoteViews);
method public android.app.Notification.Builder setContentInfo(java.lang.CharSequence);
@@ -5095,7 +5099,6 @@
method public android.app.Notification.Builder setSubText(java.lang.CharSequence);
method public android.app.Notification.Builder setTicker(java.lang.CharSequence);
method public deprecated android.app.Notification.Builder setTicker(java.lang.CharSequence, android.widget.RemoteViews);
- method public android.app.Notification.Builder setTopic(android.app.Notification.Topic);
method public android.app.Notification.Builder setUsesChronometer(boolean);
method public android.app.Notification.Builder setVibrate(long[]);
method public android.app.Notification.Builder setVisibility(int);
@@ -5133,6 +5136,16 @@
method public android.app.PendingIntent getReplyPendingIntent();
}
+ public static class Notification.DecoratedCustomViewStyle extends android.app.Notification.Style {
+ ctor public Notification.DecoratedCustomViewStyle();
+ ctor public Notification.DecoratedCustomViewStyle(android.app.Notification.Builder);
+ }
+
+ public static class Notification.DecoratedMediaCustomViewStyle extends android.app.Notification.MediaStyle {
+ ctor public Notification.DecoratedMediaCustomViewStyle();
+ ctor public Notification.DecoratedMediaCustomViewStyle(android.app.Notification.Builder);
+ }
+
public static abstract interface Notification.Extender {
method public abstract android.app.Notification.Builder extend(android.app.Notification.Builder);
}
@@ -5163,16 +5176,6 @@
field protected android.app.Notification.Builder mBuilder;
}
- public static class Notification.Topic implements android.os.Parcelable {
- ctor public Notification.Topic(java.lang.String, java.lang.CharSequence);
- method public android.app.Notification.Topic clone();
- method public int describeContents();
- method public java.lang.String getId();
- method public java.lang.CharSequence getLabel();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.app.Notification.Topic> CREATOR;
- }
-
public static final class Notification.WearableExtender implements android.app.Notification.Extender {
ctor public Notification.WearableExtender();
ctor public Notification.WearableExtender(android.app.Notification);
@@ -5226,16 +5229,16 @@
}
public class NotificationManager {
- method public android.app.AutomaticZenRule addAutomaticZenRule(android.app.AutomaticZenRule);
+ method public java.lang.String addAutomaticZenRule(android.app.AutomaticZenRule);
method public boolean areNotificationsEnabled();
method public void cancel(int);
method public void cancel(java.lang.String, int);
method public void cancelAll();
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String);
- method public java.util.List<android.app.AutomaticZenRule> getAutomaticZenRules();
+ method public java.util.Map<java.lang.String, android.app.AutomaticZenRule> getAutomaticZenRules();
method public final int getCurrentInterruptionFilter();
- method public int getImportance(java.lang.String);
+ method public int getImportance();
method public android.app.NotificationManager.Policy getNotificationPolicy();
method public boolean isNotificationPolicyAccessGranted();
method public void notify(int, android.app.Notification);
@@ -5243,7 +5246,7 @@
method public boolean removeAutomaticZenRule(java.lang.String);
method public final void setInterruptionFilter(int);
method public void setNotificationPolicy(android.app.NotificationManager.Policy);
- method public boolean updateAutomaticZenRule(android.app.AutomaticZenRule);
+ method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule);
field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
field public static final java.lang.String ACTION_NOTIFICATION_POLICY_CHANGED = "android.app.action.NOTIFICATION_POLICY_CHANGED";
@@ -5255,7 +5258,7 @@
}
public static class NotificationManager.Policy implements android.os.Parcelable {
- ctor public deprecated NotificationManager.Policy(int, int, int);
+ ctor public NotificationManager.Policy(int, int, int);
ctor public NotificationManager.Policy(int, int, int, int);
method public int describeContents();
method public static java.lang.String priorityCategoriesToString(int);
@@ -5712,6 +5715,7 @@
public class WallpaperManager {
method public void clear() throws java.io.IOException;
+ method public void clear(int) throws java.io.IOException;
method public void clearWallpaperOffsets(android.os.IBinder);
method public void forgetLoadedWallpaper();
method public android.graphics.drawable.Drawable getBuiltInDrawable();
@@ -5722,6 +5726,7 @@
method public android.graphics.drawable.Drawable getDrawable();
method public android.graphics.drawable.Drawable getFastDrawable();
method public static android.app.WallpaperManager getInstance(android.content.Context);
+ method public android.os.ParcelFileDescriptor getWallpaperFile(int);
method public android.app.WallpaperInfo getWallpaperInfo();
method public boolean hasResourceWallpaper(int);
method public boolean isWallpaperSettingAllowed();
@@ -5832,9 +5837,7 @@
method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
method public void clearProfileOwner(android.content.ComponentName);
method public void clearUserRestriction(android.content.ComponentName, java.lang.String);
- method public deprecated android.os.UserHandle createAndInitializeUser(android.content.ComponentName, java.lang.String, java.lang.String, android.content.ComponentName, android.os.Bundle);
method public android.os.UserHandle createAndManageUser(android.content.ComponentName, java.lang.String, android.content.ComponentName, android.os.PersistableBundle, int);
- method public deprecated android.os.UserHandle createUser(android.content.ComponentName, java.lang.String);
method public void enableSystemApp(android.content.ComponentName, java.lang.String);
method public int enableSystemApp(android.content.ComponentName, android.content.Intent);
method public java.lang.String[] getAccountTypesWithManagementDisabled();
@@ -5889,6 +5892,7 @@
method public boolean hasGrantedPolicy(android.content.ComponentName, int);
method public boolean installCaCert(android.content.ComponentName, byte[]);
method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate, java.lang.String);
+ method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate, java.lang.String, boolean);
method public boolean isActivePasswordSufficient();
method public boolean isAdminActive(android.content.ComponentName);
method public boolean isApplicationHidden(android.content.ComponentName, java.lang.String);
@@ -6591,7 +6595,7 @@
field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
}
- public static class SecurityLog.SecurityEvent implements android.os.Parcelable {
+ public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
method public int describeContents();
method public java.lang.Object getData();
method public int getTag();
@@ -7335,15 +7339,6 @@
field public static final int TYPE_SCO = 2; // 0x2
}
- public class OobData implements android.os.Parcelable {
- ctor public OobData();
- method public int describeContents();
- method public byte[] getSecurityManagerTk();
- method public void setSecurityManagerTk(byte[]);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.bluetooth.OobData> CREATOR;
- }
-
}
package android.bluetooth.le {
@@ -8476,6 +8471,7 @@
field public static final java.lang.String ACTION_AIRPLANE_MODE_CHANGED = "android.intent.action.AIRPLANE_MODE";
field public static final java.lang.String ACTION_ALL_APPS = "android.intent.action.ALL_APPS";
field public static final java.lang.String ACTION_ANSWER = "android.intent.action.ANSWER";
+ field public static final java.lang.String ACTION_APPLICATION_PREFERENCES = "android.intent.action.APPLICATION_PREFERENCES";
field public static final java.lang.String ACTION_APPLICATION_RESTRICTIONS_CHANGED = "android.intent.action.APPLICATION_RESTRICTIONS_CHANGED";
field public static final java.lang.String ACTION_APP_ERROR = "android.intent.action.APP_ERROR";
field public static final java.lang.String ACTION_ASSIST = "android.intent.action.ASSIST";
@@ -9794,6 +9790,8 @@
field public static final java.lang.String FEATURE_VERIFIED_BOOT = "android.software.verified_boot";
field public static final java.lang.String FEATURE_VR_MODE = "android.software.vr.mode";
field public static final java.lang.String FEATURE_VR_MODE_HIGH_PERFORMANCE = "android.hardware.vr.high_performance";
+ field public static final java.lang.String FEATURE_VULKAN_HARDWARE_LEVEL = "android.hardware.vulkan.level";
+ field public static final java.lang.String FEATURE_VULKAN_HARDWARE_VERSION = "android.hardware.vulkan.version";
field public static final java.lang.String FEATURE_WATCH = "android.hardware.type.watch";
field public static final java.lang.String FEATURE_WEBVIEW = "android.software.webview";
field public static final java.lang.String FEATURE_WIFI = "android.hardware.wifi";
@@ -10478,7 +10476,6 @@
method public boolean hasNext();
method public java.util.Iterator<android.database.CursorJoiner.Result> iterator();
method public android.database.CursorJoiner.Result next();
- method public void remove();
}
public static final class CursorJoiner.Result extends java.lang.Enum {
@@ -11955,6 +11952,8 @@
ctor public Outline(android.graphics.Outline);
method public boolean canClip();
method public float getAlpha();
+ method public float getRadius();
+ method public boolean getRect(android.graphics.Rect);
method public boolean isEmpty();
method public void offset(int, int);
method public void set(android.graphics.Outline);
@@ -12982,12 +12981,10 @@
ctor public deprecated NinePatchDrawable(android.graphics.NinePatch);
ctor public NinePatchDrawable(android.content.res.Resources, android.graphics.NinePatch);
method public void draw(android.graphics.Canvas);
- method public android.graphics.NinePatch getNinePatch();
method public int getOpacity();
method public android.graphics.Paint getPaint();
method public void setAlpha(int);
method public void setColorFilter(android.graphics.ColorFilter);
- method public void setNinePatch(android.graphics.NinePatch);
method public void setTargetDensity(android.graphics.Canvas);
method public void setTargetDensity(android.util.DisplayMetrics);
method public void setTargetDensity(int);
@@ -13210,8 +13207,8 @@
method public final void takePicture(android.hardware.Camera.ShutterCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback);
method public final void takePicture(android.hardware.Camera.ShutterCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback);
method public final void unlock();
- field public static final java.lang.String ACTION_NEW_PICTURE = "android.hardware.action.NEW_PICTURE";
- field public static final java.lang.String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO";
+ field public static final deprecated java.lang.String ACTION_NEW_PICTURE = "android.hardware.action.NEW_PICTURE";
+ field public static final deprecated java.lang.String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO";
field public static final int CAMERA_ERROR_EVICTED = 2; // 0x2
field public static final int CAMERA_ERROR_SERVER_DIED = 100; // 0x64
field public static final int CAMERA_ERROR_UNKNOWN = 1; // 0x1
@@ -19168,178 +19165,110 @@
public final class GnssClock implements android.os.Parcelable {
method public int describeContents();
- method public double getBiasInNs();
- method public double getBiasUncertaintyInNs();
- method public double getDriftInNsPerSec();
- method public double getDriftUncertaintyInNsPerSec();
- method public long getFullBiasInNs();
- method public short getLeapSecond();
- method public long getTimeInNs();
- method public long getTimeOfLastHwClockDiscontinuityInNs();
- method public double getTimeUncertaintyInNs();
- method public byte getType();
- method public boolean hasBiasInNs();
- method public boolean hasBiasUncertaintyInNs();
- method public boolean hasDriftInNsPerSec();
- method public boolean hasDriftUncertaintyInNsPerSec();
- method public boolean hasFullBiasInNs();
+ method public double getBiasNanos();
+ method public double getBiasUncertaintyNanos();
+ method public double getDriftNanosPerSecond();
+ method public double getDriftUncertaintyNanosPerSecond();
+ method public long getFullBiasNanos();
+ method public int getHardwareClockDiscontinuityCount();
+ method public int getLeapSecond();
+ method public long getTimeNanos();
+ method public double getTimeUncertaintyNanos();
+ method public boolean hasBiasNanos();
+ method public boolean hasBiasUncertaintyNanos();
+ method public boolean hasDriftNanosPerSecond();
+ method public boolean hasDriftUncertaintyNanosPerSecond();
+ method public boolean hasFullBiasNanos();
method public boolean hasLeapSecond();
- method public boolean hasTimeUncertaintyInNs();
+ method public boolean hasTimeUncertaintyNanos();
method public void reset();
- method public void resetBiasInNs();
- method public void resetBiasUncertaintyInNs();
- method public void resetDriftInNsPerSec();
- method public void resetDriftUncertaintyInNsPerSec();
- method public void resetFullBiasInNs();
+ method public void resetBiasNanos();
+ method public void resetBiasUncertaintyNanos();
+ method public void resetDriftNanosPerSecond();
+ method public void resetDriftUncertaintyNanosPerSecond();
+ method public void resetFullBiasNanos();
method public void resetLeapSecond();
- method public void resetTimeUncertaintyInNs();
+ method public void resetTimeUncertaintyNanos();
method public void set(android.location.GnssClock);
- method public void setBiasInNs(double);
- method public void setBiasUncertaintyInNs(double);
- method public void setDriftInNsPerSec(double);
- method public void setDriftUncertaintyInNsPerSec(double);
- method public void setFullBiasInNs(long);
- method public void setLeapSecond(short);
- method public void setTimeInNs(long);
- method public void setTimeOfLastHwClockDiscontinuityInNs(long);
- method public void setTimeUncertaintyInNs(double);
- method public void setType(byte);
+ method public void setBiasNanos(double);
+ method public void setBiasUncertaintyNanos(double);
+ method public void setDriftNanosPerSecond(double);
+ method public void setDriftUncertaintyNanosPerSecond(double);
+ method public void setFullBiasNanos(long);
+ method public void setHardwareClockDiscontinuityCount(int);
+ method public void setLeapSecond(int);
+ method public void setTimeNanos(long);
+ method public void setTimeUncertaintyNanos(double);
method public void writeToParcel(android.os.Parcel, int);
- field public static final byte CLOCK_TYPE_GPS_TIME = 2; // 0x2
- field public static final byte CLOCK_TYPE_LOCAL_HW_TIME = 1; // 0x1
- field public static final byte CLOCK_TYPE_UNKNOWN = 0; // 0x0
field public static final android.os.Parcelable.Creator<android.location.GnssClock> CREATOR;
}
- public static abstract class GnssClock.GnssClockType implements java.lang.annotation.Annotation {
- }
-
public final class GnssMeasurement implements android.os.Parcelable {
method public int describeContents();
- method public double getAccumulatedDeltaRangeInMeters();
- method public short getAccumulatedDeltaRangeState();
- method public double getAccumulatedDeltaRangeUncertaintyInMeters();
- method public double getAzimuthInDeg();
- method public double getAzimuthUncertaintyInDeg();
- method public int getBitNumber();
+ method public double getAccumulatedDeltaRangeMeters();
+ method public int getAccumulatedDeltaRangeState();
+ method public double getAccumulatedDeltaRangeUncertaintyMeters();
method public long getCarrierCycles();
- method public float getCarrierFrequencyInHz();
+ method public float getCarrierFrequencyHz();
method public double getCarrierPhase();
method public double getCarrierPhaseUncertainty();
- method public double getCn0InDbHz();
- method public double getCodePhaseInChips();
- method public double getCodePhaseUncertaintyInChips();
- method public double getDopplerShiftInHz();
- method public double getDopplerShiftUncertaintyInHz();
- method public double getElevationInDeg();
- method public double getElevationUncertaintyInDeg();
- method public byte getLossOfLock();
- method public byte getMultipathIndicator();
- method public double getPseudorangeInMeters();
- method public double getPseudorangeRateCarrierInMetersPerSec();
- method public double getPseudorangeRateCarrierUncertaintyInMetersPerSec();
- method public double getPseudorangeRateInMetersPerSec();
- method public double getPseudorangeRateUncertaintyInMetersPerSec();
- method public double getPseudorangeUncertaintyInMeters();
- method public long getReceivedGpsTowInNs();
- method public long getReceivedGpsTowUncertaintyInNs();
+ method public double getCn0DbHz();
+ method public int getConstellationType();
+ method public int getMultipathIndicator();
+ method public double getPseudorangeRateMetersPerSecond();
+ method public double getPseudorangeRateUncertaintyMetersPerSecond();
+ method public long getReceivedSvTimeNanos();
+ method public long getReceivedSvTimeUncertaintyNanos();
method public double getSnrInDb();
- method public short getState();
- method public short getSvid();
- method public short getTimeFromLastBitInMs();
- method public double getTimeOffsetInNs();
- method public boolean hasAzimuthInDeg();
- method public boolean hasAzimuthUncertaintyInDeg();
- method public boolean hasBitNumber();
+ method public int getState();
+ method public int getSvid();
+ method public double getTimeOffsetNanos();
method public boolean hasCarrierCycles();
- method public boolean hasCarrierFrequencyInHz();
+ method public boolean hasCarrierFrequencyHz();
method public boolean hasCarrierPhase();
method public boolean hasCarrierPhaseUncertainty();
- method public boolean hasCodePhaseInChips();
- method public boolean hasCodePhaseUncertaintyInChips();
- method public boolean hasDopplerShiftInHz();
- method public boolean hasDopplerShiftUncertaintyInHz();
- method public boolean hasElevationInDeg();
- method public boolean hasElevationUncertaintyInDeg();
- method public boolean hasPseudorangeInMeters();
- method public boolean hasPseudorangeUncertaintyInMeters();
method public boolean hasSnrInDb();
- method public boolean hasTimeFromLastBitInMs();
method public boolean isPseudorangeRateCorrected();
- method public boolean isUsedInFix();
method public void reset();
- method public void resetAzimuthInDeg();
- method public void resetAzimuthUncertaintyInDeg();
- method public void resetBitNumber();
method public void resetCarrierCycles();
- method public void resetCarrierFrequencyInHz();
+ method public void resetCarrierFrequencyHz();
method public void resetCarrierPhase();
method public void resetCarrierPhaseUncertainty();
- method public void resetCodePhaseInChips();
- method public void resetCodePhaseUncertaintyInChips();
- method public void resetDopplerShiftInHz();
- method public void resetDopplerShiftUncertaintyInHz();
- method public void resetElevationInDeg();
- method public void resetElevationUncertaintyInDeg();
- method public void resetPseudorangeInMeters();
- method public void resetPseudorangeUncertaintyInMeters();
method public void resetSnrInDb();
- method public void resetTimeFromLastBitInMs();
method public void set(android.location.GnssMeasurement);
- method public void setAccumulatedDeltaRangeInMeters(double);
- method public void setAccumulatedDeltaRangeState(short);
- method public void setAccumulatedDeltaRangeUncertaintyInMeters(double);
- method public void setAzimuthInDeg(double);
- method public void setAzimuthUncertaintyInDeg(double);
- method public void setBitNumber(int);
+ method public void setAccumulatedDeltaRangeMeters(double);
+ method public void setAccumulatedDeltaRangeState(int);
+ method public void setAccumulatedDeltaRangeUncertaintyMeters(double);
method public void setCarrierCycles(long);
- method public void setCarrierFrequencyInHz(float);
+ method public void setCarrierFrequencyHz(float);
method public void setCarrierPhase(double);
method public void setCarrierPhaseUncertainty(double);
- method public void setCn0InDbHz(double);
- method public void setCodePhaseInChips(double);
- method public void setCodePhaseUncertaintyInChips(double);
- method public void setDopplerShiftInHz(double);
- method public void setDopplerShiftUncertaintyInHz(double);
- method public void setElevationInDeg(double);
- method public void setElevationUncertaintyInDeg(double);
- method public void setLossOfLock(byte);
- method public void setMultipathIndicator(byte);
- method public void setPseudorangeInMeters(double);
- method public void setPseudorangeRateCarrierInMetersPerSec(double);
- method public void setPseudorangeRateCarrierUncertaintyInMetersPerSec(double);
- method public void setPseudorangeRateInMetersPerSec(double);
- method public void setPseudorangeRateUncertaintyInMetersPerSec(double);
- method public void setPseudorangeUncertaintyInMeters(double);
- method public void setReceivedGpsTowInNs(long);
- method public void setReceivedGpsTowUncertaintyInNs(long);
+ method public void setCn0DbHz(double);
+ method public void setConstellationType(int);
+ method public void setMultipathIndicator(int);
+ method public void setPseudorangeRateMetersPerSecond(double);
+ method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
+ method public void setReceivedSvTimeNanos(long);
+ method public void setReceivedSvTimeUncertaintyNanos(long);
method public void setSnrInDb(double);
- method public void setState(short);
- method public void setSvid(short);
- method public void setTimeFromLastBitInMs(short);
- method public void setTimeOffsetInNs(double);
- method public void setUsedInFix(boolean);
+ method public void setState(int);
+ method public void setSvid(int);
+ method public void setTimeOffsetNanos(double);
method public void writeToParcel(android.os.Parcel, int);
- field public static final short ADR_STATE_CYCLE_SLIP = 4; // 0x4
- field public static final short ADR_STATE_RESET = 2; // 0x2
- field public static final short ADR_STATE_UNKNOWN = 0; // 0x0
- field public static final short ADR_STATE_VALID = 1; // 0x1
+ field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
+ field public static final int ADR_STATE_RESET = 2; // 0x2
+ field public static final int ADR_STATE_UNKNOWN = 0; // 0x0
+ field public static final int ADR_STATE_VALID = 1; // 0x1
field public static final android.os.Parcelable.Creator<android.location.GnssMeasurement> CREATOR;
- field public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2; // 0x2
- field public static final byte LOSS_OF_LOCK_OK = 1; // 0x1
- field public static final byte LOSS_OF_LOCK_UNKNOWN = 0; // 0x0
- field public static final byte MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
- field public static final byte MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
- field public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
- field public static final short STATE_BIT_SYNC = 2; // 0x2
- field public static final short STATE_CODE_LOCK = 1; // 0x1
- field public static final short STATE_MSEC_AMBIGUOUS = 16; // 0x10
- field public static final short STATE_SUBFRAME_SYNC = 4; // 0x4
- field public static final short STATE_TOW_DECODED = 8; // 0x8
- field public static final short STATE_UNKNOWN = 0; // 0x0
- }
-
- public static abstract class GnssMeasurement.LossOfLockStatus implements java.lang.annotation.Annotation {
+ field public static final int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
+ field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+ field public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
+ field public static final int STATE_BIT_SYNC = 2; // 0x2
+ field public static final int STATE_CODE_LOCK = 1; // 0x1
+ field public static final int STATE_MSEC_AMBIGUOUS = 16; // 0x10
+ field public static final int STATE_SUBFRAME_SYNC = 4; // 0x4
+ field public static final int STATE_TOW_DECODED = 8; // 0x8
+ field public static final int STATE_UNKNOWN = 0; // 0x0
}
public static abstract class GnssMeasurement.MultipathIndicator implements java.lang.annotation.Annotation {
@@ -19352,7 +19281,7 @@
method public java.util.Collection<android.location.GnssMeasurement> getMeasurements();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementsEvent> CREATOR;
- field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+ field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
field public static final int STATUS_READY = 1; // 0x1
}
@@ -19369,29 +19298,34 @@
public final class GnssNavigationMessage implements android.os.Parcelable {
method public int describeContents();
method public byte[] getData();
- method public short getMessageId();
- method public short getStatus();
- method public short getSubmessageId();
- method public short getSvid();
- method public byte getType();
+ method public int getMessageId();
+ method public int getStatus();
+ method public int getSubmessageId();
+ method public int getSvid();
+ method public int getType();
method public void reset();
method public void set(android.location.GnssNavigationMessage);
method public void setData(byte[]);
- method public void setMessageId(short);
- method public void setStatus(short);
- method public void setSubmessageId(short);
- method public void setSvid(short);
- method public void setType(byte);
+ method public void setMessageId(int);
+ method public void setStatus(int);
+ method public void setSubmessageId(int);
+ method public void setSvid(int);
+ method public void setType(int);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
- field public static final byte MESSAGE_TYPE_CNAV2 = 4; // 0x4
- field public static final byte MESSAGE_TYPE_L1CA = 1; // 0x1
- field public static final byte MESSAGE_TYPE_L2CNAV = 2; // 0x2
- field public static final byte MESSAGE_TYPE_L5CNAV = 3; // 0x3
- field public static final byte MESSAGE_TYPE_UNKNOWN = 0; // 0x0
- field public static final short STATUS_PARITY_PASSED = 1; // 0x1
- field public static final short STATUS_PARITY_REBUILT = 2; // 0x2
- field public static final short STATUS_UNKNOWN = 0; // 0x0
+ field public static final int STATUS_PARITY_PASSED = 1; // 0x1
+ field public static final int STATUS_PARITY_REBUILT = 2; // 0x2
+ field public static final int STATUS_UNKNOWN = 0; // 0x0
+ field public static final int TYPE_BDS_D1 = 1281; // 0x501
+ field public static final int TYPE_BDS_D2 = 1282; // 0x502
+ field public static final int TYPE_GAL_F = 1538; // 0x602
+ field public static final int TYPE_GAL_I = 1537; // 0x601
+ field public static final int TYPE_GLO_L1CA = 769; // 0x301
+ field public static final int TYPE_GPS_CNAV2 = 260; // 0x104
+ field public static final int TYPE_GPS_L1CA = 257; // 0x101
+ field public static final int TYPE_GPS_L2CNAV = 258; // 0x102
+ field public static final int TYPE_GPS_L5CNAV = 259; // 0x103
+ field public static final int TYPE_UNKNOWN = 0; // 0x0
}
public static abstract class GnssNavigationMessage.GnssNavigationMessageType implements java.lang.annotation.Annotation {
@@ -19403,7 +19337,7 @@
method public android.location.GnssNavigationMessage getNavigationMessage();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessageEvent> CREATOR;
- field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+ field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
field public static final int STATUS_READY = 1; // 0x1
}
@@ -19422,11 +19356,11 @@
}
public final class GnssStatus {
- method public float getAzimuth(int);
+ method public float getAzimuthDegrees(int);
+ method public float getCn0DbHz(int);
method public int getConstellationType(int);
- method public float getElevation(int);
+ method public float getElevationDegrees(int);
method public int getNumSatellites();
- method public float getSnr(int);
method public int getSvid(int);
method public boolean hasAlmanac(int);
method public boolean hasEphemeris(int);
@@ -19440,6 +19374,9 @@
field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
}
+ public static abstract class GnssStatus.ConstellationType implements java.lang.annotation.Annotation {
+ }
+
public abstract class GnssStatusCallback {
ctor public GnssStatusCallback();
method public void onFirstFix(int);
@@ -19543,15 +19480,15 @@
method public void clearTestProviderStatus(java.lang.String);
method public java.util.List<java.lang.String> getAllProviders();
method public java.lang.String getBestProvider(android.location.Criteria, boolean);
+ method public int getGnssYearOfHardware();
method public deprecated android.location.GpsStatus getGpsStatus(android.location.GpsStatus);
- method public int getGpsYearOfHardware();
method public android.location.Location getLastKnownLocation(java.lang.String);
method public android.location.LocationProvider getProvider(java.lang.String);
method public java.util.List<java.lang.String> getProviders(boolean);
method public java.util.List<java.lang.String> getProviders(android.location.Criteria, boolean);
method public boolean isProviderEnabled(java.lang.String);
- method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
- method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
+ method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
+ method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback, android.os.Handler);
method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback);
@@ -19576,7 +19513,7 @@
method public void setTestProviderEnabled(java.lang.String, boolean);
method public void setTestProviderLocation(java.lang.String, android.location.Location);
method public void setTestProviderStatus(java.lang.String, int, android.os.Bundle, long);
- method public void unregisterGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
+ method public void unregisterGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
field public static final java.lang.String GPS_PROVIDER = "gps";
@@ -19696,6 +19633,7 @@
field public static final int TYPE_BUILTIN_EARPIECE = 1; // 0x1
field public static final int TYPE_BUILTIN_MIC = 15; // 0xf
field public static final int TYPE_BUILTIN_SPEAKER = 2; // 0x2
+ field public static final int TYPE_BUS = 21; // 0x15
field public static final int TYPE_DOCK = 13; // 0xd
field public static final int TYPE_FM = 14; // 0xe
field public static final int TYPE_FM_TUNER = 16; // 0x10
@@ -19713,12 +19651,14 @@
field public static final int TYPE_WIRED_HEADSET = 3; // 0x3
}
- public class AudioFormat {
+ public final class AudioFormat implements android.os.Parcelable {
+ method public int describeContents();
method public int getChannelCount();
method public int getChannelIndexMask();
method public int getChannelMask();
method public int getEncoding();
method public int getSampleRate();
+ method public void writeToParcel(android.os.Parcel, int);
field public static final deprecated int CHANNEL_CONFIGURATION_DEFAULT = 1; // 0x1
field public static final deprecated int CHANNEL_CONFIGURATION_INVALID = 0; // 0x0
field public static final deprecated int CHANNEL_CONFIGURATION_MONO = 2; // 0x2
@@ -19760,6 +19700,7 @@
field public static final int CHANNEL_OUT_SIDE_RIGHT = 4096; // 0x1000
field public static final int CHANNEL_OUT_STEREO = 12; // 0xc
field public static final int CHANNEL_OUT_SURROUND = 1052; // 0x41c
+ field public static final android.os.Parcelable.Creator<android.media.AudioFormat> CREATOR;
field public static final int ENCODING_AC3 = 5; // 0x5
field public static final int ENCODING_DEFAULT = 1; // 0x1
field public static final int ENCODING_DTS = 7; // 0x7
@@ -19770,6 +19711,7 @@
field public static final int ENCODING_PCM_16BIT = 2; // 0x2
field public static final int ENCODING_PCM_8BIT = 3; // 0x3
field public static final int ENCODING_PCM_FLOAT = 4; // 0x4
+ field public static final int SAMPLE_RATE_UNSPECIFIED = 0; // 0x0
}
public static class AudioFormat.Builder {
@@ -19935,7 +19877,7 @@
public static abstract class AudioManager.AudioRecordingCallback {
ctor public AudioManager.AudioRecordingCallback();
- method public void onRecordConfigChanged();
+ method public void onRecordConfigChanged(android.media.AudioRecordConfiguration[]);
}
public static abstract interface AudioManager.OnAudioFocusChangeListener {
@@ -20009,7 +19951,7 @@
method public abstract void onRoutingChanged(android.media.AudioRecord);
}
- public class AudioRecordConfiguration implements android.os.Parcelable {
+ public final class AudioRecordConfiguration implements android.os.Parcelable {
method public int describeContents();
method public android.media.AudioDeviceInfo getAudioDevice();
method public int getClientAudioSessionId();
@@ -20023,6 +19965,7 @@
public abstract interface AudioRouting {
method public abstract void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public abstract android.media.AudioDeviceInfo getPreferredDevice();
+ method public abstract android.media.AudioDeviceInfo getRoutedDevice();
method public abstract void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener);
method public abstract boolean setPreferredDevice(android.media.AudioDeviceInfo);
}
@@ -20203,6 +20146,8 @@
public class ExifInterface {
ctor public ExifInterface(java.lang.String) throws java.io.IOException;
+ ctor public ExifInterface(java.io.FileDescriptor) throws java.io.IOException;
+ ctor public ExifInterface(java.io.InputStream) throws java.io.IOException;
method public double getAltitude(double);
method public java.lang.String getAttribute(java.lang.String);
method public double getAttributeDouble(java.lang.String, double);
@@ -20224,6 +20169,10 @@
field public static final java.lang.String TAG_APERTURE = "FNumber";
field public static final java.lang.String TAG_DATETIME = "DateTime";
field public static final java.lang.String TAG_DATETIME_DIGITIZED = "DateTimeDigitized";
+ field public static final java.lang.String TAG_DIGITAL_ZOOM_RATIO = "DigitalZoomRatio";
+ field public static final java.lang.String TAG_EXPOSURE_BIAS_VALUE = "ExposureBiasValue";
+ field public static final java.lang.String TAG_EXPOSURE_MODE = "ExposureMode";
+ field public static final java.lang.String TAG_EXPOSURE_PROGRAM = "ExposureProgram";
field public static final java.lang.String TAG_EXPOSURE_TIME = "ExposureTime";
field public static final java.lang.String TAG_FLASH = "Flash";
field public static final java.lang.String TAG_FOCAL_LENGTH = "FocalLength";
@@ -20239,9 +20188,12 @@
field public static final java.lang.String TAG_IMAGE_LENGTH = "ImageLength";
field public static final java.lang.String TAG_IMAGE_WIDTH = "ImageWidth";
field public static final java.lang.String TAG_ISO = "ISOSpeedRatings";
+ field public static final java.lang.String TAG_LIGHT_SOURCE = "LightSource";
field public static final java.lang.String TAG_MAKE = "Make";
+ field public static final java.lang.String TAG_METERING_MODE = "MeteringMode";
field public static final java.lang.String TAG_MODEL = "Model";
field public static final java.lang.String TAG_ORIENTATION = "Orientation";
+ field public static final java.lang.String TAG_SUBJECT_DISTANCE = "SubjectDistance";
field public static final java.lang.String TAG_SUBSEC_TIME = "SubSecTime";
field public static final java.lang.String TAG_SUBSEC_TIME_DIG = "SubSecTimeDigitized";
field public static final java.lang.String TAG_SUBSEC_TIME_ORIG = "SubSecTimeOriginal";
@@ -20651,6 +20603,7 @@
field public static final int HEVCMainTierLevel62 = 16777216; // 0x1000000
field public static final int HEVCProfileMain = 1; // 0x1
field public static final int HEVCProfileMain10 = 2; // 0x2
+ field public static final int HEVCProfileMain10HDR10 = 4096; // 0x1000
field public static final int MPEG2LevelH14 = 2; // 0x2
field public static final int MPEG2LevelHL = 3; // 0x3
field public static final int MPEG2LevelLL = 0; // 0x0
@@ -20908,6 +20861,7 @@
method public final void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
method public final void setDataSource(java.lang.String, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
method public final void setDataSource(java.lang.String) throws java.io.IOException;
+ method public final void setDataSource(android.content.res.AssetFileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public final void setDataSource(java.io.FileDescriptor) throws java.io.IOException;
method public final void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException;
method public void unselectTrack(int);
@@ -20982,6 +20936,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_PCM_ENCODING = "pcm-encoding";
field public static final java.lang.String KEY_PRIORITY = "priority";
field public static final java.lang.String KEY_PROFILE = "profile";
field public static final java.lang.String KEY_PUSH_BLANK_BUFFERS_ON_STOP = "push-blank-buffers-on-shutdown";
@@ -20991,6 +20946,7 @@
field public static final java.lang.String KEY_SLICE_HEIGHT = "slice-height";
field public static final java.lang.String KEY_STRIDE = "stride";
field public static final java.lang.String KEY_TEMPORAL_LAYERING = "ts-schema";
+ field public static final java.lang.String KEY_TRACK_ID = "track-id";
field public static final java.lang.String KEY_WIDTH = "width";
field public static final java.lang.String MIMETYPE_AUDIO_AAC = "audio/mp4a-latm";
field public static final java.lang.String MIMETYPE_AUDIO_AC3 = "audio/ac3";
@@ -21190,6 +21146,7 @@
method public void setDataSource(android.content.Context, android.net.Uri) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
method public void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
method public void setDataSource(java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
+ method public void setDataSource(android.content.res.AssetFileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public void setDataSource(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public void setDataSource(android.media.MediaDataSource) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
@@ -22556,6 +22513,10 @@
method public void playFromMediaId(java.lang.String, android.os.Bundle);
method public void playFromSearch(java.lang.String, android.os.Bundle);
method public void playFromUri(android.net.Uri, android.os.Bundle);
+ method public void prepare();
+ method public void prepareFromMediaId(java.lang.String, android.os.Bundle);
+ method public void prepareFromSearch(java.lang.String, android.os.Bundle);
+ method public void prepareFromUri(android.net.Uri, android.os.Bundle);
method public void rewind();
method public void seekTo(long);
method public void sendCustomAction(android.media.session.PlaybackState.CustomAction, android.os.Bundle);
@@ -22589,7 +22550,6 @@
method public void setRatingType(int);
method public void setSessionActivity(android.app.PendingIntent);
field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
- field public static final int FLAG_HANDLES_PREPARE_ONLY = 4; // 0x4
field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
}
@@ -22604,6 +22564,10 @@
method public void onPlayFromMediaId(java.lang.String, android.os.Bundle);
method public void onPlayFromSearch(java.lang.String, android.os.Bundle);
method public void onPlayFromUri(android.net.Uri, android.os.Bundle);
+ method public void onPrepare();
+ method public void onPrepareFromMediaId(java.lang.String, android.os.Bundle);
+ method public void onPrepareFromSearch(java.lang.String, android.os.Bundle);
+ method public void onPrepareFromUri(android.net.Uri, android.os.Bundle);
method public void onRewind();
method public void onSeekTo(long);
method public void onSetRating(android.media.Rating);
@@ -22660,6 +22624,10 @@
field public static final long ACTION_PLAY_FROM_SEARCH = 2048L; // 0x800L
field public static final long ACTION_PLAY_FROM_URI = 8192L; // 0x2000L
field public static final long ACTION_PLAY_PAUSE = 512L; // 0x200L
+ field public static final long ACTION_PREPARE = 16384L; // 0x4000L
+ field public static final long ACTION_PREPARE_FROM_MEDIA_ID = 32768L; // 0x8000L
+ field public static final long ACTION_PREPARE_FROM_SEARCH = 65536L; // 0x10000L
+ field public static final long ACTION_PREPARE_FROM_URI = 131072L; // 0x20000L
field public static final long ACTION_REWIND = 8L; // 0x8L
field public static final long ACTION_SEEK_TO = 256L; // 0x100L
field public static final long ACTION_SET_RATING = 128L; // 0x80L
@@ -22668,7 +22636,6 @@
field public static final long ACTION_SKIP_TO_QUEUE_ITEM = 4096L; // 0x1000L
field public static final long ACTION_STOP = 1L; // 0x1L
field public static final android.os.Parcelable.Creator<android.media.session.PlaybackState> CREATOR;
- field public static final java.lang.String EXTRA_PREPARE_ONLY = "android.media.session.extra.PREPARE_ONLY";
field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL
field public static final int STATE_BUFFERING = 6; // 0x6
field public static final int STATE_CONNECTING = 8; // 0x8
@@ -22744,6 +22711,10 @@
method public static final android.net.Uri buildProgramsUriForChannel(long, long, long);
method public static final android.net.Uri buildProgramsUriForChannel(android.net.Uri, long, long);
method public static final android.net.Uri buildRecordedProgramUri(long);
+ method public static final boolean isChannelUri(android.net.Uri);
+ method public static final boolean isChannelUriForPassthroughInput(android.net.Uri);
+ method public static final boolean isChannelUriForTunerInput(android.net.Uri);
+ method public static final boolean isProgramUri(android.net.Uri);
field public static final java.lang.String AUTHORITY = "android.media.tv";
}
@@ -22835,7 +22806,8 @@
field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
- field public static final java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
+ field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
+ field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
@@ -22845,7 +22817,9 @@
field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
- field public static final java.lang.String COLUMN_SEASON_NUMBER = "season_number";
+ field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
+ field public static final deprecated java.lang.String COLUMN_SEASON_NUMBER = "season_number";
+ field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
@@ -22861,6 +22835,7 @@
public static final class TvContract.Programs.Genres {
method public static java.lang.String[] decode(java.lang.String);
method public static java.lang.String encode(java.lang.String...);
+ method public static boolean isCanonical(java.lang.String);
field public static final java.lang.String ANIMAL_WILDLIFE = "ANIMAL_WILDLIFE";
field public static final java.lang.String ARTS = "ARTS";
field public static final java.lang.String COMEDY = "COMEDY";
@@ -22887,7 +22862,7 @@
field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
- field public static final java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
+ field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
field public static final java.lang.String COLUMN_INPUT_ID = "input_id";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
@@ -22902,7 +22877,8 @@
field public static final java.lang.String COLUMN_RECORDING_DURATION_MILLIS = "recording_duration_millis";
field public static final java.lang.String COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS = "recording_expire_time_utc_millis";
field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
- field public static final java.lang.String COLUMN_SEASON_NUMBER = "season_number";
+ field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
+ field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
@@ -22946,7 +22922,7 @@
}
public static final class TvInputInfo.Builder {
- ctor public TvInputInfo.Builder(android.content.Context, java.lang.Class<?>);
+ ctor public TvInputInfo.Builder(android.content.Context, android.content.ComponentName);
method public android.media.tv.TvInputInfo build() throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public android.media.tv.TvInputInfo.Builder setCanRecord(boolean);
method public android.media.tv.TvInputInfo.Builder setTunerCount(int);
@@ -22963,6 +22939,7 @@
field public static final java.lang.String ACTION_BLOCKED_RATINGS_CHANGED = "android.media.tv.action.BLOCKED_RATINGS_CHANGED";
field public static final java.lang.String ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED = "android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED";
field public static final java.lang.String ACTION_QUERY_CONTENT_RATING_SYSTEMS = "android.media.tv.action.QUERY_CONTENT_RATING_SYSTEMS";
+ field public static final java.lang.String ACTION_SETUP_INPUTS = "android.media.tv.action.SETUP_INPUTS";
field public static final int INPUT_STATE_CONNECTED = 0; // 0x0
field public static final int INPUT_STATE_CONNECTED_STANDBY = 1; // 0x1
field public static final int INPUT_STATE_DISCONNECTED = 2; // 0x2
@@ -23013,7 +22990,7 @@
ctor public TvInputService.RecordingSession(android.content.Context);
method public void notifyError(int);
method public void notifyRecordingStopped(android.net.Uri);
- method public void notifyTuned();
+ method public void notifyTuned(android.net.Uri);
method public abstract void onRelease();
method public abstract void onStartRecording(android.net.Uri);
method public abstract void onStopRecording();
@@ -23072,7 +23049,7 @@
method public void onDisconnected(java.lang.String);
method public void onError(int);
method public void onRecordingStopped(android.net.Uri);
- method public void onTuned();
+ method public void onTuned(android.net.Uri);
}
public final class TvTrackInfo implements android.os.Parcelable {
@@ -23499,7 +23476,7 @@
method public int getUid();
}
- public class DataUsageRequest implements android.os.Parcelable {
+ public final class DataUsageRequest 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.net.DataUsageRequest> CREATOR;
@@ -26817,7 +26794,8 @@
method public static void glGetSynciv(long, int, int, int[], int, int[], int);
method public static void glGetSynciv(long, int, int, java.nio.IntBuffer, java.nio.IntBuffer);
method public static void glGetTransformFeedbackVarying(int, int, int, int[], int, int[], int, int[], int, byte[], int);
- method public static void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte);
+ method public static deprecated void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte);
+ method public static void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.ByteBuffer);
method public static java.lang.String glGetTransformFeedbackVarying(int, int, int[], int, int[], int);
method public static java.lang.String glGetTransformFeedbackVarying(int, int, java.nio.IntBuffer, java.nio.IntBuffer);
method public static int glGetUniformBlockIndex(int, java.lang.String);
@@ -26843,6 +26821,7 @@
method public static void glProgramBinary(int, int, java.nio.Buffer, int);
method public static void glProgramParameteri(int, int, int);
method public static void glReadBuffer(int);
+ method public static void glReadPixels(int, int, int, int, int, int, int);
method public static void glRenderbufferStorageMultisample(int, int, int, int, int);
method public static void glResumeTransformFeedback();
method public static void glSamplerParameterf(int, int, float);
@@ -28428,6 +28407,10 @@
ctor public DeadObjectException(java.lang.String);
}
+ public class DeadSystemException extends android.os.DeadObjectException {
+ ctor public DeadSystemException();
+ }
+
public final class Debug {
method public static deprecated void changeDebugPort(int);
method public static void dumpHprofData(java.lang.String) throws java.io.IOException;
@@ -29060,7 +29043,6 @@
field public static final int RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY = 1; // 0x1
field public static final deprecated int SCREEN_BRIGHT_WAKE_LOCK = 10; // 0xa
field public static final deprecated int SCREEN_DIM_WAKE_LOCK = 6; // 0x6
- field public static final int SUSTAINED_PERFORMANCE_WAKE_LOCK = 256; // 0x100
}
public final class PowerManager.WakeLock {
@@ -29077,6 +29059,8 @@
ctor public Process();
method public static final long getElapsedCpuTime();
method public static final int getGidForName(java.lang.String);
+ method public static final long getStartElapsedRealtime();
+ method public static final long getStartUptimeMillis();
method public static final int getThreadPriority(int) throws java.lang.IllegalArgumentException;
method public static final int getUidForName(java.lang.String);
method public static final boolean is64Bit();
@@ -29383,7 +29367,7 @@
method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener);
}
- public class StorageVolume implements android.os.Parcelable {
+ public final class StorageVolume implements android.os.Parcelable {
method public android.content.Intent createAccessIntent(java.lang.String);
method public int describeContents();
method public java.lang.String getDescription(android.content.Context);
@@ -29511,6 +29495,7 @@
method protected int getPersistedInt(int);
method protected long getPersistedLong(long);
method protected java.lang.String getPersistedString(java.lang.String);
+ method public java.util.Set<java.lang.String> getPersistedStringSet(java.util.Set<java.lang.String>);
method public android.preference.PreferenceManager getPreferenceManager();
method public android.content.SharedPreferences getSharedPreferences();
method public boolean getShouldDisableView();
@@ -29545,6 +29530,7 @@
method protected boolean persistInt(int);
method protected boolean persistLong(long);
method protected boolean persistString(java.lang.String);
+ method public boolean persistStringSet(java.util.Set<java.lang.String>);
method public void restoreHierarchyState(android.os.Bundle);
method public void saveHierarchyState(android.os.Bundle);
method public void setDefaultValue(java.lang.Object);
@@ -30217,7 +30203,7 @@
field public static final java.lang.String COLUMN_ID = "_id";
field public static final java.lang.String COLUMN_ORIGINAL_NUMBER = "original_number";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/blocked_number";
- field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_numbers";
+ field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_number";
field public static final android.net.Uri CONTENT_URI;
}
@@ -31744,6 +31730,7 @@
public static final class DocumentsContract.Root {
field public static final java.lang.String COLUMN_AVAILABLE_BYTES = "available_bytes";
+ field public static final java.lang.String COLUMN_CAPACITY_BYTES = "capacity_bytes";
field public static final java.lang.String COLUMN_DOCUMENT_ID = "document_id";
field public static final java.lang.String COLUMN_FLAGS = "flags";
field public static final java.lang.String COLUMN_ICON = "icon";
@@ -34108,6 +34095,7 @@
method public java.lang.String[] getSignaturePaddings();
method public int getUserAuthenticationValidityDurationSeconds();
method public boolean isDigestsSpecified();
+ method public boolean isInvalidatedByBiometricEnrollment();
method public boolean isRandomizedEncryptionRequired();
method public boolean isUserAuthenticationRequired();
method public boolean isUserAuthenticationValidWhileOnBody();
@@ -34125,6 +34113,7 @@
method public android.security.keystore.KeyGenParameterSpec.Builder setCertificateSubject(javax.security.auth.x500.X500Principal);
method public android.security.keystore.KeyGenParameterSpec.Builder setDigests(java.lang.String...);
method public android.security.keystore.KeyGenParameterSpec.Builder setEncryptionPaddings(java.lang.String...);
+ method public android.security.keystore.KeyGenParameterSpec.Builder setInvalidatedByBiometricEnrollment(boolean);
method public android.security.keystore.KeyGenParameterSpec.Builder setKeySize(int);
method public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityEnd(java.util.Date);
method public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityForConsumptionEnd(java.util.Date);
@@ -34151,6 +34140,7 @@
method public java.lang.String[] getSignaturePaddings();
method public int getUserAuthenticationValidityDurationSeconds();
method public boolean isInsideSecureHardware();
+ method public boolean isInvalidatedByBiometricEnrollment();
method public boolean isUserAuthenticationRequired();
method public boolean isUserAuthenticationRequirementEnforcedBySecureHardware();
method public boolean isUserAuthenticationValidWhileOnBody();
@@ -34214,6 +34204,7 @@
method public java.lang.String[] getSignaturePaddings();
method public int getUserAuthenticationValidityDurationSeconds();
method public boolean isDigestsSpecified();
+ method public boolean isInvalidatedByBiometricEnrollment();
method public boolean isRandomizedEncryptionRequired();
method public boolean isUserAuthenticationRequired();
method public boolean isUserAuthenticationValidWhileOnBody();
@@ -34225,6 +34216,7 @@
method public android.security.keystore.KeyProtection.Builder setBlockModes(java.lang.String...);
method public android.security.keystore.KeyProtection.Builder setDigests(java.lang.String...);
method public android.security.keystore.KeyProtection.Builder setEncryptionPaddings(java.lang.String...);
+ method public android.security.keystore.KeyProtection.Builder setInvalidatedByBiometricEnrollment(boolean);
method public android.security.keystore.KeyProtection.Builder setKeyValidityEnd(java.util.Date);
method public android.security.keystore.KeyProtection.Builder setKeyValidityForConsumptionEnd(java.util.Date);
method public android.security.keystore.KeyProtection.Builder setKeyValidityForOriginationEnd(java.util.Date);
@@ -34263,7 +34255,8 @@
ctor public CarrierMessagingService();
method public android.os.IBinder onBind(android.content.Intent);
method public void onDownloadMms(android.net.Uri, int, android.net.Uri, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Integer>);
- method public void onFilterSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Boolean>);
+ method public deprecated void onFilterSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Boolean>);
+ method public void onReceiveTextSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Integer>);
method public deprecated void onSendDataSms(byte[], int, java.lang.String, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
method public void onSendDataSms(byte[], int, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
method public void onSendMms(android.net.Uri, int, android.net.Uri, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendMmsResult>);
@@ -34274,6 +34267,9 @@
field public static final int DOWNLOAD_STATUS_ERROR = 2; // 0x2
field public static final int DOWNLOAD_STATUS_OK = 0; // 0x0
field public static final int DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK = 1; // 0x1
+ field public static final int RECEIVE_OPTIONS_DEFAULT = 0; // 0x0
+ field public static final int RECEIVE_OPTIONS_DROP = 1; // 0x1
+ field public static final int RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE = 2; // 0x2
field public static final int SEND_FLAG_REQUEST_DELIVERY_STATUS = 1; // 0x1
field public static final int SEND_STATUS_ERROR = 2; // 0x2
field public static final int SEND_STATUS_OK = 0; // 0x0
@@ -34505,7 +34501,7 @@
method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
method public final void requestInterruptionFilter(int);
method public final void requestListenerHints(int);
- method public static final void requestRebind(android.content.ComponentName) throws android.os.RemoteException;
+ method public static void requestRebind(android.content.ComponentName) throws android.os.RemoteException;
method public final void requestUnbind() throws android.os.RemoteException;
method public final void setNotificationsShown(java.lang.String[]);
field public static final java.lang.String CATEGORY_VR_NOTIFICATIONS = "android.intent.category.vr.notifications";
@@ -34529,10 +34525,11 @@
method public int getSuppressedVisualEffects();
method public boolean isAmbient();
method public boolean matchesInterruptionFilter();
- field public static final int IMPORTANCE_DEFAULT = 2; // 0x2
- field public static final int IMPORTANCE_HIGH = 3; // 0x3
- field public static final int IMPORTANCE_LOW = 1; // 0x1
- field public static final int IMPORTANCE_MAX = 4; // 0x4
+ field public static final int IMPORTANCE_DEFAULT = 3; // 0x3
+ field public static final int IMPORTANCE_HIGH = 4; // 0x4
+ field public static final int IMPORTANCE_LOW = 2; // 0x2
+ field public static final int IMPORTANCE_MAX = 5; // 0x5
+ field public static final int IMPORTANCE_MIN = 1; // 0x1
field public static final int IMPORTANCE_NONE = 0; // 0x0
field public static final int IMPORTANCE_UNSPECIFIED = -1000; // 0xfffffc18
}
@@ -34603,6 +34600,7 @@
method public final void startActivityAndCollapse(android.content.Intent);
method public final void unlockAndRun(java.lang.Runnable);
field public static final java.lang.String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE";
+ field public static final java.lang.String ACTION_QS_TILE_PREFERENCES = "android.service.quicksettings.action.QS_TILE_PREFERENCES";
field public static final int TILE_MODE_ACTIVE = 2; // 0x2
field public static final int TILE_MODE_PASSIVE = 1; // 0x1
}
@@ -36093,6 +36091,7 @@
method public final void conferenceRemoteConnections(android.telecom.RemoteConnection, android.telecom.RemoteConnection);
method public final android.telecom.RemoteConnection createRemoteIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public final android.telecom.RemoteConnection createRemoteOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
+ method public final java.util.Collection<android.telecom.Conference> getAllConferences();
method public final java.util.Collection<android.telecom.Connection> getAllConnections();
method public final android.os.IBinder onBind(android.content.Intent);
method public void onConference(android.telecom.Connection, android.telecom.Connection);
@@ -36369,6 +36368,7 @@
public class TelecomManager {
method public void addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle);
method public void cancelMissedCallsNotification();
+ method public android.content.Intent createManageBlockedNumbersIntent();
method public android.net.Uri getAdnUriForPhoneAccount(android.telecom.PhoneAccountHandle);
method public java.util.List<android.telecom.PhoneAccountHandle> getCallCapablePhoneAccounts();
method public java.lang.String getDefaultDialerPackage();
@@ -36381,7 +36381,7 @@
method public boolean handleMmi(java.lang.String, android.telecom.PhoneAccountHandle);
method public boolean isInCall();
method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String);
- method public void launchManageBlockedNumbersActivity();
+ method public deprecated void launchManageBlockedNumbersActivity();
method public void placeCall(android.net.Uri, android.os.Bundle);
method public void registerPhoneAccount(android.telecom.PhoneAccount);
method public void showInCallScreen(boolean);
@@ -36461,9 +36461,11 @@
package android.telephony {
public class CarrierConfigManager {
+ method public android.os.PersistableBundle getConfig(int);
method public android.os.PersistableBundle getConfig();
- method public android.os.PersistableBundle getConfigForSubId(int);
- method public void notifyConfigChangedForSubId(int);
+ method public deprecated android.os.PersistableBundle getConfigForSubId(int);
+ method public void notifyConfigChanged(int);
+ method public deprecated void notifyConfigChangedForSubId(int);
field public static final java.lang.String ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED";
field public static final java.lang.String BOOL_ALLOW_EMERGENCY_VIDEO_CALLS = "bool_allow_emergency_video_calls";
field public static final java.lang.String BOOL_ALLOW_VIDEO_PAUSE = "bool_allow_video_pause";
@@ -37101,12 +37103,18 @@
method public int getVoiceNetworkType(int);
method public android.net.Uri getVoicemailRingtoneUri(android.telecom.PhoneAccountHandle);
method public boolean hasCarrierPrivileges();
+ method public boolean hasCarrierPrivileges(int);
method public boolean hasIccCard();
method public boolean iccCloseLogicalChannel(int);
+ method public boolean iccCloseLogicalChannel(int, int);
method public byte[] iccExchangeSimIO(int, int, int, int, int, java.lang.String);
+ method public byte[] iccExchangeSimIO(int, int, int, int, int, int, java.lang.String);
method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String);
+ method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(int, java.lang.String);
method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, java.lang.String);
+ method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, int, java.lang.String);
method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
+ method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, int, java.lang.String);
method public boolean isHearingAidCompatibilitySupported();
method public boolean isNetworkRoaming();
method public boolean isNetworkRoaming(int);
@@ -37117,10 +37125,13 @@
method public boolean isWorldPhone();
method public void listen(android.telephony.PhoneStateListener, int);
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
+ method public java.lang.String sendEnvelopeWithStatus(int, java.lang.String);
method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
method public boolean setLine1NumberForDisplay(int, java.lang.String, java.lang.String);
method public boolean setOperatorBrandOverride(java.lang.String);
+ method public boolean setOperatorBrandOverride(int, java.lang.String);
method public boolean setPreferredNetworkTypeToGlobal();
+ method public boolean setPreferredNetworkTypeToGlobal(int);
method public boolean setVoiceMailNumber(java.lang.String, java.lang.String);
method public boolean setVoiceMailNumber(int, java.lang.String, java.lang.String);
field public static final java.lang.String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL";
@@ -38487,7 +38498,6 @@
method public boolean hasNext();
method public java.util.Iterator<java.lang.String> iterator();
method public java.lang.String next();
- method public void remove();
method public void setString(java.lang.String);
}
@@ -40099,6 +40109,7 @@
method public int describeContents();
method public static android.util.LocaleList forLanguageTags(java.lang.String);
method public java.util.Locale get(int);
+ method public static android.util.LocaleList getAdjustedDefault();
method public static android.util.LocaleList getDefault();
method public static android.util.LocaleList getEmptyLocaleList();
method public java.util.Locale getFirstMatch(java.lang.String[]);
@@ -44026,6 +44037,7 @@
field public static final int TYPE_ACCESSIBILITY_OVERLAY = 4; // 0x4
field public static final int TYPE_APPLICATION = 1; // 0x1
field public static final int TYPE_INPUT_METHOD = 2; // 0x2
+ field public static final int TYPE_SPLIT_SCREEN_DIVIDER = 5; // 0x5
field public static final int TYPE_SYSTEM = 3; // 0x3
}
@@ -44365,6 +44377,7 @@
method public int getCursorCapsMode(int);
method public android.text.Editable getEditable();
method public android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int);
+ method public android.os.Handler getHandler();
method public java.lang.CharSequence getSelectedText(int);
method public java.lang.CharSequence getTextAfterCursor(int, int);
method public java.lang.CharSequence getTextBeforeCursor(int, int);
@@ -44528,6 +44541,7 @@
method public abstract boolean finishComposingText();
method public abstract int getCursorCapsMode(int);
method public abstract android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int);
+ method public abstract android.os.Handler getHandler();
method public abstract java.lang.CharSequence getSelectedText(int);
method public abstract java.lang.CharSequence getTextAfterCursor(int, int);
method public abstract java.lang.CharSequence getTextBeforeCursor(int, int);
@@ -44559,6 +44573,7 @@
method public boolean finishComposingText();
method public int getCursorCapsMode(int);
method public android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int);
+ method public android.os.Handler getHandler();
method public java.lang.CharSequence getSelectedText(int);
method public java.lang.CharSequence getTextAfterCursor(int, int);
method public java.lang.CharSequence getTextBeforeCursor(int, int);
@@ -46065,7 +46080,9 @@
method public long getBase();
method public java.lang.String getFormat();
method public android.widget.Chronometer.OnChronometerTickListener getOnChronometerTickListener();
+ method public boolean isCountDown();
method public void setBase(long);
+ method public void setCountDown(boolean);
method public void setFormat(java.lang.String);
method public void setOnChronometerTickListener(android.widget.Chronometer.OnChronometerTickListener);
method public void start();
@@ -47157,6 +47174,7 @@
method public void setChar(int, java.lang.String, char);
method public void setCharSequence(int, java.lang.String, java.lang.CharSequence);
method public void setChronometer(int, long, java.lang.String, boolean);
+ method public void setChronometerCountsDown(int, boolean);
method public void setContentDescription(int, java.lang.CharSequence);
method public void setDisplayedChild(int, int);
method public void setDouble(int, java.lang.String, double);
@@ -50403,6 +50421,7 @@
method public static long doubleToRawLongBits(double);
method public double doubleValue();
method public float floatValue();
+ method public static int hashCode(double);
method public int intValue();
method public static boolean isInfinite(double);
method public boolean isInfinite();
@@ -50410,11 +50429,15 @@
method public boolean isNaN();
method public static double longBitsToDouble(long);
method public long longValue();
+ method public static double max(double, double);
+ method public static double min(double, double);
method public static double parseDouble(java.lang.String) throws java.lang.NumberFormatException;
+ method public static double sum(double, double);
method public static java.lang.String toHexString(double);
method public static java.lang.String toString(double);
method public static java.lang.Double valueOf(java.lang.String) throws java.lang.NumberFormatException;
method public static java.lang.Double valueOf(double);
+ field public static final int BYTES = 8; // 0x8
field public static final int MAX_EXPONENT = 1023; // 0x3ff
field public static final double MAX_VALUE = 1.7976931348623157E308;
field public static final int MIN_EXPONENT = -1022; // 0xfffffc02
@@ -50577,10 +50600,13 @@
method public static java.lang.Integer getInteger(java.lang.String);
method public static java.lang.Integer getInteger(java.lang.String, int);
method public static java.lang.Integer getInteger(java.lang.String, java.lang.Integer);
+ method public static int hashCode(int);
method public static int highestOneBit(int);
method public int intValue();
method public long longValue();
method public static int lowestOneBit(int);
+ method public static int max(int, int);
+ method public static int min(int, int);
method public static int numberOfLeadingZeros(int);
method public static int numberOfTrailingZeros(int);
method public static int parseInt(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -50590,6 +50616,7 @@
method public static int rotateLeft(int, int);
method public static int rotateRight(int, int);
method public static int signum(int);
+ method public static int sum(int, int);
method public static java.lang.String toBinaryString(int);
method public static java.lang.String toHexString(int);
method public static java.lang.String toOctalString(int);
@@ -50598,6 +50625,7 @@
method public static java.lang.Integer valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
method public static java.lang.Integer valueOf(java.lang.String) throws java.lang.NumberFormatException;
method public static java.lang.Integer valueOf(int);
+ field public static final int BYTES = 4; // 0x4
field public static final int MAX_VALUE = 2147483647; // 0x7fffffff
field public static final int MIN_VALUE = -2147483648; // 0x80000000
field public static final int SIZE = 32; // 0x20
@@ -50617,6 +50645,7 @@
}
public abstract interface Iterable {
+ method public default void forEach(java.util.function.Consumer<? super T>);
method public abstract java.util.Iterator<T> iterator();
}
@@ -50638,10 +50667,13 @@
method public static java.lang.Long getLong(java.lang.String);
method public static java.lang.Long getLong(java.lang.String, long);
method public static java.lang.Long getLong(java.lang.String, java.lang.Long);
+ method public static int hashCode(long);
method public static long highestOneBit(long);
method public int intValue();
method public long longValue();
method public static long lowestOneBit(long);
+ method public static long max(long, long);
+ method public static long min(long, long);
method public static int numberOfLeadingZeros(long);
method public static int numberOfTrailingZeros(long);
method public static long parseLong(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -50651,6 +50683,7 @@
method public static long rotateLeft(long, int);
method public static long rotateRight(long, int);
method public static int signum(long);
+ method public static long sum(long, long);
method public static java.lang.String toBinaryString(long);
method public static java.lang.String toHexString(long);
method public static java.lang.String toOctalString(long);
@@ -53069,7 +53102,7 @@
ctor public ConnectionPendingException();
}
- public abstract class DatagramChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.ByteChannel java.nio.channels.GatheringByteChannel java.nio.channels.ScatteringByteChannel {
+ public abstract class DatagramChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.ByteChannel java.nio.channels.GatheringByteChannel java.nio.channels.NetworkChannel java.nio.channels.ScatteringByteChannel {
ctor protected DatagramChannel(java.nio.channels.spi.SelectorProvider);
method public abstract java.nio.channels.DatagramChannel bind(java.net.SocketAddress) throws java.io.IOException;
method public abstract java.nio.channels.DatagramChannel connect(java.net.SocketAddress) throws java.io.IOException;
@@ -54092,6 +54125,7 @@
public abstract class Provider extends java.util.Properties {
ctor protected Provider(java.lang.String, double, java.lang.String);
+ method public synchronized void forEach(java.util.function.BiConsumer<? super java.lang.Object, ? super java.lang.Object>);
method public java.lang.String getInfo();
method public java.lang.String getName();
method public synchronized java.security.Provider.Service getService(java.lang.String, java.lang.String);
@@ -57041,6 +57075,7 @@
ctor public ArrayList(java.util.Collection<? extends E>);
method public java.lang.Object clone();
method public void ensureCapacity(int);
+ method public void forEach(java.util.function.Consumer<? super E>);
method public E get(int);
method public int size();
method public void trimToSize();
@@ -57604,6 +57639,7 @@
ctor public HashMap(java.util.Map<? extends K, ? extends V>);
method public java.lang.Object clone();
method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+ method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
}
public class HashSet extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
@@ -57628,6 +57664,7 @@
method public boolean containsValue(java.lang.Object);
method public synchronized java.util.Enumeration<V> elements();
method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+ method public synchronized void forEach(java.util.function.BiConsumer<? super K, ? super V>);
method public synchronized V get(java.lang.Object);
method public synchronized boolean isEmpty();
method public java.util.Set<K> keySet();
@@ -57646,6 +57683,7 @@
ctor public IdentityHashMap(java.util.Map<? extends K, ? extends V>);
method public java.lang.Object clone();
method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+ method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
}
public class IllegalFormatCodePointException extends java.util.IllegalFormatException {
@@ -57695,9 +57733,10 @@
}
public abstract interface Iterator {
+ method public default void forEachRemaining(java.util.function.Consumer<? super E>);
method public abstract boolean hasNext();
method public abstract E next();
- method public abstract void remove();
+ method public default void remove();
}
public class LinkedHashMap extends java.util.HashMap implements java.util.Map {
@@ -57885,6 +57924,7 @@
method public abstract boolean containsValue(java.lang.Object);
method public abstract java.util.Set<java.util.Map.Entry<K, V>> entrySet();
method public abstract boolean equals(java.lang.Object);
+ method public default void forEach(java.util.function.BiConsumer<? super K, ? super V>);
method public abstract V get(java.lang.Object);
method public abstract int hashCode();
method public abstract boolean isEmpty();
@@ -57999,6 +58039,79 @@
method public abstract void update(java.util.Observable, java.lang.Object);
}
+ public final class Optional {
+ method public static java.util.Optional<T> empty();
+ method public java.util.Optional<T> filter(java.util.function.Predicate<? super T>);
+ method public java.util.Optional<U> flatMap(java.util.function.Function<? super T, java.util.Optional<U>>);
+ method public T get();
+ method public void ifPresent(java.util.function.Consumer<? super T>);
+ method public boolean isPresent();
+ method public java.util.Optional<U> map(java.util.function.Function<? super T, ? extends U>);
+ method public static java.util.Optional<T> of(T);
+ method public static java.util.Optional<T> ofNullable(T);
+ method public T orElse(T);
+ method public T orElseGet(java.util.function.Supplier<? extends T>);
+ method public T orElseThrow(java.util.function.Supplier<? extends X>) throws java.lang.Throwable;
+ }
+
+ public final class OptionalDouble {
+ method public static java.util.OptionalDouble empty();
+ method public double getAsDouble();
+ method public void ifPresent(java.util.function.DoubleConsumer);
+ method public boolean isPresent();
+ method public static java.util.OptionalDouble of(double);
+ method public double orElse(double);
+ method public double orElseGet(java.util.function.DoubleSupplier);
+ method public double orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+ }
+
+ public final class OptionalInt {
+ method public static java.util.OptionalInt empty();
+ method public int getAsInt();
+ method public void ifPresent(java.util.function.IntConsumer);
+ method public boolean isPresent();
+ method public static java.util.OptionalInt of(int);
+ method public int orElse(int);
+ method public int orElseGet(java.util.function.IntSupplier);
+ method public int orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+ }
+
+ public final class OptionalLong {
+ method public static java.util.OptionalLong empty();
+ method public long getAsLong();
+ method public void ifPresent(java.util.function.LongConsumer);
+ method public boolean isPresent();
+ method public static java.util.OptionalLong of(long);
+ method public long orElse(long);
+ method public long orElseGet(java.util.function.LongSupplier);
+ method public long orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+ }
+
+ public abstract interface PrimitiveIterator implements java.util.Iterator {
+ method public abstract void forEachRemaining(T_CONS);
+ }
+
+ public static abstract interface PrimitiveIterator.OfDouble implements java.util.PrimitiveIterator {
+ method public default void forEachRemaining(java.util.function.DoubleConsumer);
+ method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Double>);
+ method public default java.lang.Double next();
+ method public abstract double nextDouble();
+ }
+
+ public static abstract interface PrimitiveIterator.OfInt implements java.util.PrimitiveIterator {
+ method public default void forEachRemaining(java.util.function.IntConsumer);
+ method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Integer>);
+ method public default java.lang.Integer next();
+ method public abstract int nextInt();
+ }
+
+ public static abstract interface PrimitiveIterator.OfLong implements java.util.PrimitiveIterator {
+ method public default void forEachRemaining(java.util.function.LongConsumer);
+ method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Long>);
+ method public default java.lang.Long next();
+ method public abstract long nextLong();
+ }
+
public class PriorityQueue extends java.util.AbstractQueue implements java.io.Serializable {
ctor public PriorityQueue();
ctor public PriorityQueue(int);
@@ -58170,7 +58283,6 @@
method public short nextShort();
method public short nextShort(int);
method public int radix();
- method public void remove();
method public java.util.Scanner reset();
method public java.util.Scanner skip(java.util.regex.Pattern);
method public java.util.Scanner skip(java.lang.String);
@@ -58346,6 +58458,7 @@
method public K firstKey();
method public java.util.Map.Entry<K, V> floorEntry(K);
method public K floorKey(K);
+ method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
method public java.util.NavigableMap<K, V> headMap(K, boolean);
method public java.util.SortedMap<K, V> headMap(K);
method public java.util.Map.Entry<K, V> higherEntry(K);
@@ -58428,6 +58541,7 @@
method public java.util.Enumeration<E> elements();
method public synchronized void ensureCapacity(int);
method public synchronized E firstElement();
+ method public synchronized void forEach(java.util.function.Consumer<? super E>);
method public synchronized E get(int);
method public synchronized int indexOf(java.lang.Object, int);
method public synchronized void insertElementAt(E, int);
@@ -58451,6 +58565,7 @@
ctor public WeakHashMap();
ctor public WeakHashMap(java.util.Map<? extends K, ? extends V>);
method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+ method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
}
}
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 0bf6594..115224c 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -9,6 +9,8 @@
package android.app.admin {
public class DevicePolicyManager {
+ method public deprecated android.os.UserHandle createAndInitializeUser(android.content.ComponentName, java.lang.String, java.lang.String, android.content.ComponentName, android.os.Bundle);
+ method public deprecated android.os.UserHandle createUser(android.content.ComponentName, java.lang.String);
method public deprecated java.lang.String getDeviceInitializerApp();
method public deprecated android.content.ComponentName getDeviceInitializerComponent();
}
@@ -35,7 +37,7 @@
package android.media {
- public class AudioFormat {
+ public final class AudioFormat implements android.os.Parcelable {
ctor public AudioFormat();
}
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index eedb82b..e6c5768 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -577,7 +577,7 @@
return;
}
List<ResolveInfo> activities = pm.queryIntentActivities(intent, mimeType, 0,
- mUserId);
+ mUserId).getList();
if (activities == null || activities.size() <= 0) {
System.err.println("Error: Intent does not match any activities: "
+ intent);
@@ -606,7 +606,7 @@
new File(mProfileFile),
ParcelFileDescriptor.MODE_CREATE |
ParcelFileDescriptor.MODE_TRUNCATE |
- ParcelFileDescriptor.MODE_READ_WRITE);
+ ParcelFileDescriptor.MODE_WRITE_ONLY);
} catch (FileNotFoundException e) {
System.err.println("Error: Unable to open file: " + mProfileFile);
System.err.println("Consider using a file under /data/local/tmp/");
@@ -903,7 +903,7 @@
fd = openForSystemServer(file,
ParcelFileDescriptor.MODE_CREATE |
ParcelFileDescriptor.MODE_TRUNCATE |
- ParcelFileDescriptor.MODE_READ_WRITE);
+ ParcelFileDescriptor.MODE_WRITE_ONLY);
} catch (FileNotFoundException e) {
System.err.println("Error: Unable to open file: " + filename);
System.err.println("Consider using a file under /data/local/tmp/");
@@ -992,7 +992,7 @@
new File(profileFile),
ParcelFileDescriptor.MODE_CREATE |
ParcelFileDescriptor.MODE_TRUNCATE |
- ParcelFileDescriptor.MODE_READ_WRITE);
+ ParcelFileDescriptor.MODE_WRITE_ONLY);
} catch (FileNotFoundException e) {
System.err.println("Error: Unable to open file: " + profileFile);
System.err.println("Consider using a file under /data/local/tmp/");
@@ -1052,7 +1052,7 @@
fd = openForSystemServer(file,
ParcelFileDescriptor.MODE_CREATE |
ParcelFileDescriptor.MODE_TRUNCATE |
- ParcelFileDescriptor.MODE_READ_WRITE);
+ ParcelFileDescriptor.MODE_WRITE_ONLY);
} catch (FileNotFoundException e) {
System.err.println("Error: Unable to open file: " + heapFile);
System.err.println("Consider using a file under /data/local/tmp/");
@@ -1216,6 +1216,7 @@
class MyActivityController extends IActivityController.Stub {
final String mGdbPort;
+ final boolean mMonkey;
static final int STATE_NORMAL = 0;
static final int STATE_CRASHED = 1;
@@ -1242,8 +1243,9 @@
Thread mGdbThread;
boolean mGotGdbPrint;
- MyActivityController(String gdbPort) {
+ MyActivityController(String gdbPort, boolean monkey) {
mGdbPort = gdbPort;
+ mMonkey = monkey;
}
@Override
@@ -1443,7 +1445,7 @@
try {
printMessageForState();
- mAm.setActivityController(this);
+ mAm.setActivityController(this, mMonkey);
mState = STATE_NORMAL;
InputStreamReader converter = new InputStreamReader(System.in);
@@ -1498,7 +1500,7 @@
} catch (IOException e) {
e.printStackTrace();
} finally {
- mAm.setActivityController(null);
+ mAm.setActivityController(null, mMonkey);
}
}
}
@@ -1506,16 +1508,19 @@
private void runMonitor() throws Exception {
String opt;
String gdbPort = null;
+ boolean monkey = false;
while ((opt=nextOption()) != null) {
if (opt.equals("--gdb")) {
gdbPort = nextArgRequired();
+ } else if (opt.equals("-m")) {
+ monkey = true;
} else {
System.err.println("Error: Unknown option: " + opt);
return;
}
}
- MyActivityController controller = new MyActivityController(gdbPort);
+ MyActivityController controller = new MyActivityController(gdbPort, monkey);
controller.run();
}
diff --git a/cmds/app_process/Android.mk b/cmds/app_process/Android.mk
index 51bbb81..3ae9e12 100644
--- a/cmds/app_process/Android.mk
+++ b/cmds/app_process/Android.mk
@@ -20,6 +20,7 @@
libutils \
liblog \
libbinder \
+ libnativeloader \
libandroid_runtime \
$(app_process_common_shared_libs) \
@@ -52,6 +53,7 @@
libutils \
liblog \
libbinder \
+ libnativeloader \
libandroid_runtime \
$(app_process_common_shared_libs) \
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index 2e02382..8bcbf51 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -21,6 +21,7 @@
#include <cutils/properties.h>
#include <cutils/trace.h>
#include <android_runtime/AndroidRuntime.h>
+#include <nativeloader/native_loader.h>
#include <private/android_filesystem_config.h> // for AID_SYSTEM
namespace android {
@@ -304,6 +305,7 @@
}
if (zygote) {
+ PreloadPublicNativeLibraries();
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
diff --git a/cmds/hid/jni/Android.mk b/cmds/hid/jni/Android.mk
index 8163a9d..d41d39d 100644
--- a/cmds/hid/jni/Android.mk
+++ b/cmds/hid/jni/Android.mk
@@ -18,6 +18,6 @@
LOCAL_MODULE := libhidcommand_jni
LOCAL_MODULE_TAGS := optional
-LOCAL_CFLAGS += -Wall
+LOCAL_CFLAGS += -Wall -Wextra -Werror
include $(BUILD_SHARED_LIBRARY)
diff --git a/cmds/hid/jni/com_android_commands_hid_Device.cpp b/cmds/hid/jni/com_android_commands_hid_Device.cpp
index 4278e7d..1ea33ce 100644
--- a/cmds/hid/jni/com_android_commands_hid_Device.cpp
+++ b/cmds/hid/jni/com_android_commands_hid_Device.cpp
@@ -49,7 +49,7 @@
jmethodID onDeviceError;
} gDeviceCallbackClassInfo;
-static int handleLooperEvents(int fd, int events, void* data) {
+static int handleLooperEvents(int /* fd */, int events, void* data) {
Device* d = reinterpret_cast<Device*>(data);
return d->handleEvents(events);
}
@@ -183,7 +183,7 @@
return data;
}
-static jlong openDevice(JNIEnv* env, jclass clazz, jstring rawName, jint id, jint vid, jint pid,
+static jlong openDevice(JNIEnv* env, jclass /* clazz */, jstring rawName, jint id, jint vid, jint pid,
jbyteArray rawDescriptor, jobject queue, jobject callback) {
ScopedUtfChars name(env, rawName);
if (name.c_str() == nullptr) {
@@ -202,7 +202,7 @@
return reinterpret_cast<jlong>(d);
}
-static void sendReport(JNIEnv* env, jclass clazz, jlong ptr,jbyteArray rawReport) {
+static void sendReport(JNIEnv* env, jclass /* clazz */, jlong ptr,jbyteArray rawReport) {
size_t size;
std::unique_ptr<uint8_t[]> report = getData(env, rawReport, size);
uhid::Device* d = reinterpret_cast<uhid::Device*>(ptr);
@@ -211,7 +211,7 @@
}
}
-static void closeDevice(JNIEnv* env, jclass clazz, jlong ptr) {
+static void closeDevice(JNIEnv* /* env */, jclass /* clazz */, jlong ptr) {
uhid::Device* d = reinterpret_cast<uhid::Device*>(ptr);
if (d) {
delete d;
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 24449d4..4025553 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -1490,7 +1490,7 @@
System.err.println(" -i: specify the installer package name");
System.err.println(" -s: install application on sdcard");
System.err.println(" -f: install application on internal flash");
- System.err.println(" -d: allow version code downgrade");
+ System.err.println(" -d: allow version code downgrade (debuggable packages only)");
System.err.println(" -p: partial application install");
System.err.println(" -g: grant all runtime permissions");
System.err.println(" -S: size in bytes of entire session");
diff --git a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java
index 1fa9bac..ddeb8e7 100644
--- a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java
+++ b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java
@@ -50,9 +50,9 @@
}
try {
if (isSet) {
- am.setActivityController(new DummyActivityController());
+ am.setActivityController(new DummyActivityController(), true);
} else {
- am.setActivityController(null);
+ am.setActivityController(null, true);
}
} catch (RemoteException e) {
throw new RuntimeException(e);
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 4bc6b97..ac3b8e3 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -334,7 +334,7 @@
public static final int GLOBAL_ACTION_HOME = 2;
/**
- * Action to open the recent apps.
+ * Action to toggle showing the overview of recent apps
*/
public static final int GLOBAL_ACTION_RECENTS = 3;
@@ -353,6 +353,11 @@
*/
public static final int GLOBAL_ACTION_POWER_DIALOG = 6;
+ /**
+ * Action to toggle docking the current app's window
+ */
+ public static final int GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN = 7;
+
private static final String LOG_TAG = "AccessibilityService";
/**
@@ -378,13 +383,7 @@
@Retention(RetentionPolicy.SOURCE)
@IntDef({SHOW_MODE_AUTO, SHOW_MODE_HIDDEN})
public @interface SoftKeyboardShowMode {};
- /**
- * @hide
- */
public static final int SHOW_MODE_AUTO = 0;
- /**
- * @hide
- */
public static final int SHOW_MODE_HIDDEN = 1;
private int mConnectionId;
@@ -1132,7 +1131,7 @@
}
/**
- * Removes all instances of the specified change listener from teh list of magnification
+ * Removes all instances of the specified change listener from the list of magnification
* change listeners.
*
* @param listener the listener to remove, must be non-null
@@ -1211,14 +1210,11 @@
/**
* Returns the show mode of the soft keyboard. The default show mode is
- * {@code Settings.Secure.SHOW_MODE_AUTO}, where the soft keyboard is shown when a text
- * input field is focused. An AccessibilityService can also request the show mode
- * {@code Settings.Secure.SHOW_MODE_HIDDEN}, where the soft keyboard is never shown.
+ * {@code SHOW_MODE_AUTO}, where the soft keyboard is shown when a text input field is
+ * focused. An AccessibilityService can also request the show mode
+ * {@code SHOW_MODE_HIDDEN}, where the soft keyboard is never shown.
*
* @return the current soft keyboard show mode
- *
- * @see Settings#Secure#SHOW_MODE_AUTO
- * @see Settings#Secure#SHOW_MODE_HIDDEN
*/
@SoftKeyboardShowMode
public int getShowMode() {
@@ -1234,9 +1230,9 @@
/**
* Sets the soft keyboard show mode. The default show mode is
- * {@code Settings.Secure.SHOW_MODE_AUTO}, where the soft keyboard is shown when a text
- * input field is focused. An AccessibilityService can also request the show mode
- * {@code Settings.Secure.SHOW_MODE_HIDDEN}, where the soft keyboard is never shown. The
+ * {@code SHOW_MODE_AUTO}, where the soft keyboard is shown when a text input field is
+ * focused. An AccessibilityService can also request the show mode
+ * {@code SHOW_MODE_HIDDEN}, where the soft keyboard is never shown. The
* The lastto this method will be honored, regardless of any previous calls (including those
* made by other AccessibilityServices).
* <p>
@@ -1246,9 +1242,6 @@
*
* @param showMode the new show mode for the soft keyboard
* @return {@code true} on success
- *
- * @see Settings#Secure#SHOW_MODE_AUTO
- * @see Settings#Secure#SHOW_MODE_HIDDEN
*/
public boolean setShowMode(@SoftKeyboardShowMode int showMode) {
final IAccessibilityServiceConnection connection =
@@ -1258,9 +1251,13 @@
try {
return connection.setSoftKeyboardShowMode(showMode);
} catch (RemoteException re) {
- Log.w(LOG_TAG, "Falied to set soft keyboard behavior", re);
+ Log.w(LOG_TAG, "Failed to set soft keyboard behavior", re);
+ re.rethrowFromSystemServer();
}
+ } else {
+ throw new RuntimeException("AccessibilityServiceConnection is null");
}
+
return false;
}
@@ -1270,9 +1267,9 @@
public interface OnShowModeChangedListener {
/**
* Called when the soft keyboard behavior changes. The default show mode is
- * {@code Settings.Secure.SHOW_MODE_AUTO}, where the soft keyboard is shown when a text
- * input field is focused. An AccessibilityService can also request the show mode
- * {@code Settings.Secure.SHOW_MODE_HIDDEN}, where the soft keyboard is never shown.
+ * {@code SHOW_MODE_AUTO}, where the soft keyboard is shown when a text input field is
+ * focused. An AccessibilityService can also request the show mode
+ * {@code SHOW_MODE_HIDDEN}, where the soft keyboard is never shown.
*
* @param controller the soft keyboard controller
* @param showMode the current soft keyboard show mode
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 079bdfc..75680e6 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -686,6 +686,11 @@
return null;
}
+ /** {@hide} */
+ public boolean isEncryptionAware() {
+ return mResolveInfo.serviceInfo.encryptionAware;
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 1d9e3bb..e520b40 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -353,8 +353,7 @@
try {
return mService.getPassword(account);
} catch (RemoteException e) {
- // won't ever happen
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -382,8 +381,7 @@
try {
return mService.getUserData(account, key);
} catch (RemoteException e) {
- // won't ever happen
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -402,8 +400,7 @@
try {
return mService.getAuthenticatorTypes(UserHandle.getCallingUserId());
} catch (RemoteException e) {
- // will never happen
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -424,8 +421,7 @@
try {
return mService.getAuthenticatorTypes(userId);
} catch (RemoteException e) {
- // will never happen
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -449,8 +445,7 @@
try {
return mService.getAccounts(null, mContext.getOpPackageName());
} catch (RemoteException e) {
- // won't ever happen
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -475,8 +470,7 @@
try {
return mService.getAccountsAsUser(null, userId, mContext.getOpPackageName());
} catch (RemoteException e) {
- // won't ever happen
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -493,8 +487,7 @@
try {
return mService.getAccountsForPackage(packageName, uid, mContext.getOpPackageName());
} catch (RemoteException re) {
- // won't ever happen
- throw new RuntimeException(re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -512,8 +505,7 @@
return mService.getAccountsByTypeForPackage(type, packageName,
mContext.getOpPackageName());
} catch (RemoteException re) {
- // won't ever happen
- throw new RuntimeException(re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -552,8 +544,7 @@
return mService.getAccountsAsUser(type, userHandle.getIdentifier(),
mContext.getOpPackageName());
} catch (RemoteException e) {
- // won't ever happen
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -572,8 +563,7 @@
try {
mService.updateAppPermission(account, authTokenType, uid, value);
} catch (RemoteException e) {
- // won't ever happen
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -742,8 +732,7 @@
try {
return mService.addAccountExplicitly(account, password, userdata);
} catch (RemoteException e) {
- // Can happen if there was a SecurityException was thrown.
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -768,7 +757,7 @@
try {
return mService.accountAuthenticated(account);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -836,8 +825,7 @@
try {
return mService.getPreviousName(account);
} catch (RemoteException e) {
- // will never happen
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1008,8 +996,7 @@
try {
return mService.removeAccountExplicitly(account);
} catch (RemoteException e) {
- // May happen if the caller doesn't match the signature of the authenticator.
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1036,8 +1023,7 @@
mService.invalidateAuthToken(accountType, authToken);
}
} catch (RemoteException e) {
- // won't ever happen
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1068,8 +1054,7 @@
try {
return mService.peekAuthToken(account, authTokenType);
} catch (RemoteException e) {
- // won't ever happen
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1098,8 +1083,7 @@
try {
mService.setPassword(account, password);
} catch (RemoteException e) {
- // won't ever happen
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1127,8 +1111,7 @@
try {
mService.clearPassword(account);
} catch (RemoteException e) {
- // won't ever happen
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1156,8 +1139,7 @@
try {
mService.setUserData(account, key, value);
} catch (RemoteException e) {
- // Will happen if there is not signature match.
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1186,8 +1168,7 @@
try {
mService.setAuthToken(account, authTokenType, authToken);
} catch (RemoteException e) {
- // won't ever happen
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1588,7 +1569,7 @@
mService.addSharedAccountsFromParentUser(parentUser.getIdentifier(),
user.getIdentifier());
} catch (RemoteException re) {
- throw new IllegalStateException(re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -1641,8 +1622,7 @@
boolean val = mService.removeSharedAccountAsUser(account, user.getIdentifier());
return val;
} catch (RemoteException re) {
- // won't ever happen
- throw new RuntimeException(re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -1655,8 +1635,7 @@
try {
return mService.getSharedAccountsAsUser(user.getIdentifier());
} catch (RemoteException re) {
- // won't ever happen
- throw new RuntimeException(re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -1878,7 +1857,7 @@
try {
return mService.someUserHasAccount(account);
} catch (RemoteException re) {
- throw new RuntimeException(re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -2039,8 +2018,7 @@
try {
doWork();
} catch (RemoteException e) {
- // this will only happen if the system process is dead, which means
- // we will be dying ourselves
+ throw e.rethrowFromSystemServer();
}
} else {
set(bundle);
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java
index 20d71a6..8d03b55 100644
--- a/core/java/android/animation/AnimatorInflater.java
+++ b/core/java/android/animation/AnimatorInflater.java
@@ -108,7 +108,7 @@
float pathErrorScale) throws NotFoundException {
final ConfigurationBoundResourceCache<Animator> animatorCache = resources
.getAnimatorCache();
- Animator animator = animatorCache.getInstance(id, theme);
+ Animator animator = animatorCache.getInstance(id, resources, theme);
if (animator != null) {
if (DBG_ANIMATOR_INFLATER) {
Log.d(TAG, "loaded animator from cache, " + resources.getResourceName(id));
@@ -157,7 +157,7 @@
final ConfigurationBoundResourceCache<StateListAnimator> cache = resources
.getStateListAnimatorCache();
final Theme theme = context.getTheme();
- StateListAnimator animator = cache.getInstance(id, theme);
+ StateListAnimator animator = cache.getInstance(id, resources, theme);
if (animator != null) {
return animator;
}
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 980329f..3385a17 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -807,6 +807,8 @@
}
/**
+ * AnimatorSet is only reversible when the set contains no sequential animation, and no child
+ * animators have a start delay.
* @hide
*/
@Override
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index e721de9..5ab2c1d 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -1029,8 +1029,16 @@
@Override
public void resume() {
- if (mPaused) {
+ if (Looper.myLooper() == null) {
+ throw new AndroidRuntimeException("Animators may only be resumed from the same " +
+ "thread that the animator was started on");
+ }
+ if (mPaused && !mResumed) {
mResumed = true;
+ if (mPauseTime > 0) {
+ AnimationHandler handler = AnimationHandler.getInstance();
+ handler.addAnimationFrameCallback(this, 0);
+ }
}
super.resume();
}
@@ -1235,9 +1243,8 @@
}
mLastFrameTime = frameTime;
if (mPaused) {
- if (mPauseTime < 0) {
- mPauseTime = frameTime;
- }
+ mPauseTime = frameTime;
+ handler.removeCallback(this);
return;
} else if (mResumed) {
mResumed = false;
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index e3adbda..b87e9fa2 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -41,6 +41,7 @@
import android.content.IntentSender;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
@@ -68,6 +69,7 @@
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.StrictMode;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.text.Selection;
import android.text.SpannableStringBuilder;
@@ -110,6 +112,7 @@
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityEvent;
import android.widget.AdapterView;
+import android.widget.Toast;
import android.widget.Toolbar;
import com.android.internal.app.IVoiceInteractor;
@@ -815,6 +818,9 @@
private int mDefaultKeyMode = DEFAULT_KEYS_DISABLE;
private SpannableStringBuilder mDefaultKeySsb = null;
+ private ActivityManager.TaskDescription mTaskDescription =
+ new ActivityManager.TaskDescription();
+
protected static final int[] FOCUSED_STATE_SET = {com.android.internal.R.attr.state_focused};
@SuppressWarnings("unused")
@@ -829,6 +835,8 @@
private boolean mHasCurrentPermissionsRequest;
private boolean mEatKeyUpEvent;
+ private static native String getDlWarning();
+
/** Return the intent that started this activity. */
public Intent getIntent() {
return mIntent;
@@ -1136,6 +1144,7 @@
mTitleReady = true;
onTitleChanged(getTitle(), getTitleColor());
}
+
mCalled = true;
}
@@ -3977,55 +3986,25 @@
}
// Get the primary color and update the TaskDescription for this activity
- if (theme != null) {
- TypedArray a = theme.obtainStyledAttributes(com.android.internal.R.styleable.Theme);
- int windowBgResourceId = a.getResourceId(
- com.android.internal.R.styleable.Window_windowBackground, 0);
- int windowBgFallbackResourceId = a.getResourceId(
- com.android.internal.R.styleable.Window_windowBackgroundFallback, 0);
- int colorPrimary = a.getColor(com.android.internal.R.styleable.Theme_colorPrimary, 0);
- int colorBg = tryExtractColorFromDrawable(DecorView.getResizingBackgroundDrawable(this,
- windowBgResourceId, windowBgFallbackResourceId));
- a.recycle();
- if (colorPrimary != 0) {
- ActivityManager.TaskDescription td = new ActivityManager.TaskDescription();
- if (Color.alpha(colorPrimary) == 0xFF) {
- td.setPrimaryColor(colorPrimary);
- }
- if (Color.alpha(colorBg) == 0xFF) {
- td.setBackgroundColor(colorBg);
- }
- setTaskDescription(td);
+ TypedArray a = theme.obtainStyledAttributes(
+ com.android.internal.R.styleable.ActivityTaskDescription);
+ if (mTaskDescription.getPrimaryColor() == 0) {
+ int colorPrimary = a.getColor(
+ com.android.internal.R.styleable.ActivityTaskDescription_colorPrimary, 0);
+ if (colorPrimary != 0 && Color.alpha(colorPrimary) == 0xFF) {
+ mTaskDescription.setPrimaryColor(colorPrimary);
}
}
- }
-
- /**
- * Attempts to extract the color from a given drawable.
- *
- * @return the extracted color or 0 if no color could be extracted.
- */
- private int tryExtractColorFromDrawable(Drawable drawable) {
- if (drawable instanceof ColorDrawable) {
- return ((ColorDrawable) drawable).getColor();
- } else if (drawable instanceof InsetDrawable) {
- return tryExtractColorFromDrawable(((InsetDrawable) drawable).getDrawable());
- } else if (drawable instanceof ShapeDrawable) {
- Paint p = ((ShapeDrawable) drawable).getPaint();
- if (p != null) {
- return p.getColor();
- }
- } else if (drawable instanceof LayerDrawable) {
- LayerDrawable ld = (LayerDrawable) drawable;
- int numLayers = ld.getNumberOfLayers();
- for (int i = 0; i < numLayers; i++) {
- int color = tryExtractColorFromDrawable(ld.getDrawable(i));
- if (color != 0) {
- return color;
- }
+ // For dev-preview only.
+ if (mTaskDescription.getBackgroundColor() == 0) {
+ int colorBackground = a.getColor(
+ com.android.internal.R.styleable.ActivityTaskDescription_colorBackground, 0);
+ if (colorBackground != 0 && Color.alpha(colorBackground) == 0xFF) {
+ mTaskDescription.setBackgroundColor(colorBackground);
}
}
- return 0;
+ a.recycle();
+ setTaskDescription(mTaskDescription);
}
/**
@@ -4100,7 +4079,7 @@
* }
* </code></pre></p>
*
- * @param permissions The requested permissions.
+ * @param permissions The requested permissions. Must me non-null and not empty.
* @param requestCode Application specific request code to match with a result
* reported to {@link #onRequestPermissionsResult(int, String[], int[])}.
* Should be >= 0.
@@ -5651,18 +5630,18 @@
* @param taskDescription The TaskDescription properties that describe the task with this activity
*/
public void setTaskDescription(ActivityManager.TaskDescription taskDescription) {
- ActivityManager.TaskDescription td;
- // Scale the icon down to something reasonable if it is provided
- if (taskDescription.getIconFilename() == null && taskDescription.getIcon() != null) {
- final int size = ActivityManager.getLauncherLargeIconSizeInner(this);
- final Bitmap icon = Bitmap.createScaledBitmap(taskDescription.getIcon(), size, size, true);
- td = new ActivityManager.TaskDescription(taskDescription);
- td.setIcon(icon);
- } else {
- td = taskDescription;
+ if (mTaskDescription != taskDescription) {
+ mTaskDescription.copyFrom(taskDescription);
+ // Scale the icon down to something reasonable if it is provided
+ if (taskDescription.getIconFilename() == null && taskDescription.getIcon() != null) {
+ final int size = ActivityManager.getLauncherLargeIconSizeInner(this);
+ final Bitmap icon = Bitmap.createScaledBitmap(taskDescription.getIcon(), size, size,
+ true);
+ mTaskDescription.setIcon(icon);
+ }
}
try {
- ActivityManagerNative.getDefault().setTaskDescription(mToken, td);
+ ActivityManagerNative.getDefault().setTaskDescription(mToken, mTaskDescription);
} catch (RemoteException e) {
}
}
@@ -6611,6 +6590,32 @@
}
mFragments.dispatchStart();
mFragments.reportLoaderStart();
+
+ // This property is set for all builds except final release
+ boolean isDlwarningEnabled = SystemProperties.getInt("ro.bionic.ld.warning", 0) == 1;
+ boolean isAppDebuggable =
+ (mApplication.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
+
+ if (isAppDebuggable || isDlwarningEnabled) {
+ String dlwarning = getDlWarning();
+ if (dlwarning != null) {
+ String appName = getApplicationInfo().loadLabel(getPackageManager())
+ .toString();
+ String warning = "Detected problems with app native libraries\n" +
+ "(please consult log for detail):\n" + dlwarning;
+ if (isAppDebuggable) {
+ new AlertDialog.Builder(this).
+ setTitle(appName).
+ setMessage(warning).
+ setPositiveButton(android.R.string.ok, null).
+ setCancelable(false).
+ show();
+ } else {
+ Toast.makeText(this, appName + "\n" + warning, Toast.LENGTH_LONG).show();
+ }
+ }
+ }
+
mActivityTransitionState.enterReady(this);
}
@@ -6618,9 +6623,7 @@
mFragments.noteStateNotSaved();
if (mToken != null && mParent == null) {
- // We might have view roots that were preserved during a relaunch, we need to start them
- // again. We don't need to check mStopped, the roots will check if they were actually
- // stopped.
+ // No need to check mStopped, the roots will check if they were actually stopped.
WindowManagerGlobal.getInstance().setStoppedState(mToken, false /* stopped */);
}
@@ -6718,7 +6721,7 @@
onUserLeaveHint();
}
- final void performStop() {
+ final void performStop(boolean preserveWindow) {
mDoReportFullyDrawn = false;
mFragments.doLoaderStop(mChangingConfigurations /*retain*/);
@@ -6727,7 +6730,10 @@
mWindow.closeAllPanels();
}
- if (mToken != null && mParent == null) {
+ // If we're preserving the window, don't setStoppedState to true, since we
+ // need the window started immediately again. Stopping the window will
+ // destroys hardware resources and causes flicker.
+ if (!preserveWindow && mToken != null && mParent == null) {
WindowManagerGlobal.getInstance().setStoppedState(mToken, true);
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 7771139..a4e5b90 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -577,6 +577,16 @@
}
/**
+ * Return whether a stackId is a stack containing floating windows. Floating windows
+ * are laid out differently as they are allowed to extend past the display bounds
+ * without overscan insets.
+ */
+ public static boolean tasksAreFloating(int stackId) {
+ return stackId == FREEFORM_WORKSPACE_STACK_ID
+ || stackId == PINNED_STACK_ID;
+ }
+
+ /**
* Returns true if animation specs should be constructed for app transition that moves
* the task to the specified stack.
*/
@@ -647,6 +657,16 @@
return stackId != PINNED_STACK_ID && stackId != FREEFORM_WORKSPACE_STACK_ID
&& stackId != DOCKED_STACK_ID;
}
+
+ /**
+ * Returns true if the input stack id should only be present on a device that supports
+ * multi-window mode.
+ * @see android.app.ActivityManager#supportsMultiWindow
+ */
+ public static boolean isMultiWindowStack(int stackId) {
+ return isStaticStack(stackId) || stackId == PINNED_STACK_ID
+ || stackId == FREEFORM_WORKSPACE_STACK_ID || stackId == DOCKED_STACK_ID;
+ }
}
/**
@@ -716,8 +736,7 @@
try {
return ActivityManagerNative.getDefault().getFrontActivityScreenCompatMode();
} catch (RemoteException e) {
- // System dead, we will be dead too soon!
- return 0;
+ throw e.rethrowFromSystemServer();
}
}
@@ -726,7 +745,7 @@
try {
ActivityManagerNative.getDefault().setFrontActivityScreenCompatMode(mode);
} catch (RemoteException e) {
- // System dead, we will be dead too soon!
+ throw e.rethrowFromSystemServer();
}
}
@@ -735,8 +754,7 @@
try {
return ActivityManagerNative.getDefault().getPackageScreenCompatMode(packageName);
} catch (RemoteException e) {
- // System dead, we will be dead too soon!
- return 0;
+ throw e.rethrowFromSystemServer();
}
}
@@ -745,7 +763,7 @@
try {
ActivityManagerNative.getDefault().setPackageScreenCompatMode(packageName, mode);
} catch (RemoteException e) {
- // System dead, we will be dead too soon!
+ throw e.rethrowFromSystemServer();
}
}
@@ -754,8 +772,7 @@
try {
return ActivityManagerNative.getDefault().getPackageAskScreenCompat(packageName);
} catch (RemoteException e) {
- // System dead, we will be dead too soon!
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -764,7 +781,7 @@
try {
ActivityManagerNative.getDefault().setPackageAskScreenCompat(packageName, ask);
} catch (RemoteException e) {
- // System dead, we will be dead too soon!
+ throw e.rethrowFromSystemServer();
}
}
@@ -871,6 +888,17 @@
}
/**
+ * Returns true if the system supports at least one form of multi-window.
+ * E.g. freeform, split-screen, picture-in-picture.
+ * @hide
+ */
+ static public boolean supportsMultiWindow() {
+ return !isLowRamDeviceStatic()
+ && Resources.getSystem().getBoolean(
+ com.android.internal.R.bool.config_supportsMultiWindow);
+ }
+
+ /**
* Information you can set and retrieve about the current activity within the recent task list.
*/
public static class TaskDescription implements Parcelable {
@@ -946,11 +974,19 @@
* Creates a copy of another TaskDescription.
*/
public TaskDescription(TaskDescription td) {
- mLabel = td.mLabel;
- mIcon = td.mIcon;
- mIconFilename = td.mIconFilename;
- mColorPrimary = td.mColorPrimary;
- mColorBackground = td.mColorBackground;
+ copyFrom(td);
+ }
+
+ /**
+ * Copies this the values from another TaskDescription.
+ * @hide
+ */
+ public void copyFrom(TaskDescription other) {
+ mLabel = other.mLabel;
+ mIcon = other.mIcon;
+ mIconFilename = other.mIconFilename;
+ mColorPrimary = other.mColorPrimary;
+ mColorBackground = other.mColorBackground;
}
private TaskDescription(Parcel source) {
@@ -1041,6 +1077,7 @@
return ActivityManagerNative.getDefault().getTaskDescriptionIcon(iconFilename,
userId);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -1421,8 +1458,7 @@
return ActivityManagerNative.getDefault().getRecentTasks(maxNum,
flags, UserHandle.myUserId());
} catch (RemoteException e) {
- // System dead, we will be dead too soon!
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1447,8 +1483,7 @@
return ActivityManagerNative.getDefault().getRecentTasks(maxNum,
flags, userId);
} catch (RemoteException e) {
- // System dead, we will be dead too soon!
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1583,8 +1618,7 @@
try {
appTasks = ActivityManagerNative.getDefault().getAppTasks(mContext.getPackageName());
} catch (RemoteException e) {
- // System dead, we will be dead too soon!
- return null;
+ throw e.rethrowFromSystemServer();
}
int numAppTasks = appTasks.size();
for (int i = 0; i < numAppTasks; i++) {
@@ -1609,7 +1643,7 @@
try {
mAppTaskThumbnailSize = ActivityManagerNative.getDefault().getAppTaskThumbnailSize();
} catch (RemoteException e) {
- throw new IllegalStateException("System dead?", e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1675,7 +1709,7 @@
return ActivityManagerNative.getDefault().addAppTask(activity.getActivityToken(),
intent, description, thumbnail);
} catch (RemoteException e) {
- throw new IllegalStateException("System dead?", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1717,8 +1751,7 @@
try {
return ActivityManagerNative.getDefault().getTasks(maxNum, 0);
} catch (RemoteException e) {
- // System dead, we will be dead too soon!
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1734,8 +1767,7 @@
try {
return ActivityManagerNative.getDefault().removeTask(taskId);
} catch (RemoteException e) {
- // System dead, we will be dead too soon!
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1894,8 +1926,7 @@
try {
return ActivityManagerNative.getDefault().getTaskThumbnail(id);
} catch (RemoteException e) {
- // System dead, we will be dead too soon!
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1904,8 +1935,7 @@
try {
return ActivityManagerNative.getDefault().isInHomeStack(taskId);
} catch (RemoteException e) {
- // System dead, we will be dead too soon!
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1954,7 +1984,7 @@
try {
ActivityManagerNative.getDefault().moveTaskToFront(taskId, flags, options);
} catch (RemoteException e) {
- // System dead, we will be dead too soon!
+ throw e.rethrowFromSystemServer();
}
}
@@ -2140,8 +2170,7 @@
return ActivityManagerNative.getDefault()
.getServices(maxNum, 0);
} catch (RemoteException e) {
- // System dead, we will be dead too soon!
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2156,8 +2185,7 @@
return ActivityManagerNative.getDefault()
.getRunningServiceControlPanel(service);
} catch (RemoteException e) {
- // System dead, we will be dead too soon!
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2261,6 +2289,7 @@
try {
ActivityManagerNative.getDefault().getMemoryInfo(outInfo);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2379,7 +2408,7 @@
return ActivityManagerNative.getDefault().clearApplicationUserData(packageName,
observer, UserHandle.myUserId());
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2413,8 +2442,7 @@
return ActivityManagerNative.getDefault().getGrantedUriPermissions(packageName,
UserHandle.myUserId());
} catch (RemoteException e) {
- Log.e(TAG, "Couldn't get granted URI permissions for :" + packageName, e);
- return ParceledListSlice.emptyList();
+ throw e.rethrowFromSystemServer();
}
}
@@ -2432,7 +2460,7 @@
ActivityManagerNative.getDefault().clearGrantedUriPermissions(packageName,
UserHandle.myUserId());
} catch (RemoteException e) {
- Log.e(TAG, "Couldn't clear granted URI permissions for :" + packageName, e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2552,7 +2580,7 @@
try {
return ActivityManagerNative.getDefault().getProcessesInErrorState();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2866,7 +2894,7 @@
try {
return ActivityManagerNative.getDefault().getRunningExternalApplications();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2883,7 +2911,7 @@
return ActivityManagerNative.getDefault().setProcessMemoryTrimLevel(process, userId,
level);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2901,7 +2929,7 @@
try {
return ActivityManagerNative.getDefault().getRunningAppProcesses();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2920,7 +2948,7 @@
mContext.getOpPackageName());
return RunningAppProcessInfo.procStateToImportance(procState);
} catch (RemoteException e) {
- return RunningAppProcessInfo.IMPORTANCE_GONE;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2939,6 +2967,7 @@
try {
ActivityManagerNative.getDefault().getMyMemoryState(outState);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2957,7 +2986,7 @@
try {
return ActivityManagerNative.getDefault().getProcessMemoryInfo(pids);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2991,6 +3020,7 @@
ActivityManagerNative.getDefault().killBackgroundProcesses(packageName,
UserHandle.myUserId());
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -3007,7 +3037,7 @@
ActivityManagerNative.getDefault().killUid(UserHandle.getAppId(uid),
UserHandle.getUserId(uid), reason);
} catch (RemoteException e) {
- Log.e(TAG, "Couldn't kill uid:" + uid, e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -3034,6 +3064,7 @@
try {
ActivityManagerNative.getDefault().forceStopPackage(packageName, userId);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -3052,8 +3083,8 @@
try {
return ActivityManagerNative.getDefault().getDeviceConfigurationInfo();
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return null;
}
/**
@@ -3142,8 +3173,8 @@
try {
return ActivityManagerNative.getDefault().isUserAMonkey();
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return false;
}
/**
@@ -3218,10 +3249,8 @@
return AppGlobals.getPackageManager()
.checkUidPermission(permission, uid);
} catch (RemoteException e) {
- // Should never happen, but if it does... deny!
- Slog.e(TAG, "PackageManager is dead?!?", e);
+ throw e.rethrowFromSystemServer();
}
- return PackageManager.PERMISSION_DENIED;
}
/** @hide */
@@ -3230,10 +3259,8 @@
return AppGlobals.getPackageManager()
.checkUidPermission(permission, uid);
} catch (RemoteException e) {
- // Should never happen, but if it does... deny!
- Slog.e(TAG, "PackageManager is dead?!?", e);
+ throw e.rethrowFromSystemServer();
}
- return PackageManager.PERMISSION_DENIED;
}
/**
@@ -3269,7 +3296,7 @@
return ActivityManagerNative.getDefault().handleIncomingUser(callingPid,
callingUid, userId, allowAll, requireFull, name, callerPackage);
} catch (RemoteException e) {
- throw new SecurityException("Failed calling activity manager", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -3284,7 +3311,7 @@
ui = ActivityManagerNative.getDefault().getCurrentUser();
return ui != null ? ui.id : 0;
} catch (RemoteException e) {
- return 0;
+ throw e.rethrowFromSystemServer();
}
}
@@ -3296,7 +3323,7 @@
try {
return ActivityManagerNative.getDefault().switchUser(userid);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -3320,7 +3347,7 @@
try {
return ActivityManagerNative.getDefault().isUserRunning(userId, 0);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -3330,7 +3357,7 @@
return ActivityManagerNative.getDefault().isUserRunning(userId,
ActivityManager.FLAG_AND_LOCKED);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -3340,7 +3367,7 @@
return ActivityManagerNative.getDefault().isUserRunning(userId,
ActivityManager.FLAG_AND_UNLOCKED);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -3425,6 +3452,7 @@
ActivityManagerNative.getDefault().setDumpHeapDebugLimit(null, 0, pssSize,
mContext.getPackageName());
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -3443,6 +3471,7 @@
try {
ActivityManagerNative.getDefault().setDumpHeapDebugLimit(null, 0, 0, null);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -3453,6 +3482,7 @@
try {
ActivityManagerNative.getDefault().startLockTaskMode(taskId);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -3463,6 +3493,7 @@
try {
ActivityManagerNative.getDefault().stopLockTaskMode();
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -3489,7 +3520,7 @@
try {
return ActivityManagerNative.getDefault().getLockTaskModeState();
} catch (RemoteException e) {
- return ActivityManager.LOCK_TASK_MODE_NONE;
+ throw e.rethrowFromSystemServer();
}
}
@@ -3512,7 +3543,7 @@
try {
mAppTaskImpl.finishAndRemoveTask();
} catch (RemoteException e) {
- Slog.e(TAG, "Invalid AppTask", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -3525,8 +3556,7 @@
try {
return mAppTaskImpl.getTaskInfo();
} catch (RemoteException e) {
- Slog.e(TAG, "Invalid AppTask", e);
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -3540,7 +3570,7 @@
try {
mAppTaskImpl.moveToFront();
} catch (RemoteException e) {
- Slog.e(TAG, "Invalid AppTask", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -3582,7 +3612,7 @@
try {
mAppTaskImpl.setExcludeFromRecents(exclude);
} catch (RemoteException e) {
- Slog.e(TAG, "Invalid AppTask", e);
+ throw e.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 4fa654f..7310d67 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -29,6 +29,31 @@
* @hide Only for use within the system server.
*/
public abstract class ActivityManagerInternal {
+
+ /**
+ * Type for {@link #notifyAppTransitionStarting}: The transition was started because we had
+ * the surface saved.
+ */
+ public static final int APP_TRANSITION_SAVED_SURFACE = 0;
+
+ /**
+ * Type for {@link #notifyAppTransitionStarting}: The transition was started because we drew
+ * the starting window.
+ */
+ public static final int APP_TRANSITION_STARTING_WINDOW = 1;
+
+ /**
+ * Type for {@link #notifyAppTransitionStarting}: The transition was started because we all
+ * app windows were drawn
+ */
+ public static final int APP_TRANSITION_WINDOWS_DRAWN = 2;
+
+ /**
+ * Type for {@link #notifyAppTransitionStarting}: The transition was started because of a
+ * timeout.
+ */
+ public static final int APP_TRANSITION_TIMEOUT = 3;
+
// Called by the power manager.
public abstract void onWakefulnessChanged(int wakefulness);
@@ -48,6 +73,7 @@
* with underlying activities.
*/
public static abstract class SleepToken {
+
/**
* Releases the sleep token.
*/
@@ -56,6 +82,7 @@
/**
* Returns home activity for the specified user.
+ *
* @param userId ID of the user or {@link android.os.UserHandle#USER_ALL}
*/
public abstract ComponentName getHomeActivityForUser(int userId);
@@ -72,4 +99,19 @@
public abstract void onLocalVoiceInteractionStarted(IBinder callingActivity,
IVoiceInteractionSession mSession,
IVoiceInteractor mInteractor);
+
+ /**
+ * Callback for window manager to let activity manager know that the starting window has been
+ * drawn
+ */
+ public abstract void notifyStartingWindowDrawn();
+
+ /**
+ * Callback for window manager to let activity manager know that we are finally starting the
+ * app transition;
+ *
+ * @param reason The reason why the app transition started. Must be one of the APP_TRANSITION_*
+ * values.
+ */
+ public abstract void notifyAppTransitionStarting(int reason);
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 04979ef..ff7f70d 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -792,8 +792,9 @@
if (hasBounds) {
bounds = Rect.CREATOR.createFromParcel(data);
}
- moveTaskToDockedStack(taskId, createMode, toTop, animate, bounds);
+ boolean res = moveTaskToDockedStack(taskId, createMode, toTop, animate, bounds);
reply.writeNoException();
+ reply.writeInt(res ? 1 : 0);
return true;
}
@@ -822,7 +823,21 @@
reply.writeNoException();
return true;
}
-
+ case RESIZE_PINNED_STACK_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ final boolean hasBounds = data.readInt() != 0;
+ Rect bounds = null;
+ if (hasBounds) {
+ bounds = Rect.CREATOR.createFromParcel(data);
+ }
+ final boolean hasTempPinnedTaskBounds = data.readInt() != 0;
+ Rect tempPinnedTaskBounds = null;
+ if (hasTempPinnedTaskBounds) {
+ tempPinnedTaskBounds = Rect.CREATOR.createFromParcel(data);
+ }
+ resizePinnedStack(bounds, tempPinnedTaskBounds);
+ return true;
+ }
case RESIZE_DOCKED_STACK_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
final boolean hasBounds = data.readInt() != 0;
@@ -1527,11 +1542,28 @@
data.enforceInterface(IActivityManager.descriptor);
IActivityController watcher = IActivityController.Stub.asInterface(
data.readStrongBinder());
- setActivityController(watcher);
+ boolean imAMonkey = data.readInt() != 0;
+ setActivityController(watcher, imAMonkey);
reply.writeNoException();
return true;
}
+ case SET_LENIENT_BACKGROUND_CHECK_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ boolean enabled = data.readInt() != 0;
+ setLenientBackgroundCheck(enabled);
+ reply.writeNoException();
+ return true;
+ }
+
+ case GET_MEMORY_TRIM_LEVEL_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ int level = getMemoryTrimLevel();
+ reply.writeNoException();
+ reply.writeInt(level);
+ return true;
+ }
+
case ENTER_SAFE_MODE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
enterSafeMode();
@@ -3792,7 +3824,7 @@
reply.recycle();
}
@Override
- public void moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
+ public boolean moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
Rect initialBounds) throws RemoteException
{
Parcel data = Parcel.obtain();
@@ -3810,8 +3842,10 @@
}
mRemote.transact(MOVE_TASK_TO_DOCKED_STACK_TRANSACTION, data, reply, 0);
reply.readException();
+ boolean res = reply.readInt() > 0;
data.recycle();
reply.recycle();
+ return res;
}
@Override
public boolean moveTopActivityToPinnedStack(int stackId, Rect r)
@@ -3894,6 +3928,31 @@
data.recycle();
reply.recycle();
}
+
+ @Override
+ public void resizePinnedStack(Rect pinnedBounds, Rect tempPinnedTaskBounds) throws RemoteException
+ {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ if (pinnedBounds != null) {
+ data.writeInt(1);
+ pinnedBounds.writeToParcel(data, 0);
+ } else {
+ data.writeInt(0);
+ }
+ if (tempPinnedTaskBounds != null) {
+ data.writeInt(1);
+ tempPinnedTaskBounds.writeToParcel(data, 0);
+ } else {
+ data.writeInt(0);
+ }
+ mRemote.transact(RESIZE_PINNED_STACK_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
@Override
public void positionTaskInStack(int taskId, int stackId, int position) throws RemoteException
{
@@ -4844,17 +4903,42 @@
data.recycle();
reply.recycle();
}
- public void setActivityController(IActivityController watcher) throws RemoteException
+ public void setActivityController(IActivityController watcher, boolean imAMonkey)
+ throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(watcher != null ? watcher.asBinder() : null);
+ data.writeInt(imAMonkey ? 1 : 0);
mRemote.transact(SET_ACTIVITY_CONTROLLER_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}
+ public void setLenientBackgroundCheck(boolean enabled) throws RemoteException
+ {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeInt(enabled ? 1 : 0);
+ mRemote.transact(SET_LENIENT_BACKGROUND_CHECK_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+ public int getMemoryTrimLevel() throws RemoteException
+ {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ mRemote.transact(GET_MEMORY_TRIM_LEVEL_TRANSACTION, data, reply, 0);
+ reply.readException();
+ int level = reply.readInt();
+ data.recycle();
+ reply.recycle();
+ return level;
+ }
public void enterSafeMode() throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 04883a9..a452d20 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -75,6 +75,7 @@
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
+import android.os.TransactionTooLargeException;
import android.os.UserHandle;
import android.provider.Settings;
import android.security.NetworkSecurityPolicy;
@@ -112,6 +113,7 @@
import com.android.internal.os.RuntimeInit;
import com.android.internal.os.SamplingProfilerIntegration;
import com.android.internal.os.SomeArgs;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.org.conscrypt.OpenSSLSocketImpl;
import com.android.org.conscrypt.TrustedCertificateStore;
@@ -174,6 +176,7 @@
private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003;
private static final int LOG_AM_ON_PAUSE_CALLED = 30021;
private static final int LOG_AM_ON_RESUME_CALLED = 30022;
+ private static final int LOG_AM_ON_STOP_CALLED = 30049;
/** Type for IActivityManager.serviceDoneExecuting: anonymous operation */
public static final int SERVICE_DONE_EXECUTING_ANON = 0;
@@ -191,7 +194,7 @@
private ContextImpl mSystemContext;
- static IPackageManager sPackageManager;
+ static volatile IPackageManager sPackageManager;
final ApplicationThread mAppThread = new ApplicationThread();
final Looper mLooper = Looper.myLooper();
@@ -216,7 +219,7 @@
// set of instantiated backup agents, keyed by package name
final ArrayMap<String, BackupAgent> mBackupAgents = new ArrayMap<String, BackupAgent>();
/** Reference to singleton {@link ActivityThread} */
- private static ActivityThread sCurrentActivityThread;
+ private static volatile ActivityThread sCurrentActivityThread;
Instrumentation mInstrumentation;
String mInstrumentationPackageName = null;
String mInstrumentationAppDir = null;
@@ -294,7 +297,7 @@
final GcIdler mGcIdler = new GcIdler();
boolean mGcIdlerScheduled = false;
- static Handler sMainThreadHandler; // set once in main()
+ static volatile Handler sMainThreadHandler; // set once in main()
Bundle mCoreSettings = null;
@@ -977,18 +980,19 @@
@Override
public void dumpMemInfo(FileDescriptor fd, Debug.MemoryInfo mem, boolean checkin,
- boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly, String[] args) {
+ boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
+ boolean dumpUnreachable, String[] args) {
FileOutputStream fout = new FileOutputStream(fd);
PrintWriter pw = new FastPrintWriter(fout);
try {
- dumpMemInfo(pw, mem, checkin, dumpFullInfo, dumpDalvik, dumpSummaryOnly);
+ dumpMemInfo(pw, mem, checkin, dumpFullInfo, dumpDalvik, dumpSummaryOnly, dumpUnreachable);
} finally {
pw.flush();
}
}
private void dumpMemInfo(PrintWriter pw, Debug.MemoryInfo memInfo, boolean checkin,
- boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly) {
+ boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly, boolean dumpUnreachable) {
long nativeMax = Debug.getNativeHeapSize() / 1024;
long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
@@ -1102,6 +1106,16 @@
pw.println(" Asset Allocations");
pw.print(assetAlloc);
}
+
+ // Unreachable native memory
+ if (dumpUnreachable) {
+ boolean showContents = ((mBoundApplication != null)
+ && ((mBoundApplication.appInfo.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0))
+ || android.os.Build.IS_DEBUGGABLE;
+ pw.println(" ");
+ pw.println(" Unreachable memory");
+ pw.print(Debug.getUnreachableMemory(100, showContents));
+ }
}
@Override
@@ -1395,7 +1409,7 @@
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
- handleLaunchActivity(r, null);
+ handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case RELAUNCH_ACTIVITY: {
@@ -1446,7 +1460,7 @@
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
SomeArgs args = (SomeArgs) msg.obj;
handleResumeActivity((IBinder) args.arg1, true, args.argi1 != 0, true,
- args.argi3);
+ args.argi3, "RESUME_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SEND_RESULT:
@@ -1693,7 +1707,7 @@
am.activityIdle(a.token, a.createdConfig, stopProfiling);
a.createdConfig = null;
} catch (RemoteException ex) {
- // Ignore
+ throw ex.rethrowFromSystemServer();
}
}
prev = a;
@@ -1775,7 +1789,8 @@
}
/**
- * Creates the top level resources for the given package.
+ * Creates the top level resources for the given package. Will return an existing
+ * Resources if one has already been created.
*/
Resources getTopLevelResources(String resDir, String[] splitResDirs, String[] overlayDirs,
String[] libDirs, int displayId, Configuration overrideConfiguration,
@@ -1785,6 +1800,19 @@
pkgInfo.getClassLoader());
}
+ /**
+ * Creates a new top level resources for the given package. Will always create a new
+ * Resources, regardless if one has already been created.
+ */
+ Resources getNewTopLevelResources(String resDir, String[] splitResDirs, String[] overlayDirs,
+ String[] libDirs, int displayId, Configuration overrideConfiguration,
+ LoadedApk pkgInfo) {
+ mResourcesManager.removeTopLevelResources(
+ resDir, displayId, overrideConfiguration, pkgInfo.getCompatibilityInfo());
+ return getTopLevelResources(resDir, splitResDirs, overlayDirs, libDirs,
+ displayId, overrideConfiguration, pkgInfo);
+ }
+
final Handler getHandler() {
return mH;
}
@@ -1833,7 +1861,7 @@
| PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
userId);
} catch (RemoteException e) {
- // Ignore
+ throw e.rethrowFromSystemServer();
}
if (ai != null) {
@@ -2241,8 +2269,8 @@
memInfo.getTotalSwappablePss(),
memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(),
memInfo.getTotalSharedClean(), memInfo.getTotalPrivateClean(),
- memInfo.hasSwappedOutPss ? memInfo.getTotalSwappedOut() :
- memInfo.getTotalSwappedOutPss(),
+ memInfo.hasSwappedOutPss ? memInfo.getTotalSwappedOutPss() :
+ memInfo.getTotalSwappedOut(),
nativeMax+dalvikMax, nativeAllocated+dalvikAllocated,
nativeFree+dalvikFree);
} else {
@@ -2592,6 +2620,7 @@
try {
displayId = ActivityManagerNative.getDefault().getActivityDisplayId(r.token);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
ContextImpl appContext = ContextImpl.createActivityContext(
@@ -2618,7 +2647,7 @@
return baseContext;
}
- private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
+ private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
@@ -2645,7 +2674,7 @@
reportSizeConfigurations(r);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward,
- !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq);
+ !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
if (!r.activity.mFinished && r.startsNotResumed) {
// The activity manager actually wants this one to start out
@@ -2660,6 +2689,8 @@
try {
r.activity.mCalled = false;
mInstrumentation.callActivityOnPause(r.activity);
+ EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(),
+ r.activity.getComponentName().getClassName(), reason);
// We need to keep around the original state, in case
// we need to be created again. But we only do this
// for pre-Honeycomb apps, which always save their state
@@ -2697,7 +2728,7 @@
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
- // Ignore
+ throw ex.rethrowFromSystemServer();
}
}
}
@@ -2726,6 +2757,7 @@
ActivityManagerNative.getDefault().reportSizeConfigurations(r.token,
horizontal.copyKeys(), vertical.copyKeys(), smallest.copyKeys());
} catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
}
}
@@ -2802,6 +2834,7 @@
try {
mgr.reportAssistContextExtras(cmd.requestToken, data, structure, content, referrer);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2838,6 +2871,7 @@
try {
ActivityManagerNative.getDefault().backgroundResourcesReleased(token);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2992,8 +3026,7 @@
return;
}
} catch (RemoteException e) {
- Slog.e(TAG, "Can't reach package manager", e);
- return;
+ throw e.rethrowFromSystemServer();
}
// no longer idle; we have backup work to do
@@ -3054,7 +3087,7 @@
try {
ActivityManagerNative.getDefault().backupAgentCreated(packageName, binder);
} catch (RemoteException e) {
- // nothing to do.
+ throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
throw new RuntimeException("Unable to create BackupAgent "
@@ -3116,7 +3149,7 @@
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
- // nothing to do.
+ throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
@@ -3147,6 +3180,7 @@
}
ensureJitEnabled();
} catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
@@ -3174,6 +3208,7 @@
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
} catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
@@ -3255,7 +3290,7 @@
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
} catch (RemoteException e) {
- // nothing to do.
+ throw e.rethrowFromSystemServer();
}
ensureJitEnabled();
} catch (Exception e) {
@@ -3286,9 +3321,7 @@
ActivityManagerNative.getDefault().serviceDoneExecuting(
token, SERVICE_DONE_EXECUTING_STOP, 0, 0);
} catch (RemoteException e) {
- // nothing to do.
- Slog.i(TAG, "handleStopService: unable to execute serviceDoneExecuting for "
- + token, e);
+ throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
@@ -3305,7 +3338,7 @@
}
public final ActivityClientRecord performResumeActivity(IBinder token,
- boolean clearHide) {
+ boolean clearHide, String reason) {
ActivityClientRecord r = mActivities.get(token);
if (localLOGV) Slog.v(TAG, "Performing resume of " + r
+ " finished=" + r.activity.mFinished);
@@ -3327,8 +3360,20 @@
}
r.activity.performResume();
- EventLog.writeEvent(LOG_AM_ON_RESUME_CALLED,
- UserHandle.myUserId(), r.activity.getComponentName().getClassName());
+ // If there is a pending local relaunch that was requested when the activity was
+ // paused, it will put the activity into paused state when it finally happens.
+ // Since the activity resumed before being relaunched, we don't want that to happen,
+ // so we need to clear the request to relaunch paused.
+ for (int i = mRelaunchingActivities.size() - 1; i >= 0; i--) {
+ final ActivityClientRecord relaunching = mRelaunchingActivities.get(i);
+ if (relaunching.token == r.token
+ && relaunching.onlyLocalRequest && relaunching.startsNotResumed) {
+ relaunching.startsNotResumed = false;
+ }
+ }
+
+ EventLog.writeEvent(LOG_AM_ON_RESUME_CALLED, UserHandle.myUserId(),
+ r.activity.getComponentName().getClassName(), reason);
r.paused = false;
r.stopped = false;
@@ -3364,7 +3409,7 @@
}
final void handleResumeActivity(IBinder token,
- boolean clearHide, boolean isForward, boolean reallyResume, int seq) {
+ boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
ActivityClientRecord r = mActivities.get(token);
if (!checkAndUpdateLifecycleSeq(seq, r, "resumeActivity")) {
return;
@@ -3376,7 +3421,7 @@
mSomeActivitiesChanged = true;
// TODO Push resumeArgs into the activity for consideration
- r = performResumeActivity(token, clearHide);
+ r = performResumeActivity(token, clearHide, reason);
if (r != null) {
final Activity a = r.activity;
@@ -3398,6 +3443,7 @@
willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
a.getActivityToken());
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
if (r.window == null && !a.mFinished && willBeVisible) {
@@ -3481,6 +3527,7 @@
try {
ActivityManagerNative.getDefault().activityResumed(token);
} catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
}
}
@@ -3492,6 +3539,7 @@
.finishActivity(token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
}
}
}
@@ -3555,6 +3603,7 @@
private void handlePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges, boolean dontReport, int seq) {
ActivityClientRecord r = mActivities.get(token);
+ if (DEBUG_ORDER) Slog.d(TAG, "handlePauseActivity " + r + ", seq: " + seq);
if (!checkAndUpdateLifecycleSeq(seq, r, "pauseActivity")) {
return;
}
@@ -3565,7 +3614,7 @@
}
r.activity.mConfigChangeFlags |= configChanges;
- performPauseActivity(token, finished, r.isPreHoneycomb());
+ performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");
// Make sure any pending writes are now committed.
if (r.isPreHoneycomb()) {
@@ -3577,6 +3626,7 @@
try {
ActivityManagerNative.getDefault().activityPaused(token);
} catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
}
}
mSomeActivitiesChanged = true;
@@ -3588,13 +3638,13 @@
}
final Bundle performPauseActivity(IBinder token, boolean finished,
- boolean saveState) {
+ boolean saveState, String reason) {
ActivityClientRecord r = mActivities.get(token);
- return r != null ? performPauseActivity(r, finished, saveState) : null;
+ return r != null ? performPauseActivity(r, finished, saveState, reason) : null;
}
final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
- boolean saveState) {
+ boolean saveState, String reason) {
if (r.paused) {
if (r.activity.mFinished) {
// If we are finishing, we won't call onResume() in certain cases.
@@ -3619,7 +3669,7 @@
r.activity.mCalled = false;
mInstrumentation.callActivityOnPause(r.activity);
EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(),
- r.activity.getComponentName().getClassName());
+ r.activity.getComponentName().getClassName(), reason);
if (!r.activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
@@ -3652,9 +3702,9 @@
return !r.activity.mFinished && saveState ? r.state : null;
}
- final void performStopActivity(IBinder token, boolean saveState) {
+ final void performStopActivity(IBinder token, boolean saveState, String reason) {
ActivityClientRecord r = mActivities.get(token);
- performStopActivityInner(r, null, false, saveState);
+ performStopActivityInner(r, null, false, saveState, reason);
}
private static class StopInfo implements Runnable {
@@ -3670,6 +3720,13 @@
ActivityManagerNative.getDefault().activityStopped(
activity.token, state, persistentState, description);
} catch (RemoteException ex) {
+ if (ex instanceof TransactionTooLargeException
+ && activity.packageInfo.getTargetSdkVersion() < Build.VERSION_CODES.N) {
+ Log.e(TAG, "App tried sending too much data in instance state", ex);
+ return;
+ }
+
+ throw ex.rethrowFromSystemServer();
}
}
}
@@ -3705,7 +3762,7 @@
* the activity's UI visibillity changes.
*/
private void performStopActivityInner(ActivityClientRecord r,
- StopInfo info, boolean keepShown, boolean saveState) {
+ StopInfo info, boolean keepShown, boolean saveState, String reason) {
if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
if (r != null) {
if (!keepShown && r.stopped) {
@@ -3747,7 +3804,7 @@
if (!keepShown) {
try {
// Now we are idle.
- r.activity.performStop();
+ r.activity.performStop(false /*preserveWindow*/);
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException(
@@ -3757,6 +3814,8 @@
}
}
r.stopped = true;
+ EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(),
+ r.activity.getComponentName().getClassName(), reason);
}
r.paused = true;
@@ -3803,7 +3862,7 @@
r.activity.mConfigChangeFlags |= configChanges;
StopInfo info = new StopInfo();
- performStopActivityInner(r, info, show, true);
+ performStopActivityInner(r, info, show, true, "handleStopActivity");
if (localLOGV) Slog.v(
TAG, "Finishing stop of " + r + ": show=" + show
@@ -3859,7 +3918,7 @@
}
if (!show && !r.stopped) {
- performStopActivityInner(r, null, show, false);
+ performStopActivityInner(r, null, show, false, "handleWindowVisibility");
} else if (show && r.stopped) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
@@ -3888,7 +3947,7 @@
if (!r.stopped && !r.isPreHoneycomb()) {
try {
// Now we are idle.
- r.activity.performStop();
+ r.activity.performStop(false /*preserveWindow*/);
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException(
@@ -3898,6 +3957,8 @@
}
}
r.stopped = true;
+ EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(),
+ r.activity.getComponentName().getClassName(), "sleeping");
}
// Make sure any pending writes are now committed.
@@ -3909,6 +3970,7 @@
try {
ActivityManagerNative.getDefault().activitySlept(r.token);
} catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
}
} else {
if (r.stopped && r.activity.mVisibleFromServer) {
@@ -4038,7 +4100,7 @@
r.activity.mCalled = false;
mInstrumentation.callActivityOnPause(r.activity);
EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(),
- r.activity.getComponentName().getClassName());
+ r.activity.getComponentName().getClassName(), "destroy");
if (!r.activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + safeToComponentShortString(r.intent)
@@ -4058,7 +4120,7 @@
}
if (!r.stopped) {
try {
- r.activity.performStop();
+ r.activity.performStop(r.mPreserveWindow);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
@@ -4070,6 +4132,8 @@
}
}
r.stopped = true;
+ EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(),
+ r.activity.getComponentName().getClassName(), "destroy");
}
if (getNonConfigInstance) {
try {
@@ -4175,7 +4239,7 @@
try {
ActivityManagerNative.getDefault().activityDestroyed(token);
} catch (RemoteException ex) {
- // If the system process has died, it's game over for everyone.
+ throw ex.rethrowFromSystemServer();
}
}
mSomeActivitiesChanged = true;
@@ -4194,6 +4258,7 @@
synchronized (mResourcesManager) {
for (int i=0; i<mRelaunchingActivities.size(); i++) {
ActivityClientRecord r = mRelaunchingActivities.get(i);
+ if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: " + this + ", trying: " + r);
if (r.token == token) {
target = r;
if (pendingResults != null) {
@@ -4216,7 +4281,7 @@
try {
ActivityManagerNative.getDefault().activityRelaunched(token);
} catch (RemoteException e) {
- e.printStackTrace();
+ throw e.rethrowFromSystemServer();
}
}
break;
@@ -4224,14 +4289,19 @@
}
if (target == null) {
+ if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: target is null, fromServer:"
+ + fromServer);
target = new ActivityClientRecord();
target.token = token;
target.pendingResults = pendingResults;
target.pendingIntents = pendingNewIntents;
target.mPreserveWindow = preserveWindow;
if (!fromServer) {
- ActivityClientRecord existing = mActivities.get(token);
+ final ActivityClientRecord existing = mActivities.get(token);
+ if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: " + existing);
if (existing != null) {
+ if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: paused= "
+ + existing.paused);;
target.startsNotResumed = existing.paused;
target.overrideConfig = existing.overrideConfig;
}
@@ -4254,8 +4324,8 @@
target.pendingConfigChanges |= configChanges;
target.relaunchSeq = getLifecycleSeq();
}
- if (DEBUG_ORDER) Slog.d(TAG, "relaunchActivity " + ActivityThread.this
- + " operation received seq: " + target.relaunchSeq);
+ if (DEBUG_ORDER) Slog.d(TAG, "relaunchActivity " + ActivityThread.this + ", target "
+ + target + " operation received seq: " + target.relaunchSeq);
}
private void handleRelaunchActivity(ActivityClientRecord tmp) {
@@ -4337,7 +4407,7 @@
try {
ActivityManagerNative.getDefault().activityRelaunched(tmp.token);
} catch (RemoteException e) {
- // If the system process has died, it's game over for everyone.
+ throw e.rethrowFromSystemServer();
}
}
return;
@@ -4363,13 +4433,13 @@
WindowManagerGlobal.getWindowSession().prepareToReplaceChildren(r.token);
}
} catch (RemoteException e) {
- // If the system process has died, it's game over for everyone.
+ throw e.rethrowFromSystemServer();
}
// Need to ensure state is saved.
if (!r.paused) {
- performPauseActivity(r.token, false, r.isPreHoneycomb());
+ performPauseActivity(r.token, false, r.isPreHoneycomb(), "handleRelaunchActivity");
}
if (r.state == null && !r.stopped && !r.isPreHoneycomb()) {
callCallActivityOnSaveInstanceState(r);
@@ -4399,7 +4469,7 @@
r.startsNotResumed = tmp.startsNotResumed;
r.overrideConfig = tmp.overrideConfig;
- handleLaunchActivity(r, currentIntent);
+ handleLaunchActivity(r, currentIntent, "handleRelaunchActivity");
if (!tmp.onlyLocalRequest) {
try {
@@ -4408,7 +4478,7 @@
r.window.reportActivityRelaunched();
}
} catch (RemoteException e) {
- // If the system process has died, it's game over for everyone.
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4688,34 +4758,93 @@
try {
ActivityManagerNative.getDefault().dumpHeapFinished(dhd.path);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
boolean hasPkgInfo = false;
- if (packages != null) {
- synchronized (mResourcesManager) {
- for (int i=packages.length-1; i>=0; i--) {
- //Slog.i(TAG, "Cleaning old package: " + packages[i]);
- if (!hasPkgInfo) {
- WeakReference<LoadedApk> ref;
- ref = mPackages.get(packages[i]);
- if (ref != null && ref.get() != null) {
+ switch (cmd) {
+ case IApplicationThread.PACKAGE_REMOVED:
+ case IApplicationThread.PACKAGE_REMOVED_DONT_KILL:
+ {
+ final boolean killApp = cmd == IApplicationThread.PACKAGE_REMOVED;
+ if (packages == null) {
+ break;
+ }
+ synchronized (mResourcesManager) {
+ for (int i = packages.length - 1; i >= 0; i--) {
+ if (!hasPkgInfo) {
+ WeakReference<LoadedApk> ref = mPackages.get(packages[i]);
+ if (ref != null && ref.get() != null) {
+ hasPkgInfo = true;
+ } else {
+ ref = mResourcePackages.get(packages[i]);
+ if (ref != null && ref.get() != null) {
+ hasPkgInfo = true;
+ }
+ }
+ }
+ if (killApp) {
+ mPackages.remove(packages[i]);
+ mResourcePackages.remove(packages[i]);
+ }
+ }
+ }
+ break;
+ }
+ case IApplicationThread.PACKAGE_REPLACED:
+ {
+ if (packages == null) {
+ break;
+ }
+ synchronized (mResourcesManager) {
+ for (int i = packages.length - 1; i >= 0; i--) {
+ WeakReference<LoadedApk> ref = mPackages.get(packages[i]);
+ LoadedApk pkgInfo = ref != null ? ref.get() : null;
+ if (pkgInfo != null) {
hasPkgInfo = true;
} else {
ref = mResourcePackages.get(packages[i]);
- if (ref != null && ref.get() != null) {
+ pkgInfo = ref != null ? ref.get() : null;
+ if (pkgInfo != null) {
hasPkgInfo = true;
}
}
+ // If the package is being replaced, yet it still has a valid
+ // LoadedApk object, the package was updated with _DONT_KILL.
+ // Adjust it's internal references to the application info and
+ // resources.
+ if (pkgInfo != null) {
+ try {
+ final String packageName = packages[i];
+ final ApplicationInfo aInfo =
+ sPackageManager.getApplicationInfo(
+ packageName,
+ 0 /*flags*/,
+ UserHandle.myUserId());
+
+ if (mActivities.size() > 0) {
+ for (ActivityClientRecord ar : mActivities.values()) {
+ if (ar.activityInfo.applicationInfo.packageName
+ .equals(packageName)) {
+ ar.activityInfo.applicationInfo = aInfo;
+ ar.packageInfo = pkgInfo;
+ }
+ }
+ }
+ final List<String> oldPaths =
+ sPackageManager.getPreviousCodePaths(packageName);
+ pkgInfo.updateApplicationInfo(aInfo, oldPaths);
+ } catch (RemoteException e) {
+ }
+ }
}
- mPackages.remove(packages[i]);
- mResourcePackages.remove(packages[i]);
}
+ break;
}
}
- ApplicationPackageManager.handlePackageBroadcast(cmd, packages,
- hasPkgInfo);
+ ApplicationPackageManager.handlePackageBroadcast(cmd, packages, hasPkgInfo);
}
final void handleLowMemory() {
@@ -4770,10 +4899,17 @@
RenderScriptCacheDir.setupDiskCache(cacheDir);
}
} catch (RemoteException e) {
- // Ignore
+ throw e.rethrowFromSystemServer();
}
}
+ // Keep in sync with installd (frameworks/native/cmds/installd/commands.cpp).
+ private static File getPrimaryProfileFile(String packageName) {
+ File profileDir = Environment.getDataProfilesDePackageDirectory(
+ UserHandle.myUserId(), packageName);
+ return new File(profileDir, "primary.prof");
+ }
+
private static void setupJitProfileSupport(LoadedApk loadedApk, File cacheDir) {
if (!SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) {
return;
@@ -4793,10 +4929,7 @@
return;
}
- // Add an extension to the file name to better reveal its intended use.
- // Keep in sync with BackgroundDexOptService.
- final String profileExtension = ".prof";
- final File profileFile = new File(cacheDir, loadedApk.mPackageName + profileExtension);
+ final File profileFile = getPrimaryProfileFile(loadedApk.mPackageName);
if (!profileFile.exists()) {
FileDescriptor fd = null;
try {
@@ -4805,11 +4938,15 @@
Os.fchmod(fd, permissions);
Os.fchown(fd, appInfo.uid, appInfo.uid);
} catch (ErrnoException e) {
- Log.w(TAG, "Unable to create jit profile file " + profileFile, e);
+ Log.v(TAG, "Unable to create jit profile file "
+ + profileFile + ": " + e.getMessage());
try {
Os.unlink(profileFile.getAbsolutePath());
} catch (ErrnoException unlinkErr) {
- Log.v(TAG, "Unable to unlink jit profile file " + profileFile, unlinkErr);
+ if (unlinkErr.errno != OsConstants.ENOENT) {
+ Log.v(TAG, "Unable to unlink jit profile file "
+ + profileFile + ": " + unlinkErr.getMessage());
+ }
}
return;
} finally {
@@ -4817,8 +4954,17 @@
}
}
+ final File foreignDexProfilesFile =
+ Environment.getDataProfilesDeForeignDexDirectory(UserHandle.myUserId());
+ String foreignDexProfilesPath = null;
+ if (!foreignDexProfilesFile.exists()) {
+ Log.v(TAG, "ForeignDexProfilesPath does not exists:" +
+ foreignDexProfilesFile.getPath());
+ } else {
+ foreignDexProfilesPath = foreignDexProfilesFile.getAbsolutePath();
+ }
VMRuntime.registerAppInfo(profileFile.getAbsolutePath(), appInfo.dataDir,
- codePaths.toArray(new String[codePaths.size()]));
+ codePaths.toArray(new String[codePaths.size()]), foreignDexProfilesPath);
}
private void updateDefaultDensity() {
@@ -4836,6 +4982,9 @@
DdmVmInternal.enableRecentAllocations(true);
}
+ // Note when this process has started.
+ Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
+
mBoundApplication = data;
mConfiguration = new Configuration(data.config);
mCompatConfiguration = new Configuration(data.config);
@@ -4959,6 +5108,7 @@
try {
mgr.showWaitingForDebugger(mAppThread, true);
} catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
}
Debug.waitForDebugger();
@@ -4966,6 +5116,7 @@
try {
mgr.showWaitingForDebugger(mAppThread, false);
} catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
}
} else {
@@ -4993,7 +5144,9 @@
try {
final ProxyInfo proxyInfo = service.getProxyForNetwork(null);
Proxy.setHttpProxySystemProperty(proxyInfo);
- } catch (RemoteException e) {}
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
// Instrumentation info affects the class loader, so load it before
@@ -5112,9 +5265,8 @@
// don't bring up providers in restricted mode; they may depend on the
// app's custom Application class
if (!data.restrictedBackupMode) {
- List<ProviderInfo> providers = data.providers;
- if (providers != null) {
- installContentProviders(app, providers);
+ if (!ArrayUtils.isEmpty(data.providers)) {
+ installContentProviders(app, data.providers);
// For process that contains content providers, we want to
// ensure that the JIT is enabled "at some point".
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
@@ -5157,6 +5309,7 @@
try {
am.finishInstrumentation(mAppThread, resultCode, results);
} catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
}
}
@@ -5186,6 +5339,7 @@
ActivityManagerNative.getDefault().publishContentProviders(
getApplicationThread(), results);
} catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
}
}
@@ -5207,6 +5361,7 @@
holder = ActivityManagerNative.getDefault().getContentProvider(
getApplicationThread(), auth, userId, stable);
} catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
}
if (holder == null) {
Slog.e(TAG, "Failed to find provider info for " + auth);
@@ -5494,6 +5649,7 @@
ActivityManagerNative.getDefault()
.appNotRespondingViaProvider(prc.holder.connection);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -5673,7 +5829,7 @@
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
- // Ignore
+ throw ex.rethrowFromSystemServer();
}
// Watch for getting close to heap limit.
BinderInternal.addGcWatcher(new Runnable() {
@@ -5692,6 +5848,7 @@
try {
mgr.releaseSomeActivities(mAppThread);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index b569416..455f869 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -201,6 +201,7 @@
try {
mService.remove(null, this);
} catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
}
synchronized (AlarmManager.class) {
@@ -656,6 +657,7 @@
mService.set(mPackageName, type, triggerAtMillis, windowMillis, intervalMillis, flags,
operation, recipientWrapper, listenerTag, workSource, alarmClock);
} catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
}
}
@@ -886,6 +888,7 @@
try {
mService.remove(operation, null);
} catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
}
}
@@ -926,6 +929,7 @@
try {
mService.setTime(millis);
} catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
}
}
@@ -965,6 +969,7 @@
try {
mService.setTimeZone(timeZone);
} catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
}
}
@@ -973,7 +978,7 @@
try {
return mService.getNextWakeFromIdleTime();
} catch (RemoteException ex) {
- return Long.MAX_VALUE;
+ throw ex.rethrowFromSystemServer();
}
}
@@ -1005,7 +1010,7 @@
try {
return mService.getNextAlarmClock(userId);
} catch (RemoteException ex) {
- return null;
+ throw ex.rethrowFromSystemServer();
}
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index f0453e9..82c4c51 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -704,8 +704,8 @@
* (and system ui) to bypass the user restriction when active.
*/
private static boolean[] sOpAllowSystemRestrictionBypass = new boolean[] {
- false, //COARSE_LOCATION
- false, //FINE_LOCATION
+ true, //COARSE_LOCATION
+ true, //FINE_LOCATION
false, //GPS
false, //VIBRATE
false, //READ_CONTACTS
@@ -1236,8 +1236,8 @@
try {
return mService.getPackagesForOps(ops);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return null;
}
/**
@@ -1252,8 +1252,8 @@
try {
return mService.getOpsForPackage(uid, packageName, ops);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return null;
}
/** @hide */
@@ -1261,6 +1261,16 @@
try {
mService.setUidMode(code, uid, mode);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /** @hide */
+ public void setUserRestriction(int code, boolean restricted, IBinder token) {
+ try {
+ mService.setUserRestriction(code, restricted, token, mContext.getUserId());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1269,6 +1279,7 @@
try {
mService.setMode(code, uid, packageName, mode);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1289,6 +1300,7 @@
final int uid = Binder.getCallingUid();
mService.setAudioRestriction(code, usage, uid, mode, exceptionPackages);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1297,6 +1309,7 @@
try {
mService.resetAllModes(UserHandle.myUserId(), null);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1353,6 +1366,7 @@
try {
mService.startWatchingMode(op, packageName, cb);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1368,6 +1382,7 @@
try {
mService.stopWatchingMode(cb);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1532,8 +1547,8 @@
}
return mode;
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return MODE_IGNORED;
}
/**
@@ -1545,8 +1560,8 @@
try {
return mService.checkOperation(op, uid, packageName);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return MODE_ERRORED;
}
/**
@@ -1562,7 +1577,7 @@
"Package " + packageName + " does not belong to " + uid);
}
} catch (RemoteException e) {
- throw new SecurityException("Unable to verify package ownership", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1578,8 +1593,8 @@
}
return mode;
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return MODE_IGNORED;
}
/**
@@ -1591,8 +1606,8 @@
try {
return mService.checkAudioOperation(op, stream, uid, packageName);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return MODE_ERRORED;
}
/**
@@ -1618,8 +1633,8 @@
}
return mode;
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return MODE_IGNORED;
}
/**
@@ -1661,8 +1676,8 @@
return mService.noteProxyOperation(op, mContext.getOpPackageName(),
Binder.getCallingUid(), proxiedPackageName);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return MODE_ERRORED;
}
/**
@@ -1674,8 +1689,8 @@
try {
return mService.noteOperation(op, uid, packageName);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return MODE_ERRORED;
}
/** @hide */
@@ -1692,7 +1707,7 @@
try {
sToken = service.getToken(new Binder());
} catch (RemoteException e) {
- // System is dead, whatevs.
+ throw e.rethrowFromSystemServer();
}
return sToken;
}
@@ -1723,8 +1738,8 @@
}
return mode;
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return MODE_IGNORED;
}
/**
@@ -1736,8 +1751,8 @@
try {
return mService.startOperation(getToken(mService), op, uid, packageName);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return MODE_ERRORED;
}
/** @hide */
@@ -1756,6 +1771,7 @@
try {
mService.finishOperation(getToken(mService), op, uid, packageName);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java
index 7d0d1b4..0fc097e 100644
--- a/core/java/android/app/ApplicationLoaders.java
+++ b/core/java/android/app/ApplicationLoaders.java
@@ -20,16 +20,14 @@
import android.util.ArrayMap;
import dalvik.system.PathClassLoader;
-class ApplicationLoaders
-{
- public static ApplicationLoaders getDefault()
- {
+class ApplicationLoaders {
+ public static ApplicationLoaders getDefault() {
return gApplicationLoaders;
}
- public ClassLoader getClassLoader(String zip, boolean isBundled, String librarySearchPath,
- String libraryPermittedPath, ClassLoader parent)
- {
+ public ClassLoader getClassLoader(String zip, int targetSdkVersion, boolean isBundled,
+ String librarySearchPath, String libraryPermittedPath,
+ ClassLoader parent) {
/*
* This is the parent we use if they pass "null" in. In theory
* this should be the "system" class loader; in practice we
@@ -55,11 +53,22 @@
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, zip);
+
PathClassLoader pathClassloader =
- new PathClassLoader(zip, isBundled, librarySearchPath,
- libraryPermittedPath, parent);
+ new PathClassLoader(zip, librarySearchPath, parent);
+
+ String errorMessage = createClassloaderNamespace(pathClassloader,
+ targetSdkVersion,
+ librarySearchPath,
+ libraryPermittedPath,
+ isBundled);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ if (errorMessage != null) {
+ throw new UnsatisfiedLinkError("Unable to create namespace for the classloader " +
+ pathClassloader + ": " + errorMessage);
+ }
+
mLoaders.put(zip, pathClassloader);
return pathClassloader;
}
@@ -71,6 +80,24 @@
}
}
+ private static native String createClassloaderNamespace(ClassLoader classLoader,
+ int targetSdkVersion,
+ String librarySearchPath,
+ String libraryPermittedPath,
+ boolean isShared);
+
+ /**
+ * Adds a new path the classpath of the given loader.
+ * @throws IllegalStateException if the provided class loader is not a {@link PathClassLoader}.
+ */
+ void addPath(ClassLoader classLoader, String dexPath) {
+ if (!(classLoader instanceof PathClassLoader)) {
+ throw new IllegalStateException("class loader is not a PathClassLoader");
+ }
+ final PathClassLoader baseDexClassLoader = (PathClassLoader) classLoader;
+ baseDexClassLoader.addDexPath(dexPath);
+ }
+
private final ArrayMap<String, ClassLoader> mLoaders = new ArrayMap<String, ClassLoader>();
private static final ApplicationLoaders gApplicationLoaders
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 91eabcc..0b44925 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -30,7 +30,6 @@
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ComponentInfo;
-import android.content.pm.ContainerEncryptionParams;
import android.content.pm.EphemeralApplicationInfo;
import android.content.pm.FeatureInfo;
import android.content.pm.IOnPermissionsChangeListener;
@@ -54,7 +53,6 @@
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
-import android.content.pm.VerificationParams;
import android.content.pm.VerifierDeviceIdentity;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
@@ -143,7 +141,7 @@
return pi;
}
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
throw new NameNotFoundException(packageName);
@@ -154,7 +152,7 @@
try {
return mPM.currentToCanonicalPackageNames(names);
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -163,7 +161,7 @@
try {
return mPM.canonicalToCurrentPackageNames(names);
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -227,7 +225,7 @@
return gids;
}
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
throw new NameNotFoundException(packageName);
@@ -252,7 +250,7 @@
return uid;
}
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
throw new NameNotFoundException(packageName);
@@ -267,7 +265,7 @@
return pi;
}
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
throw new NameNotFoundException(name);
@@ -277,12 +275,12 @@
public List<PermissionInfo> queryPermissionsByGroup(String group, int flags)
throws NameNotFoundException {
try {
- List<PermissionInfo> pi = mPM.queryPermissionsByGroup(group, flags);
+ List<PermissionInfo> pi = mPM.queryPermissionsByGroup(group, flags).getList();
if (pi != null) {
return pi;
}
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
throw new NameNotFoundException(group);
@@ -297,7 +295,7 @@
return pgi;
}
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
throw new NameNotFoundException(name);
@@ -306,9 +304,9 @@
@Override
public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
try {
- return mPM.getAllPermissionGroups(flags);
+ return mPM.getAllPermissionGroups(flags).getList();
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -330,7 +328,7 @@
return maybeAdjustApplicationInfo(ai);
}
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
throw new NameNotFoundException(packageName);
@@ -370,7 +368,7 @@
return ai;
}
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
throw new NameNotFoundException(className.toString());
@@ -385,7 +383,7 @@
return ai;
}
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
throw new NameNotFoundException(className.toString());
@@ -400,7 +398,7 @@
return si;
}
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
throw new NameNotFoundException(className.toString());
@@ -415,7 +413,7 @@
return pi;
}
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
throw new NameNotFoundException(className.toString());
@@ -426,7 +424,7 @@
try {
return mPM.getSystemSharedLibraryNames();
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -436,16 +434,21 @@
try {
return mPM.getServicesSystemSharedLibraryPackageName();
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@Override
public FeatureInfo[] getSystemAvailableFeatures() {
try {
- return mPM.getSystemAvailableFeatures();
+ final List<FeatureInfo> list = mPM.getSystemAvailableFeatures().getList();
+ final FeatureInfo[] res = new FeatureInfo[list.size()];
+ for (int i = 0; i < res.length; i++) {
+ res[i] = list.get(i);
+ }
+ return res;
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -459,7 +462,7 @@
try {
return mPM.hasSystemFeature(name, version);
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -468,7 +471,7 @@
try {
return mPM.checkPermission(permName, pkgName, mContext.getUserId());
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -477,7 +480,7 @@
try {
return mPM.isPermissionRevokedByPolicy(permName, pkgName, mContext.getUserId());
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -491,7 +494,7 @@
try {
mPermissionsControllerPackageName = mPM.getPermissionControllerPackageName();
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
return mPermissionsControllerPackageName;
@@ -503,7 +506,7 @@
try {
return mPM.addPermission(info);
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -512,7 +515,7 @@
try {
return mPM.addPermissionAsync(info);
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -521,7 +524,7 @@
try {
mPM.removePermission(name);
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -531,7 +534,7 @@
try {
mPM.grantRuntimePermission(packageName, permissionName, user.getIdentifier());
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -541,7 +544,7 @@
try {
mPM.revokeRuntimePermission(packageName, permissionName, user.getIdentifier());
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -550,7 +553,7 @@
try {
return mPM.getPermissionFlags(permissionName, packageName, user.getIdentifier());
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -561,7 +564,7 @@
mPM.updatePermissionFlags(permissionName, packageName, flagMask,
flagValues, user.getIdentifier());
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -571,7 +574,7 @@
return mPM.shouldShowRequestPermissionRationale(permission,
mContext.getPackageName(), mContext.getUserId());
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -580,7 +583,7 @@
try {
return mPM.checkSignatures(pkg1, pkg2);
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -589,7 +592,7 @@
try {
return mPM.checkUidSignatures(uid1, uid2);
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -598,7 +601,7 @@
try {
return mPM.getPackagesForUid(uid);
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -607,7 +610,7 @@
try {
return mPM.getNameForUid(uid);
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -620,7 +623,7 @@
return uid;
}
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
throw new NameNotFoundException("No shared userid for user:"+sharedUserName);
}
@@ -638,7 +641,7 @@
ParceledListSlice<PackageInfo> slice = mPM.getInstalledPackages(flags, userId);
return slice.getList();
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -652,7 +655,7 @@
permissions, flags, userId);
return slice.getList();
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -664,7 +667,7 @@
ParceledListSlice<ApplicationInfo> slice = mPM.getInstalledApplications(flags, userId);
return slice.getList();
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -680,7 +683,7 @@
}
return Collections.emptyList();
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -695,7 +698,7 @@
}
return null;
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -705,9 +708,8 @@
return mPM.isEphemeralApplication(
mContext.getPackageName(), mContext.getUserId());
} catch (RemoteException e) {
- Log.e(TAG, "System server is dead", e);
+ throw e.rethrowFromSystemServer();
}
- return false;
}
@Override
@@ -724,11 +726,12 @@
mContext.getPackageName(), mContext.getUserId());
if (cookie != null) {
return cookie;
+ } else {
+ return EmptyArray.BYTE;
}
} catch (RemoteException e) {
- Log.e(TAG, "System server is dead", e);
+ throw e.rethrowFromSystemServer();
}
- return EmptyArray.BYTE;
}
@Override
@@ -737,9 +740,8 @@
return mPM.setEphemeralApplicationCookie(
mContext.getPackageName(), cookie, mContext.getUserId());
} catch (RemoteException e) {
- Log.e(TAG, "System server is dead", e);
+ throw e.rethrowFromSystemServer();
}
- return false;
}
@Override
@@ -756,7 +758,7 @@
flags,
userId);
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -775,9 +777,9 @@
intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
flags,
- userId);
+ userId).getList();
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -805,11 +807,12 @@
}
try {
- return mPM.queryIntentActivityOptions(caller, specifics,
- specificTypes, intent, intent.resolveTypeIfNeeded(resolver),
- flags, mContext.getUserId());
+ return mPM
+ .queryIntentActivityOptions(caller, specifics, specificTypes, intent,
+ intent.resolveTypeIfNeeded(resolver), flags, mContext.getUserId())
+ .getList();
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -823,9 +826,9 @@
intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
flags,
- userId);
+ userId).getList();
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -843,7 +846,7 @@
flags,
mContext.getUserId());
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -854,9 +857,9 @@
intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
flags,
- userId);
+ userId).getList();
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -870,9 +873,10 @@
Intent intent, int flags, int userId) {
try {
return mPM.queryIntentContentProviders(intent,
- intent.resolveTypeIfNeeded(mContext.getContentResolver()), flags, userId);
+ intent.resolveTypeIfNeeded(mContext.getContentResolver()), flags, userId)
+ .getList();
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -892,7 +896,7 @@
try {
return mPM.resolveContentProvider(name, flags, userId);
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -904,7 +908,7 @@
= mPM.queryContentProviders(processName, uid, flags);
return slice != null ? slice.getList() : null;
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -919,7 +923,7 @@
return ii;
}
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
throw new NameNotFoundException(className.toString());
@@ -929,9 +933,9 @@
public List<InstrumentationInfo> queryInstrumentation(
String targetPackage, int flags) {
try {
- return mPM.queryInstrumentation(targetPackage, flags);
+ return mPM.queryInstrumentation(targetPackage, flags).getList();
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1096,6 +1100,14 @@
}
@Override
+ public Drawable getManagedUserBadgedDrawable(Drawable drawable, Rect badgeLocation,
+ int badgeDensity) {
+ Drawable badgeDrawable = getDrawableForDensity(
+ com.android.internal.R.drawable.ic_corp_badge, badgeDensity);
+ return getBadgedDrawable(drawable, badgeDrawable, badgeLocation, true);
+ }
+
+ @Override
public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
final int badgeResId = getBadgeResIdForUser(user.getIdentifier());
if (badgeResId == 0) {
@@ -1117,24 +1129,27 @@
@Override
public Drawable getUserBadgeForDensity(UserHandle user, int density) {
- return getManagedProfileIconForDensity(user, density,
- com.android.internal.R.drawable.ic_corp_badge);
+ return getManagedProfileIconForDensity(user, com.android.internal.R.drawable.ic_corp_badge,
+ density);
}
@Override
public Drawable getUserBadgeForDensityNoBackground(UserHandle user, int density) {
- return getManagedProfileIconForDensity(user, density,
- com.android.internal.R.drawable.ic_corp_badge_no_background);
+ return getManagedProfileIconForDensity(user,
+ com.android.internal.R.drawable.ic_corp_badge_no_background, density);
}
- private Drawable getManagedProfileIconForDensity(UserHandle user, int density,
- int drawableId) {
+ private Drawable getDrawableForDensity(int drawableId, int density) {
+ if (density <= 0) {
+ density = mContext.getResources().getDisplayMetrics().densityDpi;
+ }
+ return Resources.getSystem().getDrawableForDensity(drawableId, density);
+ }
+
+ private Drawable getManagedProfileIconForDensity(UserHandle user, int drawableId, int density) {
UserInfo userInfo = getUserIfProfile(user.getIdentifier());
if (userInfo != null && userInfo.isManagedProfile()) {
- if (density <= 0) {
- density = mContext.getResources().getDisplayMetrics().densityDpi;
- }
- return Resources.getSystem().getDrawableForDensity(drawableId, density);
+ return getDrawableForDensity(drawableId, density);
}
return null;
}
@@ -1198,7 +1213,7 @@
return getResourcesForApplication(ai);
}
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
throw new NameNotFoundException("Package " + appPackageName + " doesn't exist");
}
@@ -1213,7 +1228,7 @@
}
return mCachedSafeMode != 0;
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1229,7 +1244,7 @@
mPM.addOnPermissionsChangeListener(delegate);
mPermissionListeners.put(listener, delegate);
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1243,7 +1258,7 @@
mPM.removeOnPermissionsChangeListener(delegate);
mPermissionListeners.remove(listener);
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1470,81 +1485,29 @@
@Override
public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
String installerPackageName) {
- final VerificationParams verificationParams = new VerificationParams(null, null,
- null, VerificationParams.NO_UID);
installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags,
- installerPackageName, verificationParams, null, mContext.getUserId());
- }
-
- @Override
- public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
- int flags, String installerPackageName, Uri verificationURI,
- ContainerEncryptionParams encryptionParams) {
- final VerificationParams verificationParams = new VerificationParams(verificationURI, null,
- null, VerificationParams.NO_UID);
- installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags,
- installerPackageName, verificationParams, encryptionParams, mContext.getUserId());
- }
-
- @Override
- public void installPackageWithVerificationAndEncryption(Uri packageURI,
- IPackageInstallObserver observer, int flags, String installerPackageName,
- VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
- installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags,
- installerPackageName, verificationParams, encryptionParams, mContext.getUserId());
+ installerPackageName, mContext.getUserId());
}
@Override
public void installPackage(Uri packageURI, PackageInstallObserver observer,
int flags, String installerPackageName) {
- installPackageAsUser(packageURI, observer, flags, installerPackageName,
- mContext.getUserId());
- }
-
- @Override
- public void installPackageAsUser(Uri packageURI, PackageInstallObserver observer, int flags,
- String installerPackageName, int userId) {
- final VerificationParams verificationParams = new VerificationParams(null, null,
- null, VerificationParams.NO_UID);
- installCommon(packageURI, observer, flags, installerPackageName, verificationParams, null,
- userId);
- }
-
- @Override
- public void installPackageWithVerification(Uri packageURI,
- PackageInstallObserver observer, int flags, String installerPackageName,
- Uri verificationURI,
- ContainerEncryptionParams encryptionParams) {
- final VerificationParams verificationParams = new VerificationParams(verificationURI, null,
- null, VerificationParams.NO_UID);
- installCommon(packageURI, observer, flags, installerPackageName, verificationParams,
- encryptionParams, mContext.getUserId());
- }
-
- @Override
- public void installPackageWithVerificationAndEncryption(Uri packageURI,
- PackageInstallObserver observer, int flags, String installerPackageName,
- VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
- installCommon(packageURI, observer, flags, installerPackageName, verificationParams,
- encryptionParams, mContext.getUserId());
+ installCommon(packageURI, observer, flags, installerPackageName, mContext.getUserId());
}
private void installCommon(Uri packageURI,
PackageInstallObserver observer, int flags, String installerPackageName,
- VerificationParams verificationParams, ContainerEncryptionParams encryptionParams,
int userId) {
if (!"file".equals(packageURI.getScheme())) {
throw new UnsupportedOperationException("Only file:// URIs are supported");
}
- if (encryptionParams != null) {
- throw new UnsupportedOperationException("ContainerEncryptionParams not supported");
- }
final String originPath = packageURI.getPath();
try {
mPM.installPackageAsUser(originPath, observer.getBinder(), flags, installerPackageName,
- verificationParams, null, userId);
- } catch (RemoteException ignored) {
+ userId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1563,8 +1526,7 @@
}
return res;
} catch (RemoteException e) {
- // Should never happen!
- throw new NameNotFoundException("Package " + packageName + " doesn't exist");
+ throw e.rethrowFromSystemServer();
}
}
@@ -1573,7 +1535,7 @@
try {
mPM.verifyPendingInstall(id, response);
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
}
@@ -1583,16 +1545,16 @@
try {
mPM.extendVerificationTimeout(id, verificationCodeAtTimeout, millisecondsToDelay);
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
}
@Override
- public void verifyIntentFilter(int id, int verificationCode, List<String> outFailedDomains) {
+ public void verifyIntentFilter(int id, int verificationCode, List<String> failedDomains) {
try {
- mPM.verifyIntentFilter(id, verificationCode, outFailedDomains);
+ mPM.verifyIntentFilter(id, verificationCode, failedDomains);
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
}
@@ -1601,8 +1563,7 @@
try {
return mPM.getIntentVerificationStatus(packageName, userId);
} catch (RemoteException e) {
- // Should never happen!
- return PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1611,28 +1572,25 @@
try {
return mPM.updateIntentVerificationStatus(packageName, status, userId);
} catch (RemoteException e) {
- // Should never happen!
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@Override
public List<IntentFilterVerificationInfo> getIntentFilterVerifications(String packageName) {
try {
- return mPM.getIntentFilterVerifications(packageName);
+ return mPM.getIntentFilterVerifications(packageName).getList();
} catch (RemoteException e) {
- // Should never happen!
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@Override
public List<IntentFilter> getAllIntentFilters(String packageName) {
try {
- return mPM.getAllIntentFilters(packageName);
+ return mPM.getAllIntentFilters(packageName).getList();
} catch (RemoteException e) {
- // Should never happen!
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1641,8 +1599,7 @@
try {
return mPM.getDefaultBrowserPackageName(userId);
} catch (RemoteException e) {
- // Should never happen!
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1651,8 +1608,7 @@
try {
return mPM.setDefaultBrowserPackageName(packageName, userId);
} catch (RemoteException e) {
- // Should never happen!
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1662,7 +1618,7 @@
try {
mPM.setInstallerPackageName(targetPackage, installerPackageName);
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
}
@@ -1671,9 +1627,8 @@
try {
return mPM.getInstallerPackageName(packageName);
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
- return null;
}
@Override
@@ -1681,7 +1636,7 @@
try {
return mPM.getMoveStatus(moveId);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -1693,7 +1648,7 @@
try {
mPM.registerMoveCallback(delegate);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
mDelegates.add(delegate);
}
@@ -1708,7 +1663,7 @@
try {
mPM.unregisterMoveCallback(delegate);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
i.remove();
}
@@ -1730,7 +1685,7 @@
return mPM.movePackage(packageName, volumeUuid);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -1796,7 +1751,7 @@
return false;
}
} catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
// Otherwise we can move to any private volume
@@ -1817,7 +1772,7 @@
return mPM.movePrimaryStorage(volumeUuid);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -1874,7 +1829,7 @@
try {
mPM.deletePackageAsUser(packageName, observer, userId, flags);
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
}
@@ -1884,7 +1839,7 @@
try {
mPM.clearApplicationUserData(packageName, observer, mContext.getUserId());
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
}
@Override
@@ -1893,7 +1848,7 @@
try {
mPM.deleteApplicationCacheFiles(packageName, observer);
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
}
@@ -1903,7 +1858,7 @@
try {
mPM.freeStorageAndNotify(volumeUuid, idealStorageSize, observer);
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
}
@@ -1912,7 +1867,7 @@
try {
mPM.freeStorage(volumeUuid, freeStorageSize, pi);
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
}
@@ -1922,9 +1877,8 @@
try {
return mPM.setPackagesSuspendedAsUser(packageNames, suspended, userId);
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
- return packageNames;
}
@Override
@@ -1932,9 +1886,8 @@
try {
return mPM.isPackageSuspendedForUser(packageName, userId);
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
- return false;
}
@Override
@@ -1943,35 +1896,24 @@
try {
mPM.getPackageSizeInfo(packageName, userHandle, observer);
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
}
+
@Override
public void addPackageToPreferred(String packageName) {
- try {
- mPM.addPackageToPreferred(packageName);
- } catch (RemoteException e) {
- // Should never happen!
- }
+ Log.w(TAG, "addPackageToPreferred() is a no-op");
}
@Override
public void removePackageFromPreferred(String packageName) {
- try {
- mPM.removePackageFromPreferred(packageName);
- } catch (RemoteException e) {
- // Should never happen!
- }
+ Log.w(TAG, "removePackageFromPreferred() is a no-op");
}
@Override
public List<PackageInfo> getPreferredPackages(int flags) {
- try {
- return mPM.getPreferredPackages(flags);
- } catch (RemoteException e) {
- // Should never happen!
- }
- return new ArrayList<PackageInfo>();
+ Log.w(TAG, "getPreferredPackages() is a no-op");
+ return Collections.emptyList();
}
@Override
@@ -1980,7 +1922,7 @@
try {
mPM.addPreferredActivity(filter, match, set, activity, mContext.getUserId());
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
}
@@ -1990,7 +1932,7 @@
try {
mPM.addPreferredActivity(filter, match, set, activity, userId);
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
}
@@ -2000,7 +1942,7 @@
try {
mPM.replacePreferredActivity(filter, match, set, activity, mContext.getUserId());
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
}
@@ -2011,7 +1953,7 @@
try {
mPM.replacePreferredActivity(filter, match, set, activity, userId);
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
}
@@ -2020,7 +1962,7 @@
try {
mPM.clearPackagePreferredActivities(packageName);
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
}
@@ -2030,9 +1972,8 @@
try {
return mPM.getPreferredActivities(outFilters, outActivities, packageName);
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
- return 0;
}
@Override
@@ -2040,9 +1981,8 @@
try {
return mPM.getHomeActivities(outActivities);
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
- return null;
}
@Override
@@ -2051,7 +1991,7 @@
try {
mPM.setComponentEnabledSetting(componentName, newState, flags, mContext.getUserId());
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
}
@@ -2060,9 +2000,8 @@
try {
return mPM.getComponentEnabledSetting(componentName, mContext.getUserId());
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
- return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
}
@Override
@@ -2072,7 +2011,7 @@
mPM.setApplicationEnabledSetting(packageName, newState, flags,
mContext.getUserId(), mContext.getOpPackageName());
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
}
@@ -2081,9 +2020,8 @@
try {
return mPM.getApplicationEnabledSetting(packageName, mContext.getUserId());
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
- return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
}
@Override
@@ -2092,20 +2030,18 @@
try {
return mPM.setApplicationHiddenSettingAsUser(packageName, hidden,
user.getIdentifier());
- } catch (RemoteException re) {
- // Should never happen!
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return false;
}
@Override
public boolean getApplicationHiddenSettingAsUser(String packageName, UserHandle user) {
try {
return mPM.getApplicationHiddenSettingAsUser(packageName, user.getIdentifier());
- } catch (RemoteException re) {
- // Should never happen!
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return false;
}
/** @hide */
@@ -2113,26 +2049,22 @@
public KeySet getKeySetByAlias(String packageName, String alias) {
Preconditions.checkNotNull(packageName);
Preconditions.checkNotNull(alias);
- KeySet ks;
try {
- ks = mPM.getKeySetByAlias(packageName, alias);
+ return mPM.getKeySetByAlias(packageName, alias);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
- return ks;
}
/** @hide */
@Override
public KeySet getSigningKeySet(String packageName) {
Preconditions.checkNotNull(packageName);
- KeySet ks;
try {
- ks = mPM.getSigningKeySet(packageName);
+ return mPM.getSigningKeySet(packageName);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
- return ks;
}
/** @hide */
@@ -2143,7 +2075,7 @@
try {
return mPM.isPackageSignedByKeySet(packageName, ks);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2155,7 +2087,7 @@
try {
return mPM.isPackageSignedByKeySetExactly(packageName, ks);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2167,9 +2099,8 @@
try {
return mPM.getVerifierDeviceIdentity();
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
- return null;
}
/**
@@ -2180,7 +2111,7 @@
try {
return mPM.isUpgrade();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2192,7 +2123,7 @@
mInstaller = new PackageInstaller(mContext, this, mPM.getPackageInstaller(),
mContext.getPackageName(), mContext.getUserId());
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
return mInstaller;
@@ -2204,7 +2135,7 @@
try {
return mPM.isPackageAvailable(packageName, mContext.getUserId());
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -2218,7 +2149,7 @@
mPM.addCrossProfileIntentFilter(filter, mContext.getOpPackageName(),
sourceUserId, targetUserId, flags);
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
}
@@ -2230,7 +2161,7 @@
try {
mPM.clearCrossProfileIntentFilters(sourceUserId, mContext.getOpPackageName());
} catch (RemoteException e) {
- // Should never happen!
+ throw e.rethrowFromSystemServer();
}
}
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 59ecc03..744ddf7 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -548,11 +548,12 @@
boolean dumpInfo = data.readInt() != 0;
boolean dumpDalvik = data.readInt() != 0;
boolean dumpSummaryOnly = data.readInt() != 0;
+ boolean dumpUnreachable = data.readInt() != 0;
String[] args = data.readStringArray();
if (fd != null) {
try {
dumpMemInfo(fd.getFileDescriptor(), mi, checkin, dumpInfo,
- dumpDalvik, dumpSummaryOnly, args);
+ dumpDalvik, dumpSummaryOnly, dumpUnreachable, args);
} finally {
try {
fd.close();
@@ -1328,7 +1329,8 @@
}
public void dumpMemInfo(FileDescriptor fd, Debug.MemoryInfo mem, boolean checkin,
- boolean dumpInfo, boolean dumpDalvik, boolean dumpSummaryOnly, String[] args) throws RemoteException {
+ boolean dumpInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
+ boolean dumpUnreachable, String[] args) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
@@ -1338,6 +1340,7 @@
data.writeInt(dumpInfo ? 1 : 0);
data.writeInt(dumpDalvik ? 1 : 0);
data.writeInt(dumpSummaryOnly ? 1 : 0);
+ data.writeInt(dumpUnreachable ? 1 : 0);
data.writeStringArray(args);
mRemote.transact(DUMP_MEM_INFO_TRANSACTION, data, reply, 0);
reply.readException();
diff --git a/core/java/android/app/AutomaticZenRule.java b/core/java/android/app/AutomaticZenRule.java
index e5fa02b..1f1f318 100644
--- a/core/java/android/app/AutomaticZenRule.java
+++ b/core/java/android/app/AutomaticZenRule.java
@@ -16,6 +16,7 @@
package android.app;
+import android.app.NotificationManager.InterruptionFilter;
import android.content.ComponentName;
import android.net.Uri;
import android.os.Parcel;
@@ -26,14 +27,13 @@
/**
* Rule instance information for zen mode.
*/
-public class AutomaticZenRule implements Parcelable {
+public final class AutomaticZenRule implements Parcelable {
private boolean enabled = false;
private String name;
- private int interruptionFilter;
+ private @InterruptionFilter int interruptionFilter;
private Uri conditionId;
private ComponentName owner;
- private String id;
private long creationTime;
/**
@@ -62,9 +62,8 @@
* @hide
*/
public AutomaticZenRule(String name, ComponentName owner, Uri conditionId,
- int interruptionFilter, boolean enabled, String id, long creationTime) {
+ int interruptionFilter, boolean enabled, long creationTime) {
this(name, owner, conditionId, interruptionFilter, enabled);
- this.id = id;
this.creationTime = creationTime;
}
@@ -76,9 +75,6 @@
interruptionFilter = source.readInt();
conditionId = source.readParcelable(null);
owner = source.readParcelable(null);
- if (source.readInt() == 1) {
- id = source.readString();
- }
creationTime = source.readLong();
}
@@ -118,20 +114,13 @@
}
/**
- * Returns the wall time in milliseconds when this rule was created, if known.
+ * Returns the time this rule was created, represented as milliseconds since the epoch.
*/
public long getCreationTime() {
return creationTime;
}
/**
- * Returns the unique identifier for this rule.
- */
- public String getId() {
- return id;
- }
-
- /**
* Sets the representation of the state that causes this rule to become active.
*/
public void setConditionId(Uri conditionId) {
@@ -140,9 +129,9 @@
/**
* Sets the interruption filter that is applied when this rule is active.
- * @param interruptionFilter One of the INTERRUPTION_FILTER_ constants in NotificationManager.
+ * @param interruptionFilter The do not disturb mode to enter when this rule is active.
*/
- public void setInterruptionFilter(int interruptionFilter) {
+ public void setInterruptionFilter(@InterruptionFilter int interruptionFilter) {
this.interruptionFilter = interruptionFilter;
}
@@ -177,12 +166,6 @@
dest.writeInt(interruptionFilter);
dest.writeParcelable(conditionId, 0);
dest.writeParcelable(owner, 0);
- if (id != null) {
- dest.writeInt(1);
- dest.writeString(id);
- } else {
- dest.writeInt(0);
- }
dest.writeLong(creationTime);
}
@@ -194,7 +177,6 @@
.append(",interruptionFilter=").append(interruptionFilter)
.append(",conditionId=").append(conditionId)
.append(",owner=").append(owner)
- .append(",id=").append(id)
.append(",creationTime=").append(creationTime)
.append(']').toString();
}
@@ -209,13 +191,12 @@
&& other.interruptionFilter == interruptionFilter
&& Objects.equals(other.conditionId, conditionId)
&& Objects.equals(other.owner, owner)
- && Objects.equals(other.id, id)
&& other.creationTime == creationTime;
}
@Override
public int hashCode() {
- return Objects.hash(enabled, name, interruptionFilter, conditionId, owner, id, creationTime);
+ return Objects.hash(enabled, name, interruptionFilter, conditionId, owner, creationTime);
}
public static final Parcelable.Creator<AutomaticZenRule> CREATOR
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index eb4b13e..3a51aff 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -16,8 +16,6 @@
package android.app;
-import com.android.internal.util.FastPrintWriter;
-
import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcelable;
@@ -33,6 +31,8 @@
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
+import com.android.internal.util.FastPrintWriter;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -470,6 +470,10 @@
}
if (containerViewId != 0) {
+ if (containerViewId == View.NO_ID) {
+ throw new IllegalArgumentException("Can't add fragment "
+ + fragment + " with tag " + tag + " to container view with no id");
+ }
if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) {
throw new IllegalStateException("Can't change container ID of fragment "
+ fragment + ": was " + fragment.mFragmentId
@@ -713,10 +717,12 @@
bumpBackStackNesting(1);
- SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();
- SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();
- calculateFragments(firstOutFragments, lastInFragments);
- beginTransition(firstOutFragments, lastInFragments, false);
+ if (mManager.mCurState >= Fragment.CREATED) {
+ SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();
+ SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();
+ calculateFragments(firstOutFragments, lastInFragments);
+ beginTransition(firstOutFragments, lastInFragments, false);
+ }
Op op = mHead;
while (op != null) {
@@ -838,6 +844,14 @@
firstOutFragments.remove(containerId);
}
}
+ /**
+ * Ensure that fragments that are entering are at least at the CREATED state
+ * so that they may load Transitions using TransitionInflater.
+ */
+ if (fragment.mState < Fragment.CREATED && mManager.mCurState >= Fragment.CREATED) {
+ mManager.makeActive(fragment);
+ mManager.moveToState(fragment, Fragment.CREATED, 0, 0, false);
+ }
}
}
@@ -982,7 +996,6 @@
*/
private TransitionState beginTransition(SparseArray<Fragment> firstOutFragments,
SparseArray<Fragment> lastInFragments, boolean isBack) {
- ensureFragmentsAreInitialized(lastInFragments);
TransitionState state = new TransitionState();
// Adding a non-existent target view makes sure that the transitions don't target
@@ -1008,21 +1021,6 @@
return state;
}
- /**
- * Ensure that fragments that are entering are at least at the CREATED state
- * so that they may load Transitions using TransitionInflater.
- */
- private void ensureFragmentsAreInitialized(SparseArray<Fragment> lastInFragments) {
- final int count = lastInFragments.size();
- for (int i = 0; i < count; i++) {
- final Fragment fragment = lastInFragments.valueAt(i);
- if (fragment.mState < Fragment.CREATED) {
- mManager.makeActive(fragment);
- mManager.moveToState(fragment, Fragment.CREATED, 0, 0, false);
- }
- }
- }
-
private static Transition cloneTransition(Transition transition) {
if (transition != null) {
transition = transition.clone();
@@ -1659,12 +1657,14 @@
pw.flush();
}
- if (state == null) {
- if (firstOutFragments.size() != 0 || lastInFragments.size() != 0) {
- state = beginTransition(firstOutFragments, lastInFragments, true);
+ if (mManager.mCurState >= Fragment.CREATED) {
+ if (state == null) {
+ if (firstOutFragments.size() != 0 || lastInFragments.size() != 0) {
+ state = beginTransition(firstOutFragments, lastInFragments, true);
+ }
+ } else if (!doStateMove) {
+ setNameOverrides(state, mSharedElementTargetNames, mSharedElementSourceNames);
}
- } else if (!doStateMove) {
- setNameOverrides(state, mSharedElementTargetNames, mSharedElementSourceNames);
}
bumpBackStackNesting(-1);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 8884949..e76f991 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -396,9 +396,11 @@
/**
* Try our best to migrate all files from source to target that match
- * requested prefix. Return false if we have any trouble migrating.
+ * requested prefix.
+ *
+ * @return the number of files moved, or -1 if there was trouble.
*/
- private static boolean migrateFiles(File sourceDir, File targetDir, final String prefix) {
+ private static int migrateFiles(File sourceDir, File targetDir, final String prefix) {
final File[] sourceFiles = FileUtils.listFilesOrEmpty(sourceDir, new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
@@ -406,7 +408,7 @@
}
});
- boolean res = true;
+ int res = 0;
for (File sourceFile : sourceFiles) {
final File targetFile = new File(targetDir, sourceFile.getName());
Log.d(TAG, "Migrating " + sourceFile + " to " + targetFile);
@@ -416,9 +418,12 @@
if (!sourceFile.delete()) {
throw new IOException("Failed to clean up " + sourceFile);
}
+ if (res != -1) {
+ res++;
+ }
} catch (IOException e) {
Log.w(TAG, "Failed to migrate " + sourceFile + ": " + e);
- res = false;
+ res = -1;
}
}
return res;
@@ -430,12 +435,17 @@
final File source = sourceContext.getSharedPreferencesPath(name);
final File target = getSharedPreferencesPath(name);
- // Evict any in-memory caches for either location
- final ArrayMap<File, SharedPreferencesImpl> cache = getSharedPreferencesCacheLocked();
- cache.remove(source);
- cache.remove(target);
-
- return migrateFiles(source.getParentFile(), target.getParentFile(), source.getName());
+ final int res = migrateFiles(source.getParentFile(), target.getParentFile(),
+ source.getName());
+ if (res > 0) {
+ // We moved at least one file, so evict any in-memory caches for
+ // either location
+ final ArrayMap<File, SharedPreferencesImpl> cache =
+ getSharedPreferencesCacheLocked();
+ cache.remove(source);
+ cache.remove(target);
+ }
+ return res != -1;
}
}
@@ -675,7 +685,8 @@
synchronized (ContextImpl.class) {
final File source = sourceContext.getDatabasePath(name);
final File target = getDatabasePath(name);
- return migrateFiles(source.getParentFile(), target.getParentFile(), source.getName());
+ return migrateFiles(source.getParentFile(), target.getParentFile(),
+ source.getName()) != -1;
}
}
@@ -813,7 +824,7 @@
null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, options,
user.getIdentifier());
} catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -878,7 +889,7 @@
}
Instrumentation.checkStartActivityResult(result, null);
} catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -893,7 +904,7 @@
Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
getUserId());
} catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -910,7 +921,7 @@
Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE,
null, false, false, getUserId());
} catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -925,7 +936,7 @@
Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE,
null, false, false, getUserId());
} catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -942,7 +953,7 @@
Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE,
options, false, false, getUserId());
} catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -959,7 +970,7 @@
Activity.RESULT_OK, null, null, receiverPermissions, appOp, null, false, false,
getUserId());
} catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -976,7 +987,7 @@
Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE,
null, true, false, getUserId());
} catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1039,7 +1050,7 @@
initialCode, initialData, initialExtras, receiverPermissions, appOp,
options, true, false, getUserId());
} catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1052,7 +1063,7 @@
intent, resolvedType, null, Activity.RESULT_OK, null, null, null,
AppOpsManager.OP_NONE, null, false, false, user.getIdentifier());
} catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1075,7 +1086,7 @@
Activity.RESULT_OK, null, null, receiverPermissions, appOp, null, false, false,
user.getIdentifier());
} catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1126,7 +1137,7 @@
initialCode, initialData, initialExtras, receiverPermissions,
appOp, options, true, false, user.getIdentifier());
} catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1142,7 +1153,7 @@
Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, true,
getUserId());
} catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1178,7 +1189,7 @@
initialCode, initialData, initialExtras, null,
AppOpsManager.OP_NONE, null, true, true, getUserId());
} catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1195,7 +1206,7 @@
ActivityManagerNative.getDefault().unbroadcastIntent(
mMainThread.getApplicationThread(), intent, getUserId());
} catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1210,7 +1221,7 @@
Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, true,
user.getIdentifier());
} catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1225,7 +1236,7 @@
Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, options, false, true,
user.getIdentifier());
} catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1260,7 +1271,7 @@
initialCode, initialData, initialExtras, null,
AppOpsManager.OP_NONE, null, true, true, user.getIdentifier());
} catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1277,7 +1288,7 @@
ActivityManagerNative.getDefault().unbroadcastIntent(
mMainThread.getApplicationThread(), intent, user.getIdentifier());
} catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1325,7 +1336,7 @@
mMainThread.getApplicationThread(), mBasePackageName,
rd, filter, broadcastPermission, userId);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1337,6 +1348,7 @@
try {
ActivityManagerNative.getDefault().unregisterReceiver(rd);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
} else {
throw new RuntimeException("Not supported in system context");
@@ -1393,7 +1405,7 @@
}
return cn;
} catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1415,7 +1427,7 @@
}
return res != 0;
} catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1474,7 +1486,7 @@
}
return res != 0;
} catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1489,6 +1501,7 @@
try {
ActivityManagerNative.getDefault().unbindService(sd);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
} else {
throw new RuntimeException("Not supported in system context");
@@ -1506,7 +1519,7 @@
className, profileFile, 0, arguments, null, null, getUserId(),
null /* ABI override */);
} catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1530,7 +1543,7 @@
return ActivityManagerNative.getDefault().checkPermission(
permission, pid, uid);
} catch (RemoteException e) {
- return PackageManager.PERMISSION_DENIED;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1545,7 +1558,7 @@
return ActivityManagerNative.getDefault().checkPermissionWithToken(
permission, pid, uid, callerToken);
} catch (RemoteException e) {
- return PackageManager.PERMISSION_DENIED;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1631,6 +1644,7 @@
mMainThread.getApplicationThread(), toPackage,
ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri));
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1641,6 +1655,7 @@
mMainThread.getApplicationThread(),
ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri));
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1651,7 +1666,7 @@
ContentProvider.getUriWithoutUserId(uri), pid, uid, modeFlags,
resolveUserId(uri), null);
} catch (RemoteException e) {
- return PackageManager.PERMISSION_DENIED;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1663,7 +1678,7 @@
ContentProvider.getUriWithoutUserId(uri), pid, uid, modeFlags,
resolveUserId(uri), callerToken);
} catch (RemoteException e) {
- return PackageManager.PERMISSION_DENIED;
+ throw e.rethrowFromSystemServer();
}
}
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index 1e5f007..ed4bb28 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -1193,52 +1193,13 @@
boolean isMediaScannerScannable, String mimeType, String path, long length,
boolean showNotification) {
return addCompletedDownload(title, description, isMediaScannerScannable, mimeType, path,
- length, showNotification, false, null, null);
- }
-
- /**
- * Adds a file to the downloads database system, so it could appear in Downloads App
- * (and thus become eligible for management by the Downloads App).
- * <p>
- * It is helpful to make the file scannable by MediaScanner by setting the param
- * isMediaScannerScannable to true. It makes the file visible in media managing
- * applications such as Gallery App, which could be a useful purpose of using this API.
- *
- * @param title the title that would appear for this file in Downloads App.
- * @param description the description that would appear for this file in Downloads App.
- * @param isMediaScannerScannable true if the file is to be scanned by MediaScanner. Files
- * scanned by MediaScanner appear in the applications used to view media (for example,
- * Gallery app).
- * @param mimeType mimetype of the file.
- * @param path absolute pathname to the file. The file should be world-readable, so that it can
- * be managed by the Downloads App and any other app that is used to read it (for example,
- * Gallery app to display the file, if the file contents represent a video/image).
- * @param length length of the downloaded file
- * @param showNotification true if a notification is to be sent, false otherwise
- * @param uri the original HTTP URI of the download
- * @param referer the HTTP Referer for the download
- * @return an ID for the download entry added to the downloads app, unique across the system
- * This ID is used to make future calls related to this download.
- */
- public long addCompletedDownload(String title, String description,
- boolean isMediaScannerScannable, String mimeType, String path, long length,
- boolean showNotification, Uri uri, Uri referer) {
- return addCompletedDownload(title, description, isMediaScannerScannable, mimeType, path,
- length, showNotification, false, uri, referer);
+ length, showNotification, false);
}
/** {@hide} */
public long addCompletedDownload(String title, String description,
boolean isMediaScannerScannable, String mimeType, String path, long length,
boolean showNotification, boolean allowWrite) {
- return addCompletedDownload(title, description, isMediaScannerScannable, mimeType, path,
- length, showNotification, allowWrite, null, null);
- }
-
- /** {@hide} */
- public long addCompletedDownload(String title, String description,
- boolean isMediaScannerScannable, String mimeType, String path, long length,
- boolean showNotification, boolean allowWrite, Uri uri, Uri referer) {
// make sure the input args are non-null/non-zero
validateArgumentIsNonEmpty("title", title);
validateArgumentIsNonEmpty("description", description);
@@ -1249,18 +1210,10 @@
}
// if there is already an entry with the given path name in downloads.db, return its id
- Request request;
- if (uri != null) {
- request = new Request(uri);
- } else {
- request = new Request(NON_DOWNLOADMANAGER_DOWNLOAD);
- }
- request.setTitle(title)
+ Request request = new Request(NON_DOWNLOADMANAGER_DOWNLOAD)
+ .setTitle(title)
.setDescription(description)
.setMimeType(mimeType);
- if (referer != null) {
- request.addRequestHeader("Referer", referer.toString());
- }
ContentValues values = request.toContentValues(null);
values.put(Downloads.Impl.COLUMN_DESTINATION,
Downloads.Impl.DESTINATION_NON_DOWNLOADMANAGER_DOWNLOAD);
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 02a898b..6870bbf 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -1033,7 +1033,7 @@
* false if it is not.
*/
public void setUserVisibleHint(boolean isVisibleToUser) {
- if (!mUserVisibleHint && isVisibleToUser && mState < STARTED) {
+ if (!mUserVisibleHint && isVisibleToUser && mState < STARTED && mFragmentManager != null) {
mFragmentManager.performPendingDeferredStart(this);
}
mUserVisibleHint = isVisibleToUser;
@@ -1203,7 +1203,7 @@
* }
* </code></pre></p>
*
- * @param permissions The requested permissions.
+ * @param permissions The requested permissions. Must me non-null and not empty.
* @param requestCode Application specific request code to match with a result
* reported to {@link #onRequestPermissionsResult(int, String[], int[])}.
* Should be >= 0.
@@ -2509,6 +2509,7 @@
throw new SuperNotCalledException("Fragment " + this
+ " did not call through to super.onDestroy()");
}
+ mChildFragmentManager = null;
}
private static Transition loadTransition(Context context, TypedArray typedArray,
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 4c8761c..0631943 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -24,6 +24,7 @@
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Configuration;
+import android.content.res.Resources.NotFoundException;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.os.Debug;
@@ -960,12 +961,24 @@
if (!f.mFromLayout) {
ViewGroup container = null;
if (f.mContainerId != 0) {
- container = (ViewGroup)mContainer.onFindViewById(f.mContainerId);
+ if (f.mContainerId == View.NO_ID) {
+ throwException(new IllegalArgumentException(
+ "Cannot create fragment "
+ + f
+ + " for a container view with no id"));
+ }
+ container = (ViewGroup) mContainer.onFindViewById(f.mContainerId);
if (container == null && !f.mRestored) {
+ String resName;
+ try {
+ resName = f.getResources().getResourceName(f.mContainerId);
+ } catch (NotFoundException e) {
+ resName = "unknown";
+ }
throwException(new IllegalArgumentException(
"No view found for id 0x"
+ Integer.toHexString(f.mContainerId) + " ("
- + f.getResources().getResourceName(f.mContainerId)
+ + resName
+ ") for fragment " + f));
}
}
@@ -1512,7 +1525,7 @@
throw new IllegalStateException("Must be called from main thread of fragment host");
}
- if (allowStateLoss) {
+ if (!allowStateLoss) {
checkStateLoss();
}
@@ -1612,7 +1625,9 @@
final BackStackRecord bss = mBackStack.remove(last);
SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();
SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();
- bss.calculateBackFragments(firstOutFragments, lastInFragments);
+ if (mCurState >= Fragment.CREATED) {
+ bss.calculateBackFragments(firstOutFragments, lastInFragments);
+ }
bss.popFromBackStack(true, null, firstOutFragments, lastInFragments);
reportBackStackChanged();
} else {
@@ -1659,8 +1674,10 @@
final int LAST = states.size()-1;
SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();
SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();
- for (int i=0; i<=LAST; i++) {
- states.get(i).calculateBackFragments(firstOutFragments, lastInFragments);
+ if (mCurState >= Fragment.CREATED) {
+ for (int i = 0; i <= LAST; i++) {
+ states.get(i).calculateBackFragments(firstOutFragments, lastInFragments);
+ }
}
BackStackRecord.TransitionState state = null;
for (int i=0; i<=LAST; i++) {
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index ca86c18..70bff80 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -143,7 +143,7 @@
public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) throws RemoteException;
public void moveTaskBackwards(int task) throws RemoteException;
public void moveTaskToStack(int taskId, int stackId, boolean toTop) throws RemoteException;
- public void moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
+ public boolean moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
Rect initialBounds) throws RemoteException;
public boolean moveTopActivityToPinnedStack(int stackId, Rect bounds) throws RemoteException;
public void resizeStack(int stackId, Rect bounds, boolean allowResizeInDockedMode,
@@ -171,6 +171,16 @@
public void resizeDockedStack(Rect dockedBounds, Rect tempDockedTaskBounds,
Rect tempDockedTaskInsetBounds,
Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds) throws RemoteException;
+ /**
+ * Resizes the pinned stack.
+ *
+ * @param pinnedBounds The bounds for the pinned stack.
+ * @param tempPinnedTaskBounds The temporary bounds for the tasks in the pinned stack, which
+ * might be different from the stack bounds to allow more
+ * flexibility while resizing, or {@code null} if they should be the
+ * same as the stack bounds.
+ */
+ public void resizePinnedStack(Rect pinnedBounds, Rect tempPinnedTaskBounds) throws RemoteException;
public void positionTaskInStack(int taskId, int stackId, int position) throws RemoteException;
public List<StackInfo> getAllStackInfos() throws RemoteException;
public StackInfo getStackInfo(int stackId) throws RemoteException;
@@ -305,8 +315,10 @@
String packageName, boolean waitForDebugger, boolean persistent)
throws RemoteException;
public void setAlwaysFinish(boolean enabled) throws RemoteException;
- public void setActivityController(IActivityController watcher)
+ public void setActivityController(IActivityController watcher, boolean imAMonkey)
throws RemoteException;
+ public void setLenientBackgroundCheck(boolean enabled) throws RemoteException;
+ public int getMemoryTrimLevel() throws RemoteException;
public void enterSafeMode() throws RemoteException;
@@ -978,4 +990,7 @@
int SUPPORTS_LOCAL_VOICE_INTERACTION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 365;
int NOTIFY_PINNED_STACK_ANIMATION_ENDED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 366;
int REMOVE_STACK = IBinder.FIRST_CALL_TRANSACTION + 367;
+ int SET_LENIENT_BACKGROUND_CHECK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+368;
+ int GET_MEMORY_TRIM_LEVEL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+369;
+ int RESIZE_PINNED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 370;
}
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index b55da88..628bde0 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -123,8 +123,13 @@
void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd)
throws RemoteException;
void setSchedulingGroup(int group) throws RemoteException;
+ // the package has been removed, clean up internal references
static final int PACKAGE_REMOVED = 0;
static final int EXTERNAL_STORAGE_UNAVAILABLE = 1;
+ // the package is being modified in-place, don't kill it and retain references to it
+ static final int PACKAGE_REMOVED_DONT_KILL = 2;
+ // a previously removed package was replaced with a new version [eg. upgrade, split added, ...]
+ static final int PACKAGE_REPLACED = 3;
void dispatchPackageBroadcast(int cmd, String[] packages) throws RemoteException;
void scheduleCrash(String msg) throws RemoteException;
void dumpActivity(FileDescriptor fd, IBinder servicetoken, String prefix, String[] args)
@@ -133,7 +138,8 @@
void updatePackageCompatibilityInfo(String pkg, CompatibilityInfo info) throws RemoteException;
void scheduleTrimMemory(int level) throws RemoteException;
void dumpMemInfo(FileDescriptor fd, Debug.MemoryInfo mem, boolean checkin, boolean dumpInfo,
- boolean dumpDalvik, boolean dumpSummaryOnly, String[] args) throws RemoteException;
+ boolean dumpDalvik, boolean dumpSummaryOnly, boolean dumpUnreachable,
+ String[] args) throws RemoteException;
void dumpGfxInfo(FileDescriptor fd, String[] args) throws RemoteException;
void dumpDbInfo(FileDescriptor fd, String[] args) throws RemoteException;
void unstableProviderDied(IBinder provider) throws RemoteException;
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 3c8dfce..5697924 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -48,16 +48,13 @@
boolean areNotificationsEnabledForPackage(String pkg, int uid);
boolean areNotificationsEnabled(String pkg);
- ParceledListSlice getTopics(String pkg, int uid);
- void setVisibilityOverride(String pkg, int uid, in Notification.Topic topic, int visibility);
- int getVisibilityOverride(String pkg, int uid, in Notification.Topic topic);
- void setPriority(String pkg, int uid, in Notification.Topic topic, int priority);
- int getPriority(String pkg, int uid, in Notification.Topic topic);
- void setImportance(String pkg, int uid, in Notification.Topic topic, int importance);
- int getImportance(String pkg, int uid, in Notification.Topic topic);
- int getTopicImportance(String pkg, String topicId);
- boolean doesUserUseTopics(String pkg, int uid);
- boolean hasBannedTopics(String pkg, int uid);
+ void setVisibilityOverride(String pkg, int uid, int visibility);
+ int getVisibilityOverride(String pkg, int uid);
+ void setPriority(String pkg, int uid, int priority);
+ int getPriority(String pkg, int uid);
+ void setImportance(String pkg, int uid, int importance);
+ int getImportance(String pkg, int uid);
+ int getPackageImportance(String pkg);
// TODO: Remove this when callers have been migrated to the equivalent
// INotificationListener method.
@@ -100,9 +97,9 @@
boolean isNotificationPolicyAccessGrantedForPackage(String pkg);
void setNotificationPolicyAccessGranted(String pkg, boolean granted);
AutomaticZenRule getAutomaticZenRule(String id);
- List<AutomaticZenRule> getAutomaticZenRules();
- AutomaticZenRule addAutomaticZenRule(in AutomaticZenRule automaticZenRule);
- boolean updateAutomaticZenRule(in AutomaticZenRule automaticZenRule);
+ List<ZenModeConfig.ZenRule> getZenRules();
+ String addAutomaticZenRule(in AutomaticZenRule automaticZenRule);
+ boolean updateAutomaticZenRule(String id, in AutomaticZenRule automaticZenRule);
boolean removeAutomaticZenRule(String id);
boolean removeAutomaticZenRules(String packageName);
int getRuleInstanceCount(in ComponentName owner);
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl
index 04493cb..1143c6a 100644
--- a/core/java/android/app/IWallpaperManager.aidl
+++ b/core/java/android/app/IWallpaperManager.aidl
@@ -27,7 +27,7 @@
interface IWallpaperManager {
/**
- * Set the wallpaper.
+ * Set the wallpaper for the current user.
*
* If 'extras' is non-null, on successful return it will contain:
* EXTRA_SET_WALLPAPER_ID : integer ID that the new wallpaper will have
@@ -56,10 +56,10 @@
void setWallpaperComponent(in ComponentName name);
/**
- * Get the system wallpaper.
+ * Get the wallpaper for a given user.
*/
- ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb,
- out Bundle outParams);
+ ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb, int which,
+ out Bundle outParams, int userId);
/**
* If the current system wallpaper is a live wallpaper component, return the
@@ -71,7 +71,7 @@
/**
* Clear the system wallpaper.
*/
- void clearWallpaper(in String callingPackage);
+ void clearWallpaper(in String callingPackage, int which, int userId);
/**
* Return whether the current system wallpaper has the given name.
@@ -118,4 +118,10 @@
* Check whether setting of wallpapers are allowed for the calling user.
*/
boolean isWallpaperSettingAllowed(in String callingPackage);
+
+ /*
+ * Keyguard: register a callback for being notified that lock-state relevant
+ * wallpaper content has changed.
+ */
+ boolean setLockWallpaperCallback(IWallpaperManagerCallback cb);
}
diff --git a/core/java/android/app/JobSchedulerImpl.java b/core/java/android/app/JobSchedulerImpl.java
index dacf4ea..b3a486f 100644
--- a/core/java/android/app/JobSchedulerImpl.java
+++ b/core/java/android/app/JobSchedulerImpl.java
@@ -46,9 +46,9 @@
}
@Override
- public int scheduleAsPackage(JobInfo job, String packageName, int userId) {
+ public int scheduleAsPackage(JobInfo job, String packageName, int userId, String tag) {
try {
- return mBinder.scheduleAsPackage(job, packageName, userId);
+ return mBinder.scheduleAsPackage(job, packageName, userId, tag);
} catch (RemoteException e) {
return JobScheduler.RESULT_FAILURE;
}
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 8717353..cd17078 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -58,6 +58,7 @@
import java.net.URL;
import java.util.List;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Objects;
@@ -83,24 +84,25 @@
private static final String TAG = "LoadedApk";
private final ActivityThread mActivityThread;
- private ApplicationInfo mApplicationInfo;
final String mPackageName;
- private final String mAppDir;
- private final String mResDir;
- private final String[] mSplitAppDirs;
- private final String[] mSplitResDirs;
- private final String[] mOverlayDirs;
- private final String[] mSharedLibraries;
- private final String mDataDir;
- private final String mLibDir;
- private final File mDataDirFile;
- private final File mDeviceEncryptedDataDirFile;
- private final File mCredentialEncryptedDataDirFile;
+ private ApplicationInfo mApplicationInfo;
+ private String mAppDir;
+ private String mResDir;
+ private String[] mSplitAppDirs;
+ private String[] mSplitResDirs;
+ private String[] mOverlayDirs;
+ private String[] mSharedLibraries;
+ private String mDataDir;
+ private String mLibDir;
+ private File mDataDirFile;
+ private File mDeviceEncryptedDataDirFile;
+ private File mCredentialEncryptedDataDirFile;
private final ClassLoader mBaseClassLoader;
private final boolean mSecurityViolation;
private final boolean mIncludeCode;
private final boolean mRegisterPackage;
private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
+ /** WARNING: This may change. Don't hold external references to it. */
Resources mResources;
private ClassLoader mClassLoader;
private Application mApplication;
@@ -129,23 +131,10 @@
public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
CompatibilityInfo compatInfo, ClassLoader baseLoader,
boolean securityViolation, boolean includeCode, boolean registerPackage) {
- final int myUid = Process.myUid();
- aInfo = adjustNativeLibraryPaths(aInfo);
mActivityThread = activityThread;
- mApplicationInfo = aInfo;
+ setApplicationInfo(aInfo);
mPackageName = aInfo.packageName;
- mAppDir = aInfo.sourceDir;
- mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
- mSplitAppDirs = aInfo.splitSourceDirs;
- mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
- mOverlayDirs = aInfo.resourceDirs;
- mSharedLibraries = aInfo.sharedLibraryFiles;
- mDataDir = aInfo.dataDir;
- mDataDirFile = FileUtils.newFileOrNull(mDataDir);
- mDeviceEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceEncryptedDataDir);
- mCredentialEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialEncryptedDataDir);
- mLibDir = aInfo.nativeLibraryDir;
mBaseClassLoader = baseLoader;
mSecurityViolation = securityViolation;
mIncludeCode = includeCode;
@@ -225,6 +214,10 @@
return mApplicationInfo;
}
+ public int getTargetSdkVersion() {
+ return mApplicationInfo.targetSdkVersion;
+ }
+
public boolean isSecurityViolation() {
return mSecurityViolation;
}
@@ -252,7 +245,7 @@
ai = ActivityThread.getPackageManager().getApplicationInfo(packageName,
PackageManager.GET_SHARED_LIBRARY_FILES, UserHandle.myUserId());
} catch (RemoteException e) {
- throw new AssertionError(e);
+ throw e.rethrowFromSystemServer();
}
if (ai == null) {
@@ -262,159 +255,248 @@
return ai.sharedLibraryFiles;
}
- public ClassLoader getClassLoader() {
+ public void updateApplicationInfo(ApplicationInfo aInfo, List<String> oldPaths) {
+ setApplicationInfo(aInfo);
+
+ final List<String> newPaths = new ArrayList<>();
+ makePaths(mActivityThread, aInfo, newPaths, null /*libPaths*/);
+ final List<String> addedPaths = new ArrayList<>(newPaths.size());
+
+ if (oldPaths != null) {
+ for (String path : newPaths) {
+ final String apkName = path.substring(path.lastIndexOf(File.separator));
+ boolean match = false;
+ for (String oldPath : oldPaths) {
+ final String oldApkName = oldPath.substring(path.lastIndexOf(File.separator));
+ if (apkName.equals(oldApkName)) {
+ match = true;
+ break;
+ }
+ }
+ if (!match) {
+ addedPaths.add(path);
+ }
+ }
+ } else {
+ addedPaths.addAll(newPaths);
+ }
synchronized (this) {
- if (mClassLoader != null) {
- return mClassLoader;
+ mClassLoader = createOrUpdateClassLoaderLocked(addedPaths);
+ if (mResources != null) {
+ mResources = mActivityThread.getNewTopLevelResources(mResDir, mSplitResDirs,
+ mOverlayDirs, mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY,
+ null /*overrideConfiguration*/, this);
+ }
+ }
+ }
+
+ private void setApplicationInfo(ApplicationInfo aInfo) {
+ final int myUid = Process.myUid();
+ aInfo = adjustNativeLibraryPaths(aInfo);
+ mApplicationInfo = aInfo;
+ mAppDir = aInfo.sourceDir;
+ mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
+ mSplitAppDirs = aInfo.splitSourceDirs;
+ mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
+ mOverlayDirs = aInfo.resourceDirs;
+ mSharedLibraries = aInfo.sharedLibraryFiles;
+ mDataDir = aInfo.dataDir;
+ mLibDir = aInfo.nativeLibraryDir;
+ mDataDirFile = FileUtils.newFileOrNull(aInfo.dataDir);
+ mDeviceEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceEncryptedDataDir);
+ mCredentialEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialEncryptedDataDir);
+ }
+
+ public static void makePaths(ActivityThread activityThread, ApplicationInfo aInfo,
+ List<String> outZipPaths, List<String> outLibPaths) {
+ final String appDir = aInfo.sourceDir;
+ final String[] splitAppDirs = aInfo.splitSourceDirs;
+ final String libDir = aInfo.nativeLibraryDir;
+ final String[] sharedLibraries = aInfo.sharedLibraryFiles;
+
+ outZipPaths.clear();
+ outZipPaths.add(appDir);
+ if (splitAppDirs != null) {
+ Collections.addAll(outZipPaths, splitAppDirs);
+ }
+
+ if (outLibPaths != null) {
+ outLibPaths.clear();
+ }
+
+ /*
+ * The following is a bit of a hack to inject
+ * instrumentation into the system: If the app
+ * being started matches one of the instrumentation names,
+ * then we combine both the "instrumentation" and
+ * "instrumented" app into the path, along with the
+ * concatenation of both apps' shared library lists.
+ */
+
+ String instrumentationPackageName = activityThread.mInstrumentationPackageName;
+ String instrumentationAppDir = activityThread.mInstrumentationAppDir;
+ String[] instrumentationSplitAppDirs = activityThread.mInstrumentationSplitAppDirs;
+ String instrumentationLibDir = activityThread.mInstrumentationLibDir;
+
+ String instrumentedAppDir = activityThread.mInstrumentedAppDir;
+ String[] instrumentedSplitAppDirs = activityThread.mInstrumentedSplitAppDirs;
+ String instrumentedLibDir = activityThread.mInstrumentedLibDir;
+ String[] instrumentationLibs = null;
+
+ if (appDir.equals(instrumentationAppDir)
+ || appDir.equals(instrumentedAppDir)) {
+ outZipPaths.clear();
+ outZipPaths.add(instrumentationAppDir);
+ if (instrumentationSplitAppDirs != null) {
+ Collections.addAll(outZipPaths, instrumentationSplitAppDirs);
+ }
+ outZipPaths.add(instrumentedAppDir);
+ if (instrumentedSplitAppDirs != null) {
+ Collections.addAll(outZipPaths, instrumentedSplitAppDirs);
}
- if (mIncludeCode && !mPackageName.equals("android")) {
- // Avoid the binder call when the package is the current application package.
- // The activity manager will perform ensure that dexopt is performed before
- // spinning up the process.
- if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) {
- final String isa = VMRuntime.getRuntime().vmInstructionSet();
- try {
- ActivityThread.getPackageManager().notifyPackageUse(mPackageName);
- } catch (RemoteException re) {
- // Ignored.
- }
+ if (outLibPaths != null) {
+ outLibPaths.add(instrumentationLibDir);
+ outLibPaths.add(instrumentedLibDir);
+ }
+
+ if (!instrumentedAppDir.equals(instrumentationAppDir)) {
+ instrumentationLibs = getLibrariesFor(instrumentationPackageName);
+ }
+ }
+
+ if (outLibPaths != null) {
+ if (outLibPaths.isEmpty()) {
+ outLibPaths.add(libDir);
+ }
+
+ // Add path to libraries in apk for current abi. Do this now because more entries
+ // will be added to zipPaths that shouldn't be part of the library path.
+ if (aInfo.primaryCpuAbi != null) {
+ for (String apk : outZipPaths) {
+ outLibPaths.add(apk + "!/lib/" + aInfo.primaryCpuAbi);
}
+ }
- final List<String> zipPaths = new ArrayList<>();
- final List<String> apkPaths = new ArrayList<>();
- final List<String> libPaths = new ArrayList<>();
+ if (aInfo.isSystemApp() && !aInfo.isUpdatedSystemApp()) {
+ // Add path to system libraries to libPaths;
+ // Access to system libs should be limited
+ // to bundled applications; this is why updated
+ // system apps are not included.
+ outLibPaths.add(System.getProperty("java.library.path"));
+ }
+ }
- if (mRegisterPackage) {
- try {
- ActivityManagerNative.getDefault().addPackageDependency(mPackageName);
- } catch (RemoteException e) {
- }
+ if (sharedLibraries != null) {
+ for (String lib : sharedLibraries) {
+ if (!outZipPaths.contains(lib)) {
+ outZipPaths.add(0, lib);
}
+ }
+ }
- zipPaths.add(mAppDir);
- if (mSplitAppDirs != null) {
- Collections.addAll(zipPaths, mSplitAppDirs);
+ if (instrumentationLibs != null) {
+ for (String lib : instrumentationLibs) {
+ if (!outZipPaths.contains(lib)) {
+ outZipPaths.add(0, lib);
}
+ }
+ }
- libPaths.add(mLibDir);
+ final String zip = TextUtils.join(File.pathSeparator, outZipPaths);
+ }
- /*
- * The following is a bit of a hack to inject
- * instrumentation into the system: If the app
- * being started matches one of the instrumentation names,
- * then we combine both the "instrumentation" and
- * "instrumented" app into the path, along with the
- * concatenation of both apps' shared library lists.
- */
-
- String instrumentationPackageName = mActivityThread.mInstrumentationPackageName;
- String instrumentationAppDir = mActivityThread.mInstrumentationAppDir;
- String[] instrumentationSplitAppDirs = mActivityThread.mInstrumentationSplitAppDirs;
- String instrumentationLibDir = mActivityThread.mInstrumentationLibDir;
-
- String instrumentedAppDir = mActivityThread.mInstrumentedAppDir;
- String[] instrumentedSplitAppDirs = mActivityThread.mInstrumentedSplitAppDirs;
- String instrumentedLibDir = mActivityThread.mInstrumentedLibDir;
- String[] instrumentationLibs = null;
-
- if (mAppDir.equals(instrumentationAppDir)
- || mAppDir.equals(instrumentedAppDir)) {
- zipPaths.clear();
- zipPaths.add(instrumentationAppDir);
- if (instrumentationSplitAppDirs != null) {
- Collections.addAll(zipPaths, instrumentationSplitAppDirs);
- }
- zipPaths.add(instrumentedAppDir);
- if (instrumentedSplitAppDirs != null) {
- Collections.addAll(zipPaths, instrumentedSplitAppDirs);
- }
-
- libPaths.clear();
- libPaths.add(instrumentationLibDir);
- libPaths.add(instrumentedLibDir);
-
- if (!instrumentedAppDir.equals(instrumentationAppDir)) {
- instrumentationLibs = getLibrariesFor(instrumentationPackageName);
- }
+ private ClassLoader createOrUpdateClassLoaderLocked(List<String> addedPaths) {
+ final ClassLoader classLoader;
+ if (mIncludeCode && !mPackageName.equals("android")) {
+ // Avoid the binder call when the package is the current application package.
+ // The activity manager will perform ensure that dexopt is performed before
+ // spinning up the process.
+ if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) {
+ VMRuntime.getRuntime().vmInstructionSet();
+ try {
+ ActivityThread.getPackageManager().notifyPackageUse(mPackageName);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
}
+ }
- apkPaths.addAll(zipPaths);
+ final List<String> zipPaths = new ArrayList<>();
+ final List<String> libPaths = new ArrayList<>();
- if (mSharedLibraries != null) {
- for (String lib : mSharedLibraries) {
- if (!zipPaths.contains(lib)) {
- zipPaths.add(0, lib);
- }
- }
+ if (mRegisterPackage) {
+ try {
+ ActivityManagerNative.getDefault().addPackageDependency(mPackageName);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
+ }
- if (instrumentationLibs != null) {
- for (String lib : instrumentationLibs) {
- if (!zipPaths.contains(lib)) {
- zipPaths.add(0, lib);
- }
- }
- }
+ makePaths(mActivityThread, mApplicationInfo, zipPaths, libPaths);
+ final String zip = TextUtils.join(File.pathSeparator, zipPaths);
+ final boolean isBundledApp = mApplicationInfo.isSystemApp()
+ && !mApplicationInfo.isUpdatedSystemApp();
+ String libraryPermittedPath = mDataDir;
+ if (isBundledApp) {
+ // This is necessary to grant bundled apps access to
+ // libraries located in subdirectories of /system/lib
+ libraryPermittedPath += File.pathSeparator +
+ System.getProperty("java.library.path");
+ }
+ // DO NOT SHIP: this is a workaround for apps loading native libraries
+ // provided by 3rd party apps using absolute path instead of corresponding
+ // classloader; see http://b/26954419 for example.
+ if (mApplicationInfo.targetSdkVersion <= 23) {
+ libraryPermittedPath += File.pathSeparator + "/data/app";
+ }
+ // -----------------------------------------------------------------------------
- final String zip = TextUtils.join(File.pathSeparator, zipPaths);
+ final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
- // Add path to libraries in apk for current abi
- if (mApplicationInfo.primaryCpuAbi != null) {
- for (String apk : apkPaths) {
- libPaths.add(apk + "!/lib/" + mApplicationInfo.primaryCpuAbi);
- }
- }
+ /*
+ * With all the combination done (if necessary, actually
+ * create the class loader.
+ */
- String libraryPermittedPath = mDataDir;
- boolean isBundledApp = false;
+ if (ActivityThread.localLOGV)
+ Slog.v(ActivityThread.TAG, "Class path: " + zip +
+ ", JNI path: " + librarySearchPath);
- if (mApplicationInfo.isSystemApp()) {
- isBundledApp = true;
- // Add path to system libraries to libPaths;
- // Access to system libs should be limited
- // to bundled applications; this is why updated
- // system apps are not included.
- libPaths.add(System.getProperty("java.library.path"));
-
- // This is necessary to grant bundled apps access to
- // libraries located in subdirectories of /system/lib
- libraryPermittedPath += File.pathSeparator +
- System.getProperty("java.library.path");
- }
- // DO NOT SHIP: this is a workaround for apps loading native libraries
- // provided by 3rd party apps using absolute path instead of corresponding
- // classloader; see http://b/26954419 for example.
- if (mApplicationInfo.targetSdkVersion <= 23) {
- libraryPermittedPath += File.pathSeparator + "/data/app";
- }
- // -----------------------------------------------------------------------------
-
- final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
-
- /*
- * With all the combination done (if necessary, actually
- * create the class loader.
- */
-
- if (ActivityThread.localLOGV)
- Slog.v(ActivityThread.TAG, "Class path: " + zip +
- ", JNI path: " + librarySearchPath);
-
+ if (mClassLoader == null) {
// Temporarily disable logging of disk reads on the Looper thread
// as this is early and necessary.
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
- mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip, isBundledApp,
- librarySearchPath, libraryPermittedPath, mBaseClassLoader);
+ classLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
+ mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
+ libraryPermittedPath, mBaseClassLoader);
StrictMode.setThreadPolicy(oldPolicy);
+ } else if (addedPaths != null && addedPaths.size() > 0) {
+ final String add = TextUtils.join(File.pathSeparator, addedPaths);
+ ApplicationLoaders.getDefault().addPath(mClassLoader, add);
+ classLoader = mClassLoader;
} else {
+ classLoader = mClassLoader;
+ }
+ } else {
+ if (mClassLoader == null) {
if (mBaseClassLoader == null) {
- mClassLoader = ClassLoader.getSystemClassLoader();
+ classLoader = ClassLoader.getSystemClassLoader();
} else {
- mClassLoader = mBaseClassLoader;
+ classLoader = mBaseClassLoader;
}
+ } else {
+ classLoader = mClassLoader;
+ }
+ }
+ return classLoader;
+ }
+
+ public ClassLoader getClassLoader() {
+ synchronized (this) {
+ if (mClassLoader == null) {
+ mClassLoader = createOrUpdateClassLoaderLocked(null /*addedPaths*/);
}
return mClassLoader;
}
@@ -450,8 +532,7 @@
pi = pm.getPackageInfo(mPackageName, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
UserHandle.myUserId());
} catch (RemoteException e) {
- throw new IllegalStateException("Unable to get package info for "
- + mPackageName + "; is system dying?", e);
+ throw e.rethrowFromSystemServer();
}
if (pi == null) {
throw new IllegalStateException("Unable to get package info for "
@@ -708,7 +789,7 @@
ActivityManagerNative.getDefault().unregisterReceiver(
rd.getIIntentReceiver());
} catch (RemoteException e) {
- // system crashed, nothing we can do
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -734,7 +815,7 @@
ActivityManagerNative.getDefault().unbindService(
sd.getIServiceConnection());
} catch (RemoteException e) {
- // system crashed, nothing we can do
+ throw e.rethrowFromSystemServer();
}
sd.doForget();
}
@@ -859,7 +940,7 @@
}
mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
} catch (RemoteException e) {
- Slog.w(ActivityThread.TAG, "Couldn't finish broadcast to unregistered receiver");
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1097,7 +1178,6 @@
private RuntimeException mUnbindLocation;
- private boolean mDied;
private boolean mForgotten;
private static class ConnectionInfo {
@@ -1196,7 +1276,6 @@
ServiceDispatcher.ConnectionInfo old;
synchronized (this) {
- mDied = true;
old = mActiveConnections.remove(name);
if (old == null || old.binder != service) {
// Death for someone different than who we last
@@ -1231,7 +1310,6 @@
if (service != null) {
// A new service is being connected... set it all up.
- mDied = false;
info = new ConnectionInfo();
info.binder = service;
info.deathMonitor = new DeathMonitor(name, service);
diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java
index 873e337..2a1e3c2 100644
--- a/core/java/android/app/LocalActivityManager.java
+++ b/core/java/android/app/LocalActivityManager.java
@@ -144,7 +144,7 @@
if (desiredState == RESUMED) {
if (localLOGV) Log.v(TAG, r.id + ": resuming");
- mActivityThread.performResumeActivity(r, true);
+ mActivityThread.performResumeActivity(r, true, "moveToState-INITIALIZING");
r.curState = RESUMED;
}
@@ -167,7 +167,7 @@
if (desiredState == RESUMED) {
if (localLOGV) Log.v(TAG, r.id + ": restarting and resuming");
mActivityThread.performRestartActivity(r);
- mActivityThread.performResumeActivity(r, true);
+ mActivityThread.performResumeActivity(r, true, "moveToState-CREATED");
r.curState = RESUMED;
}
return;
@@ -176,13 +176,13 @@
if (desiredState == RESUMED) {
// Need to resume it...
if (localLOGV) Log.v(TAG, r.id + ": resuming");
- mActivityThread.performResumeActivity(r, true);
+ mActivityThread.performResumeActivity(r, true, "moveToState-STARTED");
r.instanceState = null;
r.curState = RESUMED;
}
if (desiredState == CREATED) {
if (localLOGV) Log.v(TAG, r.id + ": stopping");
- mActivityThread.performStopActivity(r, false);
+ mActivityThread.performStopActivity(r, false, "moveToState-STARTED");
r.curState = CREATED;
}
return;
@@ -197,7 +197,7 @@
if (localLOGV) Log.v(TAG, r.id + ": pausing");
performPause(r, mFinishing);
if (localLOGV) Log.v(TAG, r.id + ": stopping");
- mActivityThread.performStopActivity(r, false);
+ mActivityThread.performStopActivity(r, false, "moveToState-RESUMED");
r.curState = CREATED;
}
return;
@@ -205,9 +205,9 @@
}
private void performPause(LocalActivityRecord r, boolean finishing) {
- boolean needState = r.instanceState == null;
- Bundle instanceState = mActivityThread.performPauseActivity(r,
- finishing, needState);
+ final boolean needState = r.instanceState == null;
+ final Bundle instanceState = mActivityThread.performPauseActivity(
+ r, finishing, needState, "performPause");
if (needState) {
r.instanceState = instanceState;
}
diff --git a/core/java/android/app/NativeActivity.java b/core/java/android/app/NativeActivity.java
index aa14cb5..b6e0467 100644
--- a/core/java/android/app/NativeActivity.java
+++ b/core/java/android/app/NativeActivity.java
@@ -95,8 +95,7 @@
private native long loadNativeCode(String path, String funcname, MessageQueue queue,
String internalDataPath, String obbPath, String externalDataPath, int sdkVersion,
- AssetManager assetMgr, byte[] savedState, ClassLoader classLoader, String libraryPath,
- String isolationPath);
+ AssetManager assetMgr, byte[] savedState, ClassLoader classLoader, String libraryPath);
private native String getDlError();
private native void unloadNativeCode(long handle);
private native void onStartNative(long handle);
@@ -166,7 +165,8 @@
String path = classLoader.findLibrary(libname);
if (path == null) {
- throw new IllegalArgumentException("Unable to find native library: " + libname);
+ throw new IllegalArgumentException("Unable to find native library " + libname +
+ " using classloader: " + classLoader.toString());
}
byte[] nativeSavedState = savedInstanceState != null
@@ -176,8 +176,7 @@
getAbsolutePath(getFilesDir()), getAbsolutePath(getObbDir()),
getAbsolutePath(getExternalFilesDir(null)),
Build.VERSION.SDK_INT, getAssets(), nativeSavedState,
- classLoader, classLoader.getLdLibraryPath(),
- classLoader.getLibraryPermittedPath());
+ classLoader, classLoader.getLdLibraryPath());
if (mNativeHandle == 0) {
throw new UnsatisfiedLinkError(
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 52631d1..2c34371 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -21,7 +21,6 @@
import android.annotation.IntDef;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SystemApi;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@@ -44,7 +43,12 @@
import android.os.Parcelable;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
import android.text.TextUtils;
+import android.text.style.AbsoluteSizeSpan;
+import android.text.style.RelativeSizeSpan;
+import android.text.style.TextAppearanceSpan;
import android.util.Log;
import android.util.SparseArray;
import android.util.TypedValue;
@@ -65,7 +69,6 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-import java.util.Objects;
import java.util.Set;
/**
@@ -823,6 +826,12 @@
public static final String EXTRA_SHOW_CHRONOMETER = "android.showChronometer";
/**
+ * {@link #extras} key: whether the chronometer set on the notification should count down
+ * instead of counting up. Is only relevant if key {@link #EXTRA_SHOW_CHRONOMETER} is present.
+ */
+ public static final String EXTRA_CHRONOMETER_COUNTS_DOWN = "android.chronometerCountsDown";
+
+ /**
* {@link #extras} key: whether {@link #when} should be shown,
* as supplied to {@link Builder#setShowWhen(boolean)}.
*/
@@ -895,6 +904,11 @@
*/
public static final String EXTRA_BUILDER_APPLICATION_INFO = "android.appInfo";
+ /**
+ * @hide
+ */
+ public static final String EXTRA_CONTAINS_CUSTOM_VIEW = "android.contains.customView";
+
private Icon mSmallIcon;
private Icon mLargeIcon;
@@ -1366,98 +1380,6 @@
public Notification publicVersion;
/**
- * Structure to encapsulate a topic that is shown in Notification settings.
- * It must include an id and label.
- */
- public static class Topic implements Parcelable {
- private final String id;
- private final CharSequence label;
-
- public Topic(String id, CharSequence label) {
- this.id = id;
- this.label = safeCharSequence(label);
- }
-
- private Topic(Parcel in) {
- if (in.readInt() != 0) {
- id = in.readString();
- } else {
- id = null;
- }
- label = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
- }
-
- public String getId() {
- return id;
- }
-
- public CharSequence getLabel() {
- return label;
- }
-
- @Override
- public String toString() {
- return new StringBuilder(Topic.class.getSimpleName()).append('[')
- .append("id=").append(id)
- .append(",label=").append(label)
- .append(']').toString();
- }
-
- @Override
- public boolean equals(Object o) {
- if (!(o instanceof Topic)) return false;
- if (o == this) return true;
- final Topic other = (Topic) o;
- return Objects.equals(other.id, id)
- && Objects.equals(other.label, label);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(id, label);
- }
-
- @Override
- public Topic clone() {
- return new Topic(id, label);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- if (id != null) {
- out.writeInt(1);
- out.writeString(id);
- } else {
- out.writeInt(0);
- }
- TextUtils.writeToParcel(label, out, flags);
- }
- public static final Parcelable.Creator<Topic> CREATOR =
- new Parcelable.Creator<Topic>() {
- public Topic createFromParcel(Parcel in) {
- return new Topic(in);
- }
- public Topic[] newArray(int size) {
- return new Topic[size];
- }
- };
- }
-
- @SystemApi
- public static final String TOPIC_DEFAULT = "system_default_topic";
-
- private Topic topic;
-
- public Topic getTopic() {
- return topic;
- }
-
- /**
* Constructs a Notification object with default values.
* You might want to consider using {@link Builder} instead.
*/
@@ -1583,10 +1505,6 @@
}
color = parcel.readInt();
-
- if (parcel.readInt() != 0) {
- topic = Topic.CREATOR.createFromParcel(parcel);
- }
}
@Override
@@ -1687,10 +1605,6 @@
that.color = this.color;
- if (this.topic != null) {
- that.topic = this.topic.clone();
- }
-
if (!heavy) {
that.lightenPayload(); // will clean out extras
}
@@ -1740,8 +1654,34 @@
+ " instance is a custom Parcelable and not allowed in Notification");
return cs.toString();
}
+ return removeTextSizeSpans(cs);
+ }
- return cs;
+ private static CharSequence removeTextSizeSpans(CharSequence charSequence) {
+ if (charSequence instanceof Spanned) {
+ Spanned ss = (Spanned) charSequence;
+ Object[] spans = ss.getSpans(0, ss.length(), Object.class);
+ SpannableStringBuilder builder = new SpannableStringBuilder(ss.toString());
+ for (Object span : spans) {
+ Object resultSpan = span;
+ if (span instanceof TextAppearanceSpan) {
+ TextAppearanceSpan originalSpan = (TextAppearanceSpan) span;
+ resultSpan = new TextAppearanceSpan(
+ originalSpan.getFamily(),
+ originalSpan.getTextStyle(),
+ -1,
+ originalSpan.getTextColor(),
+ originalSpan.getLinkTextColor());
+ } else if (span instanceof RelativeSizeSpan
+ || span instanceof AbsoluteSizeSpan) {
+ continue;
+ }
+ builder.setSpan(resultSpan, ss.getSpanStart(span), ss.getSpanEnd(span),
+ ss.getSpanFlags(span));
+ }
+ return builder;
+ }
+ return charSequence;
}
public int describeContents() {
@@ -1871,13 +1811,6 @@
}
parcel.writeInt(color);
-
- if (topic != null) {
- parcel.writeInt(1);
- topic.writeToParcel(parcel, 0);
- } else {
- parcel.writeInt(0);
- }
}
/**
@@ -2020,10 +1953,6 @@
sb.append(" publicVersion=");
sb.append(publicVersion.toString());
}
- if (topic != null) {
- sb.append("topic=");
- sb.append(topic.toString());
- }
sb.append(")");
return sb.toString();
}
@@ -2264,8 +2193,12 @@
*
* Useful when showing an elapsed time (like an ongoing phone call).
*
+ * The counter can also be set to count down to <code>when</code> when using
+ * {@link #setChronometerCountsDown(boolean)}.
+ *
* @see android.widget.Chronometer
* @see Notification#when
+ * @see #setChronometerCountsDown(boolean)
*/
public Builder setUsesChronometer(boolean b) {
mN.extras.putBoolean(EXTRA_SHOW_CHRONOMETER, b);
@@ -2273,6 +2206,19 @@
}
/**
+ * Sets the Chronometer to count down instead of counting up.
+ *
+ * <p>This is only relevant if {@link #setUsesChronometer(boolean)} has been set to true.
+ * If it isn't set the chronometer will count up.
+ *
+ * @see #setUsesChronometer(boolean)
+ */
+ public Builder setChronometerCountsDown(boolean countsDown) {
+ mN.extras.putBoolean(EXTRA_CHRONOMETER_COUNTS_DOWN, countsDown);
+ return this;
+ }
+
+ /**
* Set the small icon resource, which will be used to represent the notification in the
* status bar.
*
@@ -2995,19 +2941,6 @@
return this;
}
- /**
- * Sets the topic of this notification. Topics are typically displayed in Notification
- * settings.
- * <p>
- * Every topic must have an id and a textual label.
- *
- * @param topic The topic to add.
- */
- public Builder setTopic(Topic topic) {
- mN.topic = topic;
- return this;
- }
-
private Drawable getProfileBadgeDrawable() {
// Note: This assumes that the current user can read the profile badge of the
// originating user.
@@ -3216,6 +3149,8 @@
contentView.setLong(R.id.chronometer, "setBase",
mN.when + (SystemClock.elapsedRealtime() - System.currentTimeMillis()));
contentView.setBoolean(R.id.chronometer, "setStarted", true);
+ boolean countsDown = mN.extras.getBoolean(EXTRA_CHRONOMETER_COUNTS_DOWN);
+ contentView.setChronometerCountsDown(R.id.chronometer, countsDown);
} else {
contentView.setViewVisibility(R.id.time, View.VISIBLE);
contentView.setLong(R.id.time, "setTime", mN.when);
@@ -3352,8 +3287,8 @@
* 2. Style's proposed content view
* 3. Standard template view
*/
- public RemoteViews makeContentView() {
- if (mN.contentView != null) {
+ public RemoteViews createContentView() {
+ if (mN.contentView != null && (mStyle == null || !mStyle.displayCustomViewInline())) {
return mN.contentView;
} else if (mStyle != null) {
final RemoteViews styleView = mStyle.makeContentView();
@@ -3367,9 +3302,10 @@
/**
* Construct a RemoteViews for the final big notification layout.
*/
- public RemoteViews makeBigContentView() {
+ public RemoteViews createBigContentView() {
RemoteViews result = null;
- if (mN.bigContentView != null) {
+ if (mN.bigContentView != null
+ && (mStyle == null || !mStyle.displayCustomViewInline())) {
return mN.bigContentView;
} else if (mStyle != null) {
result = mStyle.makeBigContentView();
@@ -3409,8 +3345,9 @@
/**
* Construct a RemoteViews for the final heads-up notification layout.
*/
- public RemoteViews makeHeadsUpContentView() {
- if (mN.headsUpContentView != null) {
+ public RemoteViews createHeadsUpContentView() {
+ if (mN.headsUpContentView != null
+ && (mStyle == null || !mStyle.displayCustomViewInline())) {
return mN.headsUpContentView;
} else if (mStyle != null) {
final RemoteViews styleView = mStyle.makeHeadsUpContentView();
@@ -3421,7 +3358,6 @@
return null;
}
-
return applyStandardTemplateWithActions(getBigBaseLayoutResource());
}
@@ -3433,7 +3369,7 @@
public RemoteViews makePublicContentView() {
if (mN.publicVersion != null) {
final Builder builder = recoverBuilder(mContext, mN.publicVersion);
- return builder.makeContentView();
+ return builder.createContentView();
}
Bundle savedBundle = mN.extras;
Style style = mStyle;
@@ -3445,6 +3381,8 @@
savedBundle.getBoolean(EXTRA_SHOW_WHEN));
publicExtras.putBoolean(EXTRA_SHOW_CHRONOMETER,
savedBundle.getBoolean(EXTRA_SHOW_CHRONOMETER));
+ publicExtras.putBoolean(EXTRA_CHRONOMETER_COUNTS_DOWN,
+ savedBundle.getBoolean(EXTRA_CHRONOMETER_COUNTS_DOWN));
publicExtras.putCharSequence(EXTRA_TITLE,
mContext.getString(R.string.notification_hidden_text));
mN.extras = publicExtras;
@@ -3547,9 +3485,18 @@
mN.extras.putStringArray(EXTRA_PEOPLE,
mPersonList.toArray(new String[mPersonList.size()]));
}
+ if (mN.bigContentView != null || mN.contentView != null
+ || mN.headsUpContentView != null) {
+ mN.extras.putBoolean(EXTRA_CONTAINS_CUSTOM_VIEW, true);
+ }
return mN;
}
+ /**
+ * Creates a Builder from an existing notification so further changes can be made.
+ * @param context The context for your application / activity.
+ * @param n The notification to create a Builder from.
+ */
public static Notification.Builder recoverBuilder(Context context, Notification n) {
// Re-create notification context so we can access app resources.
ApplicationInfo applicationInfo = n.extras.getParcelable(
@@ -3571,8 +3518,9 @@
}
private static Class<? extends Style> getNotificationStyleClass(String templateClass) {
- Class<? extends Style>[] classes = new Class[]{
- BigTextStyle.class, BigPictureStyle.class, InboxStyle.class, MediaStyle.class};
+ Class<? extends Style>[] classes = new Class[] {
+ BigTextStyle.class, BigPictureStyle.class, InboxStyle.class, MediaStyle.class,
+ DecoratedCustomViewStyle.class, DecoratedMediaCustomViewStyle.class };
for (Class<? extends Style> innerClass : classes) {
if (templateClass.equals(innerClass.getName())) {
return innerClass;
@@ -3608,21 +3556,22 @@
mStyle.buildStyled(mN);
}
- if (mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) {
+ if (mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N
+ && (mStyle == null || !mStyle.displayCustomViewInline())) {
if (mN.contentView == null) {
- mN.contentView = makeContentView();
+ mN.contentView = createContentView();
mN.extras.putInt(EXTRA_REBUILD_CONTENT_VIEW_ACTION_COUNT,
mN.contentView.getSequenceNumber());
}
if (mN.bigContentView == null) {
- mN.bigContentView = makeBigContentView();
+ mN.bigContentView = createBigContentView();
if (mN.bigContentView != null) {
mN.extras.putInt(EXTRA_REBUILD_BIG_CONTENT_VIEW_ACTION_COUNT,
mN.bigContentView.getSequenceNumber());
}
}
if (mN.headsUpContentView == null) {
- mN.headsUpContentView = makeHeadsUpContentView();
+ mN.headsUpContentView = createHeadsUpContentView();
if (mN.headsUpContentView != null) {
mN.extras.putInt(EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW_ACTION_COUNT,
mN.headsUpContentView.getSequenceNumber());
@@ -3877,6 +3826,14 @@
public boolean hasSummaryInHeader() {
return true;
}
+
+ /**
+ * @hide
+ * @return Whether custom content views are displayed inline in the style
+ */
+ public boolean displayCustomViewInline() {
+ return false;
+ }
}
/**
@@ -4250,6 +4207,7 @@
final float density = mBuilder.mContext.getResources().getDisplayMetrics().density;
int topPadding = (int) (5 * density);
int bottomPadding = (int) (13 * density);
+ boolean first = true;
while (i < mTexts.size() && i < rowIds.length) {
CharSequence str = mTexts.get(i);
if (str != null && !str.equals("")) {
@@ -4261,23 +4219,26 @@
}
contentView.setViewPadding(rowIds[i], 0, topPadding, 0,
i == rowIds.length - 1 || i == mTexts.size() - 1 ? bottomPadding : 0);
+ handleInboxImageMargin(contentView, rowIds[i], first);
+ first = false;
}
i++;
}
- handleInboxImageMargin(contentView, rowIds[0]);
return contentView;
}
- private void handleInboxImageMargin(RemoteViews contentView, int id) {
- final int max = mBuilder.mN.extras.getInt(EXTRA_PROGRESS_MAX, 0);
- final boolean ind = mBuilder.mN.extras.getBoolean(EXTRA_PROGRESS_INDETERMINATE);
- boolean hasProgress = max != 0 || ind;
+ private void handleInboxImageMargin(RemoteViews contentView, int id, boolean first) {
int endMargin = 0;
- if (mTexts.size() > 0 && mBuilder.mN.mLargeIcon != null && !hasProgress) {
- endMargin = mBuilder.mContext.getResources().getDimensionPixelSize(
- R.dimen.notification_content_picture_margin);
+ if (first) {
+ final int max = mBuilder.mN.extras.getInt(EXTRA_PROGRESS_MAX, 0);
+ final boolean ind = mBuilder.mN.extras.getBoolean(EXTRA_PROGRESS_INDETERMINATE);
+ boolean hasProgress = max != 0 || ind;
+ if (mBuilder.mN.mLargeIcon != null && !hasProgress) {
+ endMargin = mBuilder.mContext.getResources().getDimensionPixelSize(
+ R.dimen.notification_content_picture_margin);
+ }
}
contentView.setViewLayoutMarginEnd(id, endMargin);
}
@@ -4460,13 +4421,11 @@
}
handleImage(view);
// handle the content margin
- int endMargin;
+ int endMargin = mBuilder.mContext.getResources().getDimensionPixelSize(
+ R.dimen.notification_content_margin_end);;
if (mBuilder.mN.mLargeIcon != null) {
- endMargin = mBuilder.mContext.getResources().getDimensionPixelSize(
- R.dimen.notification_content_picture_margin_media);
- } else {
- endMargin = mBuilder.mContext.getResources().getDimensionPixelSize(
- R.dimen.notification_content_margin_end);
+ endMargin += mBuilder.mContext.getResources().getDimensionPixelSize(
+ R.dimen.notification_content_picture_margin);
}
view.setViewLayoutMarginEnd(R.id.notification_main_column, endMargin);
return view;
@@ -4513,6 +4472,224 @@
}
}
+ /**
+ * Notification style for custom views that are decorated by the system
+ *
+ * <p>Instead of providing a notification that is completely custom, a developer can set this
+ * style and still obtain system decorations like the notification header with the expand
+ * affordance and actions.
+ *
+ * <p>Use {@link android.app.Notification.Builder#setCustomContentView(RemoteViews)},
+ * {@link android.app.Notification.Builder#setCustomBigContentView(RemoteViews)} and
+ * {@link android.app.Notification.Builder#setCustomHeadsUpContentView(RemoteViews)} to set the
+ * corresponding custom views to display.
+ *
+ * To use this style with your Notification, feed it to
+ * {@link Notification.Builder#setStyle(android.app.Notification.Style)} like so:
+ * <pre class="prettyprint">
+ * Notification noti = new Notification.Builder()
+ * .setSmallIcon(R.drawable.ic_stat_player)
+ * .setLargeIcon(albumArtBitmap))
+ * .setCustomContentView(contentView);
+ * .setStyle(<b>new Notification.DecoratedCustomViewStyle()</b>)
+ * .build();
+ * </pre>
+ */
+ public static class DecoratedCustomViewStyle extends Style {
+
+ public DecoratedCustomViewStyle() {
+ }
+
+ public DecoratedCustomViewStyle(Builder builder) {
+ setBuilder(builder);
+ }
+
+ /**
+ * @hide
+ */
+ public boolean displayCustomViewInline() {
+ return true;
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public RemoteViews makeContentView() {
+ return makeStandardTemplateWithCustomContent(mBuilder.mN.contentView);
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public RemoteViews makeBigContentView() {
+ return makeDecoratedBigContentView();
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public RemoteViews makeHeadsUpContentView() {
+ return makeDecoratedHeadsUpContentView();
+ }
+
+ private RemoteViews makeDecoratedHeadsUpContentView() {
+ RemoteViews headsUpContentView = mBuilder.mN.headsUpContentView == null
+ ? mBuilder.mN.contentView
+ : mBuilder.mN.headsUpContentView;
+ if (mBuilder.mActions.size() == 0) {
+ return makeStandardTemplateWithCustomContent(headsUpContentView);
+ }
+ RemoteViews remoteViews = mBuilder.applyStandardTemplateWithActions(
+ mBuilder.getBigBaseLayoutResource());
+ buildIntoRemoteViewContent(remoteViews, headsUpContentView);
+ return remoteViews;
+ }
+
+ private RemoteViews makeStandardTemplateWithCustomContent(RemoteViews customContent) {
+ RemoteViews remoteViews = mBuilder.applyStandardTemplate(
+ mBuilder.getBaseLayoutResource());
+ buildIntoRemoteViewContent(remoteViews, customContent);
+ return remoteViews;
+ }
+
+ private RemoteViews makeDecoratedBigContentView() {
+ RemoteViews bigContentView = mBuilder.mN.bigContentView == null
+ ? mBuilder.mN.contentView
+ : mBuilder.mN.bigContentView;
+ if (mBuilder.mActions.size() == 0) {
+ return makeStandardTemplateWithCustomContent(bigContentView);
+ }
+ RemoteViews remoteViews = mBuilder.applyStandardTemplateWithActions(
+ mBuilder.getBigBaseLayoutResource());
+ buildIntoRemoteViewContent(remoteViews, bigContentView);
+ return remoteViews;
+ }
+
+ private void buildIntoRemoteViewContent(RemoteViews remoteViews,
+ RemoteViews customContent) {
+ remoteViews.removeAllViews(R.id.notification_main_column);
+ // Need to clone customContent before adding, because otherwise it can no longer be
+ // parceled independently of remoteViews.
+ if (customContent != null) {
+ customContent = customContent.clone();
+ }
+ remoteViews.addView(R.id.notification_main_column, customContent);
+ // also update the end margin if there is an image
+ int endMargin = mBuilder.mContext.getResources().getDimensionPixelSize(
+ R.dimen.notification_content_margin_end);
+ if (mBuilder.mN.mLargeIcon != null) {
+ endMargin += mBuilder.mContext.getResources().getDimensionPixelSize(
+ R.dimen.notification_content_picture_margin);
+ }
+ remoteViews.setViewLayoutMarginEnd(R.id.notification_main_column, endMargin);
+ }
+ }
+
+ /**
+ * Notification style for media custom views that are decorated by the system
+ *
+ * <p>Instead of providing a media notification that is completely custom, a developer can set
+ * this style and still obtain system decorations like the notification header with the expand
+ * affordance and actions.
+ *
+ * <p>Use {@link android.app.Notification.Builder#setCustomContentView(RemoteViews)},
+ * {@link android.app.Notification.Builder#setCustomBigContentView(RemoteViews)} and
+ * {@link android.app.Notification.Builder#setCustomHeadsUpContentView(RemoteViews)} to set the
+ * corresponding custom views to display.
+ *
+ * To use this style with your Notification, feed it to
+ * {@link Notification.Builder#setStyle(android.app.Notification.Style)} like so:
+ * <pre class="prettyprint">
+ * Notification noti = new Notification.Builder()
+ * .setSmallIcon(R.drawable.ic_stat_player)
+ * .setLargeIcon(albumArtBitmap))
+ * .setCustomContentView(contentView);
+ * .setStyle(<b>new Notification.DecoratedMediaCustomViewStyle()</b>
+ * .setMediaSession(mySession))
+ * .build();
+ * </pre>
+ *
+ * @see android.app.Notification.DecoratedCustomViewStyle
+ * @see android.app.Notification.MediaStyle
+ */
+ public static class DecoratedMediaCustomViewStyle extends MediaStyle {
+
+ public DecoratedMediaCustomViewStyle() {
+ }
+
+ public DecoratedMediaCustomViewStyle(Builder builder) {
+ setBuilder(builder);
+ }
+
+ /**
+ * @hide
+ */
+ public boolean displayCustomViewInline() {
+ return true;
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public RemoteViews makeContentView() {
+ RemoteViews remoteViews = super.makeContentView();
+ return buildIntoRemoteView(remoteViews, R.id.notification_content_container,
+ mBuilder.mN.contentView);
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public RemoteViews makeBigContentView() {
+ RemoteViews customRemoteView = mBuilder.mN.bigContentView != null
+ ? mBuilder.mN.bigContentView
+ : mBuilder.mN.contentView;
+ return makeBigContentViewWithCustomContent(customRemoteView);
+ }
+
+ private RemoteViews makeBigContentViewWithCustomContent(RemoteViews customRemoteView) {
+ RemoteViews remoteViews = super.makeBigContentView();
+ if (remoteViews != null) {
+ return buildIntoRemoteView(remoteViews, R.id.notification_main_column,
+ customRemoteView);
+ } else if (customRemoteView != mBuilder.mN.contentView){
+ remoteViews = super.makeContentView();
+ return buildIntoRemoteView(remoteViews, R.id.notification_content_container,
+ customRemoteView);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public RemoteViews makeHeadsUpContentView() {
+ RemoteViews customRemoteView = mBuilder.mN.headsUpContentView != null
+ ? mBuilder.mN.headsUpContentView
+ : mBuilder.mN.contentView;
+ return makeBigContentViewWithCustomContent(customRemoteView);
+ }
+
+ private RemoteViews buildIntoRemoteView(RemoteViews remoteViews, int id,
+ RemoteViews customContent) {
+ remoteViews.removeAllViews(id);
+ // Need to clone customContent before adding, because otherwise it can no longer be
+ // parceled independently of remoteViews.
+ if (customContent != null) {
+ customContent = customContent.clone();
+ }
+ remoteViews.addView(id, customContent);
+ return remoteViews;
+ }
+ }
+
// When adding a new Style subclass here, don't forget to update
// Builder.getNotificationStyleClass.
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index ff2cfd6..16aee78 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -18,6 +18,7 @@
import com.android.internal.util.Preconditions;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
@@ -45,8 +46,14 @@
import android.util.ArraySet;
import android.util.Log;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Objects;
import java.util.List;
+import java.util.Set;
/**
* Class to notify the user of events that happen. This is how you tell
@@ -138,6 +145,13 @@
public static final String ACTION_INTERRUPTION_FILTER_CHANGED_INTERNAL
= "android.app.action.INTERRUPTION_FILTER_CHANGED_INTERNAL";
+
+ /** @hide */
+ @IntDef({INTERRUPTION_FILTER_NONE, INTERRUPTION_FILTER_PRIORITY, INTERRUPTION_FILTER_ALARMS,
+ INTERRUPTION_FILTER_ALL, INTERRUPTION_FILTER_UNKNOWN})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface InterruptionFilter {}
+
/**
* {@link #getCurrentInterruptionFilter() Interruption filter} constant -
* Normal interruption filter.
@@ -254,6 +268,7 @@
Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
}
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -294,6 +309,7 @@
try {
service.cancelNotificationWithTag(pkg, tag, id, user.getIdentifier());
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -309,6 +325,7 @@
try {
service.cancelAllNotifications(pkg, UserHandle.myUserId());
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -320,7 +337,7 @@
try {
return service.getEffectsSuppressor();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -332,7 +349,7 @@
try {
return service.matchesCallFilter(extras);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -344,7 +361,7 @@
try {
return service.isSystemConditionProviderEnabled(path);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -356,6 +373,7 @@
try {
service.setZenMode(mode, conditionId, reason);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -367,8 +385,8 @@
try {
return service.getZenMode();
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return Global.ZEN_MODE_OFF;
}
/**
@@ -379,8 +397,8 @@
try {
return service.getZenModeConfig();
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return null;
}
/**
@@ -391,31 +409,38 @@
try {
return service.getRuleInstanceCount(owner);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return 0;
}
/**
* Returns AutomaticZenRules owned by the caller.
*
* <p>
- * Only available if policy access is granted to this package.
+ * Throws a SecurityException if policy access is granted to this package.
* See {@link #isNotificationPolicyAccessGranted}.
*/
- public List<AutomaticZenRule> getAutomaticZenRules() {
+ public Map<String, AutomaticZenRule> getAutomaticZenRules() {
INotificationManager service = getService();
try {
- return service.getAutomaticZenRules();
+ List<ZenModeConfig.ZenRule> rules = service.getZenRules();
+ Map<String, AutomaticZenRule> ruleMap = new HashMap<>();
+ for (ZenModeConfig.ZenRule rule : rules) {
+ ruleMap.put(rule.id, new AutomaticZenRule(rule.name, rule.component,
+ rule.conditionId, zenModeToInterruptionFilter(rule.zenMode), rule.enabled,
+ rule.creationTime));
+ }
+ return ruleMap;
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return null;
}
/**
* Returns the AutomaticZenRule with the given id, if it exists and the caller has access.
*
* <p>
- * Only available if policy access is granted to this package.
+ * Throws a SecurityException if policy access is granted to this package.
* See {@link #isNotificationPolicyAccessGranted}.
*
* <p>
@@ -427,56 +452,56 @@
try {
return service.getAutomaticZenRule(id);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return null;
}
/**
* Creates the given zen rule.
*
* <p>
- * Only available if policy access is granted to this package.
+ * Throws a SecurityException if policy access is granted to this package.
* See {@link #isNotificationPolicyAccessGranted}.
*
* @param automaticZenRule the rule to create.
- * @return A fully populated {@link AutomaticZenRule} if the rule was persisted successfully,
- * null otherwise.
+ * @return The id of the newly created rule; null if the rule could not be created.
*/
- public AutomaticZenRule addAutomaticZenRule(AutomaticZenRule automaticZenRule) {
+ public String addAutomaticZenRule(AutomaticZenRule automaticZenRule) {
INotificationManager service = getService();
try {
return service.addAutomaticZenRule(automaticZenRule);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return null;
}
/**
* Updates the given zen rule.
*
* <p>
- * Only available if policy access is granted to this package.
+ * Throws a SecurityException if policy access is granted to this package.
* See {@link #isNotificationPolicyAccessGranted}.
*
* <p>
* Callers can only update rules that they own. See {@link AutomaticZenRule#getOwner}.
+ * @param id The id of the rule to update
* @param automaticZenRule the rule to update.
* @return Whether the rule was successfully updated.
*/
- public boolean updateAutomaticZenRule(AutomaticZenRule automaticZenRule) {
+ public boolean updateAutomaticZenRule(String id, AutomaticZenRule automaticZenRule) {
INotificationManager service = getService();
try {
- return service.updateAutomaticZenRule(automaticZenRule);
+ return service.updateAutomaticZenRule(id, automaticZenRule);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return false;
}
/**
* Deletes the automatic zen rule with the given id.
*
* <p>
- * Only available if policy access is granted to this package.
+ * Throws a SecurityException if policy access is granted to this package.
* See {@link #isNotificationPolicyAccessGranted}.
*
* <p>
@@ -489,8 +514,8 @@
try {
return service.removeAutomaticZenRule(id);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return false;
}
/**
@@ -503,27 +528,32 @@
try {
return service.removeAutomaticZenRules(packageName);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return false;
}
- public int getImportance(String topicId) {
- Preconditions.checkNotNull(topicId);
+ /**
+ * Returns the user specified importance for notifications from the calling package.
+ */
+ public @NotificationListenerService.Ranking.Importance int getImportance() {
INotificationManager service = getService();
try {
- return service.getTopicImportance(mContext.getPackageName(), topicId);
+ return service.getPackageImportance(mContext.getPackageName());
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
}
+ /**
+ * Returns whether notifications from the calling package are blocked.
+ */
public boolean areNotificationsEnabled() {
INotificationManager service = getService();
try {
return service.areNotificationsEnabled(mContext.getPackageName());
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return false;
}
/**
@@ -545,8 +575,8 @@
try {
return service.isNotificationPolicyAccessGranted(mContext.getOpPackageName());
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return false;
}
/** @hide */
@@ -555,8 +585,8 @@
try {
return service.isNotificationPolicyAccessGrantedForPackage(pkg);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return false;
}
/**
@@ -571,8 +601,8 @@
try {
return service.getNotificationPolicy(mContext.getOpPackageName());
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return null;
}
/**
@@ -590,6 +620,7 @@
try {
service.setNotificationPolicy(mContext.getOpPackageName(), policy);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -599,6 +630,7 @@
try {
service.setNotificationPolicyAccessGranted(pkg, granted);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -615,8 +647,9 @@
return rt;
}
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return new ArraySet<String>();
+ return new ArraySet<>();
}
private Context mContext;
@@ -629,7 +662,7 @@
/**
* Notification policy configuration. Represents user-preferences for notification
- * filtering and prioritization.
+ * filtering.
*/
public static class Policy implements android.os.Parcelable {
/** Reminder notifications are prioritized. */
@@ -674,13 +707,13 @@
*/
public static final int SUPPRESSED_EFFECTS_UNSET = -1;
/**
- * Whether notification suppressed by DND should not interruption visually when the screen
- * is off.
+ * Whether notifications suppressed by DND should not interrupt visually (e.g. with
+ * notification lights or by turning the screen on) when the screen is off.
*/
public static final int SUPPRESSED_EFFECT_SCREEN_OFF = 1 << 0;
/**
- * Whether notification suppressed by DND should not interruption visually when the screen
- * is on.
+ * Whether notifications suppressed by DND should not interrupt visually when the screen
+ * is on (e.g. by peeking onto the screen).
*/
public static final int SUPPRESSED_EFFECT_SCREEN_ON = 1 << 1;
@@ -695,13 +728,27 @@
*/
public final int suppressedVisualEffects;
-
- @Deprecated
+ /**
+ * Constructs a policy for Do Not Disturb priority mode behavior.
+ *
+ * @param priorityCategories bitmask of categories of notifications that can bypass DND.
+ * @param priorityCallSenders which callers can bypass DND.
+ * @param priorityMessageSenders which message senders can bypass DND.
+ */
public Policy(int priorityCategories, int priorityCallSenders, int priorityMessageSenders) {
this(priorityCategories, priorityCallSenders, priorityMessageSenders,
SUPPRESSED_EFFECTS_UNSET);
}
+ /**
+ * Constructs a policy for Do Not Disturb priority mode behavior.
+ *
+ * @param priorityCategories bitmask of categories of notifications that can bypass DND.
+ * @param priorityCallSenders which callers can bypass DND.
+ * @param priorityMessageSenders which message senders can bypass DND.
+ * @param suppressedVisualEffects which visual interruptions should be suppressed from
+ * notifications that are filtered by DND.
+ */
public Policy(int priorityCategories, int priorityCallSenders, int priorityMessageSenders,
int suppressedVisualEffects) {
this.priorityCategories = priorityCategories;
@@ -832,7 +879,6 @@
return new Policy[size];
}
};
-
}
/**
@@ -857,9 +903,8 @@
final List<StatusBarNotification> list = parceledList.getList();
return list.toArray(new StatusBarNotification[list.size()]);
} catch (RemoteException e) {
- Log.e(TAG, "Unable to talk to notification manager. Woe!", e);
+ throw e.rethrowFromSystemServer();
}
- return new StatusBarNotification[0];
}
/**
@@ -875,14 +920,13 @@
* Only available if policy access is granted to this package.
* See {@link #isNotificationPolicyAccessGranted}.
*/
- public final int getCurrentInterruptionFilter() {
+ public final @InterruptionFilter int getCurrentInterruptionFilter() {
final INotificationManager service = getService();
try {
return zenModeToInterruptionFilter(service.getZenMode());
} catch (RemoteException e) {
- Log.e(TAG, "Unable to talk to notification manager. Woe!", e);
+ throw e.rethrowFromSystemServer();
}
- return INTERRUPTION_FILTER_UNKNOWN;
}
/**
@@ -903,7 +947,7 @@
try {
service.setInterruptionFilter(mContext.getOpPackageName(), interruptionFilter);
} catch (RemoteException e) {
- Log.e(TAG, "Unable to talk to notification manager. Woe!", e);
+ throw e.rethrowFromSystemServer();
}
}
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 94e584e..bc44553d 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -23,6 +23,7 @@
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.content.res.ResourcesImpl;
import android.content.res.ResourcesKey;
import android.hardware.display.DisplayManagerGlobal;
import android.util.ArrayMap;
@@ -250,7 +251,8 @@
} else {
config = getConfiguration();
}
- r = new Resources(assets, dm, config, compatInfo, classLoader);
+ r = new Resources(classLoader);
+ r.setImpl(new ResourcesImpl(assets, dm, config, compatInfo));
if (DEBUG) Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
+ r.getConfiguration() + " appScale=" + r.getCompatibilityInfo().applicationScale);
@@ -288,6 +290,19 @@
}
}
+ /**
+ * Removes the top level Resources for applications with the given compatibility info.
+ * @see #getTopLevelResources(String, String[], String[], String[], int, Configuration, CompatibilityInfo, ClassLoader)
+ */
+ void removeTopLevelResources(String resDir, int displayId, Configuration overrideConfiguration,
+ CompatibilityInfo compatInfo) {
+ final float scale = compatInfo.applicationScale;
+ final Configuration overrideConfigCopy = (overrideConfiguration != null)
+ ? new Configuration(overrideConfiguration) : null;
+ final ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfigCopy, scale);
+ mActiveResources.remove(key);
+ }
+
/* package */ void setDefaultLocalesLocked(LocaleList locales) {
final int bestLocale;
if (mHasNonSystemLocales) {
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 9e32164..ac4abf5 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -686,8 +686,7 @@
try {
return mService.getGlobalSearchActivities();
} catch (RemoteException ex) {
- Log.e(TAG, "getGlobalSearchActivities() failed: " + ex);
- return null;
+ throw ex.rethrowFromSystemServer();
}
}
@@ -698,8 +697,7 @@
try {
return mService.getGlobalSearchActivity();
} catch (RemoteException ex) {
- Log.e(TAG, "getGlobalSearchActivity() failed: " + ex);
- return null;
+ throw ex.rethrowFromSystemServer();
}
}
@@ -716,8 +714,7 @@
try {
return mService.getWebSearchActivity();
} catch (RemoteException ex) {
- Log.e(TAG, "getWebSearchActivity() failed: " + ex);
- return null;
+ throw ex.rethrowFromSystemServer();
}
}
@@ -850,8 +847,7 @@
try {
return mService.getSearchableInfo(componentName);
} catch (RemoteException ex) {
- Log.e(TAG, "getSearchableInfo() failed: " + ex);
- return null;
+ throw ex.rethrowFromSystemServer();
}
}
@@ -935,8 +931,7 @@
try {
return mService.getSearchablesInGlobalSearch();
} catch (RemoteException e) {
- Log.e(TAG, "getSearchablesInGlobalSearch() failed: " + e);
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -958,8 +953,7 @@
}
return intent;
} catch (RemoteException re) {
- Log.e(TAG, "getAssistIntent() failed: " + re);
- return null;
+ throw re.rethrowFromSystemServer();
}
}
@@ -977,7 +971,7 @@
}
mService.launchAssist(args);
} catch (RemoteException re) {
- Log.e(TAG, "launchAssist() failed: " + re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -995,8 +989,7 @@
}
return mService.launchLegacyAssist(hint, userHandle, args);
} catch (RemoteException re) {
- Log.e(TAG, "launchAssist() failed: " + re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java
index c552cfc..c1180e2 100644
--- a/core/java/android/app/SharedPreferencesImpl.java
+++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -87,20 +87,20 @@
}
new Thread("SharedPreferencesImpl-load") {
public void run() {
- synchronized (SharedPreferencesImpl.this) {
- loadFromDiskLocked();
- }
+ loadFromDisk();
}
}.start();
}
- private void loadFromDiskLocked() {
- if (mLoaded) {
- return;
- }
- if (mBackupFile.exists()) {
- mFile.delete();
- mBackupFile.renameTo(mFile);
+ private void loadFromDisk() {
+ synchronized (SharedPreferencesImpl.this) {
+ if (mLoaded) {
+ return;
+ }
+ if (mBackupFile.exists()) {
+ mFile.delete();
+ mBackupFile.renameTo(mFile);
+ }
}
// Debugging
@@ -118,27 +118,27 @@
str = new BufferedInputStream(
new FileInputStream(mFile), 16*1024);
map = XmlUtils.readMapXml(str);
- } catch (XmlPullParserException e) {
- Log.w(TAG, "getSharedPreferences", e);
- } catch (FileNotFoundException e) {
- Log.w(TAG, "getSharedPreferences", e);
- } catch (IOException e) {
+ } catch (XmlPullParserException | IOException e) {
Log.w(TAG, "getSharedPreferences", e);
} finally {
IoUtils.closeQuietly(str);
}
}
} catch (ErrnoException e) {
+ /* ignore */
}
- mLoaded = true;
- if (map != null) {
- mMap = map;
- mStatTimestamp = stat.st_mtime;
- mStatSize = stat.st_size;
- } else {
- mMap = new HashMap<String, Object>();
+
+ synchronized (SharedPreferencesImpl.this) {
+ mLoaded = true;
+ if (map != null) {
+ mMap = map;
+ mStatTimestamp = stat.st_mtime;
+ mStatSize = stat.st_size;
+ } else {
+ mMap = new HashMap<>();
+ }
+ notifyAll();
}
- notifyAll();
}
static File makeBackupFile(File prefsFile) {
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index b899116..e57a9b5 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -123,8 +123,7 @@
svc.disable(what, mToken, mContext.getPackageName());
}
} catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -141,8 +140,7 @@
svc.disable2(what, mToken, mContext.getPackageName());
}
} catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -156,8 +154,7 @@
svc.expandNotificationsPanel();
}
} catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -171,8 +168,7 @@
svc.collapsePanels();
}
} catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -193,8 +189,7 @@
svc.expandSettingsPanel(subPanel);
}
} catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -206,8 +201,7 @@
contentDescription);
}
} catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -218,8 +212,7 @@
svc.removeIcon(slot);
}
} catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -230,8 +223,7 @@
svc.setIconVisibility(slot, visible);
}
} catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
+ throw ex.rethrowFromSystemServer();
}
}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 5eed781..b1c5fd8 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -89,10 +89,13 @@
import android.os.DropBoxManager;
import android.os.HardwarePropertiesManager;
import android.os.IBinder;
+import android.os.IHardwarePropertiesManager;
import android.os.IPowerManager;
+import android.os.IRecoverySystem;
import android.os.IUserManager;
import android.os.PowerManager;
import android.os.Process;
+import android.os.RecoverySystem;
import android.os.ServiceManager;
import android.os.SystemVibrator;
import android.os.UserHandle;
@@ -223,7 +226,7 @@
SYSTEM_SERVICE_NAMES.put(android.text.ClipboardManager.class, Context.CLIPBOARD_SERVICE);
registerService(Context.CONNECTIVITY_SERVICE, ConnectivityManager.class,
- new StaticOuterContextServiceFetcher<ConnectivityManager>() {
+ new StaticApplicationContextServiceFetcher<ConnectivityManager>() {
@Override
public ConnectivityManager createService(Context context) {
IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
@@ -379,6 +382,18 @@
service, ctx.mMainThread.getHandler());
}});
+ registerService(Context.RECOVERY_SERVICE, RecoverySystem.class,
+ new CachedServiceFetcher<RecoverySystem>() {
+ @Override
+ public RecoverySystem createService(ContextImpl ctx) {
+ IBinder b = ServiceManager.getService(Context.RECOVERY_SERVICE);
+ IRecoverySystem service = IRecoverySystem.Stub.asInterface(b);
+ if (service == null) {
+ Log.wtf(TAG, "Failed to get recovery service.");
+ }
+ return new RecoverySystem(service);
+ }});
+
registerService(Context.SEARCH_SERVICE, SearchManager.class,
new CachedServiceFetcher<SearchManager>() {
@Override
@@ -715,7 +730,14 @@
new CachedServiceFetcher<HardwarePropertiesManager>() {
@Override
public HardwarePropertiesManager createService(ContextImpl ctx) {
- return new HardwarePropertiesManager();
+ IBinder b = ServiceManager.getService(Context.HARDWARE_PROPERTIES_SERVICE);
+ IHardwarePropertiesManager service =
+ IHardwarePropertiesManager.Stub.asInterface(b);
+ if (service == null) {
+ Log.wtf(TAG, "Failed to get hardwareproperties service.");
+ return null;
+ }
+ return new HardwarePropertiesManager(ctx, service);
}});
registerService(Context.SOUND_TRIGGER_SERVICE, SoundTriggerManager.class,
@@ -818,22 +840,21 @@
}
/**
- * Like StaticServiceFetcher, creates only one instance of the service per process, but when
- * creating the service for the first time, passes it the outer context of the creating
- * component.
+ * Like StaticServiceFetcher, creates only one instance of the service per application, but when
+ * creating the service for the first time, passes it the application context of the creating
+ * application.
*
- * TODO: Is this safe in the case where multiple applications share the same process?
* TODO: Delete this once its only user (ConnectivityManager) is known to work well in the
* case where multiple application components each have their own ConnectivityManager object.
*/
- static abstract class StaticOuterContextServiceFetcher<T> implements ServiceFetcher<T> {
+ static abstract class StaticApplicationContextServiceFetcher<T> implements ServiceFetcher<T> {
private T mCachedInstance;
@Override
public final T getService(ContextImpl ctx) {
- synchronized (StaticOuterContextServiceFetcher.this) {
+ synchronized (StaticApplicationContextServiceFetcher.this) {
if (mCachedInstance == null) {
- mCachedInstance = createService(ctx.getOuterContext());
+ mCachedInstance = createService(ctx.getApplicationContext());
}
return mCachedInstance;
}
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
index 56b4249..69e8df8 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -17,6 +17,7 @@
package android.app;
import android.annotation.IntDef;
+import android.annotation.TestApi;
import android.content.Context;
import android.content.res.Configuration;
import android.os.RemoteException;
@@ -158,7 +159,7 @@
try {
mService.enableCarMode(flags);
} catch (RemoteException e) {
- Log.e(TAG, "disableCarMode: RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -181,7 +182,7 @@
try {
mService.disableCarMode(flags);
} catch (RemoteException e) {
- Log.e(TAG, "disableCarMode: RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -200,7 +201,7 @@
try {
return mService.getCurrentModeType();
} catch (RemoteException e) {
- Log.e(TAG, "getCurrentModeType: RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
return Configuration.UI_MODE_TYPE_NORMAL;
@@ -233,7 +234,7 @@
try {
mService.setNightMode(mode);
} catch (RemoteException e) {
- Log.e(TAG, "setNightMode: RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -257,7 +258,7 @@
try {
return mService.getNightMode();
} catch (RemoteException e) {
- Log.e(TAG, "getNightMode: RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
return -1;
@@ -266,13 +267,15 @@
/**
* @return If UI mode is locked or not. When UI mode is locked, calls to change UI mode
* like {@link #enableCarMode(int)} will silently fail.
+ * @hide
*/
+ @TestApi
public boolean isUiModeLocked() {
if (mService != null) {
try {
return mService.isUiModeLocked();
} catch (RemoteException e) {
- Log.e(TAG, "isUiModeLocked: RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
return true;
@@ -286,13 +289,15 @@
* mode will fail silently.
*
* @return {@code true} if night mode is locked or {@code false} otherwise
+ * @hide
*/
+ @TestApi
public boolean isNightModeLocked() {
if (mService != null) {
try {
return mService.isNightModeLocked();
} catch (RemoteException e) {
- Log.e(TAG, "isNightModeLocked: RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
return true;
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index eda82c0..6bc03f7 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+h * Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -49,6 +49,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
+import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
import android.view.WindowManagerGlobal;
@@ -265,11 +266,10 @@
private Bitmap mWallpaper;
private Bitmap mDefaultWallpaper;
- private static final int MSG_CLEAR_WALLPAPER = 1;
-
Globals(Looper looper) {
IBinder b = ServiceManager.getService(Context.WALLPAPER_SERVICE);
mService = IWallpaperManager.Stub.asInterface(b);
+ forgetLoadedWallpaper();
}
public void onWallpaperChanged() {
@@ -278,13 +278,14 @@
* to null so if the user requests the wallpaper again then we'll
* fetch it.
*/
- synchronized (this) {
- mWallpaper = null;
- mDefaultWallpaper = null;
- }
+ forgetLoadedWallpaper();
}
public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault) {
+ return peekWallpaperBitmap(context, returnDefault, context.getUserId());
+ }
+
+ public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault, int userId) {
synchronized (this) {
if (mService != null) {
try {
@@ -292,7 +293,7 @@
return null;
}
} catch (RemoteException e) {
- // Ignore
+ throw e.rethrowFromSystemServer();
}
}
if (mWallpaper != null) {
@@ -303,7 +304,7 @@
}
mWallpaper = null;
try {
- mWallpaper = getCurrentWallpaperLocked(context);
+ mWallpaper = getCurrentWallpaperLocked(userId);
} catch (OutOfMemoryError e) {
Log.w(TAG, "No memory load current wallpaper", e);
}
@@ -326,7 +327,7 @@
}
}
- private Bitmap getCurrentWallpaperLocked(Context context) {
+ private Bitmap getCurrentWallpaperLocked(int userId) {
if (mService == null) {
Log.w(TAG, "WallpaperService not running");
return null;
@@ -334,7 +335,8 @@
try {
Bundle params = new Bundle();
- ParcelFileDescriptor fd = mService.getWallpaper(this, params);
+ ParcelFileDescriptor fd = mService.getWallpaper(this, FLAG_SET_SYSTEM,
+ params, userId);
if (fd != null) {
try {
BitmapFactory.Options options = new BitmapFactory.Options();
@@ -347,7 +349,7 @@
}
}
} catch (RemoteException e) {
- // Ignore
+ throw e.rethrowFromSystemServer();
}
return null;
}
@@ -633,7 +635,7 @@
* wallpaper or a null pointer if these is none.
*/
public Drawable peekFastDrawable() {
- Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false);
+ Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false);
if (bm != null) {
return new FastBitmapDrawable(bm);
}
@@ -646,7 +648,52 @@
* @hide
*/
public Bitmap getBitmap() {
- return sGlobals.peekWallpaperBitmap(mContext, true);
+ return getBitmapAsUser(mContext.getUserId());
+ }
+
+ /**
+ * Like {@link #getDrawable()} but returns a Bitmap for the provided user.
+ *
+ * @hide
+ */
+ public Bitmap getBitmapAsUser(int userId) {
+ return sGlobals.peekWallpaperBitmap(mContext, true, userId);
+ }
+
+ /**
+ * Get an open, readable file descriptor to the given wallpaper image file.
+ * The callee is resopnsible for closing the fd when done ingesting the file.
+ *
+ * <p>If no lock-specific wallpaper has been configured for the given user, then
+ * this method will return {@code null} when requesting {@link #FLAG_SET_LOCK} rather than
+ * returning the system wallpaper's image file.
+ */
+ public ParcelFileDescriptor getWallpaperFile(int which) {
+ return getWallpaperFile(which, mContext.getUserId());
+ }
+
+ /**
+ * Version of {@link #getWallpaperFile(int)} that can access the wallpaper data
+ * for a given user. The caller must hold the INTERACT_ACROSS_USERS_FULL
+ * permission to access another user's wallpaper data.
+ * @hide
+ */
+ public ParcelFileDescriptor getWallpaperFile(int which, int userId) {
+ if (which != FLAG_SET_SYSTEM && which != FLAG_SET_LOCK) {
+ throw new IllegalArgumentException("Must request exactly one kind of wallpaper");
+ }
+
+ if (sGlobals.mService == null) {
+ Log.w(TAG, "WallpaperService not running");
+ return null;
+ } else {
+ try {
+ Bundle outParams = new Bundle();
+ return sGlobals.mService.getWallpaper(null, which, outParams, userId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
/**
@@ -656,9 +703,7 @@
* wallpaper will require reloading it again from disk.
*/
public void forgetLoadedWallpaper() {
- if (isWallpaperSupported()) {
- sGlobals.forgetLoadedWallpaper();
- }
+ sGlobals.forgetLoadedWallpaper();
}
/**
@@ -675,7 +720,7 @@
return sGlobals.mService.getWallpaperInfo();
}
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -722,7 +767,9 @@
}
// fallback crop activity
- cropAndSetWallpaperIntent.setPackage("com.android.wallpapercropper");
+ final String cropperPackage = mContext.getString(
+ com.android.internal.R.string.config_wallpaperCropperPackage);
+ cropAndSetWallpaperIntent.setPackage(cropperPackage);
List<ResolveInfo> cropAppList = packageManager.queryIntentActivities(
cropAndSetWallpaperIntent, 0);
if (cropAppList.size() > 0) {
@@ -797,7 +844,7 @@
}
}
} catch (RemoteException e) {
- // Ignore
+ throw e.rethrowFromSystemServer();
}
return result.getInt(EXTRA_NEW_WALLPAPER_ID, 0);
}
@@ -903,7 +950,7 @@
}
}
} catch (RemoteException e) {
- // Ignore
+ throw e.rethrowFromSystemServer();
}
return result.getInt(EXTRA_NEW_WALLPAPER_ID, 0);
}
@@ -1020,7 +1067,7 @@
}
}
} catch (RemoteException e) {
- // Ignore
+ throw e.rethrowFromSystemServer();
}
return result.getInt(EXTRA_NEW_WALLPAPER_ID, 0);
@@ -1041,7 +1088,7 @@
String name = "res:" + resources.getResourceName(resid);
return sGlobals.mService.hasNamedWallpaper(name);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1067,8 +1114,7 @@
try {
return sGlobals.mService.getWidthHint();
} catch (RemoteException e) {
- // Shouldn't happen!
- return 0;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1094,8 +1140,7 @@
try {
return sGlobals.mService.getHeightHint();
} catch (RemoteException e) {
- // Shouldn't happen!
- return 0;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1156,7 +1201,7 @@
mContext.getOpPackageName());
}
} catch (RemoteException e) {
- // Ignore
+ throw e.rethrowFromSystemServer();
}
}
@@ -1177,7 +1222,7 @@
sGlobals.mService.setDisplayPadding(padding, mContext.getOpPackageName());
}
} catch (RemoteException e) {
- // Ignore
+ throw e.rethrowFromSystemServer();
}
}
@@ -1198,7 +1243,7 @@
windowToken, x, y);
//Log.v(TAG, "...app returning after sending display offset!");
} catch (RemoteException e) {
- // Ignore.
+ throw e.rethrowFromSystemServer();
}
}
@@ -1209,14 +1254,25 @@
*/
@SystemApi
public void clearWallpaper() {
+ clearWallpaper(FLAG_SET_SYSTEM, mContext.getUserId());
+ }
+
+ /**
+ * Clear the wallpaper for a specific user. The caller must hold the
+ * INTERACT_ACROSS_USERS_FULL permission to clear another user's
+ * wallpaper.
+ * @hide
+ */
+ @SystemApi
+ public void clearWallpaper(int which, int userId) {
if (sGlobals.mService == null) {
Log.w(TAG, "WallpaperService not running");
return;
}
try {
- sGlobals.mService.clearWallpaper(mContext.getOpPackageName());
+ sGlobals.mService.clearWallpaper(mContext.getOpPackageName(), which, userId);
} catch (RemoteException e) {
- // Ignore
+ throw e.rethrowFromSystemServer();
}
}
@@ -1238,9 +1294,8 @@
sGlobals.mService.setWallpaperComponentChecked(name, mContext.getOpPackageName());
return true;
} catch (RemoteException e) {
- // Ignore
+ throw e.rethrowFromSystemServer();
}
- return false;
}
/**
@@ -1263,7 +1318,7 @@
windowToken, xOffset, yOffset, mWallpaperXStep, mWallpaperYStep);
//Log.v(TAG, "...app returning after sending offsets!");
} catch (RemoteException e) {
- // Ignore.
+ throw e.rethrowFromSystemServer();
}
}
@@ -1301,7 +1356,7 @@
windowToken, action, x, y, z, extras, false);
//Log.v(TAG, "...app returning after sending offsets!");
} catch (RemoteException e) {
- // Ignore.
+ throw e.rethrowFromSystemServer();
}
}
@@ -1317,7 +1372,7 @@
try {
return sGlobals.mService.isWallpaperSupported(mContext.getOpPackageName());
} catch (RemoteException e) {
- // Ignore
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -1337,7 +1392,7 @@
try {
return sGlobals.mService.isWallpaperSettingAllowed(mContext.getOpPackageName());
} catch (RemoteException e) {
- // Ignore
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -1358,12 +1413,12 @@
WindowManagerGlobal.getWindowSession().setWallpaperPosition(
windowToken, -1, -1, -1, -1);
} catch (RemoteException e) {
- // Ignore.
+ throw e.rethrowFromSystemServer();
}
}
/**
- * Remove any currently set wallpaper, reverting to the system's built-in
+ * Remove any currently set system wallpaper, reverting to the system's built-in
* wallpaper. On success, the intent {@link Intent#ACTION_WALLPAPER_CHANGED}
* is broadcast.
*
@@ -1378,6 +1433,25 @@
}
/**
+ * Remove one or more currently set wallpapers, reverting to the system default
+ * display for each one. If {@link #FLAG_SET_SYSTEM} is set in the {@code which}
+ * parameter, the intent {@link Intent#ACTION_WALLPAPER_CHANGED} will be broadcast
+ * upon success.
+ *
+ * @param which A bitwise combination of {@link #FLAG_SET_SYSTEM} or
+ * {@link #FLAG_SET_LOCK}
+ * @throws IOException If an error occurs reverting to the built-in wallpaper.
+ */
+ public void clear(int which) throws IOException {
+ if ((which & FLAG_SET_SYSTEM) != 0) {
+ clear();
+ }
+ if ((which & FLAG_SET_LOCK) != 0) {
+ clearWallpaper(FLAG_SET_LOCK, mContext.getUserId());
+ }
+ }
+
+ /**
* Open stream representing the default static image wallpaper.
*
* @hide
@@ -1424,6 +1498,25 @@
return null;
}
+ /**
+ * Register a callback for lock wallpaper observation. Only the OS may use this.
+ *
+ * @return true on success; false on error.
+ * @hide
+ */
+ public boolean setLockWallpaperCallback(IWallpaperManagerCallback callback) {
+ if (sGlobals.mService == null) {
+ Log.w(TAG, "WallpaperService not running");
+ return false;
+ }
+
+ try {
+ return sGlobals.mService.setLockWallpaperCallback(callback);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
// Private completion callback for setWallpaper() synchronization
private class WallpaperSetCompletion extends IWallpaperManagerCallback.Stub {
final CountDownLatch mLatch;
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index 4e9adf0..1de1d2f 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -240,7 +240,7 @@
/**
* The BroadcastReceiver that implements this device admin component.
*/
- final ResolveInfo mReceiver;
+ final ActivityInfo mActivityInfo;
/**
* Whether this should be visible to the user.
@@ -252,29 +252,42 @@
*/
int mUsesPolicies;
+
/**
* Constructor.
*
* @param context The Context in which we are parsing the device admin.
- * @param receiver The ResolveInfo returned from the package manager about
+ * @param resolveInfo The ResolveInfo returned from the package manager about
* this device admin's component.
*/
- public DeviceAdminInfo(Context context, ResolveInfo receiver)
+ public DeviceAdminInfo(Context context, ResolveInfo resolveInfo)
throws XmlPullParserException, IOException {
- mReceiver = receiver;
- ActivityInfo ai = receiver.activityInfo;
+ this(context, resolveInfo.activityInfo);
+ }
+ /**
+ * Constructor.
+ *
+ * @param context The Context in which we are parsing the device admin.
+ * @param activityInfo The ActivityInfo returned from the package manager about
+ * this device admin's component.
+ *
+ * @hide
+ */
+ public DeviceAdminInfo(Context context, ActivityInfo activityInfo)
+ throws XmlPullParserException, IOException {
+ mActivityInfo = activityInfo;
PackageManager pm = context.getPackageManager();
XmlResourceParser parser = null;
try {
- parser = ai.loadXmlMetaData(pm, DeviceAdminReceiver.DEVICE_ADMIN_META_DATA);
+ parser = mActivityInfo.loadXmlMetaData(pm, DeviceAdminReceiver.DEVICE_ADMIN_META_DATA);
if (parser == null) {
throw new XmlPullParserException("No "
+ DeviceAdminReceiver.DEVICE_ADMIN_META_DATA + " meta-data");
}
- Resources res = pm.getResourcesForApplication(ai.applicationInfo);
+ Resources res = pm.getResourcesForApplication(mActivityInfo.applicationInfo);
AttributeSet attrs = Xml.asAttributeSet(parser);
@@ -324,14 +337,14 @@
}
} catch (NameNotFoundException e) {
throw new XmlPullParserException(
- "Unable to create context for: " + ai.packageName);
+ "Unable to create context for: " + mActivityInfo.packageName);
} finally {
if (parser != null) parser.close();
}
}
DeviceAdminInfo(Parcel source) {
- mReceiver = ResolveInfo.CREATOR.createFromParcel(source);
+ mActivityInfo = ActivityInfo.CREATOR.createFromParcel(source);
mUsesPolicies = source.readInt();
}
@@ -339,7 +352,7 @@
* Return the .apk package that implements this device admin.
*/
public String getPackageName() {
- return mReceiver.activityInfo.packageName;
+ return mActivityInfo.packageName;
}
/**
@@ -347,7 +360,7 @@
* this device admin.
*/
public String getReceiverName() {
- return mReceiver.activityInfo.name;
+ return mActivityInfo.name;
}
/**
@@ -355,7 +368,7 @@
* device admin. Do not modify the returned object.
*/
public ActivityInfo getActivityInfo() {
- return mReceiver.activityInfo;
+ return mActivityInfo;
}
/**
@@ -363,8 +376,8 @@
*/
@NonNull
public ComponentName getComponent() {
- return new ComponentName(mReceiver.activityInfo.packageName,
- mReceiver.activityInfo.name);
+ return new ComponentName(mActivityInfo.packageName,
+ mActivityInfo.name);
}
/**
@@ -374,7 +387,7 @@
* resources.
*/
public CharSequence loadLabel(PackageManager pm) {
- return mReceiver.loadLabel(pm);
+ return mActivityInfo.loadLabel(pm);
}
/**
@@ -384,15 +397,9 @@
* resources.
*/
public CharSequence loadDescription(PackageManager pm) throws NotFoundException {
- if (mReceiver.activityInfo.descriptionRes != 0) {
- String packageName = mReceiver.resolvePackageName;
- ApplicationInfo applicationInfo = null;
- if (packageName == null) {
- packageName = mReceiver.activityInfo.packageName;
- applicationInfo = mReceiver.activityInfo.applicationInfo;
- }
- return pm.getText(packageName,
- mReceiver.activityInfo.descriptionRes, applicationInfo);
+ if (mActivityInfo.descriptionRes != 0) {
+ return pm.getText(mActivityInfo.packageName,
+ mActivityInfo.descriptionRes, mActivityInfo.applicationInfo);
}
throw new NotFoundException();
}
@@ -404,7 +411,7 @@
* resources.
*/
public Drawable loadIcon(PackageManager pm) {
- return mReceiver.loadIcon(pm);
+ return mActivityInfo.loadIcon(pm);
}
/**
@@ -464,12 +471,12 @@
public void dump(Printer pw, String prefix) {
pw.println(prefix + "Receiver:");
- mReceiver.dump(pw, prefix + " ");
+ mActivityInfo.dump(pw, prefix + " ");
}
@Override
public String toString() {
- return "DeviceAdminInfo{" + mReceiver.activityInfo.name + "}";
+ return "DeviceAdminInfo{" + mActivityInfo.name + "}";
}
/**
@@ -479,7 +486,7 @@
* @param flags The flags used for parceling.
*/
public void writeToParcel(Parcel dest, int flags) {
- mReceiver.writeToParcel(dest, flags);
+ mActivityInfo.writeToParcel(dest, flags);
dest.writeInt(mUsesPolicies);
}
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index 34dfb26..a34e8551e 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -117,8 +117,8 @@
= "android.app.action.DEVICE_ADMIN_DISABLED";
/**
- * Action sent to a device administrator when the user has changed the
- * password of their device. You can at this point check the characteristics
+ * Action sent to a device administrator when the user has changed the password of their device
+ * or profile challenge. You can at this point check the characteristics
* of the new password with {@link DevicePolicyManager#isActivePasswordSufficient()
* DevicePolicyManager.isActivePasswordSufficient()}.
* You will generally
@@ -133,8 +133,8 @@
= "android.app.action.ACTION_PASSWORD_CHANGED";
/**
- * Action sent to a device administrator when the user has failed at
- * attempted to enter the password. You can at this point check the
+ * Action sent to a device administrator when the user has entered an incorrect device
+ * or profile challenge password. You can at this point check the
* number of failed password attempts there have been with
* {@link DevicePolicyManager#getCurrentFailedPasswordAttempts
* DevicePolicyManager.getCurrentFailedPasswordAttempts()}. You will generally
@@ -149,8 +149,9 @@
= "android.app.action.ACTION_PASSWORD_FAILED";
/**
- * Action sent to a device administrator when the user has successfully
- * entered their password, after failing one or more times.
+ * Action sent to a device administrator when the user has successfully entered their device
+ * or profile challenge password, after failing one or more times. You will generally
+ * handle this in {@link DeviceAdminReceiver#onPasswordSucceeded}.
*
* <p>The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to receive
@@ -161,8 +162,9 @@
= "android.app.action.ACTION_PASSWORD_SUCCEEDED";
/**
- * Action periodically sent to a device administrator when the device password
- * is expiring.
+ * Action periodically sent to a device administrator when the device or profile challenge
+ * password is expiring. You will generally
+ * handle this in {@link DeviceAdminReceiver#onPasswordExpiring}.
*
* <p>The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_EXPIRE_PASSWORD} to receive
@@ -381,8 +383,8 @@
*
* <p> If the admin is activated by a device owner, then the intent
* may contain private extras that are relevant to user setup.
- * {@see DevicePolicyManager#createAndInitializeUser(ComponentName, String, String,
- * ComponentName, Intent)}
+ * {@see DevicePolicyManager#createAndManageUser(ComponentName, String, ComponentName,
+ * PersistableBundle, int)}
*
* @param context The running context as per {@link #onReceive}.
* @param intent The received intent as per {@link #onReceive}.
@@ -417,7 +419,7 @@
}
/**
- * Called after the user has changed their password, as a result of
+ * Called after the user has changed their device or profile challenge password, as a result of
* receiving {@link #ACTION_PASSWORD_CHANGED}. At this point you
* can use {@link DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
* to retrieve the active password characteristics.
@@ -428,10 +430,10 @@
}
/**
- * Called after the user has failed at entering their current password, as a result of
- * receiving {@link #ACTION_PASSWORD_FAILED}. At this point you
- * can use {@link DevicePolicyManager} to retrieve the number of failed
- * password attempts.
+ * Called after the user has failed at entering their device or profile challenge password,
+ * as a result of receiving {@link #ACTION_PASSWORD_FAILED}. At this point you can use
+ * {@link DevicePolicyManager#getCurrentFailedPasswordAttempts()} to retrieve the number of
+ * failed password attempts.
* @param context The running context as per {@link #onReceive}.
* @param intent The received intent as per {@link #onReceive}.
*/
@@ -439,7 +441,7 @@
}
/**
- * Called after the user has succeeded at entering their current password,
+ * Called after the user has succeeded at entering their device or profile challenge password,
* as a result of receiving {@link #ACTION_PASSWORD_SUCCEEDED}. This will
* only be received the first time they succeed after having previously
* failed.
@@ -450,9 +452,9 @@
}
/**
- * Called periodically when the password is about to expire or has expired. It will typically
- * be called at these times: on device boot, once per day before the password expires,
- * and at the time when the password expires.
+ * Called periodically when the device or profile challenge password is about to expire
+ * or has expired. It will typically be called at these times: on device boot, once per day
+ * before the password expires, and at the time when the password expires.
*
* <p>If the password is not updated by the user, this method will continue to be called
* once per day until the password is changed or the device admin disables password expiration.
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 7e7c5ec..c4037f8 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -100,9 +100,6 @@
private final IDevicePolicyManager mService;
private final boolean mParentInstance;
- private static final String REMOTE_EXCEPTION_MESSAGE =
- "Failed to talk with device policy manager service";
-
private DevicePolicyManager(Context context, boolean parentInstance) {
this(context,
IDevicePolicyManager.Stub.asInterface(
@@ -341,11 +338,74 @@
*
* @hide
*/
+ @SystemApi
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_PROVISION_FINALIZATION
= "android.app.action.PROVISION_FINALIZATION";
/**
+ * Action: Bugreport sharing with device owner has been accepted by the user.
+ *
+ * @hide
+ */
+ public static final String ACTION_BUGREPORT_SHARING_ACCEPTED =
+ "com.android.server.action.BUGREPORT_SHARING_ACCEPTED";
+
+ /**
+ * Action: Bugreport sharing with device owner has been declined by the user.
+ *
+ * @hide
+ */
+ public static final String ACTION_BUGREPORT_SHARING_DECLINED =
+ "com.android.server.action.BUGREPORT_SHARING_DECLINED";
+
+ /**
+ * Action: Bugreport has been collected and is dispatched to {@link DevicePolicyManagerService}.
+ *
+ * @hide
+ */
+ public static final String ACTION_REMOTE_BUGREPORT_DISPATCH =
+ "android.intent.action.REMOTE_BUGREPORT_DISPATCH";
+
+ /**
+ * Extra for shared bugreport's SHA-256 hash.
+ *
+ * @hide
+ */
+ public static final String EXTRA_REMOTE_BUGREPORT_HASH =
+ "android.intent.extra.REMOTE_BUGREPORT_HASH";
+
+ /**
+ * Extra for remote bugreport notification shown type.
+ *
+ * @hide
+ */
+ public static final String EXTRA_BUGREPORT_NOTIFICATION_TYPE =
+ "android.app.extra.bugreport_notification_type";
+
+ /**
+ * Notification type for a started remote bugreport flow.
+ *
+ * @hide
+ */
+ public static final int NOTIFICATION_BUGREPORT_STARTED = 1;
+
+ /**
+ * Notification type for a bugreport that has already been accepted to be shared, but is still
+ * being taken.
+ *
+ * @hide
+ */
+ public static final int NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED = 2;
+
+ /**
+ * Notification type for a bugreport that has been taken and can be shared or declined.
+ *
+ * @hide
+ */
+ public static final int NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED = 3;
+
+ /**
* A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that
* allows a mobile device management application or NFC programmer application which starts
* managed provisioning to pass data to the management application instance after provisioning.
@@ -849,6 +909,8 @@
* this will trigger entering a new password for the parent of the profile.
* For all other cases it will trigger entering a new password for the user
* or profile it is launched from.
+ *
+ * @see #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_SET_NEW_PASSWORD
@@ -930,30 +992,35 @@
* No management for current user in-effect. This is the default.
* @hide
*/
+ @SystemApi
public static final int STATE_USER_UNMANAGED = 0;
/**
* Management partially setup, user setup needs to be completed.
* @hide
*/
+ @SystemApi
public static final int STATE_USER_SETUP_INCOMPLETE = 1;
/**
* Management partially setup, user setup completed.
* @hide
*/
+ @SystemApi
public static final int STATE_USER_SETUP_COMPLETE = 2;
/**
* Management setup and active on current user.
* @hide
*/
+ @SystemApi
public static final int STATE_USER_SETUP_FINALIZED = 3;
/**
* Management partially setup on a managed profile.
* @hide
*/
+ @SystemApi
public static final int STATE_USER_PROFILE_COMPLETE = 4;
/**
@@ -981,7 +1048,7 @@
try {
return mService.isAdminActive(admin, userId);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -996,7 +1063,7 @@
try {
return mService.isRemovingAdmin(admin, userId);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -1021,7 +1088,7 @@
try {
return mService.getActiveAdmins(userId);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -1046,7 +1113,7 @@
try {
return mService.packageHasActiveAdmins(packageName, userId);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -1057,13 +1124,16 @@
* by the application that owns the administration component; if you
* try to remove someone else's component, a security exception will be
* thrown.
+ *
+ * <p>Note that the operation is not synchronous and the admin might still be active (as
+ * indicated by {@link #getActiveAdmins()}) by the time this method returns.
*/
public void removeActiveAdmin(@NonNull ComponentName admin) {
if (mService != null) {
try {
mService.removeActiveAdmin(admin, myUserId());
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1082,7 +1152,7 @@
try {
return mService.hasGrantedPolicy(admin, usesPolicy, myUserId());
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -1098,7 +1168,7 @@
try {
return mService.isSeparateProfileChallengeAllowed(userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -1188,7 +1258,8 @@
* restrictive as what has been set. Note that the current password
* will remain until the user has set a new one, so the change does not
* take place immediately. To prompt the user for a new password, use
- * {@link #ACTION_SET_NEW_PASSWORD} after setting this value.
+ * {@link #ACTION_SET_NEW_PASSWORD} or
+ * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after calling this method.
*
* <p>Quality constants are ordered so that higher values are more restrictive;
* thus the highest requested quality constant (between the policy set here,
@@ -1199,6 +1270,10 @@
* {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
* this method; if it has not, a security exception will be thrown.
*
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
+ * restrictions on the parent profile.
+ *
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param quality The new desired quality. One of
* {@link #PASSWORD_QUALITY_UNSPECIFIED}, {@link #PASSWORD_QUALITY_SOMETHING},
@@ -1211,14 +1286,20 @@
try {
mService.setPasswordQuality(admin, quality, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
/**
- * Retrieve the current minimum password quality for all admins of this user
- * and its profiles or a particular one.
+ * Retrieve the current minimum password quality for a particular admin or all admins that set
+ * retrictions on this user and its participating profiles. Restrictions on profiles that have
+ * a separate challenge are not taken into account.
+ *
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
+ * restrictions on the parent profile.
+ *
* @param admin The name of the admin component to check, or {@code null} to aggregate
* all admins.
*/
@@ -1232,7 +1313,7 @@
try {
return mService.getPasswordQuality(admin, userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return PASSWORD_QUALITY_UNSPECIFIED;
@@ -1245,7 +1326,8 @@
* restrictive as what has been set. Note that the current password
* will remain until the user has set a new one, so the change does not
* take place immediately. To prompt the user for a new password, use
- * {@link #ACTION_SET_NEW_PASSWORD} after setting this value. This
+ * {@link #ACTION_SET_NEW_PASSWORD} or
+ * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This
* constraint is only imposed if the administrator has also requested either
* {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_NUMERIC_COMPLEX},
* {@link #PASSWORD_QUALITY_ALPHABETIC}, {@link #PASSWORD_QUALITY_ALPHANUMERIC},
@@ -1255,6 +1337,10 @@
* {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
* this method; if it has not, a security exception will be thrown.
*
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
+ * restrictions on the parent profile.
+ *
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param length The new desired minimum password length. A value of 0
* means there is no restriction.
@@ -1264,13 +1350,20 @@
try {
mService.setPasswordMinimumLength(admin, length, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
/**
- * Retrieve the current minimum password length for all admins of this
+ * Retrieve the current minimum password length for a particular admin or all admins that set
+ * retrictions on this user and its participating profiles. Restrictions on profiles that have
+ * a separate challenge are not taken into account.
+ *
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
+ * restrictions on the parent profile.
+ *
* user and its profiles or a particular one.
* @param admin The name of the admin component to check, or {@code null} to aggregate
* all admins.
@@ -1285,7 +1378,7 @@
try {
return mService.getPasswordMinimumLength(admin, userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
@@ -1298,7 +1391,8 @@
* not at least as restrictive as what has been set. Note that the current
* password will remain until the user has set a new one, so the change does
* not take place immediately. To prompt the user for a new password, use
- * {@link #ACTION_SET_NEW_PASSWORD} after setting this value. This
+ * {@link #ACTION_SET_NEW_PASSWORD} or
+ * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This
* constraint is only imposed if the administrator has also requested
* {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The
* default value is 0.
@@ -1307,6 +1401,10 @@
* {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
* this method; if it has not, a security exception will be thrown.
*
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
+ * restrictions on the parent profile.
+ *
* @param admin Which {@link DeviceAdminReceiver} this request is associated
* with.
* @param length The new desired minimum number of upper case letters
@@ -1318,19 +1416,25 @@
try {
mService.setPasswordMinimumUpperCase(admin, length, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
/**
- * Retrieve the current number of upper case letters required in the
- * password for all admins of this user and its profiles or a particular one.
+ * Retrieve the current number of upper case letters required in the password
+ * for a particular admin or all admins that set retrictions on this user and
+ * its participating profiles. Restrictions on profiles that have a separate challenge
+ * are not taken into account.
* This is the same value as set by
- * {#link {@link #setPasswordMinimumUpperCase(ComponentName, int)}
+ * {@link #setPasswordMinimumUpperCase(ComponentName, int)}
* and only applies when the password quality is
* {@link #PASSWORD_QUALITY_COMPLEX}.
*
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
+ * restrictions on the parent profile.
+ *
* @param admin The name of the admin component to check, or {@code null} to
* aggregate all admins.
* @return The minimum number of upper case letters required in the
@@ -1346,7 +1450,7 @@
try {
return mService.getPasswordMinimumUpperCase(admin, userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
@@ -1359,7 +1463,8 @@
* not at least as restrictive as what has been set. Note that the current
* password will remain until the user has set a new one, so the change does
* not take place immediately. To prompt the user for a new password, use
- * {@link #ACTION_SET_NEW_PASSWORD} after setting this value. This
+ * {@link #ACTION_SET_NEW_PASSWORD} or
+ * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This
* constraint is only imposed if the administrator has also requested
* {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The
* default value is 0.
@@ -1368,6 +1473,10 @@
* {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
* this method; if it has not, a security exception will be thrown.
*
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
+ * restrictions on the parent profile.
+ *
* @param admin Which {@link DeviceAdminReceiver} this request is associated
* with.
* @param length The new desired minimum number of lower case letters
@@ -1379,19 +1488,25 @@
try {
mService.setPasswordMinimumLowerCase(admin, length, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
/**
- * Retrieve the current number of lower case letters required in the
- * password for all admins of this user and its profiles or a particular one.
+ * Retrieve the current number of lower case letters required in the password
+ * for a particular admin or all admins that set retrictions on this user
+ * and its participating profiles. Restrictions on profiles that have
+ * a separate challenge are not taken into account.
* This is the same value as set by
- * {#link {@link #setPasswordMinimumLowerCase(ComponentName, int)}
+ * {@link #setPasswordMinimumLowerCase(ComponentName, int)}
* and only applies when the password quality is
* {@link #PASSWORD_QUALITY_COMPLEX}.
*
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
+ * restrictions on the parent profile.
+ *
* @param admin The name of the admin component to check, or {@code null} to
* aggregate all admins.
* @return The minimum number of lower case letters required in the
@@ -1407,7 +1522,7 @@
try {
return mService.getPasswordMinimumLowerCase(admin, userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
@@ -1420,7 +1535,8 @@
* restrictive as what has been set. Note that the current password will
* remain until the user has set a new one, so the change does not take
* place immediately. To prompt the user for a new password, use
- * {@link #ACTION_SET_NEW_PASSWORD} after setting this value. This
+ * {@link #ACTION_SET_NEW_PASSWORD} or
+ * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This
* constraint is only imposed if the administrator has also requested
* {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The
* default value is 1.
@@ -1429,6 +1545,10 @@
* {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
* this method; if it has not, a security exception will be thrown.
*
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
+ * restrictions on the parent profile.
+ *
* @param admin Which {@link DeviceAdminReceiver} this request is associated
* with.
* @param length The new desired minimum number of letters required in the
@@ -1439,18 +1559,25 @@
try {
mService.setPasswordMinimumLetters(admin, length, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
/**
- * Retrieve the current number of letters required in the password for all
- * admins or a particular one. This is the same value as
- * set by {#link {@link #setPasswordMinimumLetters(ComponentName, int)}
+ * Retrieve the current number of letters required in the password
+ * for a particular admin or all admins that set retrictions on this user
+ * and its participating profiles. Restrictions on profiles that have
+ * a separate challenge are not taken into account.
+ * This is the same value as set by
+ * {@link #setPasswordMinimumLetters(ComponentName, int)}
* and only applies when the password quality is
* {@link #PASSWORD_QUALITY_COMPLEX}.
*
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
+ * restrictions on the parent profile.
+ *
* @param admin The name of the admin component to check, or {@code null} to
* aggregate all admins.
* @return The minimum number of letters required in the password.
@@ -1465,7 +1592,7 @@
try {
return mService.getPasswordMinimumLetters(admin, userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
@@ -1478,7 +1605,8 @@
* not at least as restrictive as what has been set. Note that the current
* password will remain until the user has set a new one, so the change does
* not take place immediately. To prompt the user for a new password, use
- * {@link #ACTION_SET_NEW_PASSWORD} after setting this value. This
+ * {@link #ACTION_SET_NEW_PASSWORD} or
+ * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This
* constraint is only imposed if the administrator has also requested
* {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The
* default value is 1.
@@ -1487,6 +1615,10 @@
* {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
* this method; if it has not, a security exception will be thrown.
*
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
+ * restrictions on the parent profile.
+ *
* @param admin Which {@link DeviceAdminReceiver} this request is associated
* with.
* @param length The new desired minimum number of numerical digits required
@@ -1497,19 +1629,25 @@
try {
mService.setPasswordMinimumNumeric(admin, length, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
/**
* Retrieve the current number of numerical digits required in the password
- * for all admins of this user and its profiles or a particular one.
+ * for a particular admin or all admins that set retrictions on this user
+ * and its participating profiles. Restrictions on profiles that have
+ * a separate challenge are not taken into account.
* This is the same value as set by
- * {#link {@link #setPasswordMinimumNumeric(ComponentName, int)}
+ * {@link #setPasswordMinimumNumeric(ComponentName, int)}
* and only applies when the password quality is
* {@link #PASSWORD_QUALITY_COMPLEX}.
*
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
+ * restrictions on the parent profile.
+ *
* @param admin The name of the admin component to check, or {@code null} to
* aggregate all admins.
* @return The minimum number of numerical digits required in the password.
@@ -1524,7 +1662,7 @@
try {
return mService.getPasswordMinimumNumeric(admin, userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
@@ -1537,7 +1675,8 @@
* restrictive as what has been set. Note that the current password will
* remain until the user has set a new one, so the change does not take
* place immediately. To prompt the user for a new password, use
- * {@link #ACTION_SET_NEW_PASSWORD} after setting this value. This
+ * {@link #ACTION_SET_NEW_PASSWORD} or
+ * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This
* constraint is only imposed if the administrator has also requested
* {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The
* default value is 1.
@@ -1546,6 +1685,10 @@
* {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
* this method; if it has not, a security exception will be thrown.
*
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
+ * restrictions on the parent profile.
+ *
* @param admin Which {@link DeviceAdminReceiver} this request is associated
* with.
* @param length The new desired minimum number of symbols required in the
@@ -1556,18 +1699,24 @@
try {
mService.setPasswordMinimumSymbols(admin, length, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
/**
- * Retrieve the current number of symbols required in the password for all
- * admins or a particular one. This is the same value as
- * set by {#link {@link #setPasswordMinimumSymbols(ComponentName, int)}
+ * Retrieve the current number of symbols required in the password
+ * for a particular admin or all admins that set retrictions on this user
+ * and its participating profiles. Restrictions on profiles that have
+ * a separate challenge are not taken into account. This is the same value as
+ * set by {@link #setPasswordMinimumSymbols(ComponentName, int)}
* and only applies when the password quality is
* {@link #PASSWORD_QUALITY_COMPLEX}.
*
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
+ * restrictions on the parent profile.
+ *
* @param admin The name of the admin component to check, or {@code null} to
* aggregate all admins.
* @return The minimum number of symbols required in the password.
@@ -1582,7 +1731,7 @@
try {
return mService.getPasswordMinimumSymbols(admin, userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
@@ -1595,7 +1744,8 @@
* to enter a new password that is not at least as restrictive as what has
* been set. Note that the current password will remain until the user has
* set a new one, so the change does not take place immediately. To prompt
- * the user for a new password, use {@link #ACTION_SET_NEW_PASSWORD} after
+ * the user for a new password, use {@link #ACTION_SET_NEW_PASSWORD} or
+ * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after
* setting this value. This constraint is only imposed if the administrator
* has also requested {@link #PASSWORD_QUALITY_COMPLEX} with
* {@link #setPasswordQuality}. The default value is 0.
@@ -1604,6 +1754,10 @@
* {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
* this method; if it has not, a security exception will be thrown.
*
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
+ * restrictions on the parent profile.
+ *
* @param admin Which {@link DeviceAdminReceiver} this request is associated
* with.
* @param length The new desired minimum number of letters required in the
@@ -1614,19 +1768,25 @@
try {
mService.setPasswordMinimumNonLetter(admin, length, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
/**
- * Retrieve the current number of non-letter characters required in the
- * password for all admins of this user and its profiles or a particular one.
+ * Retrieve the current number of non-letter characters required in the password
+ * for a particular admin or all admins that set retrictions on this user
+ * and its participating profiles. Restrictions on profiles that have
+ * a separate challenge are not taken into account.
* This is the same value as set by
- * {#link {@link #setPasswordMinimumNonLetter(ComponentName, int)}
+ * {@link #setPasswordMinimumNonLetter(ComponentName, int)}
* and only applies when the password quality is
* {@link #PASSWORD_QUALITY_COMPLEX}.
*
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
+ * restrictions on the parent profile.
+ *
* @param admin The name of the admin component to check, or {@code null} to
* aggregate all admins.
* @return The minimum number of letters required in the password.
@@ -1641,7 +1801,7 @@
try {
return mService.getPasswordMinimumNonLetter(admin, userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
@@ -1653,7 +1813,8 @@
* enter a new password that is the same as any password in the history. Note
* that the current password will remain until the user has set a new one, so
* the change does not take place immediately. To prompt the user for a new
- * password, use {@link #ACTION_SET_NEW_PASSWORD} after setting this value.
+ * password, use {@link #ACTION_SET_NEW_PASSWORD} or
+ * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value.
* This constraint is only imposed if the administrator has also requested
* either {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_NUMERIC_COMPLEX}
* {@link #PASSWORD_QUALITY_ALPHABETIC}, or {@link #PASSWORD_QUALITY_ALPHANUMERIC}
@@ -1664,6 +1825,10 @@
* {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this
* method; if it has not, a security exception will be thrown.
*
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
+ * restrictions on the parent profile.
+ *
* @param admin Which {@link DeviceAdminReceiver} this request is associated
* with.
* @param length The new desired length of password history. A value of 0
@@ -1674,7 +1839,7 @@
try {
mService.setPasswordHistoryLength(admin, length, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1697,6 +1862,10 @@
* <p> Note that setting the password will automatically reset the expiration time for all
* active admins. Active admins do not need to explicitly call this method in that case.
*
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
+ * restrictions on the parent profile.
+ *
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param timeout The limit (in ms) that a password can remain in effect. A value of 0
* means there is no restriction (unlimited).
@@ -1706,7 +1875,7 @@
try {
mService.setPasswordExpirationTimeout(admin, timeout, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1715,7 +1884,12 @@
* Get the password expiration timeout for the given admin. The expiration timeout is the
* recurring expiration timeout provided in the call to
* {@link #setPasswordExpirationTimeout(ComponentName, long)} for the given admin or the
- * aggregate of all policy administrators if {@code admin} is null.
+ * aggregate of all participating policy administrators if {@code admin} is null. Admins that
+ * have set restrictions on profiles that have a separate challenge are not taken into account.
+ *
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
+ * restrictions on the parent profile.
*
* @param admin The name of the admin component to check, or {@code null} to aggregate all admins.
* @return The timeout for the given admin or the minimum of all timeouts
@@ -1725,36 +1899,45 @@
try {
return mService.getPasswordExpirationTimeout(admin, myUserId(), mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
}
/**
- * Get the current password expiration time for the given admin or an aggregate of
- * all admins of this user and its profiles if admin is null. If the password is
- * expired, this will return the time since the password expired as a negative number.
- * If admin is null, then a composite of all expiration timeouts is returned
- * - which will be the minimum of all timeouts.
+ * Get the current password expiration time for a particular admin or all admins that set
+ * retrictions on this user and its participating profiles. Restrictions on profiles that have
+ * a separate challenge are not taken into account. If admin is {@code null}, then a composite
+ * of all expiration times is returned - which will be the minimum of all of them.
+ *
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
+ * the password expiration for the parent profile.
*
* @param admin The name of the admin component to check, or {@code null} to aggregate all admins.
- * @return The password expiration time, in ms.
+ * @return The password expiration time, in milliseconds since epoch.
*/
public long getPasswordExpiration(@Nullable ComponentName admin) {
if (mService != null) {
try {
return mService.getPasswordExpiration(admin, myUserId(), mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
}
/**
- * Retrieve the current password history length for all admins of this
- * user and its profiles or a particular one.
+ * Retrieve the current password history length for a particular admin or all admins that
+ * set retrictions on this user and its participating profiles. Restrictions on profiles that
+ * have a separate challenge are not taken into account.
+ *
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
+ * restrictions on the parent profile.
+ *
* @param admin The name of the admin component to check, or {@code null} to aggregate
* all admins.
* @return The length of the password history
@@ -1769,7 +1952,7 @@
try {
return mService.getPasswordHistoryLength(admin, userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
@@ -1788,13 +1971,18 @@
/**
* Determine whether the current password the user has set is sufficient
- * to meet the policy requirements (quality, minimum length) that have been
- * requested by the admins of this user and its profiles that don't have a separate challenge.
+ * to meet the policy requirements (e.g. quality, minimum length) that have been
+ * requested by the admins of this user and its participating profiles.
+ * Restrictions on profiles that have a separate challenge are not taken into account.
*
* <p>The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
* this method; if it has not, a security exception will be thrown.
*
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to determine
+ * if the password set on the parent profile is sufficient.
+ *
* @return Returns true if the password meets the current requirements, else false.
*/
public boolean isActivePasswordSufficient() {
@@ -1802,7 +1990,7 @@
try {
return mService.isActivePasswordSufficient(myUserId(), mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -1810,7 +1998,7 @@
/**
* Determine whether the current profile password the user has set is sufficient
- * to meet the policy requirements (quality, minimum length) that have been
+ * to meet the policy requirements (e.g. quality, minimum length) that have been
* requested by the admins of the parent user and its profiles.
*
* @param userHandle the userId of the profile to check the password for.
@@ -1822,7 +2010,7 @@
try {
return mService.isProfileActivePasswordSufficientForParent(userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -1832,6 +2020,10 @@
* Retrieve the number of times the user has failed at entering a
* password since that last successful password entry.
*
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
+ * the number of failed password attemts for the parent user.
+ *
* <p>The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to be able to call
* this method; if it has not, a security exception will be thrown.
@@ -1855,7 +2047,7 @@
try {
return mService.getCurrentFailedPasswordAttempts(userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return -1;
@@ -1872,7 +2064,7 @@
try {
return mService.getDoNotAskCredentialsOnBoot();
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -1880,7 +2072,7 @@
/**
* Setting this to a value greater than zero enables a built-in policy
- * that will perform a device wipe after too many incorrect
+ * that will perform a device or profile wipe after too many incorrect
* device-unlock passwords have been entered. This built-in policy combines
* watching for failed passwords and wiping the device, and requires
* that you request both {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} and
@@ -1891,26 +2083,36 @@
* failure to a server), you should implement
* {@link DeviceAdminReceiver#onPasswordFailed(Context, android.content.Intent)}
* instead. Do not use this API, because if the maximum count is reached,
- * the device will be wiped immediately, and your callback will not be invoked.
+ * the device or profile will be wiped immediately, and your callback will not be invoked.
+ *
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
+ * a value on the parent profile.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param num The number of failed password attempts at which point the
- * device will wipe its data.
+ * device or profile will be wiped.
*/
public void setMaximumFailedPasswordsForWipe(@NonNull ComponentName admin, int num) {
if (mService != null) {
try {
mService.setMaximumFailedPasswordsForWipe(admin, num, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
/**
- * Retrieve the current maximum number of login attempts that are allowed
- * before the device wipes itself, for all admins of this user and its profiles
- * or a particular one.
+ * Retrieve the current maximum number of login attempts that are allowed before the device
+ * or profile is wiped, for a particular admin or all admins that set retrictions on this user
+ * and its participating profiles. Restrictions on profiles that have a separate challenge are
+ * not taken into account.
+ *
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
+ * the value for the parent profile.
+ *
* @param admin The name of the admin component to check, or {@code null} to aggregate
* all admins.
*/
@@ -1925,7 +2127,7 @@
return mService.getMaximumFailedPasswordsForWipe(
admin, userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
@@ -1944,7 +2146,7 @@
return mService.getProfileWithMinimumFailedPasswordsForWipe(
userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return UserHandle.USER_NULL;
@@ -2012,7 +2214,7 @@
try {
return mService.resetPassword(password, flags);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -2027,6 +2229,10 @@
* {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} to be able to call
* this method; if it has not, a security exception will be thrown.
*
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
+ * restrictions on the parent profile.
+ *
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param timeMs The new desired maximum time to lock in milliseconds.
* A value of 0 means there is no restriction.
@@ -2036,14 +2242,20 @@
try {
mService.setMaximumTimeToLock(admin, timeMs, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
/**
- * Retrieve the current maximum time to unlock for all admins of this user
- * and its profiles or a particular one.
+ * Retrieve the current maximum time to unlock for a particular admin or all admins that set
+ * retrictions on this user and its participating profiles. Restrictions on profiles that have
+ * a separate challenge are not taken into account.
+ *
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
+ * restrictions on the parent profile.
+ *
* @param admin The name of the admin component to check, or {@code null} to aggregate
* all admins.
* @return time in milliseconds for the given admin or the minimum value (strictest) of
@@ -2059,7 +2271,7 @@
try {
return mService.getMaximumTimeToLock(admin, userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
@@ -2072,13 +2284,17 @@
* <p>The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} to be able to call
* this method; if it has not, a security exception will be thrown.
+ *
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to lock
+ * the parent profile.
*/
public void lockNow() {
if (mService != null) {
try {
mService.lockNow(mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2115,7 +2331,7 @@
try {
mService.wipeData(flags);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2185,7 +2401,7 @@
}
return mService.setGlobalProxy(admin, hostSpec, exclSpec);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -2213,7 +2429,7 @@
try {
mService.setRecommendedGlobalProxy(admin, proxyInfo);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2229,7 +2445,7 @@
try {
return mService.getGlobalProxyAdmin(myUserId());
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -2358,7 +2574,7 @@
try {
return mService.setStorageEncryption(admin, encrypt);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return ENCRYPTION_STATUS_UNSUPPORTED;
@@ -2378,7 +2594,7 @@
try {
return mService.getStorageEncryption(admin, myUserId());
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -2413,7 +2629,7 @@
try {
return mService.getStorageEncryptionStatus(userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return ENCRYPTION_STATUS_UNSUPPORTED;
@@ -2434,7 +2650,7 @@
try {
return mService.installCaCert(admin, certBuffer);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -2455,7 +2671,7 @@
} catch (CertificateException e) {
Log.w(TAG, "Unable to parse certificate", e);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2483,7 +2699,7 @@
}
}
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return certs;
@@ -2502,7 +2718,7 @@
mService.uninstallCaCerts(admin, new TrustedCertificateStore().userAliases()
.toArray(new String[0]));
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
}
@@ -2520,7 +2736,7 @@
mService.enforceCanManageCaCerts(admin);
return getCaCertAlias(certBuffer) != null;
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
} catch (CertificateException ce) {
Log.w(TAG, "Could not parse certificate", ce);
}
@@ -2529,8 +2745,16 @@
}
/**
- * Called by a device or profile owner to install a certificate and private key pair. The
- * keypair will be visible to all apps within the profile.
+ * Called by a device or profile owner, or delegated certificate installer, to install a
+ * certificate and corresponding private key. All apps within the profile will be able to access
+ * the certificate and use the private key, given direct user approval.
+ *
+ * <p>Access to the installed credentials will not be granted to the caller of this API without
+ * direct user approval. This is for security - should a certificate installer become
+ * compromised, certificates it had already installed will be protected.
+ *
+ * <p>If the installer must have access to the credentials, call
+ * {@link #installKeyPair(ComponentName, PrivateKey, Certificate, String, boolean)} instead.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
* {@code null} if calling from a delegated certificate installer.
@@ -2542,13 +2766,37 @@
*/
public boolean installKeyPair(@Nullable ComponentName admin, @NonNull PrivateKey privKey,
@NonNull Certificate cert, @NonNull String alias) {
+ return installKeyPair(admin, privKey, cert, alias, false);
+ }
+
+ /**
+ * Called by a device or profile owner, or delegated certificate installer, to install a
+ * certificate and corresponding private key. All apps within the profile will be able to access
+ * the certificate and use the private key, given direct user approval.
+ *
+ * <p>The caller of this API may grant itself access to the credential immediately, without user
+ * approval. It is a best practice not to request this unless strictly necessary since it opens
+ * up additional security vulnerabilities.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
+ * {@code null} if calling from a delegated certificate installer.
+ * @param privKey The private key to install.
+ * @param cert The certificate to install.
+ * @param alias The private key alias under which to install the certificate. If a certificate
+ * with that alias already exists, it will be overwritten.
+ * @param requestAccess {@code true} to request that the calling app be granted access to the
+ * credentials immediately. Otherwise, access to the credentials will be gated by user approval.
+ * @return {@code true} if the keys were installed, {@code false} otherwise.
+ */
+ public boolean installKeyPair(@Nullable ComponentName admin, @NonNull PrivateKey privKey,
+ @NonNull Certificate cert, @NonNull String alias, boolean requestAccess) {
try {
final byte[] pemCert = Credentials.convertToPem(cert);
final byte[] pkcs8Key = KeyFactory.getInstance(privKey.getAlgorithm())
.getKeySpec(privKey, PKCS8EncodedKeySpec.class).getEncoded();
- return mService.installKeyPair(admin, pkcs8Key, pemCert, alias);
+ return mService.installKeyPair(admin, pkcs8Key, pemCert, alias, requestAccess);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
Log.w(TAG, "Failed to obtain private key material", e);
} catch (CertificateException | IOException e) {
@@ -2558,21 +2806,20 @@
}
/**
- * Called by a device or profile owner to remove all user credentials installed under a given
- * alias.
+ * Called by a device or profile owner, or delegated certificate installer, to remove all user
+ * credentials installed under a given alias.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
* {@code null} if calling from a delegated certificate installer.
* @param alias The private key alias under which the certificate is installed.
- * @return {@code true} if the keys were both removed, {@code false} otherwise.
+ * @return {@code true} if the certificate alias no longer exists, {@code false} otherwise.
*/
public boolean removeKeyPair(@Nullable ComponentName admin, @NonNull String alias) {
try {
return mService.removeKeyPair(admin, alias);
} catch (RemoteException e) {
- Log.w(TAG, "Failed talking with device policy service", e);
+ throw e.rethrowFromSystemServer();
}
- return false;
}
/**
@@ -2611,7 +2858,7 @@
try {
mService.setCertInstallerPackage(admin, installerPackage);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2629,7 +2876,7 @@
try {
return mService.getCertInstallerPackage(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -2656,7 +2903,7 @@
try {
return mService.setAlwaysOnVpnPackage(admin, vpnPackage);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -2676,7 +2923,7 @@
try {
return mService.getAlwaysOnVpnPackage(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -2701,7 +2948,7 @@
try {
mService.setCameraDisabled(admin, disabled);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2722,7 +2969,7 @@
try {
return mService.getCameraDisabled(admin, userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -2732,7 +2979,7 @@
* Called by a device owner to request a bugreport.
*
* <p>There must be only one user on the device, managed by the device owner.
- * Otherwise a security exception will be thrown.
+ * Otherwise a {@link SecurityException} will be thrown.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @return {@code true} if the bugreport collection started successfully, or {@code false}
@@ -2744,7 +2991,7 @@
try {
return mService.requestBugreport(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -2781,7 +3028,7 @@
try {
mService.setScreenCaptureDisabled(admin, disabled);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2802,7 +3049,7 @@
try {
return mService.getScreenCaptureDisabled(admin, userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -2825,7 +3072,7 @@
try {
mService.setAutoTimeRequired(admin, required);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2838,7 +3085,7 @@
try {
return mService.getAutoTimeRequired();
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -2863,7 +3110,7 @@
try {
mService.setForceEphemeralUsers(admin, forceEphemeralUsers);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2877,7 +3124,7 @@
try {
return mService.getForceEphemeralUsers(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -2893,17 +3140,25 @@
* this method; if it has not, a security exception will be thrown.
*
* <p>Calling this from a managed profile before version
- * {@link android.os.Build.VERSION_CODES#M} will throw a security exception.
- *
- * <p>From version {@link android.os.Build.VERSION_CODES#M} a profile owner can set:
+ * {@link android.os.Build.VERSION_CODES#M} will throw a security exception. From version
+ * {@link android.os.Build.VERSION_CODES#M} the profile owner of a managed profile can set:
* <ul>
- * <li>{@link #KEYGUARD_DISABLE_TRUST_AGENTS}, {@link #KEYGUARD_DISABLE_FINGERPRINT}
- * these will affect the profile's parent user.
- * <li>{@link #KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS} this will affect notifications
- * generated by applications in the managed profile.
+ * <li>{@link #KEYGUARD_DISABLE_TRUST_AGENTS}, which affects the parent user, but only if there
+ * is no separate challenge set on the managed profile.
+ * <li>{@link #KEYGUARD_DISABLE_FINGERPRINT} which affects the managed profile challenge if
+ * there is one, or the parent user otherwise.
+ * <li>{@link #KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS} which affects notifications
+ * generated by applications in the managed profile.
* </ul>
- * <p>Requests to disable other features on a managed profile will be ignored. The admin
- * can check which features have been disabled by calling
+ *
+ * {@link #KEYGUARD_DISABLE_TRUST_AGENTS} and {@link #KEYGUARD_DISABLE_FINGERPRINT} can also be
+ * set on the {@link DevicePolicyManager} instance returned by
+ * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the
+ * parent profile.
+ *
+ * <p>Requests to disable other features on a managed profile will be ignored.
+ *
+ * <p>The admin can check which features have been disabled by calling
* {@link #getKeyguardDisabledFeatures(ComponentName)}
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
@@ -2918,14 +3173,20 @@
try {
mService.setKeyguardDisabledFeatures(admin, which, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
/**
* Determine whether or not features have been disabled in keyguard either by the calling
- * admin, if specified, or all admins.
+ * admin, if specified, or all admins that set retrictions on this user and its participating
+ * profiles. Restrictions on profiles that have a separate challenge are not taken into account.
+ *
+ * <p>This method can be called on the {@link DevicePolicyManager} instance
+ * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
+ * restrictions on the parent profile.
+ *
* @param admin The name of the admin component to check, or {@code null} to check whether any
* admins have disabled features in keyguard.
* @return bitfield of flags. See {@link #setKeyguardDisabledFeatures(ComponentName, int)}
@@ -2941,7 +3202,7 @@
try {
return mService.getKeyguardDisabledFeatures(admin, userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return KEYGUARD_DISABLE_FEATURES_NONE;
@@ -2956,7 +3217,7 @@
try {
mService.setActiveAdmin(policyReceiver, refreshing, userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2969,31 +3230,6 @@
}
/**
- * Returns the DeviceAdminInfo as defined by the administrator's package info & meta-data
- * @hide
- */
- public DeviceAdminInfo getAdminInfo(@NonNull ComponentName cn) {
- ActivityInfo ai;
- try {
- ai = mContext.getPackageManager().getReceiverInfo(cn,
- PackageManager.GET_META_DATA);
- } catch (PackageManager.NameNotFoundException e) {
- Log.w(TAG, "Unable to retrieve device policy " + cn, e);
- return null;
- }
-
- ResolveInfo ri = new ResolveInfo();
- ri.activityInfo = ai;
-
- try {
- return new DeviceAdminInfo(mContext, ri);
- } catch (XmlPullParserException | IOException e) {
- Log.w(TAG, "Unable to parse device policy " + cn, e);
- return null;
- }
- }
-
- /**
* @hide
*/
public void getRemoveWarning(@Nullable ComponentName admin, RemoteCallback result) {
@@ -3001,7 +3237,7 @@
try {
mService.getRemoveWarning(admin, result, myUserId());
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3016,7 +3252,7 @@
mService.setActivePasswordState(quality, length, letters, uppercase, lowercase,
numbers, symbols, nonletter, userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3029,7 +3265,7 @@
try {
mService.reportFailedPasswordAttempt(userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3042,7 +3278,7 @@
try {
mService.reportSuccessfulPasswordAttempt(userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3055,7 +3291,7 @@
try {
mService.reportFailedFingerprintAttempt(userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3068,7 +3304,7 @@
try {
mService.reportSuccessfulFingerprintAttempt(userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3082,7 +3318,7 @@
try {
mService.reportKeyguardDismissed(userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3096,7 +3332,7 @@
try {
mService.reportKeyguardSecured(userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3149,7 +3385,7 @@
try {
return mService.setDeviceOwner(who, ownerName, userId);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return false;
@@ -3231,7 +3467,7 @@
try {
return mService.getDeviceOwnerComponent(callingUserOnly);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return null;
@@ -3250,7 +3486,7 @@
try {
return mService.getDeviceOwnerUserId();
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return UserHandle.USER_NULL;
@@ -3270,7 +3506,7 @@
try {
mService.clearDeviceOwner(packageName);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
}
@@ -3313,7 +3549,7 @@
try {
return mService.getDeviceOwnerName();
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return null;
@@ -3366,7 +3602,7 @@
mService.setActiveAdmin(admin, false, myUserId);
return mService.setProfileOwner(admin, ownerName, myUserId);
} catch (RemoteException re) {
- throw new IllegalArgumentException("Couldn't set profile owner.", re);
+ throw re.rethrowFromSystemServer();
}
}
return false;
@@ -3386,7 +3622,7 @@
try {
mService.clearProfileOwner(admin);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
}
@@ -3400,7 +3636,7 @@
try {
return mService.hasUserSetupCompleted();
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return true;
@@ -3431,8 +3667,7 @@
}
return mService.setProfileOwner(admin, ownerName, userHandle);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- throw new IllegalArgumentException("Couldn't set profile owner.", re);
+ throw re.rethrowFromSystemServer();
}
}
return false;
@@ -3460,7 +3695,7 @@
try {
return mService.setDeviceOwnerLockScreenInfo(admin, info);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return false;
@@ -3474,7 +3709,7 @@
try {
return mService.getDeviceOwnerLockScreenInfo();
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return null;
@@ -3502,7 +3737,7 @@
try {
return mService.setPackagesSuspended(admin, packageNames, suspended);
} catch (RemoteException re) {
- Log.w(TAG, "Failed talking with device policy service", re);
+ throw re.rethrowFromSystemServer();
}
}
return packageNames;
@@ -3521,7 +3756,7 @@
try {
return mService.getPackageSuspended(admin, packageName);
} catch (RemoteException e) {
- Log.w(TAG, "Failed talking with device policy service", e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -3540,7 +3775,7 @@
try {
mService.setProfileEnabled(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3561,7 +3796,7 @@
try {
mService.setProfileName(admin, profileName);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3581,7 +3816,7 @@
return profileOwner != null
&& profileOwner.getPackageName().equals(packageName);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return false;
@@ -3607,9 +3842,7 @@
try {
return mService.getProfileOwner(userId);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- throw new IllegalArgumentException(
- "Requested profile owner for invalid userId", re);
+ throw re.rethrowFromSystemServer();
}
}
return null;
@@ -3626,9 +3859,7 @@
try {
return mService.getProfileOwnerName(Process.myUserHandle().getIdentifier());
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- throw new IllegalArgumentException(
- "Requested profile owner for invalid userId", re);
+ throw re.rethrowFromSystemServer();
}
}
return null;
@@ -3647,9 +3878,7 @@
try {
return mService.getProfileOwnerName(userId);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- throw new IllegalArgumentException(
- "Requested profile owner for invalid userId", re);
+ throw re.rethrowFromSystemServer();
}
}
return null;
@@ -3678,7 +3907,7 @@
try {
mService.addPersistentPreferredActivity(admin, filter, activity);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3699,7 +3928,7 @@
try {
mService.clearPackagePersistentPreferredActivities(admin, packageName);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3725,7 +3954,7 @@
try {
mService.setApplicationRestrictionsManagingPackage(admin, packageName);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3743,7 +3972,7 @@
try {
return mService.getApplicationRestrictionsManagingPackage(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -3759,7 +3988,7 @@
try {
return mService.isCallerApplicationRestrictionsManagingPackage();
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -3804,7 +4033,7 @@
try {
mService.setApplicationRestrictions(admin, packageName, settings);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3834,7 +4063,7 @@
try {
mService.setTrustAgentConfiguration(admin, target, configuration);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3865,7 +4094,7 @@
try {
return mService.getTrustAgentConfiguration(admin, agent, userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return new ArrayList<PersistableBundle>(); // empty list
@@ -3886,7 +4115,7 @@
try {
mService.setCrossProfileCallerIdDisabled(admin, disabled);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3905,7 +4134,7 @@
try {
return mService.getCrossProfileCallerIdDisabled(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -3922,7 +4151,7 @@
try {
return mService.getCrossProfileCallerIdDisabledForUser(userHandle.getIdentifier());
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -3944,7 +4173,7 @@
try {
mService.setCrossProfileContactsSearchDisabled(admin, disabled);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3963,7 +4192,7 @@
try {
return mService.getCrossProfileContactsSearchDisabled(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -3982,7 +4211,7 @@
return mService
.getCrossProfileContactsSearchDisabledForUser(userHandle.getIdentifier());
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -4000,7 +4229,7 @@
mService.startManagedQuickContact(actualLookupKey, actualContactId,
isContactIdIgnored, directoryId, originalIntent);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4034,7 +4263,7 @@
try {
mService.setBluetoothContactSharingDisabled(admin, disabled);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4056,7 +4285,7 @@
try {
return mService.getBluetoothContactSharingDisabled(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return true;
@@ -4076,7 +4305,7 @@
return mService.getBluetoothContactSharingDisabledForUser(userHandle
.getIdentifier());
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return true;
@@ -4098,7 +4327,7 @@
try {
mService.addCrossProfileIntentFilter(admin, filter, flags);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4114,7 +4343,7 @@
try {
mService.clearCrossProfileIntentFilters(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4146,7 +4375,7 @@
try {
return mService.setPermittedAccessibilityServices(admin, packageNames);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -4166,7 +4395,7 @@
try {
return mService.getPermittedAccessibilityServices(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -4189,7 +4418,7 @@
return mService.isAccessibilityServicePermittedByAdmin(admin, packageName,
userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -4213,7 +4442,7 @@
try {
return mService.getPermittedAccessibilityServicesForUser(userId);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -4247,7 +4476,7 @@
try {
return mService.setPermittedInputMethods(admin, packageNames);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -4268,7 +4497,7 @@
try {
return mService.getPermittedInputMethods(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -4290,7 +4519,7 @@
try {
return mService.isInputMethodPermittedByAdmin(admin, packageName, userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -4313,7 +4542,7 @@
try {
return mService.getPermittedInputMethodsForCurrentUser();
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -4333,7 +4562,7 @@
try {
return mService.getKeepUninstalledPackages(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -4356,7 +4585,7 @@
try {
mService.setKeepUninstalledPackages(admin, packageNames);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4374,14 +4603,10 @@
* user could not be created.
*
* @deprecated From {@link android.os.Build.VERSION_CODES#M}
+ * @removed From {@link android.os.Build.VERSION_CODES#N}
*/
@Deprecated
public UserHandle createUser(@NonNull ComponentName admin, String name) {
- try {
- return mService.createUser(admin, name);
- } catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- }
return null;
}
@@ -4411,16 +4636,11 @@
* user could not be created.
*
* @deprecated From {@link android.os.Build.VERSION_CODES#M}
+ * @removed From {@link android.os.Build.VERSION_CODES#N}
*/
@Deprecated
public UserHandle createAndInitializeUser(@NonNull ComponentName admin, String name,
String ownerName, @NonNull ComponentName profileOwnerComponent, Bundle adminExtras) {
- try {
- return mService.createAndInitializeUser(admin, name, ownerName, profileOwnerComponent,
- adminExtras);
- } catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- }
return null;
}
@@ -4470,9 +4690,8 @@
try {
return mService.createAndManageUser(admin, name, profileOwner, adminExtras, flags);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
- return null;
}
/**
@@ -4487,8 +4706,7 @@
try {
return mService.removeUser(admin, userHandle);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -4505,8 +4723,7 @@
try {
return mService.switchUser(admin, userHandle);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -4532,7 +4749,7 @@
try {
return mService.getApplicationRestrictions(admin, packageName);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -4554,7 +4771,7 @@
try {
mService.setUserRestriction(admin, key, true);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4575,7 +4792,7 @@
try {
mService.setUserRestriction(admin, key, false);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4602,7 +4819,7 @@
try {
ret = mService.getUserRestrictions(admin, userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return ret == null ? new Bundle() : ret;
@@ -4624,7 +4841,7 @@
try {
return mService.setApplicationHidden(admin, packageName, hidden);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -4642,7 +4859,7 @@
try {
return mService.isApplicationHidden(admin, packageName);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -4660,7 +4877,7 @@
try {
mService.enableSystemApp(admin, packageName);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4679,7 +4896,7 @@
try {
return mService.enableSystemAppWithIntent(admin, intent);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
@@ -4710,7 +4927,7 @@
try {
mService.setAccountManagementDisabled(admin, accountType, disabled);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4738,7 +4955,7 @@
try {
return mService.getAccountTypesWithManagementDisabledAsUser(userId);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -4769,7 +4986,7 @@
try {
mService.setLockTaskPackages(admin, packages);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4785,7 +5002,7 @@
try {
return mService.getLockTaskPackages(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -4801,7 +5018,7 @@
try {
return mService.isLockTaskPermitted(pkg);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -4848,7 +5065,7 @@
try {
mService.setGlobalSetting(admin, setting, value);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4876,7 +5093,7 @@
try {
mService.setSecureSetting(admin, setting, value);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4897,7 +5114,7 @@
try {
mService.setRestrictionsProvider(admin, provider);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
}
@@ -4913,7 +5130,7 @@
try {
mService.setMasterVolumeMuted(admin, on);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
}
@@ -4929,7 +5146,7 @@
try {
return mService.isMasterVolumeMuted(admin);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return false;
@@ -4949,7 +5166,7 @@
try {
mService.setUninstallBlocked(admin, packageName, uninstallBlocked);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
}
@@ -4973,7 +5190,7 @@
try {
return mService.isUninstallBlocked(admin, packageName);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return false;
@@ -5001,7 +5218,7 @@
try {
return mService.addCrossProfileWidgetProvider(admin, packageName);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return false;
@@ -5029,7 +5246,7 @@
try {
return mService.removeCrossProfileWidgetProvider(admin, packageName);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return false;
@@ -5053,7 +5270,7 @@
return providers;
}
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return Collections.emptyList();
@@ -5069,7 +5286,7 @@
try {
mService.setUserIcon(admin, icon);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -5089,7 +5306,7 @@
try {
mService.setSystemUpdatePolicy(admin, policy);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
}
@@ -5104,7 +5321,7 @@
try {
return mService.getSystemUpdatePolicy();
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return null;
@@ -5128,8 +5345,7 @@
try {
return mService.setKeyguardDisabled(admin, disabled);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5148,8 +5364,7 @@
try {
return mService.setStatusBarDisabled(admin, disabled);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5168,7 +5383,7 @@
try {
mService.notifyPendingSystemUpdate(updateReceivedTime);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
}
@@ -5194,7 +5409,7 @@
try {
mService.setPermissionPolicy(admin, policy);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -5208,7 +5423,7 @@
try {
return mService.getPermissionPolicy(admin);
} catch (RemoteException re) {
- return PERMISSION_POLICY_PROMPT;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5245,8 +5460,7 @@
try {
return mService.setPermissionGrantState(admin, packageName, permission, grantState);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5272,8 +5486,7 @@
try {
return mService.getPermissionGrantState(admin, packageName, permission);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return PERMISSION_GRANT_STATE_DEFAULT;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5291,8 +5504,7 @@
try {
return mService.isProvisioningAllowed(action);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5308,8 +5520,7 @@
try {
return mService.isManagedProfile(admin);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5324,8 +5535,7 @@
try {
return mService.isSystemOnlyUser(admin);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5341,8 +5551,7 @@
try {
return mService.getWifiMacAddress();
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return null;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5353,7 +5562,7 @@
try {
mService.reboot(admin);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -5383,7 +5592,7 @@
try {
mService.setShortSupportMessage(admin, message);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -5400,7 +5609,7 @@
try {
return mService.getShortSupportMessage(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -5426,7 +5635,7 @@
try {
mService.setLongSupportMessage(admin, message);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -5443,7 +5652,7 @@
try {
return mService.getLongSupportMessage(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -5463,7 +5672,7 @@
try {
return mService.getShortSupportMessageForUser(admin, userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -5484,7 +5693,7 @@
try {
return mService.getLongSupportMessageForUser(admin, userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -5505,8 +5714,7 @@
}
return new DevicePolicyManager(mContext, true);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -5517,6 +5725,9 @@
* <p> Device logs contain various information intended for security auditing purposes.
* See {@link SecurityEvent} for details.
*
+ * <p>There must be only one user on the device, managed by the device owner.
+ * Otherwise a {@link SecurityException} will be thrown.
+ *
* @param admin Which device owner this request is associated with.
* @param enabled whether device logging should be enabled or not.
* @see #retrieveDeviceLogs
@@ -5525,13 +5736,16 @@
try {
mService.setDeviceLoggingEnabled(admin, enabled);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
/**
* Return whether device logging is enabled or not by the device owner.
*
+ * <p>Can only be called by the device owner, otherwise a {@link SecurityException} will be
+ * thrown.
+ *
* @param admin Which device owner this request is associated with.
* @return {@code true} if device logging is enabled by device owner, {@code false} otherwise.
*/
@@ -5539,8 +5753,7 @@
try {
return mService.getDeviceLoggingEnabled(admin);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5551,6 +5764,9 @@
* <p> Access to the logs is rate limited and it will only return new logs after the device
* owner has been notified via {@link DeviceAdminReceiver#onSecurityLogsAvailable}.
*
+ * <p>There must be only one user on the device, managed by the device owner.
+ * Otherwise a {@link SecurityException} will be thrown.
+ *
* @param admin Which device owner this request is associated with.
* @return the new batch of device logs which is a list of {@link SecurityEvent},
* or {@code null} if rate limitation is exceeded or if logging is currently disabled.
@@ -5565,8 +5781,7 @@
return null;
}
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return null;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5595,6 +5810,9 @@
* result, this API is provided as best-effort and the returned logs may contain corrupted data.
* </strong>
*
+ * <p>There must be only one user on the device, managed by the device owner.
+ * Otherwise a {@link SecurityException} will be thrown.
+ *
* @param admin Which device owner this request is associated with.
* @return Device logs from before the latest reboot of the system.
*/
@@ -5603,8 +5821,7 @@
ParceledListSlice<SecurityEvent> list = mService.retrievePreviousDeviceLogs(admin);
return list.getList();
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return Collections.<SecurityEvent>emptyList();
+ throw re.rethrowFromSystemServer();
}
}
@@ -5623,7 +5840,7 @@
try {
mService.setOrganizationColor(admin, color);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -5642,7 +5859,7 @@
try {
mService.setOrganizationColorForUser(color, userId);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -5657,8 +5874,7 @@
try {
return mService.getOrganizationColor(admin);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return 0;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5673,8 +5889,7 @@
try {
return mService.getOrganizationColorForUser(userHandle);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return 0;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5693,7 +5908,7 @@
try {
mService.setOrganizationName(admin, title);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE);
+ throw re.rethrowFromSystemServer();
}
}
@@ -5708,8 +5923,7 @@
try {
return mService.getOrganizationName(admin);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE);
- return null;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5725,8 +5939,7 @@
try {
return mService.getOrganizationNameForUser(userHandle);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE);
- return null;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5735,13 +5948,14 @@
* return {@link #STATE_USER_UNMANAGED}
* @hide
*/
+ @SystemApi
@UserProvisioningState
public int getUserProvisioningState() {
if (mService != null) {
try {
return mService.getUserProvisioningState();
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return STATE_USER_UNMANAGED;
@@ -5759,7 +5973,7 @@
try {
mService.setUserProvisioningState(state, userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -5786,7 +6000,7 @@
try {
mService.setAffiliationIds(admin, new ArrayList<String>(ids));
} catch (RemoteException e) {
- Log.w(TAG, "Failed talking with device policy service", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -5801,8 +6015,7 @@
try {
return mService != null && mService.isAffiliatedUser();
} catch (RemoteException e) {
- Log.w(TAG, "Failed talking with device policy service", e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -5817,8 +6030,7 @@
try {
return mService.isUninstallInQueue(packageName);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5830,7 +6042,7 @@
try {
mService.uninstallPackageWithActiveAdmins(packageName);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index 0a0d77d..8cdfee5 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -69,4 +69,13 @@
* @return true if the uid is an active admin with the given policy.
*/
public abstract boolean isActiveAdminWithPolicy(int uid, int reqPolicy);
+
+ /**
+ * Checks if a given package has a device or a profile owner for the given user
+ *
+ * @param packageName The package to check
+ * @param userId the userId to check for.
+ * @return true if package has a device or profile owner, false otherwise.
+ */
+ public abstract boolean hasDeviceOwnerOrProfileOwner(String packageName, int userId);
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index e9af872..b7a16aa 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -145,7 +145,8 @@
void uninstallCaCerts(in ComponentName admin, in String[] aliases);
void enforceCanManageCaCerts(in ComponentName admin);
- boolean installKeyPair(in ComponentName who, in byte[] privKeyBuffer, in byte[] certBuffer, String alias);
+ boolean installKeyPair(in ComponentName who, in byte[] privKeyBuffer, in byte[] certBuffer,
+ String alias, boolean requestAccess);
boolean removeKeyPair(in ComponentName who, String alias);
void choosePrivateKeyAlias(int uid, in Uri uri, in String alias, IBinder aliasCallback);
@@ -185,8 +186,6 @@
boolean setApplicationHidden(in ComponentName admin, in String packageName, boolean hidden);
boolean isApplicationHidden(in ComponentName admin, in String packageName);
- UserHandle createUser(in ComponentName who, in String name);
- UserHandle createAndInitializeUser(in ComponentName who, in String name, in String profileOwnerName, in ComponentName profileOwnerComponent, in Bundle adminExtras);
UserHandle createAndManageUser(in ComponentName who, in String name, in ComponentName profileOwner, in PersistableBundle adminExtras, in int flags);
boolean removeUser(in ComponentName who, in UserHandle userHandle);
boolean switchUser(in ComponentName who, in UserHandle userHandle);
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 2268400..7fcca09 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -468,7 +468,7 @@
*
* @param packages List of package names to backup.
* @param observer The {@link BackupObserver} to receive callbacks during the backup
- * operation.
+ * operation. Could be {@code null}.
* @return {@link BackupManager#SUCCESS} on success; nonzero on error.
* @exception IllegalArgumentException on null or empty {@code packages} param.
*
@@ -479,8 +479,9 @@
checkServiceBinder();
if (sService != null) {
try {
- BackupObserverWrapper observerWrapper =
- new BackupObserverWrapper(mContext, observer);
+ BackupObserverWrapper observerWrapper = observer == null
+ ? null
+ : new BackupObserverWrapper(mContext, observer);
return sService.requestBackup(packages, observerWrapper);
} catch (RemoteException e) {
Log.e(TAG, "requestBackup() couldn't connect");
diff --git a/core/java/android/app/job/IJobScheduler.aidl b/core/java/android/app/job/IJobScheduler.aidl
index f0c3302..3379f2e 100644
--- a/core/java/android/app/job/IJobScheduler.aidl
+++ b/core/java/android/app/job/IJobScheduler.aidl
@@ -24,7 +24,7 @@
*/
interface IJobScheduler {
int schedule(in JobInfo job);
- int scheduleAsPackage(in JobInfo job, String packageName, int userId);
+ int scheduleAsPackage(in JobInfo job, String packageName, int userId, String tag);
void cancel(int jobId);
void cancelAll();
List<JobInfo> getAllPendingJobs();
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index 5398e7f..039c9d7 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -83,6 +83,38 @@
*/
public static final int DEFAULT_BACKOFF_POLICY = BACKOFF_POLICY_EXPONENTIAL;
+ /**
+ * Default of {@link #getPriority}.
+ * @hide
+ */
+ public static final int PRIORITY_DEFAULT = 0;
+
+ /**
+ * Value of {@link #getPriority} for expedited syncs.
+ * @hide
+ */
+ public static final int PRIORITY_SYNC_EXPEDITED = 10;
+
+ /**
+ * Value of {@link #getPriority} for first time initialization syncs.
+ * @hide
+ */
+ public static final int PRIORITY_SYNC_INITIALIZATION = 20;
+
+ /**
+ * Value of {@link #getPriority} for a foreground app (overrides the supplied
+ * JobInfo priority if it is smaller).
+ * @hide
+ */
+ public static final int PRIORITY_FOREGROUND_APP = 30;
+
+ /**
+ * Value of {@link #getPriority} for the current top app (overrides the supplied
+ * JobInfo priority if it is smaller).
+ * @hide
+ */
+ public static final int PRIORITY_TOP_APP = 40;
+
private final int jobId;
private final PersistableBundle extras;
private final ComponentName service;
@@ -406,7 +438,7 @@
private int mJobId;
private PersistableBundle mExtras = PersistableBundle.EMPTY;
private ComponentName mJobService;
- private int mPriority;
+ private int mPriority = PRIORITY_DEFAULT;
// Requirements.
private boolean mRequiresCharging;
private boolean mRequiresDeviceIdle;
diff --git a/core/java/android/app/job/JobScheduler.java b/core/java/android/app/job/JobScheduler.java
index 5e1a4256..d1e563f 100644
--- a/core/java/android/app/job/JobScheduler.java
+++ b/core/java/android/app/job/JobScheduler.java
@@ -68,10 +68,11 @@
* @param packageName The package on behalf of which the job is to be scheduled. This will be
* used to track battery usage and appIdleState.
* @param userId User on behalf of whom this job is to be scheduled.
+ * @param tag Debugging tag for dumps associated with this job (instead of the service class)
* @return {@link #RESULT_SUCCESS} or {@link #RESULT_FAILURE}
* @hide
*/
- public abstract int scheduleAsPackage(JobInfo job, String packageName, int userId);
+ public abstract int scheduleAsPackage(JobInfo job, String packageName, int userId, String tag);
/**
* Cancel a job that is pending in the JobScheduler.
diff --git a/core/java/android/app/job/JobService.java b/core/java/android/app/job/JobService.java
index 940a530..95a8ccf 100644
--- a/core/java/android/app/job/JobService.java
+++ b/core/java/android/app/job/JobService.java
@@ -46,10 +46,10 @@
* Job services must be protected with this permission:
*
* <pre class="prettyprint">
- * <service android:name="MyJobService"
- * android:permission="android.permission.BIND_JOB_SERVICE" >
+ * <service android:name="MyJobService"
+ * android:permission="android.permission.BIND_JOB_SERVICE" >
* ...
- * </service>
+ * </service>
* </pre>
*
* <p>If a job service is declared in the manifest but not protected with this
diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java
index 999d826..0f5cb6f 100644
--- a/core/java/android/app/trust/TrustManager.java
+++ b/core/java/android/app/trust/TrustManager.java
@@ -16,8 +16,6 @@
package android.app.trust;
-import com.android.internal.widget.LockPatternUtils;
-
import android.Manifest;
import android.annotation.RequiresPermission;
import android.os.Handler;
@@ -26,7 +24,8 @@
import android.os.Message;
import android.os.RemoteException;
import android.util.ArrayMap;
-import android.util.Log;
+
+import com.android.internal.widget.LockPatternUtils;
/**
* See {@link com.android.server.trust.TrustManagerService}
@@ -62,7 +61,7 @@
try {
mService.setDeviceLockedForUser(userId, locked);
} catch (RemoteException e) {
- onError(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -77,7 +76,7 @@
try {
mService.reportUnlockAttempt(successful, userId);
} catch (RemoteException e) {
- onError(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -90,7 +89,7 @@
try {
mService.reportEnabledTrustAgentsChanged(userId);
} catch (RemoteException e) {
- onError(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -103,7 +102,7 @@
try {
mService.reportKeyguardShowingChanged();
} catch (RemoteException e) {
- onError(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -134,7 +133,7 @@
mService.registerTrustListener(iTrustListener);
mTrustListeners.put(trustListener, iTrustListener);
} catch (RemoteException e) {
- onError(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -149,7 +148,7 @@
try {
mService.unregisterTrustListener(iTrustListener);
} catch (RemoteException e) {
- onError(e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -163,16 +162,10 @@
try {
return mService.isTrustUsuallyManaged(userId);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
-
-
- private void onError(Exception e) {
- Log.e(TAG, "Error while calling TrustManagerService", e);
- }
-
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl
index a9328bc..342c285 100644
--- a/core/java/android/app/usage/IUsageStatsManager.aidl
+++ b/core/java/android/app/usage/IUsageStatsManager.aidl
@@ -33,4 +33,5 @@
void setAppInactive(String packageName, boolean inactive, int userId);
boolean isAppInactive(String packageName, int userId);
void whitelistAppTemporarily(String packageName, long duration, int userId);
+ void onCarrierPrivilegedAppsChanged();
}
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index c74b0f2..2aeecfa 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -267,4 +267,15 @@
} catch (RemoteException re) {
}
}
+
+ /**
+ * Inform usage stats that the carrier privileged apps access rules have changed.
+ * @hide
+ */
+ public void onCarrierPrivilegedAppsChanged() {
+ try {
+ mService.onCarrierPrivilegedAppsChanged();
+ } catch (RemoteException re) {
+ }
+ }
}
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 278c9d6..9f654c2 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -472,9 +472,8 @@
}
try {
mService.updateAppWidgetIds(mPackageName, appWidgetIds, views);
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -495,9 +494,8 @@
}
try {
mService.updateAppWidgetOptions(mPackageName, appWidgetId, options);
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -518,9 +516,8 @@
}
try {
return mService.getAppWidgetOptions(mPackageName, appWidgetId);
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -581,7 +578,7 @@
try {
mService.partiallyUpdateAppWidgetIds(mPackageName, appWidgetIds, views);
} catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -635,9 +632,8 @@
}
try {
mService.updateAppWidgetProvider(provider, views);
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -654,9 +650,8 @@
}
try {
mService.notifyAppWidgetViewDataChanged(mPackageName, appWidgetIds, viewId);
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -764,9 +759,8 @@
convertSizesToPixels(info);
}
return providers.getList();
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -787,9 +781,8 @@
convertSizesToPixels(info);
}
return info;
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -918,9 +911,8 @@
}
try {
return mService.hasBindAppWidgetPermission(packageName, userId);
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -939,9 +931,8 @@
}
try {
return mService.hasBindAppWidgetPermission(packageName, UserHandle.myUserId());
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -979,9 +970,8 @@
}
try {
mService.setBindAppWidgetPermission(packageName, userId, permission);
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1005,9 +995,8 @@
}
try {
mService.bindRemoteViewsService(packageName, appWidgetId, intent, connection);
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1029,9 +1018,8 @@
}
try {
mService.unbindRemoteViewsService(packageName, appWidgetId, intent);
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1048,9 +1036,8 @@
}
try {
return mService.getAppWidgetIds(provider);
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1063,8 +1050,8 @@
}
try {
return mService.isBoundWidgetPackage(packageName, userId);
- } catch (RemoteException re) {
- throw new RuntimeException("system server dead?", re);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1076,9 +1063,8 @@
try {
return mService.bindAppWidgetId(mPackageName, appWidgetId,
profileId, provider, options);
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
diff --git a/core/java/android/auditing/SecurityLog.java b/core/java/android/auditing/SecurityLog.java
index f1703d6..13823a2 100644
--- a/core/java/android/auditing/SecurityLog.java
+++ b/core/java/android/auditing/SecurityLog.java
@@ -64,7 +64,8 @@
public static final int TAG_SYNC_SEND_FILE = SecurityLogTags.SECURITY_ADB_SYNC_SEND;
/**
* Indicate that an app process was started. The log entry contains the following
- * information about the process in order, accessible via {@link SecurityEvent#getData()}}:
+ * information about the process encapsulated in an {@link Object} array, accessible via
+ * {@link SecurityEvent#getData()}:
* process name (String), exact start time (long), app Uid (integer), app Pid (integer),
* seinfo tag (String), SHA-256 hash of the APK in hexadecimal (String)
*/
@@ -77,10 +78,10 @@
SecurityLogTags.SECURITY_KEYGUARD_DISMISSED;
/**
* Indicate that there has been an authentication attempt to dismiss the keyguard. The log entry
- * contains the following information about the attempt in order, accessible via
- * {@link SecurityEvent#getData()}}: attempt result (integer, 1 for successful, 0 for
- * unsuccessful), strength of auth method (integer, 1 if strong auth method was used,
- * 0 otherwise)
+ * contains the following information about the attempt encapsulated in an {@link Object} array,
+ * accessible via {@link SecurityEvent#getData()}:
+ * attempt result (integer, 1 for successful, 0 for unsuccessful), strength of auth method
+ * (integer, 1 if strong auth method was used, 0 otherwise)
*/
public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT =
SecurityLogTags.SECURITY_KEYGUARD_DISMISS_AUTH_ATTEMPT;
@@ -115,7 +116,7 @@
/**
* A class representing a security event log entry.
*/
- public static class SecurityEvent implements Parcelable {
+ public static final class SecurityEvent implements Parcelable {
private Event mEvent;
/** @hide */
diff --git a/core/java/android/bluetooth/OobData.java b/core/java/android/bluetooth/OobData.java
index 01f72ef..70d47ee 100644
--- a/core/java/android/bluetooth/OobData.java
+++ b/core/java/android/bluetooth/OobData.java
@@ -23,6 +23,7 @@
/**
* Out Of Band Data for Bluetooth device.
+ * @hide
*/
public class OobData implements Parcelable {
private byte[] securityManagerTk;
diff --git a/core/java/android/content/ClipboardManager.java b/core/java/android/content/ClipboardManager.java
index e67da2b..1266f73 100644
--- a/core/java/android/content/ClipboardManager.java
+++ b/core/java/android/content/ClipboardManager.java
@@ -122,6 +122,7 @@
}
getService().setPrimaryClip(clip, mContext.getOpPackageName());
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -132,7 +133,7 @@
try {
return getService().getPrimaryClip(mContext.getOpPackageName());
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -144,7 +145,7 @@
try {
return getService().getPrimaryClipDescription(mContext.getOpPackageName());
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -155,7 +156,7 @@
try {
return getService().hasPrimaryClip(mContext.getOpPackageName());
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -166,6 +167,7 @@
getService().addPrimaryClipChangedListener(
mPrimaryClipChangedServiceListener, mContext.getOpPackageName());
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
mPrimaryClipChangedListeners.add(what);
@@ -180,6 +182,7 @@
getService().removePrimaryClipChangedListener(
mPrimaryClipChangedServiceListener);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -213,7 +216,7 @@
try {
return getService().hasClipboardText(mContext.getOpPackageName());
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 0cdbef0..b935b25 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2863,6 +2863,16 @@
/**
* Use with {@link #getSystemService} to retrieve a
+ * {@link android.os.RecoverySystem} for accessing the recovery system
+ * service.
+ *
+ * @see #getSystemService
+ * @hide
+ */
+ public static final String RECOVERY_SERVICE = "recovery";
+
+ /**
+ * Use with {@link #getSystemService} to retrieve a
* {@link android.view.WindowManager} for accessing the system's window
* manager.
*
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 8f2b9c8..09fa5e1 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -16,24 +16,13 @@
package android.content;
-import android.content.pm.ApplicationInfo;
-import android.os.ResultReceiver;
-import android.os.ShellCommand;
-import android.provider.MediaStore;
-import android.util.ArraySet;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import android.annotation.AnyRes;
import android.annotation.IntDef;
import android.annotation.SdkConstant;
-import android.annotation.SystemApi;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
import android.content.pm.ActivityInfo;
-
-import static android.content.ContentProvider.maybeAddUserId;
-
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
@@ -41,21 +30,24 @@
import android.graphics.Rect;
import android.net.Uri;
import android.os.Bundle;
-import android.os.Environment;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Process;
+import android.os.ResultReceiver;
+import android.os.ShellCommand;
import android.os.StrictMode;
import android.os.UserHandle;
import android.provider.DocumentsContract;
import android.provider.DocumentsProvider;
+import android.provider.MediaStore;
import android.provider.OpenableColumns;
+import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Log;
-
import com.android.internal.util.XmlUtils;
-
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
@@ -71,6 +63,8 @@
import java.util.Objects;
import java.util.Set;
+import static android.content.ContentProvider.maybeAddUserId;
+
/**
* An intent is an abstract description of an operation to be performed. It
* can be used with {@link Context#startActivity(Intent) startActivity} to
@@ -759,6 +753,14 @@
"android.intent.extra.shortcut.ICON_RESOURCE";
/**
+ * An activity that provides a user interface for adjusting application preferences.
+ * Optional but recommended settings for all applications which have settings.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_APPLICATION_PREFERENCES
+ = "android.intent.action.APPLICATION_PREFERENCES";
+
+ /**
* Represents a shortcut/live folder icon resource.
*
* @see Intent#ACTION_CREATE_SHORTCUT
diff --git a/core/java/android/content/RestrictionsManager.java b/core/java/android/content/RestrictionsManager.java
index a7744e7..6893067 100644
--- a/core/java/android/content/RestrictionsManager.java
+++ b/core/java/android/content/RestrictionsManager.java
@@ -422,7 +422,7 @@
return mService.getApplicationRestrictions(mContext.getPackageName());
}
} catch (RemoteException re) {
- Log.w(TAG, "Couldn't reach service");
+ throw re.rethrowFromSystemServer();
}
return null;
}
@@ -439,7 +439,7 @@
return mService.hasRestrictionsProvider();
}
} catch (RemoteException re) {
- Log.w(TAG, "Couldn't reach service");
+ throw re.rethrowFromSystemServer();
}
return false;
}
@@ -477,7 +477,7 @@
request);
}
} catch (RemoteException re) {
- Log.w(TAG, "Couldn't reach service");
+ throw re.rethrowFromSystemServer();
}
}
@@ -487,7 +487,7 @@
return mService.createLocalApprovalIntent();
}
} catch (RemoteException re) {
- Log.w(TAG, "Couldn't reach service");
+ throw re.rethrowFromSystemServer();
}
return null;
}
@@ -519,7 +519,7 @@
mService.notifyPermissionResponse(packageName, response);
}
} catch (RemoteException re) {
- Log.w(TAG, "Couldn't reach service");
+ throw re.rethrowFromSystemServer();
}
}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 9082482..ad174f6 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -523,6 +523,14 @@
public static final int PRIVATE_FLAG_RESIZEABLE_ACTIVITIES = 1 << 11;
/**
+ * Value for {@link #privateFlags}: {@code true} means the OS should go ahead and
+ * run full-data backup operations for the app even when it is in a
+ * foreground-equivalent run state. Defaults to {@code false} if unspecified.
+ * @hide
+ */
+ public static final int PRIVATE_FLAG_BACKUP_IN_FOREGROUND = 1 << 12;
+
+ /**
* Private/hidden flags. See {@code PRIVATE_FLAG_...} constants.
* {@hide}
*/
diff --git a/core/java/android/content/pm/AppsQueryHelper.java b/core/java/android/content/pm/AppsQueryHelper.java
index e542589..4c01b27 100644
--- a/core/java/android/content/pm/AppsQueryHelper.java
+++ b/core/java/android/content/pm/AppsQueryHelper.java
@@ -171,7 +171,7 @@
return mPackageManager.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES
| PackageManager.GET_DISABLED_COMPONENTS, userId).getList();
} catch (RemoteException e) {
- throw new IllegalStateException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -181,9 +181,9 @@
return mPackageManager.queryIntentActivities(intent, null,
PackageManager.GET_DISABLED_COMPONENTS
| PackageManager.GET_UNINSTALLED_PACKAGES,
- userId);
+ userId).getList();
} catch (RemoteException e) {
- throw new IllegalStateException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -192,9 +192,9 @@
try {
return mPackageManager.queryIntentServices(intent, null,
PackageManager.GET_META_DATA
- | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS, userId);
+ | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS, userId).getList();
} catch (RemoteException e) {
- throw new IllegalStateException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -205,8 +205,7 @@
return mPackageManager.getPackagesHoldingPermissions(new String[]{perm}, 0,
userId).getList();
} catch (RemoteException e) {
- throw new IllegalStateException("Package manager has died", e);
+ throw e.rethrowFromSystemServer();
}
}
-
}
diff --git a/core/java/android/content/pm/ContainerEncryptionParams.java b/core/java/android/content/pm/ContainerEncryptionParams.java
deleted file mode 100644
index ab3aa27..0000000
--- a/core/java/android/content/pm/ContainerEncryptionParams.java
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm;
-
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.util.Slog;
-
-import java.security.InvalidAlgorithmParameterException;
-import java.security.spec.AlgorithmParameterSpec;
-import java.util.Arrays;
-
-import javax.crypto.SecretKey;
-import javax.crypto.spec.IvParameterSpec;
-
-/**
- * Represents encryption parameters used to read a container.
- *
- * @deprecated encrypted containers are legacy.
- * @hide
- */
-@SystemApi
-@Deprecated
-public class ContainerEncryptionParams implements Parcelable {
- protected static final String TAG = "ContainerEncryptionParams";
-
- /** What we print out first when toString() is called. */
- private static final String TO_STRING_PREFIX = "ContainerEncryptionParams{";
-
- /**
- * Parameter type for parceling that indicates the next parameters are
- * IvParameters.
- */
- private static final int ENC_PARAMS_IV_PARAMETERS = 1;
-
- /** Parameter type for paceling that indicates there are no MAC parameters. */
- private static final int MAC_PARAMS_NONE = 1;
-
- /** The encryption algorithm used. */
- private final String mEncryptionAlgorithm;
-
- /** The parameter spec to be used for encryption. */
- private final IvParameterSpec mEncryptionSpec;
-
- /** Secret key to be used for decryption. */
- private final SecretKey mEncryptionKey;
-
- /** Algorithm name for the MAC to be used. */
- private final String mMacAlgorithm;
-
- /** The parameter spec to be used for the MAC tag authentication. */
- private final AlgorithmParameterSpec mMacSpec;
-
- /** Secret key to be used for MAC tag authentication. */
- private final SecretKey mMacKey;
-
- /** MAC tag authenticating the data in the container. */
- private final byte[] mMacTag;
-
- /** Offset into file where authenticated (e.g., MAC protected) data begins. */
- private final long mAuthenticatedDataStart;
-
- /** Offset into file where encrypted data begins. */
- private final long mEncryptedDataStart;
-
- /**
- * Offset into file for the end of encrypted data (and, by extension,
- * authenticated data) in file.
- */
- private final long mDataEnd;
-
- public ContainerEncryptionParams(String encryptionAlgorithm,
- AlgorithmParameterSpec encryptionSpec, SecretKey encryptionKey)
- throws InvalidAlgorithmParameterException {
- this(encryptionAlgorithm, encryptionSpec, encryptionKey, null, null, null, null, -1, -1,
- -1);
- }
-
- /**
- * Creates container encryption specifications for installing from encrypted
- * containers.
- *
- * @param encryptionAlgorithm encryption algorithm to use; format matches
- * JCE
- * @param encryptionSpec algorithm parameter specification
- * @param encryptionKey key used for decryption
- * @param macAlgorithm MAC algorithm to use; format matches JCE
- * @param macSpec algorithm parameters specification, may be {@code null}
- * @param macKey key used for authentication (i.e., for the MAC tag)
- * @param macTag message authentication code (MAC) tag for the authenticated
- * data
- * @param authenticatedDataStart offset of start of authenticated data in
- * stream
- * @param encryptedDataStart offset of start of encrypted data in stream
- * @param dataEnd offset of the end of both the authenticated and encrypted
- * data
- * @throws InvalidAlgorithmParameterException
- */
- public ContainerEncryptionParams(String encryptionAlgorithm,
- AlgorithmParameterSpec encryptionSpec, SecretKey encryptionKey, String macAlgorithm,
- AlgorithmParameterSpec macSpec, SecretKey macKey, byte[] macTag,
- long authenticatedDataStart, long encryptedDataStart, long dataEnd)
- throws InvalidAlgorithmParameterException {
- if (TextUtils.isEmpty(encryptionAlgorithm)) {
- throw new NullPointerException("algorithm == null");
- } else if (encryptionSpec == null) {
- throw new NullPointerException("encryptionSpec == null");
- } else if (encryptionKey == null) {
- throw new NullPointerException("encryptionKey == null");
- }
-
- if (!TextUtils.isEmpty(macAlgorithm)) {
- if (macKey == null) {
- throw new NullPointerException("macKey == null");
- }
- }
-
- if (!(encryptionSpec instanceof IvParameterSpec)) {
- throw new InvalidAlgorithmParameterException(
- "Unknown parameter spec class; must be IvParameters");
- }
-
- mEncryptionAlgorithm = encryptionAlgorithm;
- mEncryptionSpec = (IvParameterSpec) encryptionSpec;
- mEncryptionKey = encryptionKey;
-
- mMacAlgorithm = macAlgorithm;
- mMacSpec = macSpec;
- mMacKey = macKey;
- mMacTag = macTag;
-
- mAuthenticatedDataStart = authenticatedDataStart;
- mEncryptedDataStart = encryptedDataStart;
- mDataEnd = dataEnd;
- }
-
- public String getEncryptionAlgorithm() {
- return mEncryptionAlgorithm;
- }
-
- public AlgorithmParameterSpec getEncryptionSpec() {
- return mEncryptionSpec;
- }
-
- public SecretKey getEncryptionKey() {
- return mEncryptionKey;
- }
-
- public String getMacAlgorithm() {
- return mMacAlgorithm;
- }
-
- public AlgorithmParameterSpec getMacSpec() {
- return mMacSpec;
- }
-
- public SecretKey getMacKey() {
- return mMacKey;
- }
-
- public byte[] getMacTag() {
- return mMacTag;
- }
-
- public long getAuthenticatedDataStart() {
- return mAuthenticatedDataStart;
- }
-
- public long getEncryptedDataStart() {
- return mEncryptedDataStart;
- }
-
- public long getDataEnd() {
- return mDataEnd;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
-
- if (!(o instanceof ContainerEncryptionParams)) {
- return false;
- }
-
- final ContainerEncryptionParams other = (ContainerEncryptionParams) o;
-
- // Primitive comparison
- if ((mAuthenticatedDataStart != other.mAuthenticatedDataStart)
- || (mEncryptedDataStart != other.mEncryptedDataStart)
- || (mDataEnd != other.mDataEnd)) {
- return false;
- }
-
- // String comparison
- if (!mEncryptionAlgorithm.equals(other.mEncryptionAlgorithm)
- || !mMacAlgorithm.equals(other.mMacAlgorithm)) {
- return false;
- }
-
- // Object comparison
- if (!isSecretKeyEqual(mEncryptionKey, other.mEncryptionKey)
- || !isSecretKeyEqual(mMacKey, other.mMacKey)) {
- return false;
- }
-
- if (!Arrays.equals(mEncryptionSpec.getIV(), other.mEncryptionSpec.getIV())
- || !Arrays.equals(mMacTag, other.mMacTag) || (mMacSpec != other.mMacSpec)) {
- return false;
- }
-
- return true;
- }
-
- private static final boolean isSecretKeyEqual(SecretKey key1, SecretKey key2) {
- final String keyFormat = key1.getFormat();
- final String otherKeyFormat = key2.getFormat();
-
- if (keyFormat == null) {
- if (keyFormat != otherKeyFormat) {
- return false;
- }
-
- if (key1.getEncoded() != key2.getEncoded()) {
- return false;
- }
- } else {
- if (!keyFormat.equals(key2.getFormat())) {
- return false;
- }
-
- if (!Arrays.equals(key1.getEncoded(), key2.getEncoded())) {
- return false;
- }
- }
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int hash = 3;
-
- hash += 5 * mEncryptionAlgorithm.hashCode();
- hash += 7 * Arrays.hashCode(mEncryptionSpec.getIV());
- hash += 11 * mEncryptionKey.hashCode();
- hash += 13 * mMacAlgorithm.hashCode();
- hash += 17 * mMacKey.hashCode();
- hash += 19 * Arrays.hashCode(mMacTag);
- hash += 23 * mAuthenticatedDataStart;
- hash += 29 * mEncryptedDataStart;
- hash += 31 * mDataEnd;
-
- return hash;
- }
-
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder(TO_STRING_PREFIX);
-
- sb.append("mEncryptionAlgorithm=\"");
- sb.append(mEncryptionAlgorithm);
- sb.append("\",");
- sb.append("mEncryptionSpec=");
- sb.append(mEncryptionSpec.toString());
- sb.append("mEncryptionKey=");
- sb.append(mEncryptionKey.toString());
-
- sb.append("mMacAlgorithm=\"");
- sb.append(mMacAlgorithm);
- sb.append("\",");
- sb.append("mMacSpec=");
- sb.append(mMacSpec.toString());
- sb.append("mMacKey=");
- sb.append(mMacKey.toString());
-
- sb.append(",mAuthenticatedDataStart=");
- sb.append(mAuthenticatedDataStart);
- sb.append(",mEncryptedDataStart=");
- sb.append(mEncryptedDataStart);
- sb.append(",mDataEnd=");
- sb.append(mDataEnd);
- sb.append('}');
-
- return sb.toString();
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mEncryptionAlgorithm);
- dest.writeInt(ENC_PARAMS_IV_PARAMETERS);
- dest.writeByteArray(mEncryptionSpec.getIV());
- dest.writeSerializable(mEncryptionKey);
-
- dest.writeString(mMacAlgorithm);
- dest.writeInt(MAC_PARAMS_NONE);
- dest.writeByteArray(new byte[0]);
- dest.writeSerializable(mMacKey);
-
- dest.writeByteArray(mMacTag);
-
- dest.writeLong(mAuthenticatedDataStart);
- dest.writeLong(mEncryptedDataStart);
- dest.writeLong(mDataEnd);
- }
-
- private ContainerEncryptionParams(Parcel source) throws InvalidAlgorithmParameterException {
- mEncryptionAlgorithm = source.readString();
- final int encParamType = source.readInt();
- final byte[] encParamsEncoded = source.createByteArray();
- mEncryptionKey = (SecretKey) source.readSerializable();
-
- mMacAlgorithm = source.readString();
- final int macParamType = source.readInt();
- source.createByteArray(); // byte[] macParamsEncoded
- mMacKey = (SecretKey) source.readSerializable();
-
- mMacTag = source.createByteArray();
-
- mAuthenticatedDataStart = source.readLong();
- mEncryptedDataStart = source.readLong();
- mDataEnd = source.readLong();
-
- switch (encParamType) {
- case ENC_PARAMS_IV_PARAMETERS:
- mEncryptionSpec = new IvParameterSpec(encParamsEncoded);
- break;
- default:
- throw new InvalidAlgorithmParameterException("Unknown parameter type "
- + encParamType);
- }
-
- switch (macParamType) {
- case MAC_PARAMS_NONE:
- mMacSpec = null;
- break;
- default:
- throw new InvalidAlgorithmParameterException("Unknown parameter type "
- + macParamType);
- }
-
- if (mEncryptionKey == null) {
- throw new NullPointerException("encryptionKey == null");
- }
- }
-
- public static final Parcelable.Creator<ContainerEncryptionParams> CREATOR =
- new Parcelable.Creator<ContainerEncryptionParams>() {
- public ContainerEncryptionParams createFromParcel(Parcel source) {
- try {
- return new ContainerEncryptionParams(source);
- } catch (InvalidAlgorithmParameterException e) {
- Slog.e(TAG, "Invalid algorithm parameters specified", e);
- return null;
- }
- }
-
- public ContainerEncryptionParams[] newArray(int size) {
- return new ContainerEncryptionParams[size];
- }
- };
-}
\ No newline at end of file
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index d6b674c..b4e9f60 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -46,7 +46,6 @@
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
-import android.content.pm.VerificationParams;
import android.content.pm.VerifierDeviceIdentity;
import android.graphics.Bitmap;
import android.net.Uri;
@@ -72,11 +71,11 @@
PermissionInfo getPermissionInfo(String name, int flags);
- List<PermissionInfo> queryPermissionsByGroup(String group, int flags);
+ ParceledListSlice queryPermissionsByGroup(String group, int flags);
PermissionGroupInfo getPermissionGroupInfo(String name, int flags);
- List<PermissionGroupInfo> getAllPermissionGroups(int flags);
+ ParceledListSlice getAllPermissionGroups(int flags);
ApplicationInfo getApplicationInfo(String packageName, int flags ,int userId);
@@ -139,24 +138,24 @@
boolean canForwardTo(in Intent intent, String resolvedType, int sourceUserId, int targetUserId);
- List<ResolveInfo> queryIntentActivities(in Intent intent,
+ ParceledListSlice queryIntentActivities(in Intent intent,
String resolvedType, int flags, int userId);
- List<ResolveInfo> queryIntentActivityOptions(
+ ParceledListSlice queryIntentActivityOptions(
in ComponentName caller, in Intent[] specifics,
in String[] specificTypes, in Intent intent,
String resolvedType, int flags, int userId);
- List<ResolveInfo> queryIntentReceivers(in Intent intent,
+ ParceledListSlice queryIntentReceivers(in Intent intent,
String resolvedType, int flags, int userId);
ResolveInfo resolveService(in Intent intent,
String resolvedType, int flags, int userId);
- List<ResolveInfo> queryIntentServices(in Intent intent,
+ ParceledListSlice queryIntentServices(in Intent intent,
String resolvedType, int flags, int userId);
- List<ResolveInfo> queryIntentContentProviders(in Intent intent,
+ ParceledListSlice queryIntentContentProviders(in Intent intent,
String resolvedType, int flags, int userId);
/**
@@ -190,7 +189,7 @@
* @return A List<applicationInfo> containing one entry for each persistent
* application.
*/
- List<ApplicationInfo> getPersistentApplications(int flags);
+ ParceledListSlice getPersistentApplications(int flags);
ProviderInfo resolveContentProvider(String name, int flags, int userId);
@@ -211,22 +210,14 @@
InstrumentationInfo getInstrumentationInfo(
in ComponentName className, int flags);
- List<InstrumentationInfo> queryInstrumentation(
+ ParceledListSlice queryInstrumentation(
String targetPackage, int flags);
- void installPackage(in String originPath,
- in IPackageInstallObserver2 observer,
- int flags,
- in String installerPackageName,
- in VerificationParams verificationParams,
- in String packageAbiOverride);
-
+ /** @deprecated Use PackageInstaller instead */
void installPackageAsUser(in String originPath,
in IPackageInstallObserver2 observer,
int flags,
in String installerPackageName,
- in VerificationParams verificationParams,
- in String packageAbiOverride,
int userId);
void finishPackageInstall(int token);
@@ -249,12 +240,6 @@
String getInstallerPackageName(in String packageName);
- void addPackageToPreferred(String packageName);
-
- void removePackageFromPreferred(String packageName);
-
- List<PackageInfo> getPreferredPackages(int flags);
-
void resetApplicationPreferences(int userId);
ResolveInfo getLastChosenActivity(in Intent intent,
@@ -415,7 +400,7 @@
* Get a list of features that are available on the
* system.
*/
- FeatureInfo[] getSystemAvailableFeatures();
+ ParceledListSlice getSystemAvailableFeatures();
boolean hasSystemFeature(String name, int version);
@@ -489,8 +474,8 @@
void verifyIntentFilter(int id, int verificationCode, in List<String> failedDomains);
int getIntentVerificationStatus(String packageName, int userId);
boolean updateIntentVerificationStatus(String packageName, int status, int userId);
- List<IntentFilterVerificationInfo> getIntentFilterVerifications(String packageName);
- List<IntentFilter> getAllIntentFilters(String packageName);
+ ParceledListSlice getIntentFilterVerifications(String packageName);
+ ParceledListSlice getAllIntentFilters(String packageName);
boolean setDefaultBrowserPackageName(String packageName, int userId);
String getDefaultBrowserPackageName(int userId);
@@ -539,4 +524,7 @@
String getServicesSystemSharedLibraryPackageName();
boolean isPackageDeviceAdminOnAnyUser(String packageName);
+
+ List<String> getPreviousCodePaths(in String packageName);
+
}
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 8c7d327..e443d50 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -171,7 +171,7 @@
try {
activities = mService.getLauncherActivities(packageName, user);
} catch (RemoteException re) {
- throw new RuntimeException("Failed to call LauncherAppsService", re);
+ throw re.rethrowFromSystemServer();
}
if (activities == null) {
return Collections.EMPTY_LIST;
@@ -208,7 +208,7 @@
return info;
}
} catch (RemoteException re) {
- throw new RuntimeException("Failed to call LauncherAppsService", re);
+ throw re.rethrowFromSystemServer();
}
return null;
}
@@ -229,7 +229,7 @@
try {
mService.startActivityAsUser(component, sourceBounds, opts, user);
} catch (RemoteException re) {
- // Oops!
+ throw re.rethrowFromSystemServer();
}
}
@@ -247,7 +247,7 @@
try {
mService.showAppDetailsAsUser(component, sourceBounds, opts, user);
} catch (RemoteException re) {
- // Oops!
+ throw re.rethrowFromSystemServer();
}
}
@@ -263,7 +263,7 @@
try {
return mService.isPackageEnabled(packageName, user);
} catch (RemoteException re) {
- throw new RuntimeException("Failed to call LauncherAppsService", re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -282,7 +282,7 @@
try {
return mService.getApplicationInfo(packageName, flags, user);
} catch (RemoteException re) {
- throw new RuntimeException("Failed to call LauncherAppsService", re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -298,7 +298,7 @@
try {
return mService.isActivityEnabled(component, user);
} catch (RemoteException re) {
- throw new RuntimeException("Failed to call LauncherAppsService", re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -327,6 +327,7 @@
try {
mService.addOnAppsChangedListener(mAppsChangedListener);
} catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
}
}
}
@@ -346,6 +347,7 @@
try {
mService.removeOnAppsChangedListener(mAppsChangedListener);
} catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 3283005..700a40d 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -301,7 +301,7 @@
ExceptionUtils.maybeUnwrapIOException(e);
throw e;
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -321,7 +321,7 @@
ExceptionUtils.maybeUnwrapIOException(e);
throw e;
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -337,7 +337,7 @@
try {
mInstaller.updateSessionAppIcon(sessionId, appIcon);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -353,7 +353,7 @@
final String val = (appLabel != null) ? appLabel.toString() : null;
mInstaller.updateSessionAppLabel(sessionId, val);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -370,7 +370,7 @@
try {
mInstaller.abandonSession(sessionId);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -385,7 +385,7 @@
try {
return mInstaller.getSessionInfo(sessionId);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -403,7 +403,7 @@
try {
return mInstaller.getAllSessions(mUserId).getList();
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -414,7 +414,7 @@
try {
return mInstaller.getMySessions(mInstallerPackageName, mUserId).getList();
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -427,7 +427,7 @@
try {
mInstaller.uninstall(packageName, mInstallerPackageName, 0, statusReceiver, mUserId);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -436,7 +436,7 @@
try {
mInstaller.setPermissionsResult(sessionId, accepted);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -611,7 +611,7 @@
try {
mInstaller.registerCallback(delegate, mUserId);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
mDelegates.add(delegate);
}
@@ -634,7 +634,7 @@
try {
mInstaller.unregisterCallback(delegate);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
i.remove();
}
@@ -681,7 +681,7 @@
try {
mSession.setClientProgress(progress);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -690,7 +690,7 @@
try {
mSession.addClientProgress(progress);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -734,7 +734,7 @@
ExceptionUtils.maybeUnwrapIOException(e);
throw e;
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -767,7 +767,7 @@
ExceptionUtils.maybeUnwrapIOException(e);
throw e;
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -790,7 +790,7 @@
ExceptionUtils.maybeUnwrapIOException(e);
throw e;
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -810,7 +810,7 @@
try {
mSession.commit(statusReceiver);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -823,7 +823,7 @@
try {
mSession.close();
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -837,7 +837,7 @@
try {
mSession.abandon();
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1042,6 +1042,11 @@
}
/** {@hide} */
+ public void setInstallFlagsDontKillApp() {
+ installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
+ }
+
+ /** {@hide} */
public void dump(IndentingPrintWriter pw) {
pw.printPair("mode", mode);
pw.printHexPair("installFlags", installFlags);
diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java
index 4df83036..edd888b 100644
--- a/core/java/android/content/pm/PackageItemInfo.java
+++ b/core/java/android/content/pm/PackageItemInfo.java
@@ -16,12 +16,16 @@
package android.content.pm;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Parcel;
import android.os.UserHandle;
+import android.text.BidiFormatter;
+import android.text.TextPaint;
import android.text.TextUtils;
import android.util.Printer;
@@ -38,6 +42,8 @@
* in the implementation of Parcelable in subclasses.
*/
public class PackageItemInfo {
+ private static final float MAX_LABEL_SIZE_PX = 500f;
+
/**
* Public name of this item. From the "android:name" attribute.
*/
@@ -140,6 +146,56 @@
}
/**
+ * Same as {@link #loadLabel(PackageManager)} with the addition that
+ * the returned label is safe for being presented in the UI since it
+ * will not contain new lines and the length will be limited to a
+ * reasonable amount. This prevents a malicious party to influence UI
+ * layout via the app label misleading the user into performing a
+ * detrimental for them action. If the label is too long it will be
+ * truncated and ellipsized at the end.
+ *
+ * @param pm A PackageManager from which the label can be loaded; usually
+ * the PackageManager from which you originally retrieved this item
+ * @return Returns a CharSequence containing the item's label. If the
+ * item does not have a label, its name is returned.
+ *
+ * @hide
+ */
+ @SystemApi
+ public @NonNull CharSequence loadSafeLabel(@NonNull PackageManager pm) {
+ // loadLabel() always returns non-null
+ CharSequence label = loadLabel(pm);
+
+ // If the label contains new line characters it may push the UI
+ // down to hide a part of it. Labels shouldn't have new line
+ // characters, so just truncate at the first time one is seen.
+ String labelStr = label.toString();
+ final int labelLength = labelStr.length();
+ int offset = 0;
+ while (offset < labelLength) {
+ final int codePoint = labelStr.codePointAt(offset);
+ final int type = Character.getType(codePoint);
+ if (type == Character.LINE_SEPARATOR
+ || type == Character.CONTROL
+ || type == Character.PARAGRAPH_SEPARATOR) {
+ labelStr = labelStr.substring(0, offset);
+ break;
+ }
+ offset += Character.charCount(codePoint);
+ }
+
+ if (labelStr.isEmpty()) {
+ return labelStr;
+ }
+
+ TextPaint paint = new TextPaint();
+ paint.setTextSize(42);
+
+ return TextUtils.ellipsize(labelStr, paint, MAX_LABEL_SIZE_PX,
+ TextUtils.TruncateAt.END);
+ }
+
+ /**
* Retrieve the current graphical icon associated with this item. This
* will call back on the given PackageManager to load the icon from
* the application.
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 0967608..0dc856c 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -538,6 +538,7 @@
INSTALL_FORCE_VOLUME_UUID,
INSTALL_FORCE_PERMISSION_PROMPT,
INSTALL_EPHEMERAL,
+ INSTALL_DONT_KILL_APP,
})
@Retention(RetentionPolicy.SOURCE)
public @interface InstallFlags {}
@@ -602,7 +603,8 @@
/**
* Flag parameter for {@link #installPackage} to indicate that it is okay
* to install an update to an app where the newly installed app has a lower
- * version code than the currently installed app.
+ * version code than the currently installed app. This is permitted only if
+ * the currently installed app is marked debuggable.
*
* @hide
*/
@@ -639,6 +641,15 @@
public static final int INSTALL_EPHEMERAL = 0x00000800;
/**
+ * Flag parameter for {@link #installPackage} to indicate that this package contains
+ * a feature split to an existing application and the existing application should not
+ * be killed during the installation process.
+ *
+ * @hide
+ */
+ public static final int INSTALL_DONT_KILL_APP = 0x00001000;
+
+ /**
* Flag parameter for
* {@link #setComponentEnabledSetting(android.content.ComponentName, int, int)} to indicate
* that you don't want to kill the app containing the component. Be careful when you set this
@@ -1087,6 +1098,7 @@
DELETE_KEEP_DATA,
DELETE_ALL_USERS,
DELETE_SYSTEM_APP,
+ DELETE_DONT_KILL_APP,
})
@Retention(RetentionPolicy.SOURCE)
public @interface DeleteFlags {}
@@ -1119,6 +1131,15 @@
public static final int DELETE_SYSTEM_APP = 0x00000004;
/**
+ * Flag parameter for {@link #deletePackage} to indicate that, if you are calling
+ * uninstall on a package that is replaced to provide new feature splits, the
+ * existing application should not be killed during the removal process.
+ *
+ * @hide
+ */
+ public static final int DELETE_DONT_KILL_APP = 0x00000008;
+
+ /**
* Return code for when package deletion succeeds. This is passed to the
* {@link IPackageDeleteObserver} if the system succeeded in deleting the
* package.
@@ -1291,6 +1312,7 @@
*
* @hide
*/
+ @SystemApi
public static final int INTENT_FILTER_VERIFICATION_SUCCESS = 1;
/**
@@ -1300,6 +1322,7 @@
*
* @hide
*/
+ @SystemApi
public static final int INTENT_FILTER_VERIFICATION_FAILURE = -1;
/**
@@ -1573,6 +1596,48 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: If this feature is supported, the Vulkan native API will enumerate
+ * at least one {@code VkPhysicalDevice}, and the feature version will indicate what
+ * level of optional hardware features limits it supports.
+ * <p>
+ * Level 0 includes the base Vulkan requirements as well as:
+ * <ul><li>{@code VkPhysicalDeviceFeatures::textureCompressionETC2}</li></ul>
+ * <p>
+ * Level 1 additionally includes:
+ * <ul>
+ * <li>{@code VkPhysicalDeviceFeatures::fullDrawIndexUint32}</li>
+ * <li>{@code VkPhysicalDeviceFeatures::imageCubeArray}</li>
+ * <li>{@code VkPhysicalDeviceFeatures::independentBlend}</li>
+ * <li>{@code VkPhysicalDeviceFeatures::geometryShader}</li>
+ * <li>{@code VkPhysicalDeviceFeatures::tessellationShader}</li>
+ * <li>{@code VkPhysicalDeviceFeatures::sampleRateShading}</li>
+ * <li>{@code VkPhysicalDeviceFeatures::textureCompressionASTC_LDR}</li>
+ * <li>{@code VkPhysicalDeviceFeatures::fragmentStoresAndAtomics}</li>
+ * <li>{@code VkPhysicalDeviceFeatures::shaderImageGatherExtended}</li>
+ * <li>{@code VkPhysicalDeviceFeatures::shaderUniformBufferArrayDynamicIndexing}</li>
+ * <li>{@code VkPhysicalDeviceFeatures::shaderSampledImageArrayDynamicIndexing}</li>
+ * </ul>
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_VULKAN_HARDWARE_LEVEL = "android.hardware.vulkan.level";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The version of this feature indicates the highest
+ * {@code VkPhysicalDeviceProperties::apiVersion} supported by the physical devices that support
+ * the hardware level indicated by {@link #FEATURE_VULKAN_HARDWARE_LEVEL}. The feature version
+ * uses the same encoding as Vulkan version numbers:
+ * <ul>
+ * <li>Major version number in bits 31-22</li>
+ * <li>Minor version number in bits 21-12</li>
+ * <li>Patch version number in bits 11-0</li>
+ * </ul>
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_VULKAN_HARDWARE_VERSION = "android.hardware.vulkan.version";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device includes an accelerometer.
*/
@SdkConstant(SdkConstantType.FEATURE)
@@ -3175,7 +3240,7 @@
*/
public Intent buildRequestPermissionsIntent(@NonNull String[] permissions) {
if (ArrayUtils.isEmpty(permissions)) {
- throw new NullPointerException("permission cannot be null or empty");
+ throw new IllegalArgumentException("permission cannot be null or empty");
}
Intent intent = new Intent(ACTION_REQUEST_PERMISSIONS);
intent.putExtra(EXTRA_REQUEST_PERMISSIONS_NAMES, permissions);
@@ -4059,7 +4124,7 @@
*
* @return A list of {@link InstrumentationInfo} objects containing one
* entry for each matching instrumentation. If there are no
- * instrumentation available, returns and empty list.
+ * instrumentation available, returns an empty list.
*
* @see #GET_META_DATA
*/
@@ -4296,6 +4361,32 @@
throws NameNotFoundException;
/**
+ * Returns a managed-user-style badged copy of the given drawable allowing the user to
+ * distinguish it from the original drawable.
+ * The caller can specify the location in the bounds of the drawable to be
+ * badged where the badge should be applied as well as the density of the
+ * badge to be used.
+ * <p>
+ * If the original drawable is a BitmapDrawable and the backing bitmap is
+ * mutable as per {@link android.graphics.Bitmap#isMutable()}, the badging
+ * is performed in place and the original drawable is returned.
+ * </p>
+ *
+ * @param drawable The drawable to badge.
+ * @param badgeLocation Where in the bounds of the badged drawable to place
+ * the badge. If it's {@code null}, the badge is applied on top of the entire
+ * drawable being badged.
+ * @param badgeDensity The optional desired density for the badge as per
+ * {@link android.util.DisplayMetrics#densityDpi}. If it's not positive,
+ * the density of the display is used.
+ * @return A drawable that combines the original drawable and a badge as
+ * determined by the system.
+ * @hide
+ */
+ public abstract Drawable getManagedUserBadgedDrawable(Drawable drawable, Rect badgeLocation,
+ int badgeDensity);
+
+ /**
* If the target user is a managed profile of the calling user or if the
* target user is the caller and is itself a managed profile, then this
* returns a badged copy of the given icon to be able to distinguish it from
@@ -4324,17 +4415,17 @@
* badge to be used.
* <p>
* If the original drawable is a BitmapDrawable and the backing bitmap is
- * mutable as per {@link android.graphics.Bitmap#isMutable()}, the bading
+ * mutable as per {@link android.graphics.Bitmap#isMutable()}, the badging
* is performed in place and the original drawable is returned.
* </p>
*
* @param drawable The drawable to badge.
* @param user The target user.
* @param badgeLocation Where in the bounds of the badged drawable to place
- * the badge. If not provided, the badge is applied on top of the entire
+ * the badge. If it's {@code null}, the badge is applied on top of the entire
* drawable being badged.
* @param badgeDensity The optional desired density for the badge as per
- * {@link android.util.DisplayMetrics#densityDpi}. If not provided,
+ * {@link android.util.DisplayMetrics#densityDpi}. If it's not positive,
* the density of the display is used.
* @return A drawable that combines the original drawable and a badge as
* determined by the system.
@@ -4555,60 +4646,20 @@
*/
@Deprecated
public abstract void installPackage(
- Uri packageURI, IPackageInstallObserver observer, @InstallFlags int flags,
+ Uri packageURI,
+ IPackageInstallObserver observer,
+ @InstallFlags int flags,
String installerPackageName);
-
/**
* @deprecated replaced by {@link PackageInstaller}
* @hide
*/
@Deprecated
- public abstract void installPackageWithVerification(Uri packageURI,
- IPackageInstallObserver observer, @InstallFlags int flags, String installerPackageName,
- Uri verificationURI, ContainerEncryptionParams encryptionParams);
-
- /**
- * @deprecated replaced by {@link PackageInstaller}
- * @hide
- */
- @Deprecated
- public abstract void installPackageWithVerificationAndEncryption(Uri packageURI,
- IPackageInstallObserver observer, @InstallFlags int flags, String installerPackageName,
- VerificationParams verificationParams, ContainerEncryptionParams encryptionParams);
-
- /**
- * @deprecated replaced by {@link PackageInstaller}
- * @hide
- */
- @Deprecated
- public abstract void installPackage(Uri packageURI, PackageInstallObserver observer,
- @InstallFlags int flags, String installerPackageName);
-
- /**
- * @deprecated replaced by {@link PackageInstaller}
- * @hide
- */
- @Deprecated
- public abstract void installPackageAsUser(Uri packageURI, PackageInstallObserver observer,
- @InstallFlags int flags, String installerPackageName, @UserIdInt int userId);
-
- /**
- * @deprecated replaced by {@link PackageInstaller}
- * @hide
- */
- @Deprecated
- public abstract void installPackageWithVerification(Uri packageURI,
- PackageInstallObserver observer, @InstallFlags int flags, String installerPackageName,
- Uri verificationURI, ContainerEncryptionParams encryptionParams);
-
- /**
- * @deprecated replaced by {@link PackageInstaller}
- * @hide
- */
- @Deprecated
- public abstract void installPackageWithVerificationAndEncryption(Uri packageURI,
- PackageInstallObserver observer, @InstallFlags int flags, String installerPackageName,
- VerificationParams verificationParams, ContainerEncryptionParams encryptionParams);
+ public abstract void installPackage(
+ Uri packageURI,
+ PackageInstallObserver observer,
+ @InstallFlags int flags,
+ String installerPackageName);
/**
* If there is already an application with the given package name installed
@@ -4682,8 +4733,8 @@
/**
* Allows a package listening to the
- * {@link Intent#ACTION_INTENT_FILTER_NEEDS_VERIFICATION intent filter verification
- * broadcast} to respond to the package manager. The response must include
+ * {@link Intent#ACTION_INTENT_FILTER_NEEDS_VERIFICATION} intent filter verification
+ * broadcast to respond to the package manager. The response must include
* the {@code verificationCode} which is one of
* {@link PackageManager#INTENT_FILTER_VERIFICATION_SUCCESS} or
* {@link PackageManager#INTENT_FILTER_VERIFICATION_FAILURE}.
@@ -4692,7 +4743,7 @@
* {@link PackageManager#EXTRA_VERIFICATION_ID} Intent extra.
* @param verificationCode either {@link PackageManager#INTENT_FILTER_VERIFICATION_SUCCESS}
* or {@link PackageManager#INTENT_FILTER_VERIFICATION_FAILURE}.
- * @param outFailedDomains a list of failed domains if the verificationCode is
+ * @param failedDomains a list of failed domains if the verificationCode is
* {@link PackageManager#INTENT_FILTER_VERIFICATION_FAILURE}, otherwise null;
* @throws SecurityException if the caller does not have the
* INTENT_FILTER_VERIFICATION_AGENT permission.
@@ -4701,7 +4752,7 @@
*/
@SystemApi
public abstract void verifyIntentFilter(int verificationId, int verificationCode,
- List<String> outFailedDomains);
+ List<String> failedDomains);
/**
* Get the status of a Domain Verification Result for an IntentFilter. This is
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 8bf20bf..89f2fc4 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -16,6 +16,8 @@
package android.content.pm;
+import android.content.pm.PackageManager.NameNotFoundException;
+
import java.util.List;
/**
@@ -59,12 +61,6 @@
public abstract void setLocationPackagesProvider(PackagesProvider provider);
/**
- * Sets the input method packages provider.
- * @param provider The packages provider.
- */
- public abstract void setImePackagesProvider(PackagesProvider provider);
-
- /**
* Sets the voice interaction packages provider.
* @param provider The packages provider.
*/
@@ -131,4 +127,17 @@
* @return True a permissions review is required.
*/
public abstract boolean isPermissionsReviewRequired(String packageName, int userId);
+
+ /**
+ * Gets all of the information we know about a particular package.
+ *
+ * @param packageName The package name to find.
+ * @param userId The user under which to check.
+ *
+ * @return An {@link ApplicationInfo} containing information about the
+ * package.
+ * @throws NameNotFoundException if a package with the given name cannot be
+ * found on the system.
+ */
+ public abstract ApplicationInfo getApplicationInfo(String packageName, int userId);
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index f6ae020..bc28ff1 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -121,6 +121,10 @@
private static final int MAX_PACKAGES_PER_APK = 5;
+ public static final int APK_SIGNING_UNKNOWN = 0;
+ public static final int APK_SIGNING_V1 = 1;
+ public static final int APK_SIGNING_V2 = 2;
+
// TODO: switch outError users to PackageParserException
// TODO: refactor "codePath" to "apkPath"
@@ -1058,12 +1062,24 @@
return pkg;
}
+ public static int getApkSigningVersion(Package pkg) {
+ try {
+ if (ApkSignatureSchemeV2Verifier.hasSignature(pkg.baseCodePath)) {
+ return APK_SIGNING_V2;
+ }
+ return APK_SIGNING_V1;
+ } catch (IOException e) {
+ }
+ return APK_SIGNING_UNKNOWN;
+ }
+
/**
* Collect certificates from all the APKs described in the given package,
* populating {@link Package#mSignatures}. Also asserts that all APK
* contents are signed correctly and consistently.
*/
- public static void collectCertificates(Package pkg, int parseFlags) throws PackageParserException {
+ public static void collectCertificates(Package pkg, int parseFlags)
+ throws PackageParserException {
collectCertificatesInternal(pkg, parseFlags);
final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
for (int i = 0; i < childCount; i++) {
@@ -1074,7 +1090,8 @@
}
}
- private static void collectCertificatesInternal(Package pkg, int parseFlags) throws PackageParserException {
+ private static void collectCertificatesInternal(Package pkg, int parseFlags)
+ throws PackageParserException {
pkg.mCertificates = null;
pkg.mSignatures = null;
pkg.mSigningKeys = null;
@@ -2669,8 +2686,9 @@
if (allowBackup) {
ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
- // backupAgent, killAfterRestore, fullBackupContent and restoreAnyVersion are only
- // relevant if backup is possible for the given application.
+ // backupAgent, killAfterRestore, fullBackupContent, backupInForeground,
+ // and restoreAnyVersion are only relevant if backup is possible for the
+ // given application.
String backupAgent = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestApplication_backupAgent,
Configuration.NATIVE_CONFIG_VERSION);
@@ -2696,6 +2714,11 @@
false)) {
ai.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
}
+ if (sa.getBoolean(
+ com.android.internal.R.styleable.AndroidManifestApplication_backupInForeground,
+ false)) {
+ ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
+ }
}
TypedValue v = sa.peekValue(
@@ -4684,9 +4707,6 @@
// preferred up order.
public int mPreferredOrder = 0;
- // For use by package manager to keep track of where it needs to do dexopt.
- public final ArraySet<String> mDexOptPerformed = new ArraySet<>(4);
-
// For use by package manager to keep track of when a package was last used.
public long mLastPackageUsageTimeInMills;
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index 9da2ba9..984a960 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -16,6 +16,7 @@
package android.content.pm;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -145,11 +146,12 @@
public static final int FLAG_COSTS_MONEY = 1<<0;
/**
- * Flag for {@link #flags}, corresponding to <code>hidden</code>
+ * Flag for {@link #flags}, corresponding to <code>removed</code>
* value of {@link android.R.attr#permissionFlags}.
* @hide
*/
- public static final int FLAG_HIDDEN = 1<<1;
+ @SystemApi
+ public static final int FLAG_REMOVED = 1<<1;
/**
* Flag for {@link #flags}, indicating that this permission has been
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 9cf4675..3139151 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -73,6 +73,9 @@
/**
* Indicates that this user is disabled.
+ *
+ * <p>Note: If an ephemeral user is disabled, it shouldn't be later re-enabled. Ephemeral users
+ * are disabled as their removal is in progress to indicate that they shouldn't be re-entered.
*/
public static final int FLAG_DISABLED = 0x00000040;
@@ -171,6 +174,10 @@
* @return true if this user can be switched to.
**/
public boolean supportsSwitchTo() {
+ if (isEphemeral() && !isEnabled()) {
+ // Don't support switching to an ephemeral user with removal in progress.
+ return false;
+ }
// TODO remove fw.show_hidden_users when we have finished developing managed profiles.
return !isManagedProfile() || SystemProperties.getBoolean("fw.show_hidden_users", false);
}
diff --git a/core/java/android/content/pm/VerificationParams.aidl b/core/java/android/content/pm/VerificationParams.aidl
deleted file mode 100644
index 5bb7f6962..0000000
--- a/core/java/android/content/pm/VerificationParams.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm;
-
-parcelable VerificationParams;
diff --git a/core/java/android/content/res/ConfigurationBoundResourceCache.java b/core/java/android/content/res/ConfigurationBoundResourceCache.java
index fecda87..40d2a82 100644
--- a/core/java/android/content/res/ConfigurationBoundResourceCache.java
+++ b/core/java/android/content/res/ConfigurationBoundResourceCache.java
@@ -23,29 +23,19 @@
* @hide For internal use only.
*/
public class ConfigurationBoundResourceCache<T> extends ThemedResourceCache<ConstantState<T>> {
- private final Resources mResources;
-
- /**
- * Creates a cache for the given Resources instance.
- *
- * @param resources the resources to use when creating new instances
- */
- public ConfigurationBoundResourceCache(Resources resources) {
- mResources = resources;
- }
-
/**
* If the resource is cached, creates and returns a new instance of it.
*
* @param key a key that uniquely identifies the drawable resource
+ * @param resources a Resources object from which to create new instances.
* @param theme the theme where the resource will be used
* @return a new instance of the resource, or {@code null} if not in
* the cache
*/
- public T getInstance(long key, Resources.Theme theme) {
+ public T getInstance(long key, Resources resources, Resources.Theme theme) {
final ConstantState<T> entry = get(key, theme);
if (entry != null) {
- return entry.newInstance(mResources, theme);
+ return entry.newInstance(resources, theme);
}
return null;
diff --git a/core/java/android/content/res/DrawableCache.java b/core/java/android/content/res/DrawableCache.java
index ba00134..7b27fac 100644
--- a/core/java/android/content/res/DrawableCache.java
+++ b/core/java/android/content/res/DrawableCache.java
@@ -22,29 +22,19 @@
* Class which can be used to cache Drawable resources against a theme.
*/
class DrawableCache extends ThemedResourceCache<Drawable.ConstantState> {
- private final Resources mResources;
-
- /**
- * Creates a cache for the given Resources instance.
- *
- * @param resources the resources to use when creating new instances
- */
- public DrawableCache(Resources resources) {
- mResources = resources;
- }
-
/**
* If the resource is cached, creates and returns a new instance of it.
*
* @param key a key that uniquely identifies the drawable resource
+ * @param resources a Resources object from which to create new instances.
* @param theme the theme where the resource will be used
* @return a new instance of the resource, or {@code null} if not in
* the cache
*/
- public Drawable getInstance(long key, Resources.Theme theme) {
+ public Drawable getInstance(long key, Resources resources, Resources.Theme theme) {
final Drawable.ConstantState entry = get(key, theme);
if (entry != null) {
- return entry.newDrawable(mResources, theme);
+ return entry.newDrawable(resources, theme);
}
return null;
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 915fae0..f337fe6 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -40,23 +40,17 @@
import android.annotation.XmlRes;
import android.content.pm.ActivityInfo;
import android.graphics.Movie;
-import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Drawable.ConstantState;
import android.graphics.drawable.DrawableInflater;
-import android.icu.text.PluralRules;
import android.os.Build;
import android.os.Bundle;
-import android.os.Trace;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
-import android.util.LocaleList;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.Pools.SynchronizedPool;
-import android.util.Slog;
import android.util.TypedValue;
-import android.util.Xml;
import android.view.ViewDebug;
import android.view.ViewHierarchyEncoder;
@@ -68,7 +62,6 @@
import java.io.IOException;
import java.io.InputStream;
-import java.util.Locale;
/**
* Class for accessing an application's resources. This sits on top of the
@@ -98,48 +91,15 @@
public class Resources {
static final String TAG = "Resources";
- private static final boolean DEBUG_LOAD = false;
- private static final boolean DEBUG_CONFIG = false;
- private static final boolean TRACE_FOR_PRELOAD = false;
- private static final boolean TRACE_FOR_MISS_PRELOAD = false;
-
- private static final int LAYOUT_DIR_CONFIG = ActivityInfo.activityInfoConfigToNative(
- ActivityInfo.CONFIG_LAYOUT_DIRECTION);
-
- private static final int ID_OTHER = 0x01000004;
-
private static final Object sSync = new Object();
- // Information about preloaded resources. Note that they are not
- // protected by a lock, because while preloading in zygote we are all
- // single-threaded, and after that these are immutable.
- private static final LongSparseArray<ConstantState>[] sPreloadedDrawables;
- private static final LongSparseArray<ConstantState> sPreloadedColorDrawables
- = new LongSparseArray<>();
- private static final LongSparseArray<android.content.res.ConstantState<ComplexColor>>
- sPreloadedComplexColors = new LongSparseArray<>();
-
- // Pool of TypedArrays targeted to this Resources object.
- final SynchronizedPool<TypedArray> mTypedArrayPool = new SynchronizedPool<>(5);
-
// Used by BridgeResources in layoutlib
static Resources mSystem = null;
- private static boolean sPreloaded;
+ private ResourcesImpl mResourcesImpl;
- /** Lock object used to protect access to caches and configuration. */
- private final Object mAccessLock = new Object();
-
- // These are protected by mAccessLock.
- private final Configuration mTmpConfig = new Configuration();
- private final DrawableCache mDrawableCache = new DrawableCache(this);
- private final DrawableCache mColorDrawableCache = new DrawableCache(this);
- private final ConfigurationBoundResourceCache<ComplexColor> mComplexColorCache =
- new ConfigurationBoundResourceCache<>(this);
- private final ConfigurationBoundResourceCache<Animator> mAnimatorCache =
- new ConfigurationBoundResourceCache<>(this);
- private final ConfigurationBoundResourceCache<StateListAnimator> mStateListAnimatorCache =
- new ConfigurationBoundResourceCache<>(this);
+ // Pool of TypedArrays targeted to this Resources object.
+ final SynchronizedPool<TypedArray> mTypedArrayPool = new SynchronizedPool<>(5);
/** Used to inflate drawable objects from XML. */
private DrawableInflater mDrawableInflater;
@@ -150,28 +110,7 @@
/** Single-item pool used to minimize TypedValue allocations. */
private TypedValue mTmpValue = new TypedValue();
- private boolean mPreloading;
-
- // Cyclical cache used for recently-accessed XML files.
- private int mLastCachedXmlBlockIndex = -1;
- private final String[] mCachedXmlBlockFiles = new String[4];
- private final XmlBlock[] mCachedXmlBlocks = new XmlBlock[4];
-
- final AssetManager mAssets;
final ClassLoader mClassLoader;
- final DisplayMetrics mMetrics = new DisplayMetrics();
-
- private final Configuration mConfiguration = new Configuration();
-
- private PluralRules mPluralRule;
-
- private CompatibilityInfo mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
-
- static {
- sPreloadedDrawables = new LongSparseArray[2];
- sPreloadedDrawables[0] = new LongSparseArray<>();
- sPreloadedDrawables[1] = new LongSparseArray<>();
- }
/**
* Returns the most appropriate default theme for the specified target SDK version.
@@ -214,32 +153,20 @@
}
/**
- * @return the inflater used to create drawable objects
- * @hide Pending API finalization.
+ * Return a global shared Resources object that provides access to only
+ * system resources (no application resources), and is not configured for
+ * the current screen (can not use dimension units, does not change based
+ * on orientation, etc).
*/
- public final DrawableInflater getDrawableInflater() {
- if (mDrawableInflater == null) {
- mDrawableInflater = new DrawableInflater(this, mClassLoader);
+ public static Resources getSystem() {
+ synchronized (sSync) {
+ Resources ret = mSystem;
+ if (ret == null) {
+ ret = new Resources();
+ mSystem = ret;
+ }
+ return ret;
}
- return mDrawableInflater;
- }
-
- /**
- * Used by AnimatorInflater.
- *
- * @hide
- */
- public ConfigurationBoundResourceCache<Animator> getAnimatorCache() {
- return mAnimatorCache;
- }
-
- /**
- * Used by AnimatorInflater.
- *
- * @hide
- */
- public ConfigurationBoundResourceCache<StateListAnimator> getStateListAnimatorCache() {
- return mStateListAnimatorCache;
}
/**
@@ -270,51 +197,73 @@
* selecting/computing resource values (optional).
*/
public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config) {
- this(assets, metrics, config, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+ this(null);
+ mResourcesImpl = new ResourcesImpl(assets, metrics, config,
+ CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
}
/**
* Creates a new Resources object with CompatibilityInfo.
*
- * @param assets Previously created AssetManager.
- * @param metrics Current display metrics to consider when
- * selecting/computing resource values.
- * @param config Desired device configuration to consider when
- * selecting/computing resource values (optional).
- * @param compatInfo this resource's compatibility info. Must not be null.
* @param classLoader class loader for the package used to load custom
* resource classes, may be {@code null} to use system
* class loader
* @hide
*/
- public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config,
- CompatibilityInfo compatInfo, @Nullable ClassLoader classLoader) {
- mAssets = assets;
+ public Resources(@Nullable ClassLoader classLoader) {
mClassLoader = classLoader == null ? ClassLoader.getSystemClassLoader() : classLoader;
- mMetrics.setToDefaults();
- if (compatInfo != null) {
- mCompatibilityInfo = compatInfo;
- }
- updateConfiguration(config, metrics);
- assets.ensureStringBlocks();
}
/**
- * Return a global shared Resources object that provides access to only
- * system resources (no application resources), and is not configured for
- * the current screen (can not use dimension units, does not change based
- * on orientation, etc).
+ * Only for creating the System resources.
*/
- public static Resources getSystem() {
- synchronized (sSync) {
- Resources ret = mSystem;
- if (ret == null) {
- ret = new Resources();
- mSystem = ret;
- }
+ private Resources() {
+ this(null);
- return ret;
+ final DisplayMetrics metrics = new DisplayMetrics();
+ metrics.setToDefaults();
+
+ final Configuration config = new Configuration();
+ config.setToDefaults();
+
+ mResourcesImpl = new ResourcesImpl(AssetManager.getSystem(), metrics, config,
+ CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
+ }
+
+ /**
+ * @hide
+ */
+ public void setImpl(ResourcesImpl impl) {
+ mResourcesImpl = impl;
+ }
+
+ /**
+ * @return the inflater used to create drawable objects
+ * @hide Pending API finalization.
+ */
+ public final DrawableInflater getDrawableInflater() {
+ if (mDrawableInflater == null) {
+ mDrawableInflater = new DrawableInflater(this, mClassLoader);
}
+ return mDrawableInflater;
+ }
+
+ /**
+ * Used by AnimatorInflater.
+ *
+ * @hide
+ */
+ public ConfigurationBoundResourceCache<Animator> getAnimatorCache() {
+ return mResourcesImpl.getAnimatorCache();
+ }
+
+ /**
+ * Used by AnimatorInflater.
+ *
+ * @hide
+ */
+ public ConfigurationBoundResourceCache<StateListAnimator> getStateListAnimatorCache() {
+ return mResourcesImpl.getStateListAnimatorCache();
}
/**
@@ -332,8 +281,8 @@
* @return CharSequence The string data associated with the resource, plus
* possibly styled text information.
*/
- public CharSequence getText(@StringRes int id) throws NotFoundException {
- CharSequence res = mAssets.getResourceText(id);
+ @NonNull public CharSequence getText(@StringRes int id) throws NotFoundException {
+ CharSequence res = mResourcesImpl.getAssets().getResourceText(id);
if (res != null) {
return res;
}
@@ -361,41 +310,10 @@
* @return CharSequence The string data associated with the resource, plus
* possibly styled text information.
*/
+ @NonNull
public CharSequence getQuantityText(@PluralsRes int id, int quantity)
throws NotFoundException {
- PluralRules rule = getPluralRule();
- CharSequence res = mAssets.getResourceBagText(id,
- attrForQuantityCode(rule.select(quantity)));
- if (res != null) {
- return res;
- }
- res = mAssets.getResourceBagText(id, ID_OTHER);
- if (res != null) {
- return res;
- }
- throw new NotFoundException("Plural resource ID #0x" + Integer.toHexString(id)
- + " quantity=" + quantity
- + " item=" + rule.select(quantity));
- }
-
- private PluralRules getPluralRule() {
- synchronized (sSync) {
- if (mPluralRule == null) {
- mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().get(0));
- }
- return mPluralRule;
- }
- }
-
- private static int attrForQuantityCode(String quantityCode) {
- switch (quantityCode) {
- case PluralRules.KEYWORD_ZERO: return 0x01000005;
- case PluralRules.KEYWORD_ONE: return 0x01000006;
- case PluralRules.KEYWORD_TWO: return 0x01000007;
- case PluralRules.KEYWORD_FEW: return 0x01000008;
- case PluralRules.KEYWORD_MANY: return 0x01000009;
- default: return ID_OTHER;
- }
+ return mResourcesImpl.getQuantityText(id, quantity);
}
/**
@@ -414,12 +332,7 @@
*/
@NonNull
public String getString(@StringRes int id) throws NotFoundException {
- final CharSequence res = getText(id);
- if (res != null) {
- return res.toString();
- }
- throw new NotFoundException("String resource ID #0x"
- + Integer.toHexString(id));
+ return getText(id).toString();
}
@@ -444,7 +357,8 @@
@NonNull
public String getString(@StringRes int id, Object... formatArgs) throws NotFoundException {
final String raw = getString(id);
- return String.format(mConfiguration.getLocales().get(0), raw, formatArgs);
+ return String.format(mResourcesImpl.getConfiguration().getLocales().get(0), raw,
+ formatArgs);
}
/**
@@ -472,10 +386,12 @@
* @return String The string data associated with the resource,
* stripped of styled text information.
*/
+ @NonNull
public String getQuantityString(@PluralsRes int id, int quantity, Object... formatArgs)
throws NotFoundException {
String raw = getQuantityText(id, quantity).toString();
- return String.format(mConfiguration.getLocales().get(0), raw, formatArgs);
+ return String.format(mResourcesImpl.getConfiguration().getLocales().get(0), raw,
+ formatArgs);
}
/**
@@ -498,8 +414,8 @@
* @return String The string data associated with the resource,
* stripped of styled text information.
*/
- public String getQuantityString(@PluralsRes int id, int quantity)
- throws NotFoundException {
+ @NonNull
+ public String getQuantityString(@PluralsRes int id, int quantity) throws NotFoundException {
return getQuantityText(id, quantity).toString();
}
@@ -518,7 +434,7 @@
* possibly styled text information, or def if id is 0 or not found.
*/
public CharSequence getText(@StringRes int id, CharSequence def) {
- CharSequence res = id != 0 ? mAssets.getResourceText(id) : null;
+ CharSequence res = id != 0 ? mResourcesImpl.getAssets().getResourceText(id) : null;
return res != null ? res : def;
}
@@ -533,13 +449,13 @@
*
* @return The styled text array associated with the resource.
*/
+ @NonNull
public CharSequence[] getTextArray(@ArrayRes int id) throws NotFoundException {
- CharSequence[] res = mAssets.getResourceTextArray(id);
+ CharSequence[] res = mResourcesImpl.getAssets().getResourceTextArray(id);
if (res != null) {
return res;
}
- throw new NotFoundException("Text array resource ID #0x"
- + Integer.toHexString(id));
+ throw new NotFoundException("Text array resource ID #0x" + Integer.toHexString(id));
}
/**
@@ -553,14 +469,14 @@
*
* @return The string array associated with the resource.
*/
+ @NonNull
public String[] getStringArray(@ArrayRes int id)
throws NotFoundException {
- String[] res = mAssets.getResourceStringArray(id);
+ String[] res = mResourcesImpl.getAssets().getResourceStringArray(id);
if (res != null) {
return res;
}
- throw new NotFoundException("String array resource ID #0x"
- + Integer.toHexString(id));
+ throw new NotFoundException("String array resource ID #0x" + Integer.toHexString(id));
}
/**
@@ -574,13 +490,13 @@
*
* @return The int array associated with the resource.
*/
+ @NonNull
public int[] getIntArray(@ArrayRes int id) throws NotFoundException {
- int[] res = mAssets.getArrayIntResource(id);
+ int[] res = mResourcesImpl.getAssets().getArrayIntResource(id);
if (res != null) {
return res;
}
- throw new NotFoundException("Int array resource ID #0x"
- + Integer.toHexString(id));
+ throw new NotFoundException("Int array resource ID #0x" + Integer.toHexString(id));
}
/**
@@ -596,16 +512,16 @@
* Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
* when done with it.
*/
- public TypedArray obtainTypedArray(@ArrayRes int id)
- throws NotFoundException {
- int len = mAssets.getArraySize(id);
+ @NonNull
+ public TypedArray obtainTypedArray(@ArrayRes int id) throws NotFoundException {
+ final ResourcesImpl impl = mResourcesImpl;
+ int len = impl.getAssets().getArraySize(id);
if (len < 0) {
- throw new NotFoundException("Array resource ID #0x"
- + Integer.toHexString(id));
+ throw new NotFoundException("Array resource ID #0x" + Integer.toHexString(id));
}
TypedArray array = TypedArray.obtain(this, len);
- array.mLength = mAssets.retrieveArray(id, array.mData);
+ array.mLength = impl.getAssets().retrieveArray(id, array.mData);
array.mIndices[0] = 0;
return array;
@@ -629,10 +545,12 @@
* @see #getDimensionPixelSize
*/
public float getDimension(@DimenRes int id) throws NotFoundException {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
+ final ResourcesImpl impl = mResourcesImpl;
+ impl.getValue(id, value, true);
if (value.type == TypedValue.TYPE_DIMENSION) {
- return TypedValue.complexToDimension(value.data, mMetrics);
+ return TypedValue.complexToDimension(value.data, impl.getDisplayMetrics());
}
throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
+ " type #0x" + Integer.toHexString(value.type) + " is not valid");
@@ -661,10 +579,13 @@
* @see #getDimensionPixelSize
*/
public int getDimensionPixelOffset(@DimenRes int id) throws NotFoundException {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
+ final ResourcesImpl impl = mResourcesImpl;
+ impl.getValue(id, value, true);
if (value.type == TypedValue.TYPE_DIMENSION) {
- return TypedValue.complexToDimensionPixelOffset(value.data, mMetrics);
+ return TypedValue.complexToDimensionPixelOffset(value.data,
+ impl.getDisplayMetrics());
}
throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
+ " type #0x" + Integer.toHexString(value.type) + " is not valid");
@@ -694,10 +615,12 @@
* @see #getDimensionPixelOffset
*/
public int getDimensionPixelSize(@DimenRes int id) throws NotFoundException {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
+ final ResourcesImpl impl = mResourcesImpl;
+ impl.getValue(id, value, true);
if (value.type == TypedValue.TYPE_DIMENSION) {
- return TypedValue.complexToDimensionPixelSize(value.data, mMetrics);
+ return TypedValue.complexToDimensionPixelSize(value.data, impl.getDisplayMetrics());
}
throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
+ " type #0x" + Integer.toHexString(value.type) + " is not valid");
@@ -724,8 +647,9 @@
* @throws NotFoundException Throws NotFoundException if the given ID does not exist.
*/
public float getFraction(@FractionRes int id, int base, int pbase) {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
+ mResourcesImpl.getValue(id, value, true);
if (value.type == TypedValue.TYPE_FRACTION) {
return TypedValue.complexToFraction(value.data, base, pbase);
}
@@ -769,7 +693,6 @@
* @deprecated Use {@link #getDrawable(int, Theme)} instead.
*/
@Deprecated
- @Nullable
public Drawable getDrawable(@DrawableRes int id) throws NotFoundException {
final Drawable d = getDrawable(id, null);
if (d != null && d.canApplyTheme()) {
@@ -794,12 +717,13 @@
* @throws NotFoundException Throws NotFoundException if the given ID does
* not exist.
*/
- @Nullable
public Drawable getDrawable(@DrawableRes int id, @Nullable Theme theme)
throws NotFoundException {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
- return loadDrawable(value, id, theme);
+ final ResourcesImpl impl = mResourcesImpl;
+ impl.getValue(id, value, true);
+ return impl.loadDrawable(this, value, id, theme, true);
} finally {
releaseTempTypedValue(value);
}
@@ -832,7 +756,6 @@
* @deprecated Use {@link #getDrawableForDensity(int, int, Theme)} instead.
*/
@Deprecated
- @Nullable
public Drawable getDrawableForDensity(@DrawableRes int id, int density)
throws NotFoundException {
return getDrawableForDensity(id, density, null);
@@ -852,16 +775,17 @@
* @throws NotFoundException Throws NotFoundException if the given ID does
* not exist.
*/
- @Nullable
public Drawable getDrawableForDensity(@DrawableRes int id, int density, @Nullable Theme theme) {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
- getValueForDensity(id, density, value, true);
+ final ResourcesImpl impl = mResourcesImpl;
+ impl.getValueForDensity(id, density, value, true);
// If the drawable's XML lives in our current density qualifier,
// it's okay to use a scaled version from the cache. Otherwise, we
// need to actually load the drawable from XML.
- final boolean useCache = value.density == mMetrics.densityDpi;
+ final DisplayMetrics metrics = impl.getDisplayMetrics();
+ final boolean useCache = value.density == metrics.densityDpi;
/*
* Pretend the requested density is actually the display density. If
@@ -872,18 +796,23 @@
*/
if (value.density > 0 && value.density != TypedValue.DENSITY_NONE) {
if (value.density == density) {
- value.density = mMetrics.densityDpi;
+ value.density = metrics.densityDpi;
} else {
- value.density = (value.density * mMetrics.densityDpi) / density;
+ value.density = (value.density * metrics.densityDpi) / density;
}
}
-
- return loadDrawable(value, id, theme, useCache);
+ return impl.loadDrawable(this, value, id, theme, useCache);
} finally {
releaseTempTypedValue(value);
}
}
+ @NonNull
+ Drawable loadDrawable(@NonNull TypedValue value, int id, @Nullable Theme theme)
+ throws NotFoundException {
+ return mResourcesImpl.loadDrawable(this, value, id, theme, true);
+ }
+
/**
* Return a movie object associated with the particular resource ID.
* @param id The desired resource identifier, as generated by the aapt
@@ -893,13 +822,12 @@
*
*/
public Movie getMovie(@RawRes int id) throws NotFoundException {
- InputStream is = openRawResource(id);
- Movie movie = Movie.decodeStream(is);
+ final InputStream is = openRawResource(id);
+ final Movie movie = Movie.decodeStream(is);
try {
is.close();
- }
- catch (java.io.IOException e) {
- // don't care, since the return value is valid
+ } catch (IOException e) {
+ // No one cares.
}
return movie;
}
@@ -943,8 +871,10 @@
*/
@ColorInt
public int getColor(@ColorRes int id, @Nullable Theme theme) throws NotFoundException {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
+ final ResourcesImpl impl = mResourcesImpl;
+ impl.getValue(id, value, true);
if (value.type >= TypedValue.TYPE_FIRST_INT
&& value.type <= TypedValue.TYPE_LAST_INT) {
return value.data;
@@ -953,7 +883,7 @@
+ " type #0x" + Integer.toHexString(value.type) + " is not valid");
}
- final ColorStateList csl = loadColorStateList(value, id, theme);
+ final ColorStateList csl = impl.loadColorStateList(this, value, id, theme);
return csl.getDefaultColor();
} finally {
releaseTempTypedValue(value);
@@ -1011,14 +941,27 @@
@Nullable
public ColorStateList getColorStateList(@ColorRes int id, @Nullable Theme theme)
throws NotFoundException {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
- return loadColorStateList(value, id, theme);
+ final ResourcesImpl impl = mResourcesImpl;
+ impl.getValue(id, value, true);
+ return impl.loadColorStateList(this, value, id, theme);
} finally {
releaseTempTypedValue(value);
}
}
+ @Nullable
+ ColorStateList loadColorStateList(@NonNull TypedValue value, int id, @Nullable Theme theme)
+ throws NotFoundException {
+ return mResourcesImpl.loadColorStateList(this, value, id, theme);
+ }
+
+ @Nullable
+ public ComplexColor loadComplexColor(@NonNull TypedValue value, int id, @Nullable Theme theme) {
+ return mResourcesImpl.loadComplexColor(this, value, id, theme);
+ }
+
/**
* Return a boolean associated with a particular resource ID. This can be
* used with any integral resource value, and will return true if it is
@@ -1033,8 +976,9 @@
* @return Returns the boolean value contained in the resource.
*/
public boolean getBoolean(@BoolRes int id) throws NotFoundException {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
+ mResourcesImpl.getValue(id, value, true);
if (value.type >= TypedValue.TYPE_FIRST_INT
&& value.type <= TypedValue.TYPE_LAST_INT) {
return value.data != 0;
@@ -1058,8 +1002,9 @@
* @return Returns the integer value contained in the resource.
*/
public int getInteger(@IntegerRes int id) throws NotFoundException {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
+ mResourcesImpl.getValue(id, value, true);
if (value.type >= TypedValue.TYPE_FIRST_INT
&& value.type <= TypedValue.TYPE_LAST_INT) {
return value.data;
@@ -1085,8 +1030,9 @@
* @hide Pending API council approval.
*/
public float getFloat(int id) {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
+ mResourcesImpl.getValue(id, value, true);
if (value.type == TypedValue.TYPE_FLOAT) {
return value.getFloat();
}
@@ -1194,20 +1140,6 @@
}
/**
- * Returns a TypedValue populated with data for the specified resource ID
- * that's suitable for temporary use. The obtained TypedValue should be
- * released using {@link #releaseTempTypedValue(TypedValue)}.
- *
- * @param id the resource ID for which data should be obtained
- * @return a populated typed value suitable for temporary use
- */
- private TypedValue obtainTempTypedValue(@AnyRes int id) {
- final TypedValue value = obtainTempTypedValue();
- getValue(id, value, true);
- return value;
- }
-
- /**
* Returns a TypedValue suitable for temporary use. The obtained TypedValue
* should be released using {@link #releaseTempTypedValue(TypedValue)}.
*
@@ -1256,17 +1188,7 @@
*/
public InputStream openRawResource(@RawRes int id, TypedValue value)
throws NotFoundException {
- getValue(id, value, true);
-
- try {
- return mAssets.openNonAsset(value.assetCookie, value.string.toString(),
- AssetManager.ACCESS_STREAMING);
- } catch (Exception e) {
- NotFoundException rnf = new NotFoundException("File " + value.string.toString() +
- " from drawable resource ID #0x" + Integer.toHexString(id));
- rnf.initCause(e);
- throw rnf;
- }
+ return mResourcesImpl.openRawResource(id, value);
}
/**
@@ -1292,12 +1214,9 @@
*/
public AssetFileDescriptor openRawResourceFd(@RawRes int id)
throws NotFoundException {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
- return mAssets.openNonAssetFd(value.assetCookie, value.string.toString());
- } catch (Exception e) {
- throw new NotFoundException("File " + value.string.toString() + " from drawable "
- + "resource ID #0x" + Integer.toHexString(id), e);
+ return mResourcesImpl.openRawResourceFd(id, value);
} finally {
releaseTempTypedValue(value);
}
@@ -1320,12 +1239,7 @@
*/
public void getValue(@AnyRes int id, TypedValue outValue, boolean resolveRefs)
throws NotFoundException {
- boolean found = mAssets.getResourceValue(id, 0, outValue, resolveRefs);
- if (found) {
- return;
- }
- throw new NotFoundException("Resource ID #0x"
- + Integer.toHexString(id));
+ mResourcesImpl.getValue(id, outValue, resolveRefs);
}
/**
@@ -1343,11 +1257,7 @@
*/
public void getValueForDensity(@AnyRes int id, int density, TypedValue outValue,
boolean resolveRefs) throws NotFoundException {
- boolean found = mAssets.getResourceValue(id, density, outValue, resolveRefs);
- if (found) {
- return;
- }
- throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id));
+ mResourcesImpl.getValueForDensity(id, density, outValue, resolveRefs);
}
/**
@@ -1372,12 +1282,7 @@
*/
public void getValue(String name, TypedValue outValue, boolean resolveRefs)
throws NotFoundException {
- int id = getIdentifier(name, "string", null);
- if (id != 0) {
- getValue(id, outValue, resolveRefs);
- return;
- }
- throw new NotFoundException("String resource name " + name);
+ mResourcesImpl.getValue(name, outValue, resolveRefs);
}
/**
@@ -1396,6 +1301,15 @@
* retrieve XML attributes with style and theme information applied.
*/
public final class Theme {
+ private ResourcesImpl.ThemeImpl mThemeImpl;
+
+ private Theme() {
+ }
+
+ void setImpl(ResourcesImpl.ThemeImpl impl) {
+ mThemeImpl = impl;
+ }
+
/**
* Place new attribute values into the theme. The style resource
* specified by <var>resid</var> will be retrieved from this Theme's
@@ -1414,12 +1328,7 @@
* if not already defined in the theme.
*/
public void applyStyle(int resId, boolean force) {
- synchronized (mKey) {
- AssetManager.applyThemeStyle(mTheme, resId, force);
-
- mThemeResId = resId;
- mKey.append(resId, force);
- }
+ mThemeImpl.applyStyle(resId, force);
}
/**
@@ -1432,14 +1341,7 @@
* @param other The existing Theme to copy from.
*/
public void setTo(Theme other) {
- synchronized (mKey) {
- synchronized (other.mKey) {
- AssetManager.copyTheme(mTheme, other.mTheme);
-
- mThemeResId = other.mThemeResId;
- mKey.setTo(other.getKey());
- }
- }
+ mThemeImpl.setTo(other.mThemeImpl);
}
/**
@@ -1462,13 +1364,7 @@
* @see #obtainStyledAttributes(AttributeSet, int[], int, int)
*/
public TypedArray obtainStyledAttributes(@StyleableRes int[] attrs) {
- synchronized (mKey) {
- final int len = attrs.length;
- final TypedArray array = TypedArray.obtain(Resources.this, len);
- array.mTheme = this;
- AssetManager.applyStyle(mTheme, 0, 0, 0, attrs, array.mData, array.mIndices);
- return array;
- }
+ return mThemeImpl.obtainStyledAttributes(this, null, attrs, 0, 0);
}
/**
@@ -1493,13 +1389,7 @@
*/
public TypedArray obtainStyledAttributes(@StyleRes int resId, @StyleableRes int[] attrs)
throws NotFoundException {
- synchronized (mKey) {
- final int len = attrs.length;
- final TypedArray array = TypedArray.obtain(Resources.this, len);
- array.mTheme = this;
- AssetManager.applyStyle(mTheme, 0, resId, 0, attrs, array.mData, array.mIndices);
- return array;
- }
+ return mThemeImpl.obtainStyledAttributes(this, null, attrs, 0, resId);
}
/**
@@ -1552,23 +1442,7 @@
*/
public TypedArray obtainStyledAttributes(AttributeSet set,
@StyleableRes int[] attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
- synchronized (mKey) {
- final int len = attrs.length;
- final TypedArray array = TypedArray.obtain(Resources.this, len);
-
- // XXX note that for now we only work with compiled XML files.
- // To support generic XML files we will need to manually parse
- // out the attributes from the XML file (applying type information
- // contained in the resources and such).
- final XmlBlock.Parser parser = (XmlBlock.Parser) set;
- AssetManager.applyStyle(mTheme, defStyleAttr, defStyleRes,
- parser != null ? parser.mParseState : 0,
- attrs, array.mData, array.mIndices);
- array.mTheme = this;
- array.mXml = parser;
-
- return array;
- }
+ return mThemeImpl.obtainStyledAttributes(this, set, attrs, defStyleAttr, defStyleRes);
}
/**
@@ -1587,20 +1461,7 @@
*/
@NonNull
public TypedArray resolveAttributes(@NonNull int[] values, @NonNull int[] attrs) {
- synchronized (mKey) {
- final int len = attrs.length;
- if (values == null || len != values.length) {
- throw new IllegalArgumentException(
- "Base attribute values must the same length as attrs");
- }
-
- final TypedArray array = TypedArray.obtain(Resources.this, len);
- AssetManager.resolveAttrs(mTheme, 0, 0, values, attrs, array.mData, array.mIndices);
- array.mTheme = this;
- array.mXml = null;
-
- return array;
- }
+ return mThemeImpl.resolveAttributes(this, values, attrs);
}
/**
@@ -1621,9 +1482,7 @@
* <var>outValue</var> is valid, else false.
*/
public boolean resolveAttribute(int resid, TypedValue outValue, boolean resolveRefs) {
- synchronized (mKey) {
- return mAssets.getThemeValue(mTheme, resid, outValue, resolveRefs);
- }
+ return mThemeImpl.resolveAttribute(resid, outValue, resolveRefs);
}
/**
@@ -1633,7 +1492,7 @@
* @hide
*/
public int[] getAllAttributes() {
- return mAssets.getStyleAttributes(getAppliedStyleResId());
+ return mThemeImpl.getAllAttributes();
}
/**
@@ -1669,11 +1528,7 @@
* @see ActivityInfo
*/
public int getChangingConfigurations() {
- synchronized (mKey) {
- final int nativeChangingConfig =
- AssetManager.getThemeChangingConfigurations(mTheme);
- return ActivityInfo.activityInfoConfigNativeToJava(nativeChangingConfig);
- }
+ return mThemeImpl.getChangingConfigurations();
}
/**
@@ -1684,43 +1539,23 @@
* @param prefix Text to prefix each line printed.
*/
public void dump(int priority, String tag, String prefix) {
- synchronized (mKey) {
- AssetManager.dumpTheme(mTheme, priority, tag, prefix);
- }
+ mThemeImpl.dump(priority, tag, prefix);
}
- @Override
- protected void finalize() throws Throwable {
- super.finalize();
- mAssets.releaseTheme(mTheme);
- }
-
- /*package*/ Theme() {
- mAssets = Resources.this.mAssets;
- mTheme = mAssets.createTheme();
- }
-
- /** Unique key for the series of styles applied to this theme. */
- private final ThemeKey mKey = new ThemeKey();
-
- @SuppressWarnings("hiding")
- private final AssetManager mAssets;
- private final long mTheme;
-
- /** Resource identifier for the theme. */
- private int mThemeResId = 0;
-
// Needed by layoutlib.
/*package*/ long getNativeTheme() {
- return mTheme;
+ return mThemeImpl.getNativeTheme();
}
/*package*/ int getAppliedStyleResId() {
- return mThemeResId;
+ return mThemeImpl.getAppliedStyleResId();
}
- /*package*/ ThemeKey getKey() {
- return mKey;
+ /**
+ * @hide
+ */
+ public ThemeKey getKey() {
+ return mThemeImpl.getKey();
}
private String getResourceNameFromHexString(String hexString) {
@@ -1728,7 +1563,7 @@
}
/**
- * Parses {@link #mKey} and returns a String array that holds pairs of
+ * Parses {@link #getKey()} and returns a String array that holds pairs of
* adjacent Theme data: resource name followed by whether or not it was
* forced, as specified by {@link #applyStyle(int, boolean)}.
*
@@ -1736,21 +1571,7 @@
*/
@ViewDebug.ExportedProperty(category = "theme", hasAdjacentMapping = true)
public String[] getTheme() {
- synchronized (mKey) {
- final int N = mKey.mCount;
- final String[] themes = new String[N * 2];
- for (int i = 0, j = N - 1; i < themes.length; i += 2, --j) {
- final int resId = mKey.mResId[j];
- final boolean forced = mKey.mForce[j];
- try {
- themes[i] = getResourceName(resId);
- } catch (NotFoundException e) {
- themes[i] = Integer.toHexString(i);
- }
- themes[i + 1] = forced ? "forced" : "not forced";
- }
- return themes;
- }
+ return mThemeImpl.getTheme();
}
/** @hide */
@@ -1771,16 +1592,7 @@
* @hide
*/
public void rebase() {
- synchronized (mKey) {
- AssetManager.clearTheme(mTheme);
-
- // Reapply the same styles in the same order.
- for (int i = 0; i < mKey.mCount; i++) {
- final int resId = mKey.mResId[i];
- final boolean force = mKey.mForce[i];
- AssetManager.applyThemeStyle(mTheme, resId, force);
- }
- }
+ mThemeImpl.rebase();
}
}
@@ -1869,7 +1681,9 @@
* @return Theme The newly created Theme container.
*/
public final Theme newTheme() {
- return new Theme();
+ Theme theme = new Theme();
+ theme.setImpl(mResourcesImpl.newThemeImpl());
+ return theme;
}
/**
@@ -1893,7 +1707,7 @@
// out the attributes from the XML file (applying type information
// contained in the resources and such).
XmlBlock.Parser parser = (XmlBlock.Parser)set;
- mAssets.retrieveAttributes(parser.mParseState, attrs,
+ mResourcesImpl.getAssets().retrieveAttributes(parser.mParseState, attrs,
array.mData, array.mIndices);
array.mXml = parser;
@@ -1904,151 +1718,16 @@
/**
* Store the newly updated configuration.
*/
- public void updateConfiguration(Configuration config,
- DisplayMetrics metrics) {
+ public void updateConfiguration(Configuration config, DisplayMetrics metrics) {
updateConfiguration(config, metrics, null);
}
/**
* @hide
*/
- public void updateConfiguration(Configuration config,
- DisplayMetrics metrics, CompatibilityInfo compat) {
- synchronized (mAccessLock) {
- if (false) {
- Slog.i(TAG, "**** Updating config of " + this + ": old config is "
- + mConfiguration + " old compat is " + mCompatibilityInfo);
- Slog.i(TAG, "**** Updating config of " + this + ": new config is "
- + config + " new compat is " + compat);
- }
- if (compat != null) {
- mCompatibilityInfo = compat;
- }
- if (metrics != null) {
- mMetrics.setTo(metrics);
- }
- // NOTE: We should re-arrange this code to create a Display
- // with the CompatibilityInfo that is used everywhere we deal
- // with the display in relation to this app, rather than
- // doing the conversion here. This impl should be okay because
- // we make sure to return a compatible display in the places
- // where there are public APIs to retrieve the display... but
- // it would be cleaner and more maintainble to just be
- // consistently dealing with a compatible display everywhere in
- // the framework.
- mCompatibilityInfo.applyToDisplayMetrics(mMetrics);
-
- final int configChanges = calcConfigChanges(config);
-
- LocaleList locales = mConfiguration.getLocales();
- if (locales.isEmpty()) {
- locales = LocaleList.getAdjustedDefault();
- mConfiguration.setLocales(locales);
- }
- if (mConfiguration.densityDpi != Configuration.DENSITY_DPI_UNDEFINED) {
- mMetrics.densityDpi = mConfiguration.densityDpi;
- mMetrics.density = mConfiguration.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
- }
- mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
-
- final int width, height;
- if (mMetrics.widthPixels >= mMetrics.heightPixels) {
- width = mMetrics.widthPixels;
- height = mMetrics.heightPixels;
- } else {
- //noinspection SuspiciousNameCombination
- width = mMetrics.heightPixels;
- //noinspection SuspiciousNameCombination
- height = mMetrics.widthPixels;
- }
-
- final int keyboardHidden;
- if (mConfiguration.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO
- && mConfiguration.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) {
- keyboardHidden = Configuration.KEYBOARDHIDDEN_SOFT;
- } else {
- keyboardHidden = mConfiguration.keyboardHidden;
- }
-
- mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc,
- adjustLanguageTag(locales.get(0).toLanguageTag()),
- mConfiguration.orientation,
- mConfiguration.touchscreen,
- mConfiguration.densityDpi, mConfiguration.keyboard,
- keyboardHidden, mConfiguration.navigation, width, height,
- mConfiguration.smallestScreenWidthDp,
- mConfiguration.screenWidthDp, mConfiguration.screenHeightDp,
- mConfiguration.screenLayout, mConfiguration.uiMode,
- Build.VERSION.RESOURCES_SDK_INT);
-
- if (DEBUG_CONFIG) {
- Slog.i(TAG, "**** Updating config of " + this + ": final config is "
- + mConfiguration + " final compat is " + mCompatibilityInfo);
- }
-
- mDrawableCache.onConfigurationChange(configChanges);
- mColorDrawableCache.onConfigurationChange(configChanges);
- mComplexColorCache.onConfigurationChange(configChanges);
- mAnimatorCache.onConfigurationChange(configChanges);
- mStateListAnimatorCache.onConfigurationChange(configChanges);
-
- flushLayoutCache();
- }
- synchronized (sSync) {
- if (mPluralRule != null) {
- mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().get(0));
- }
- }
- }
-
- /**
- * Called by ConfigurationBoundResourceCacheTest via reflection.
- */
- private int calcConfigChanges(Configuration config) {
- int configChanges = 0xfffffff;
- if (config != null) {
- mTmpConfig.setTo(config);
- int density = config.densityDpi;
- if (density == Configuration.DENSITY_DPI_UNDEFINED) {
- density = mMetrics.noncompatDensityDpi;
- }
-
- mCompatibilityInfo.applyToConfiguration(density, mTmpConfig);
-
- if (mTmpConfig.getLocales().isEmpty()) {
- mTmpConfig.setLocales(LocaleList.getDefault());
- }
- configChanges = mConfiguration.updateFrom(mTmpConfig);
- configChanges = ActivityInfo.activityInfoConfigToNative(configChanges);
- }
- return configChanges;
- }
-
- /**
- * {@code Locale.toLanguageTag} will transform the obsolete (and deprecated)
- * language codes "in", "ji" and "iw" to "id", "yi" and "he" respectively.
- *
- * All released versions of android prior to "L" used the deprecated language
- * tags, so we will need to support them for backwards compatibility.
- *
- * Note that this conversion needs to take place *after* the call to
- * {@code toLanguageTag} because that will convert all the deprecated codes to
- * the new ones, even if they're set manually.
- */
- private static String adjustLanguageTag(String languageTag) {
- final int separator = languageTag.indexOf('-');
- final String language;
- final String remainder;
-
- if (separator == -1) {
- language = languageTag;
- remainder = "";
- } else {
- language = languageTag.substring(0, separator);
- remainder = languageTag.substring(separator);
- }
-
- return Locale.adjustLanguageCode(language) + remainder;
+ public void updateConfiguration(Configuration config, DisplayMetrics metrics,
+ CompatibilityInfo compat) {
+ mResourcesImpl.updateConfiguration(config, metrics, compat);
}
/**
@@ -2073,9 +1752,7 @@
* @return The resource's current display metrics.
*/
public DisplayMetrics getDisplayMetrics() {
- if (DEBUG_CONFIG) Slog.v(TAG, "Returning DisplayMetrics: " + mMetrics.widthPixels
- + "x" + mMetrics.heightPixels + " " + mMetrics.density);
- return mMetrics;
+ return mResourcesImpl.getDisplayMetrics();
}
/**
@@ -2085,13 +1762,13 @@
* @return The resource's current configuration.
*/
public Configuration getConfiguration() {
- return mConfiguration;
+ return mResourcesImpl.getConfiguration();
}
/** @hide */
public Configuration[] getSizeConfigurations() {
- return mAssets.getSizeConfigurations();
- };
+ return mResourcesImpl.getSizeConfigurations();
+ }
/**
* Return the compatibility mode information for the application.
@@ -2101,7 +1778,7 @@
* @hide
*/
public CompatibilityInfo getCompatibilityInfo() {
- return mCompatibilityInfo;
+ return mResourcesImpl.getCompatibilityInfo();
}
/**
@@ -2110,8 +1787,7 @@
*/
public void setCompatibilityInfo(CompatibilityInfo ci) {
if (ci != null) {
- mCompatibilityInfo = ci;
- updateConfiguration(mConfiguration, mMetrics);
+ mResourcesImpl.updateConfiguration(null, null, ci);
}
}
@@ -2136,15 +1812,7 @@
* resource was found. (0 is not a valid resource ID.)
*/
public int getIdentifier(String name, String defType, String defPackage) {
- if (name == null) {
- throw new NullPointerException("name is null");
- }
- try {
- return Integer.parseInt(name);
- } catch (Exception e) {
- // Ignore
- }
- return mAssets.getResourceIdentifier(name, defType, defPackage);
+ return mResourcesImpl.getIdentifier(name, defType, defPackage);
}
/**
@@ -2171,10 +1839,7 @@
* @see #getResourceEntryName
*/
public String getResourceName(@AnyRes int resid) throws NotFoundException {
- String str = mAssets.getResourceName(resid);
- if (str != null) return str;
- throw new NotFoundException("Unable to find resource ID #0x"
- + Integer.toHexString(resid));
+ return mResourcesImpl.getResourceName(resid);
}
/**
@@ -2190,10 +1855,7 @@
* @see #getResourceName
*/
public String getResourcePackageName(@AnyRes int resid) throws NotFoundException {
- String str = mAssets.getResourcePackageName(resid);
- if (str != null) return str;
- throw new NotFoundException("Unable to find resource ID #0x"
- + Integer.toHexString(resid));
+ return mResourcesImpl.getResourcePackageName(resid);
}
/**
@@ -2209,10 +1871,7 @@
* @see #getResourceName
*/
public String getResourceTypeName(@AnyRes int resid) throws NotFoundException {
- String str = mAssets.getResourceTypeName(resid);
- if (str != null) return str;
- throw new NotFoundException("Unable to find resource ID #0x"
- + Integer.toHexString(resid));
+ return mResourcesImpl.getResourceTypeName(resid);
}
/**
@@ -2228,10 +1887,7 @@
* @see #getResourceName
*/
public String getResourceEntryName(@AnyRes int resid) throws NotFoundException {
- String str = mAssets.getResourceEntryName(resid);
- if (str != null) return str;
- throw new NotFoundException("Unable to find resource ID #0x"
- + Integer.toHexString(resid));
+ return mResourcesImpl.getResourceEntryName(resid);
}
/**
@@ -2334,7 +1990,7 @@
* Retrieve underlying AssetManager storage for these resources.
*/
public final AssetManager getAssets() {
- return mAssets;
+ return mResourcesImpl.getAssets();
}
/**
@@ -2343,19 +1999,7 @@
* tools.
*/
public final void flushLayoutCache() {
- final String[] cachedXmlBlockFiles = mCachedXmlBlockFiles;
- final XmlBlock[] cachedXmlBlocks = mCachedXmlBlocks;
- synchronized (cachedXmlBlockFiles) {
- final int num = cachedXmlBlockFiles.length;
- for (int i = 0; i < num; i++) {
- final XmlBlock oldBlock = cachedXmlBlocks[i];
- if (oldBlock != null) {
- oldBlock.close();
- }
- cachedXmlBlockFiles[i] = null;
- cachedXmlBlocks[i] = null;
- }
- }
+ mResourcesImpl.flushLayoutCache();
}
/**
@@ -2364,15 +2008,7 @@
* {@hide}
*/
public final void startPreloading() {
- synchronized (sSync) {
- if (sPreloaded) {
- throw new IllegalStateException("Resources already preloaded");
- }
- sPreloaded = true;
- mPreloading = true;
- mConfiguration.densityDpi = DisplayMetrics.DENSITY_DEVICE;
- updateConfiguration(null, null);
- }
+ mResourcesImpl.startPreloading();
}
/**
@@ -2380,441 +2016,14 @@
* to normal Resources operation.
*/
public final void finishPreloading() {
- if (mPreloading) {
- mPreloading = false;
- flushLayoutCache();
- }
+ mResourcesImpl.finishPreloading();
}
/**
* @hide
*/
public LongSparseArray<ConstantState> getPreloadedDrawables() {
- return sPreloadedDrawables[0];
- }
-
- private boolean verifyPreloadConfig(int changingConfigurations, int allowVarying,
- int resourceId, String name) {
- // We allow preloading of resources even if they vary by font scale (which
- // doesn't impact resource selection) or density (which we handle specially by
- // simply turning off all preloading), as well as any other configs specified
- // by the caller.
- if (((changingConfigurations&~(ActivityInfo.CONFIG_FONT_SCALE |
- ActivityInfo.CONFIG_DENSITY)) & ~allowVarying) != 0) {
- String resName;
- try {
- resName = getResourceName(resourceId);
- } catch (NotFoundException e) {
- resName = "?";
- }
- // This should never happen in production, so we should log a
- // warning even if we're not debugging.
- Log.w(TAG, "Preloaded " + name + " resource #0x"
- + Integer.toHexString(resourceId)
- + " (" + resName + ") that varies with configuration!!");
- return false;
- }
- if (TRACE_FOR_PRELOAD) {
- String resName;
- try {
- resName = getResourceName(resourceId);
- } catch (NotFoundException e) {
- resName = "?";
- }
- Log.w(TAG, "Preloading " + name + " resource #0x"
- + Integer.toHexString(resourceId)
- + " (" + resName + ")");
- }
- return true;
- }
-
- @Nullable
- Drawable loadDrawable(TypedValue value, int id, Theme theme) throws NotFoundException {
- return loadDrawable(value, id, theme, true);
- }
-
- @Nullable
- Drawable loadDrawable(TypedValue value, int id, Theme theme, boolean useCache)
- throws NotFoundException {
- try {
- if (TRACE_FOR_PRELOAD) {
- // Log only framework resources
- if ((id >>> 24) == 0x1) {
- final String name = getResourceName(id);
- if (name != null) {
- Log.d("PreloadDrawable", name);
- }
- }
- }
-
- final boolean isColorDrawable;
- final DrawableCache caches;
- final long key;
- if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
- && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
- isColorDrawable = true;
- caches = mColorDrawableCache;
- key = value.data;
- } else {
- isColorDrawable = false;
- caches = mDrawableCache;
- key = (((long) value.assetCookie) << 32) | value.data;
- }
-
- // First, check whether we have a cached version of this drawable
- // that was inflated against the specified theme. Skip the cache if
- // we're currently preloading or we're not using the cache.
- if (!mPreloading && useCache) {
- final Drawable cachedDrawable = caches.getInstance(key, theme);
- if (cachedDrawable != null) {
- return cachedDrawable;
- }
- }
-
- // Next, check preloaded drawables. Preloaded drawables may contain
- // unresolved theme attributes.
- final ConstantState cs;
- if (isColorDrawable) {
- cs = sPreloadedColorDrawables.get(key);
- } else {
- cs = sPreloadedDrawables[mConfiguration.getLayoutDirection()].get(key);
- }
-
- Drawable dr;
- if (cs != null) {
- dr = cs.newDrawable(this);
- } else if (isColorDrawable) {
- dr = new ColorDrawable(value.data);
- } else {
- dr = loadDrawableForCookie(value, id, null);
- }
-
- // Determine if the drawable has unresolved theme attributes. If it
- // does, we'll need to apply a theme and store it in a theme-specific
- // cache.
- final boolean canApplyTheme = dr != null && dr.canApplyTheme();
- if (canApplyTheme && theme != null) {
- dr = dr.mutate();
- dr.applyTheme(theme);
- dr.clearMutated();
- }
-
- // If we were able to obtain a drawable, store it in the appropriate
- // cache: preload, not themed, null theme, or theme-specific. Don't
- // pollute the cache with drawables loaded from a foreign density.
- if (dr != null && useCache) {
- dr.setChangingConfigurations(value.changingConfigurations);
- cacheDrawable(value, isColorDrawable, caches, theme, canApplyTheme, key, dr);
- }
-
- return dr;
- } catch (Exception e) {
- String name;
- try {
- name = getResourceName(id);
- } catch (NotFoundException e2) {
- name = "(missing name)";
- }
-
- // The target drawable might fail to load for any number of
- // reasons, but we always want to include the resource name.
- // Since the client already expects this method to throw a
- // NotFoundException, just throw one of those.
- final NotFoundException nfe = new NotFoundException("Drawable " + name
- + " with resource ID #0x" + Integer.toHexString(id), e);
- nfe.setStackTrace(new StackTraceElement[0]);
- throw nfe;
- }
- }
-
- private void cacheDrawable(TypedValue value, boolean isColorDrawable, DrawableCache caches,
- Theme theme, boolean usesTheme, long key, Drawable dr) {
- final ConstantState cs = dr.getConstantState();
- if (cs == null) {
- return;
- }
-
- if (mPreloading) {
- final int changingConfigs = cs.getChangingConfigurations();
- if (isColorDrawable) {
- if (verifyPreloadConfig(changingConfigs, 0, value.resourceId, "drawable")) {
- sPreloadedColorDrawables.put(key, cs);
- }
- } else {
- if (verifyPreloadConfig(
- changingConfigs, LAYOUT_DIR_CONFIG, value.resourceId, "drawable")) {
- if ((changingConfigs & LAYOUT_DIR_CONFIG) == 0) {
- // If this resource does not vary based on layout direction,
- // we can put it in all of the preload maps.
- sPreloadedDrawables[0].put(key, cs);
- sPreloadedDrawables[1].put(key, cs);
- } else {
- // Otherwise, only in the layout dir we loaded it for.
- sPreloadedDrawables[mConfiguration.getLayoutDirection()].put(key, cs);
- }
- }
- }
- } else {
- synchronized (mAccessLock) {
- caches.put(key, theme, cs, usesTheme);
- }
- }
- }
-
- /**
- * Loads a drawable from XML or resources stream.
- */
- private Drawable loadDrawableForCookie(TypedValue value, int id, Theme theme) {
- if (value.string == null) {
- throw new NotFoundException("Resource \"" + getResourceName(id) + "\" ("
- + Integer.toHexString(id) + ") is not a Drawable (color or path): " + value);
- }
-
- final String file = value.string.toString();
-
- if (TRACE_FOR_MISS_PRELOAD) {
- // Log only framework resources
- if ((id >>> 24) == 0x1) {
- final String name = getResourceName(id);
- if (name != null) {
- Log.d(TAG, "Loading framework drawable #" + Integer.toHexString(id)
- + ": " + name + " at " + file);
- }
- }
- }
-
- if (DEBUG_LOAD) {
- Log.v(TAG, "Loading drawable for cookie " + value.assetCookie + ": " + file);
- }
-
- final Drawable dr;
-
- Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
- try {
- if (file.endsWith(".xml")) {
- final XmlResourceParser rp = loadXmlResourceParser(
- file, id, value.assetCookie, "drawable");
- dr = Drawable.createFromXml(this, rp, theme);
- rp.close();
- } else {
- final InputStream is = mAssets.openNonAsset(
- value.assetCookie, file, AssetManager.ACCESS_STREAMING);
- dr = Drawable.createFromResourceStream(this, value, is, file, null);
- is.close();
- }
- } catch (Exception e) {
- Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
- final NotFoundException rnf = new NotFoundException(
- "File " + file + " from drawable resource ID #0x" + Integer.toHexString(id));
- rnf.initCause(e);
- throw rnf;
- }
- Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
-
- return dr;
- }
-
- /**
- * Given the value and id, we can get the XML filename as in value.data, based on that, we
- * first try to load CSL from the cache. If not found, try to get from the constant state.
- * Last, parse the XML and generate the CSL.
- */
- private ComplexColor loadComplexColorFromName(Theme theme, TypedValue value, int id) {
- final long key = (((long) value.assetCookie) << 32) | value.data;
- final ConfigurationBoundResourceCache<ComplexColor> cache = mComplexColorCache;
- ComplexColor complexColor = cache.getInstance(key, theme);
- if (complexColor != null) {
- return complexColor;
- }
-
- final android.content.res.ConstantState<ComplexColor> factory =
- sPreloadedComplexColors.get(key);
-
- if (factory != null) {
- complexColor = factory.newInstance(this, theme);
- }
- if (complexColor == null) {
- complexColor = loadComplexColorForCookie(value, id, theme);
- }
-
- if (complexColor != null) {
- if (mPreloading) {
- if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
- "color")) {
- sPreloadedComplexColors.put(key, complexColor.getConstantState());
- }
- } else {
- cache.put(key, theme, complexColor.getConstantState());
- }
- }
- return complexColor;
- }
-
- @Nullable
- public ComplexColor loadComplexColor(@NonNull TypedValue value, int id, Theme theme) {
- if (TRACE_FOR_PRELOAD) {
- // Log only framework resources
- if ((id >>> 24) == 0x1) {
- final String name = getResourceName(id);
- if (name != null) android.util.Log.d("loadComplexColor", name);
- }
- }
-
- final long key = (((long) value.assetCookie) << 32) | value.data;
-
- // Handle inline color definitions.
- if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
- && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
- return getColorStateListFromInt(value, key);
- }
-
- final String file = value.string.toString();
-
- ComplexColor complexColor;
- if (file.endsWith(".xml")) {
- try {
- complexColor = loadComplexColorFromName(theme, value, id);
- } catch (Exception e) {
- final NotFoundException rnf = new NotFoundException(
- "File " + file + " from complex color resource ID #0x"
- + Integer.toHexString(id));
- rnf.initCause(e);
- throw rnf;
- }
- } else {
- throw new NotFoundException(
- "File " + file + " from drawable resource ID #0x"
- + Integer.toHexString(id) + ": .xml extension required");
- }
-
- return complexColor;
- }
-
- @Nullable
- ColorStateList loadColorStateList(TypedValue value, int id, Theme theme)
- throws NotFoundException {
- if (TRACE_FOR_PRELOAD) {
- // Log only framework resources
- if ((id >>> 24) == 0x1) {
- final String name = getResourceName(id);
- if (name != null) android.util.Log.d("PreloadColorStateList", name);
- }
- }
-
- final long key = (((long) value.assetCookie) << 32) | value.data;
-
- // Handle inline color definitions.
- if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
- && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
- return getColorStateListFromInt(value, key);
- }
-
- ComplexColor complexColor = loadComplexColorFromName(theme, value, id);
- if (complexColor != null && complexColor instanceof ColorStateList) {
- return (ColorStateList) complexColor;
- }
-
- throw new NotFoundException(
- "Can't find ColorStateList from drawable resource ID #0x"
- + Integer.toHexString(id));
- }
-
- @NonNull
- private ColorStateList getColorStateListFromInt(@NonNull TypedValue value, long key) {
- ColorStateList csl;
- final android.content.res.ConstantState<ComplexColor> factory =
- sPreloadedComplexColors.get(key);
- if (factory != null) {
- return (ColorStateList) factory.newInstance();
- }
-
- csl = ColorStateList.valueOf(value.data);
-
- if (mPreloading) {
- if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
- "color")) {
- sPreloadedComplexColors.put(key, csl.getConstantState());
- }
- }
-
- return csl;
- }
-
- /**
- * Load a ComplexColor based on the XML file content. The result can be a GradientColor or
- * ColorStateList. Note that pure color will be wrapped into a ColorStateList.
- *
- * We deferred the parser creation to this function b/c we need to differentiate b/t gradient
- * and selector tag.
- *
- * @return a ComplexColor (GradientColor or ColorStateList) based on the XML file content.
- */
- @Nullable
- private ComplexColor loadComplexColorForCookie(TypedValue value, int id, Theme theme) {
- if (value.string == null) {
- throw new UnsupportedOperationException(
- "Can't convert to ComplexColor: type=0x" + value.type);
- }
-
- final String file = value.string.toString();
-
- if (TRACE_FOR_MISS_PRELOAD) {
- // Log only framework resources
- if ((id >>> 24) == 0x1) {
- final String name = getResourceName(id);
- if (name != null) {
- Log.d(TAG, "Loading framework ComplexColor #" + Integer.toHexString(id)
- + ": " + name + " at " + file);
- }
- }
- }
-
- if (DEBUG_LOAD) {
- Log.v(TAG, "Loading ComplexColor for cookie " + value.assetCookie + ": " + file);
- }
-
- ComplexColor complexColor = null;
-
- Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
- if (file.endsWith(".xml")) {
- try {
- final XmlResourceParser parser = loadXmlResourceParser(
- file, id, value.assetCookie, "ComplexColor");
-
- final AttributeSet attrs = Xml.asAttributeSet(parser);
- int type;
- while ((type = parser.next()) != XmlPullParser.START_TAG
- && type != XmlPullParser.END_DOCUMENT) {
- // Seek parser to start tag.
- }
- if (type != XmlPullParser.START_TAG) {
- throw new XmlPullParserException("No start tag found");
- }
-
- final String name = parser.getName();
- if (name.equals("gradient")) {
- complexColor = GradientColor.createFromXmlInner(this, parser, attrs, theme);
- } else if (name.equals("selector")) {
- complexColor = ColorStateList.createFromXmlInner(this, parser, attrs, theme);
- }
- parser.close();
- } catch (Exception e) {
- Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
- final NotFoundException rnf = new NotFoundException(
- "File " + file + " from ComplexColor resource ID #0x"
- + Integer.toHexString(id));
- rnf.initCause(e);
- throw rnf;
- }
- } else {
- Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
- throw new NotFoundException(
- "File " + file + " from drawable resource ID #0x"
- + Integer.toHexString(id) + ": .xml extension required");
- }
- Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
-
- return complexColor;
+ return mResourcesImpl.getPreloadedDrawables();
}
/**
@@ -2828,10 +2037,12 @@
@NonNull
XmlResourceParser loadXmlResourceParser(@AnyRes int id, @NonNull String type)
throws NotFoundException {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
+ final ResourcesImpl impl = mResourcesImpl;
+ impl.getValue(id, value, true);
if (value.type == TypedValue.TYPE_STRING) {
- return loadXmlResourceParser(value.string.toString(), id,
+ return impl.loadXmlResourceParser(value.string.toString(), id,
value.assetCookie, type);
}
throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
@@ -2852,47 +2063,9 @@
* @throws NotFoundException if the file could not be loaded
*/
@NonNull
- XmlResourceParser loadXmlResourceParser(@NonNull String file, @AnyRes int id,
- int assetCookie, @NonNull String type) throws NotFoundException {
- if (id != 0) {
- try {
- final String[] cachedXmlBlockFiles = mCachedXmlBlockFiles;
- final XmlBlock[] cachedXmlBlocks = mCachedXmlBlocks;
- synchronized (cachedXmlBlockFiles) {
- // First see if this block is in our cache.
- final int num = cachedXmlBlockFiles.length;
- for (int i = 0; i < num; i++) {
- if (cachedXmlBlockFiles[i] != null
- && cachedXmlBlockFiles[i].equals(file)) {
- return cachedXmlBlocks[i].newParser();
- }
- }
-
- // Not in the cache, create a new block and put it at
- // the next slot in the cache.
- final XmlBlock block = mAssets.openXmlBlockAsset(assetCookie, file);
- if (block != null) {
- final int pos = (mLastCachedXmlBlockIndex + 1) % num;
- mLastCachedXmlBlockIndex = pos;
- final XmlBlock oldBlock = cachedXmlBlocks[pos];
- if (oldBlock != null) {
- oldBlock.close();
- }
- cachedXmlBlockFiles[pos] = file;
- cachedXmlBlocks[pos] = block;
- return block.newParser();
- }
- }
- } catch (Exception e) {
- final NotFoundException rnf = new NotFoundException("File " + file
- + " from xml type " + type + " resource ID #0x" + Integer.toHexString(id));
- rnf.initCause(e);
- throw rnf;
- }
- }
-
- throw new NotFoundException("File " + file + " from xml type " + type + " resource ID #0x"
- + Integer.toHexString(id));
+ XmlResourceParser loadXmlResourceParser(String file, int id, int assetCookie,
+ String type) throws NotFoundException {
+ return mResourcesImpl.loadXmlResourceParser(file, id, assetCookie, type);
}
/**
@@ -2908,16 +2081,4 @@
}
return theme.obtainStyledAttributes(set, attrs, 0, 0);
}
-
- private Resources() {
- mAssets = AssetManager.getSystem();
- mClassLoader = ClassLoader.getSystemClassLoader();
- // NOTE: Intentionally leaving this uninitialized (all values set
- // to zero), so that anyone who tries to do something that requires
- // metrics will get a very wrong value.
- mConfiguration.setToDefaults();
- mMetrics.setToDefaults();
- updateConfiguration(null, null);
- mAssets.ensureStringBlocks();
- }
}
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
new file mode 100644
index 0000000..2ffd372
--- /dev/null
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -0,0 +1,1140 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package android.content.res;
+
+import android.animation.Animator;
+import android.animation.StateListAnimator;
+import android.annotation.AnyRes;
+import android.annotation.AttrRes;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.PluralsRes;
+import android.annotation.RawRes;
+import android.annotation.StyleRes;
+import android.annotation.StyleableRes;
+import android.content.pm.ActivityInfo;
+import android.content.res.Resources.NotFoundException;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.icu.text.PluralRules;
+import android.os.Build;
+import android.os.Trace;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.LocaleList;
+import android.util.Log;
+import android.util.LongSparseArray;
+import android.util.Slog;
+import android.util.TypedValue;
+import android.util.Xml;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Locale;
+
+/**
+ * @hide
+ */
+public class ResourcesImpl {
+ static final String TAG = "Resources";
+
+ private static final boolean DEBUG_LOAD = false;
+ private static final boolean DEBUG_CONFIG = false;
+ private static final boolean TRACE_FOR_PRELOAD = false;
+ private static final boolean TRACE_FOR_MISS_PRELOAD = false;
+
+ private static final int LAYOUT_DIR_CONFIG = ActivityInfo.activityInfoConfigToNative(
+ ActivityInfo.CONFIG_LAYOUT_DIRECTION);
+
+ private static final int ID_OTHER = 0x01000004;
+
+ private static final Object sSync = new Object();
+
+ private static boolean sPreloaded;
+ private boolean mPreloading;
+
+ // Information about preloaded resources. Note that they are not
+ // protected by a lock, because while preloading in zygote we are all
+ // single-threaded, and after that these are immutable.
+ private static final LongSparseArray<Drawable.ConstantState>[] sPreloadedDrawables;
+ private static final LongSparseArray<Drawable.ConstantState> sPreloadedColorDrawables
+ = new LongSparseArray<>();
+ private static final LongSparseArray<android.content.res.ConstantState<ComplexColor>>
+ sPreloadedComplexColors = new LongSparseArray<>();
+
+ /** Lock object used to protect access to caches and configuration. */
+ private final Object mAccessLock = new Object();
+
+ // These are protected by mAccessLock.
+ private final Configuration mTmpConfig = new Configuration();
+ private final DrawableCache mDrawableCache = new DrawableCache();
+ private final DrawableCache mColorDrawableCache = new DrawableCache();
+ private final ConfigurationBoundResourceCache<ComplexColor> mComplexColorCache =
+ new ConfigurationBoundResourceCache<>();
+ private final ConfigurationBoundResourceCache<Animator> mAnimatorCache =
+ new ConfigurationBoundResourceCache<>();
+ private final ConfigurationBoundResourceCache<StateListAnimator> mStateListAnimatorCache =
+ new ConfigurationBoundResourceCache<>();
+
+ /** Size of the cyclical cache used to map XML files to blocks. */
+ private static final int XML_BLOCK_CACHE_SIZE = 4;
+
+ // Cyclical cache used for recently-accessed XML files.
+ private int mLastCachedXmlBlockIndex = -1;
+ private final int[] mCachedXmlBlockCookies = new int[XML_BLOCK_CACHE_SIZE];
+ private final String[] mCachedXmlBlockFiles = new String[XML_BLOCK_CACHE_SIZE];
+ private final XmlBlock[] mCachedXmlBlocks = new XmlBlock[XML_BLOCK_CACHE_SIZE];
+
+
+ final AssetManager mAssets;
+ final DisplayMetrics mMetrics = new DisplayMetrics();
+
+ private PluralRules mPluralRule;
+
+ private final Configuration mConfiguration = new Configuration();
+ private CompatibilityInfo mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
+
+ static {
+ sPreloadedDrawables = new LongSparseArray[2];
+ sPreloadedDrawables[0] = new LongSparseArray<>();
+ sPreloadedDrawables[1] = new LongSparseArray<>();
+ }
+
+ /**
+ * Creates a new ResourcesImpl object with CompatibilityInfo.
+ *
+ * @param assets Previously created AssetManager.
+ * @param metrics Current display metrics to consider when
+ * selecting/computing resource values.
+ * @param config Desired device configuration to consider when
+ * selecting/computing resource values (optional).
+ * @param compatInfo this resource's compatibility info. Must not be null.
+ */
+ public ResourcesImpl(AssetManager assets, DisplayMetrics metrics, Configuration config,
+ CompatibilityInfo compatInfo) {
+ mAssets = assets;
+ mMetrics.setToDefaults();
+ updateConfiguration(config, metrics, compatInfo);
+ mAssets.ensureStringBlocks();
+ }
+
+ AssetManager getAssets() {
+ return mAssets;
+ }
+
+ DisplayMetrics getDisplayMetrics() {
+ if (DEBUG_CONFIG) Slog.v(TAG, "Returning DisplayMetrics: " + mMetrics.widthPixels
+ + "x" + mMetrics.heightPixels + " " + mMetrics.density);
+ return mMetrics;
+ }
+
+ Configuration getConfiguration() {
+ return mConfiguration;
+ }
+
+ Configuration[] getSizeConfigurations() {
+ return mAssets.getSizeConfigurations();
+ }
+
+ CompatibilityInfo getCompatibilityInfo() {
+ return mCompatibilityInfo;
+ }
+
+ private PluralRules getPluralRule() {
+ synchronized (sSync) {
+ if (mPluralRule == null) {
+ mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().get(0));
+ }
+ return mPluralRule;
+ }
+ }
+
+ void getValue(@AnyRes int id, TypedValue outValue, boolean resolveRefs)
+ throws NotFoundException {
+ boolean found = mAssets.getResourceValue(id, 0, outValue, resolveRefs);
+ if (found) {
+ return;
+ }
+ throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id));
+ }
+
+ void getValueForDensity(@AnyRes int id, int density, TypedValue outValue,
+ boolean resolveRefs) throws NotFoundException {
+ boolean found = mAssets.getResourceValue(id, density, outValue, resolveRefs);
+ if (found) {
+ return;
+ }
+ throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id));
+ }
+
+ void getValue(String name, TypedValue outValue, boolean resolveRefs)
+ throws NotFoundException {
+ int id = getIdentifier(name, "string", null);
+ if (id != 0) {
+ getValue(id, outValue, resolveRefs);
+ return;
+ }
+ throw new NotFoundException("String resource name " + name);
+ }
+
+ int getIdentifier(String name, String defType, String defPackage) {
+ if (name == null) {
+ throw new NullPointerException("name is null");
+ }
+ try {
+ return Integer.parseInt(name);
+ } catch (Exception e) {
+ // Ignore
+ }
+ return mAssets.getResourceIdentifier(name, defType, defPackage);
+ }
+
+ @NonNull
+ String getResourceName(@AnyRes int resid) throws NotFoundException {
+ String str = mAssets.getResourceName(resid);
+ if (str != null) return str;
+ throw new NotFoundException("Unable to find resource ID #0x"
+ + Integer.toHexString(resid));
+ }
+
+ @NonNull
+ String getResourcePackageName(@AnyRes int resid) throws NotFoundException {
+ String str = mAssets.getResourcePackageName(resid);
+ if (str != null) return str;
+ throw new NotFoundException("Unable to find resource ID #0x"
+ + Integer.toHexString(resid));
+ }
+
+ @NonNull
+ String getResourceTypeName(@AnyRes int resid) throws NotFoundException {
+ String str = mAssets.getResourceTypeName(resid);
+ if (str != null) return str;
+ throw new NotFoundException("Unable to find resource ID #0x"
+ + Integer.toHexString(resid));
+ }
+
+ @NonNull
+ String getResourceEntryName(@AnyRes int resid) throws NotFoundException {
+ String str = mAssets.getResourceEntryName(resid);
+ if (str != null) return str;
+ throw new NotFoundException("Unable to find resource ID #0x"
+ + Integer.toHexString(resid));
+ }
+
+ @NonNull
+ CharSequence getQuantityText(@PluralsRes int id, int quantity) throws NotFoundException {
+ PluralRules rule = getPluralRule();
+ CharSequence res = mAssets.getResourceBagText(id,
+ attrForQuantityCode(rule.select(quantity)));
+ if (res != null) {
+ return res;
+ }
+ res = mAssets.getResourceBagText(id, ID_OTHER);
+ if (res != null) {
+ return res;
+ }
+ throw new NotFoundException("Plural resource ID #0x" + Integer.toHexString(id)
+ + " quantity=" + quantity
+ + " item=" + rule.select(quantity));
+ }
+
+ private static int attrForQuantityCode(String quantityCode) {
+ switch (quantityCode) {
+ case PluralRules.KEYWORD_ZERO: return 0x01000005;
+ case PluralRules.KEYWORD_ONE: return 0x01000006;
+ case PluralRules.KEYWORD_TWO: return 0x01000007;
+ case PluralRules.KEYWORD_FEW: return 0x01000008;
+ case PluralRules.KEYWORD_MANY: return 0x01000009;
+ default: return ID_OTHER;
+ }
+ }
+
+ @NonNull
+ AssetFileDescriptor openRawResourceFd(@RawRes int id, TypedValue tempValue)
+ throws NotFoundException {
+ getValue(id, tempValue, true);
+ try {
+ return mAssets.openNonAssetFd(tempValue.assetCookie, tempValue.string.toString());
+ } catch (Exception e) {
+ throw new NotFoundException("File " + tempValue.string.toString() + " from drawable "
+ + "resource ID #0x" + Integer.toHexString(id), e);
+ }
+ }
+
+ @NonNull
+ InputStream openRawResource(@RawRes int id, TypedValue value) throws NotFoundException {
+ getValue(id, value, true);
+ try {
+ return mAssets.openNonAsset(value.assetCookie, value.string.toString(),
+ AssetManager.ACCESS_STREAMING);
+ } catch (Exception e) {
+ NotFoundException rnf = new NotFoundException("File " + value.string.toString() +
+ " from drawable resource ID #0x" + Integer.toHexString(id));
+ rnf.initCause(e);
+ throw rnf;
+ }
+ }
+
+ ConfigurationBoundResourceCache<Animator> getAnimatorCache() {
+ return mAnimatorCache;
+ }
+
+ ConfigurationBoundResourceCache<StateListAnimator> getStateListAnimatorCache() {
+ return mStateListAnimatorCache;
+ }
+
+ void updateConfiguration(Configuration config, DisplayMetrics metrics,
+ CompatibilityInfo compat) {
+ synchronized (mAccessLock) {
+ if (false) {
+ Slog.i(TAG, "**** Updating config of " + this + ": old config is "
+ + mConfiguration + " old compat is " + mCompatibilityInfo);
+ Slog.i(TAG, "**** Updating config of " + this + ": new config is "
+ + config + " new compat is " + compat);
+ }
+ if (compat != null) {
+ mCompatibilityInfo = compat;
+ }
+ if (metrics != null) {
+ mMetrics.setTo(metrics);
+ }
+ // NOTE: We should re-arrange this code to create a Display
+ // with the CompatibilityInfo that is used everywhere we deal
+ // with the display in relation to this app, rather than
+ // doing the conversion here. This impl should be okay because
+ // we make sure to return a compatible display in the places
+ // where there are public APIs to retrieve the display... but
+ // it would be cleaner and more maintainble to just be
+ // consistently dealing with a compatible display everywhere in
+ // the framework.
+ mCompatibilityInfo.applyToDisplayMetrics(mMetrics);
+
+ final int configChanges = calcConfigChanges(config);
+
+ LocaleList locales = mConfiguration.getLocales();
+ if (locales.isEmpty()) {
+ locales = LocaleList.getAdjustedDefault();
+ mConfiguration.setLocales(locales);
+ }
+ if (mConfiguration.densityDpi != Configuration.DENSITY_DPI_UNDEFINED) {
+ mMetrics.densityDpi = mConfiguration.densityDpi;
+ mMetrics.density = mConfiguration.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
+ }
+ mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
+
+ final int width, height;
+ if (mMetrics.widthPixels >= mMetrics.heightPixels) {
+ width = mMetrics.widthPixels;
+ height = mMetrics.heightPixels;
+ } else {
+ //noinspection SuspiciousNameCombination
+ width = mMetrics.heightPixels;
+ //noinspection SuspiciousNameCombination
+ height = mMetrics.widthPixels;
+ }
+
+ final int keyboardHidden;
+ if (mConfiguration.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO
+ && mConfiguration.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) {
+ keyboardHidden = Configuration.KEYBOARDHIDDEN_SOFT;
+ } else {
+ keyboardHidden = mConfiguration.keyboardHidden;
+ }
+
+ mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc,
+ adjustLanguageTag(locales.get(0).toLanguageTag()),
+ mConfiguration.orientation,
+ mConfiguration.touchscreen,
+ mConfiguration.densityDpi, mConfiguration.keyboard,
+ keyboardHidden, mConfiguration.navigation, width, height,
+ mConfiguration.smallestScreenWidthDp,
+ mConfiguration.screenWidthDp, mConfiguration.screenHeightDp,
+ mConfiguration.screenLayout, mConfiguration.uiMode,
+ Build.VERSION.RESOURCES_SDK_INT);
+
+ if (DEBUG_CONFIG) {
+ Slog.i(TAG, "**** Updating config of " + this + ": final config is "
+ + mConfiguration + " final compat is " + mCompatibilityInfo);
+ }
+
+ mDrawableCache.onConfigurationChange(configChanges);
+ mColorDrawableCache.onConfigurationChange(configChanges);
+ mComplexColorCache.onConfigurationChange(configChanges);
+ mAnimatorCache.onConfigurationChange(configChanges);
+ mStateListAnimatorCache.onConfigurationChange(configChanges);
+
+ flushLayoutCache();
+ }
+ synchronized (sSync) {
+ if (mPluralRule != null) {
+ mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().get(0));
+ }
+ }
+ }
+
+ /**
+ * Called by ConfigurationBoundResourceCacheTest via reflection.
+ */
+ private int calcConfigChanges(Configuration config) {
+ int configChanges = 0xfffffff;
+ if (config != null) {
+ mTmpConfig.setTo(config);
+ int density = config.densityDpi;
+ if (density == Configuration.DENSITY_DPI_UNDEFINED) {
+ density = mMetrics.noncompatDensityDpi;
+ }
+
+ mCompatibilityInfo.applyToConfiguration(density, mTmpConfig);
+
+ if (mTmpConfig.getLocales().isEmpty()) {
+ mTmpConfig.setLocales(LocaleList.getDefault());
+ }
+ configChanges = mConfiguration.updateFrom(mTmpConfig);
+ configChanges = ActivityInfo.activityInfoConfigToNative(configChanges);
+ }
+ return configChanges;
+ }
+
+ /**
+ * {@code Locale.toLanguageTag} will transform the obsolete (and deprecated)
+ * language codes "in", "ji" and "iw" to "id", "yi" and "he" respectively.
+ *
+ * All released versions of android prior to "L" used the deprecated language
+ * tags, so we will need to support them for backwards compatibility.
+ *
+ * Note that this conversion needs to take place *after* the call to
+ * {@code toLanguageTag} because that will convert all the deprecated codes to
+ * the new ones, even if they're set manually.
+ */
+ private static String adjustLanguageTag(String languageTag) {
+ final int separator = languageTag.indexOf('-');
+ final String language;
+ final String remainder;
+
+ if (separator == -1) {
+ language = languageTag;
+ remainder = "";
+ } else {
+ language = languageTag.substring(0, separator);
+ remainder = languageTag.substring(separator);
+ }
+
+ return Locale.adjustLanguageCode(language) + remainder;
+ }
+
+ /**
+ * Call this to remove all cached loaded layout resources from the
+ * Resources object. Only intended for use with performance testing
+ * tools.
+ */
+ public void flushLayoutCache() {
+ synchronized (mCachedXmlBlocks) {
+ Arrays.fill(mCachedXmlBlockCookies, 0);
+ Arrays.fill(mCachedXmlBlockFiles, null);
+
+ final XmlBlock[] cachedXmlBlocks = mCachedXmlBlocks;
+ for (int i = 0; i < XML_BLOCK_CACHE_SIZE; i++) {
+ final XmlBlock oldBlock = cachedXmlBlocks[i];
+ if (oldBlock != null) {
+ oldBlock.close();
+ }
+ }
+ Arrays.fill(cachedXmlBlocks, null);
+ }
+ }
+
+ @Nullable
+ Drawable loadDrawable(Resources wrapper, TypedValue value, int id, Resources.Theme theme,
+ boolean useCache) throws NotFoundException {
+ try {
+ if (TRACE_FOR_PRELOAD) {
+ // Log only framework resources
+ if ((id >>> 24) == 0x1) {
+ final String name = getResourceName(id);
+ if (name != null) {
+ Log.d("PreloadDrawable", name);
+ }
+ }
+ }
+
+ final boolean isColorDrawable;
+ final DrawableCache caches;
+ final long key;
+ if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
+ && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
+ isColorDrawable = true;
+ caches = mColorDrawableCache;
+ key = value.data;
+ } else {
+ isColorDrawable = false;
+ caches = mDrawableCache;
+ key = (((long) value.assetCookie) << 32) | value.data;
+ }
+
+ // First, check whether we have a cached version of this drawable
+ // that was inflated against the specified theme. Skip the cache if
+ // we're currently preloading or we're not using the cache.
+ if (!mPreloading && useCache) {
+ final Drawable cachedDrawable = caches.getInstance(key, wrapper, theme);
+ if (cachedDrawable != null) {
+ return cachedDrawable;
+ }
+ }
+
+ // Next, check preloaded drawables. Preloaded drawables may contain
+ // unresolved theme attributes.
+ final Drawable.ConstantState cs;
+ if (isColorDrawable) {
+ cs = sPreloadedColorDrawables.get(key);
+ } else {
+ cs = sPreloadedDrawables[mConfiguration.getLayoutDirection()].get(key);
+ }
+
+ Drawable dr;
+ if (cs != null) {
+ dr = cs.newDrawable(wrapper);
+ } else if (isColorDrawable) {
+ dr = new ColorDrawable(value.data);
+ } else {
+ dr = loadDrawableForCookie(wrapper, value, id, null);
+ }
+
+ // Determine if the drawable has unresolved theme attributes. If it
+ // does, we'll need to apply a theme and store it in a theme-specific
+ // cache.
+ final boolean canApplyTheme = dr != null && dr.canApplyTheme();
+ if (canApplyTheme && theme != null) {
+ dr = dr.mutate();
+ dr.applyTheme(theme);
+ dr.clearMutated();
+ }
+
+ // If we were able to obtain a drawable, store it in the appropriate
+ // cache: preload, not themed, null theme, or theme-specific. Don't
+ // pollute the cache with drawables loaded from a foreign density.
+ if (dr != null && useCache) {
+ dr.setChangingConfigurations(value.changingConfigurations);
+ cacheDrawable(value, isColorDrawable, caches, theme, canApplyTheme, key, dr);
+ }
+
+ return dr;
+ } catch (Exception e) {
+ String name;
+ try {
+ name = getResourceName(id);
+ } catch (NotFoundException e2) {
+ name = "(missing name)";
+ }
+
+ // The target drawable might fail to load for any number of
+ // reasons, but we always want to include the resource name.
+ // Since the client already expects this method to throw a
+ // NotFoundException, just throw one of those.
+ final NotFoundException nfe = new NotFoundException("Drawable " + name
+ + " with resource ID #0x" + Integer.toHexString(id), e);
+ nfe.setStackTrace(new StackTraceElement[0]);
+ throw nfe;
+ }
+ }
+
+ private void cacheDrawable(TypedValue value, boolean isColorDrawable, DrawableCache caches,
+ Resources.Theme theme, boolean usesTheme, long key, Drawable dr) {
+ final Drawable.ConstantState cs = dr.getConstantState();
+ if (cs == null) {
+ return;
+ }
+
+ if (mPreloading) {
+ final int changingConfigs = cs.getChangingConfigurations();
+ if (isColorDrawable) {
+ if (verifyPreloadConfig(changingConfigs, 0, value.resourceId, "drawable")) {
+ sPreloadedColorDrawables.put(key, cs);
+ }
+ } else {
+ if (verifyPreloadConfig(
+ changingConfigs, LAYOUT_DIR_CONFIG, value.resourceId, "drawable")) {
+ if ((changingConfigs & LAYOUT_DIR_CONFIG) == 0) {
+ // If this resource does not vary based on layout direction,
+ // we can put it in all of the preload maps.
+ sPreloadedDrawables[0].put(key, cs);
+ sPreloadedDrawables[1].put(key, cs);
+ } else {
+ // Otherwise, only in the layout dir we loaded it for.
+ sPreloadedDrawables[mConfiguration.getLayoutDirection()].put(key, cs);
+ }
+ }
+ }
+ } else {
+ synchronized (mAccessLock) {
+ caches.put(key, theme, cs, usesTheme);
+ }
+ }
+ }
+
+ private boolean verifyPreloadConfig(int changingConfigurations, int allowVarying,
+ int resourceId, String name) {
+ // We allow preloading of resources even if they vary by font scale (which
+ // doesn't impact resource selection) or density (which we handle specially by
+ // simply turning off all preloading), as well as any other configs specified
+ // by the caller.
+ if (((changingConfigurations&~(ActivityInfo.CONFIG_FONT_SCALE |
+ ActivityInfo.CONFIG_DENSITY)) & ~allowVarying) != 0) {
+ String resName;
+ try {
+ resName = getResourceName(resourceId);
+ } catch (NotFoundException e) {
+ resName = "?";
+ }
+ // This should never happen in production, so we should log a
+ // warning even if we're not debugging.
+ Log.w(TAG, "Preloaded " + name + " resource #0x"
+ + Integer.toHexString(resourceId)
+ + " (" + resName + ") that varies with configuration!!");
+ return false;
+ }
+ if (TRACE_FOR_PRELOAD) {
+ String resName;
+ try {
+ resName = getResourceName(resourceId);
+ } catch (NotFoundException e) {
+ resName = "?";
+ }
+ Log.w(TAG, "Preloading " + name + " resource #0x"
+ + Integer.toHexString(resourceId)
+ + " (" + resName + ")");
+ }
+ return true;
+ }
+
+ /**
+ * Loads a drawable from XML or resources stream.
+ */
+ private Drawable loadDrawableForCookie(Resources wrapper, TypedValue value, int id,
+ Resources.Theme theme) {
+ if (value.string == null) {
+ throw new NotFoundException("Resource \"" + getResourceName(id) + "\" ("
+ + Integer.toHexString(id) + ") is not a Drawable (color or path): " + value);
+ }
+
+ final String file = value.string.toString();
+
+ if (TRACE_FOR_MISS_PRELOAD) {
+ // Log only framework resources
+ if ((id >>> 24) == 0x1) {
+ final String name = getResourceName(id);
+ if (name != null) {
+ Log.d(TAG, "Loading framework drawable #" + Integer.toHexString(id)
+ + ": " + name + " at " + file);
+ }
+ }
+ }
+
+ if (DEBUG_LOAD) {
+ Log.v(TAG, "Loading drawable for cookie " + value.assetCookie + ": " + file);
+ }
+
+ final Drawable dr;
+
+ Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
+ try {
+ if (file.endsWith(".xml")) {
+ final XmlResourceParser rp = loadXmlResourceParser(
+ file, id, value.assetCookie, "drawable");
+ dr = Drawable.createFromXml(wrapper, rp, theme);
+ rp.close();
+ } else {
+ final InputStream is = mAssets.openNonAsset(
+ value.assetCookie, file, AssetManager.ACCESS_STREAMING);
+ dr = Drawable.createFromResourceStream(wrapper, value, is, file, null);
+ is.close();
+ }
+ } catch (Exception e) {
+ Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
+ final NotFoundException rnf = new NotFoundException(
+ "File " + file + " from drawable resource ID #0x" + Integer.toHexString(id));
+ rnf.initCause(e);
+ throw rnf;
+ }
+ Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
+
+ return dr;
+ }
+
+ /**
+ * Given the value and id, we can get the XML filename as in value.data, based on that, we
+ * first try to load CSL from the cache. If not found, try to get from the constant state.
+ * Last, parse the XML and generate the CSL.
+ */
+ private ComplexColor loadComplexColorFromName(Resources wrapper, Resources.Theme theme,
+ TypedValue value, int id) {
+ final long key = (((long) value.assetCookie) << 32) | value.data;
+ final ConfigurationBoundResourceCache<ComplexColor> cache = mComplexColorCache;
+ ComplexColor complexColor = cache.getInstance(key, wrapper, theme);
+ if (complexColor != null) {
+ return complexColor;
+ }
+
+ final android.content.res.ConstantState<ComplexColor> factory =
+ sPreloadedComplexColors.get(key);
+
+ if (factory != null) {
+ complexColor = factory.newInstance(wrapper, theme);
+ }
+ if (complexColor == null) {
+ complexColor = loadComplexColorForCookie(wrapper, value, id, theme);
+ }
+
+ if (complexColor != null) {
+ if (mPreloading) {
+ if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
+ "color")) {
+ sPreloadedComplexColors.put(key, complexColor.getConstantState());
+ }
+ } else {
+ cache.put(key, theme, complexColor.getConstantState());
+ }
+ }
+ return complexColor;
+ }
+
+ @Nullable
+ ComplexColor loadComplexColor(Resources wrapper, @NonNull TypedValue value, int id,
+ Resources.Theme theme) {
+ if (TRACE_FOR_PRELOAD) {
+ // Log only framework resources
+ if ((id >>> 24) == 0x1) {
+ final String name = getResourceName(id);
+ if (name != null) android.util.Log.d("loadComplexColor", name);
+ }
+ }
+
+ final long key = (((long) value.assetCookie) << 32) | value.data;
+
+ // Handle inline color definitions.
+ if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
+ && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
+ return getColorStateListFromInt(value, key);
+ }
+
+ final String file = value.string.toString();
+
+ ComplexColor complexColor;
+ if (file.endsWith(".xml")) {
+ try {
+ complexColor = loadComplexColorFromName(wrapper, theme, value, id);
+ } catch (Exception e) {
+ final NotFoundException rnf = new NotFoundException(
+ "File " + file + " from complex color resource ID #0x"
+ + Integer.toHexString(id));
+ rnf.initCause(e);
+ throw rnf;
+ }
+ } else {
+ throw new NotFoundException(
+ "File " + file + " from drawable resource ID #0x"
+ + Integer.toHexString(id) + ": .xml extension required");
+ }
+
+ return complexColor;
+ }
+
+ @Nullable
+ ColorStateList loadColorStateList(Resources wrapper, TypedValue value, int id,
+ Resources.Theme theme)
+ throws NotFoundException {
+ if (TRACE_FOR_PRELOAD) {
+ // Log only framework resources
+ if ((id >>> 24) == 0x1) {
+ final String name = getResourceName(id);
+ if (name != null) android.util.Log.d("PreloadColorStateList", name);
+ }
+ }
+
+ final long key = (((long) value.assetCookie) << 32) | value.data;
+
+ // Handle inline color definitions.
+ if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
+ && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
+ return getColorStateListFromInt(value, key);
+ }
+
+ ComplexColor complexColor = loadComplexColorFromName(wrapper, theme, value, id);
+ if (complexColor != null && complexColor instanceof ColorStateList) {
+ return (ColorStateList) complexColor;
+ }
+
+ throw new NotFoundException(
+ "Can't find ColorStateList from drawable resource ID #0x"
+ + Integer.toHexString(id));
+ }
+
+ @NonNull
+ private ColorStateList getColorStateListFromInt(@NonNull TypedValue value, long key) {
+ ColorStateList csl;
+ final android.content.res.ConstantState<ComplexColor> factory =
+ sPreloadedComplexColors.get(key);
+ if (factory != null) {
+ return (ColorStateList) factory.newInstance();
+ }
+
+ csl = ColorStateList.valueOf(value.data);
+
+ if (mPreloading) {
+ if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
+ "color")) {
+ sPreloadedComplexColors.put(key, csl.getConstantState());
+ }
+ }
+
+ return csl;
+ }
+
+ /**
+ * Load a ComplexColor based on the XML file content. The result can be a GradientColor or
+ * ColorStateList. Note that pure color will be wrapped into a ColorStateList.
+ *
+ * We deferred the parser creation to this function b/c we need to differentiate b/t gradient
+ * and selector tag.
+ *
+ * @return a ComplexColor (GradientColor or ColorStateList) based on the XML file content.
+ */
+ @Nullable
+ private ComplexColor loadComplexColorForCookie(Resources wrapper, TypedValue value, int id,
+ Resources.Theme theme) {
+ if (value.string == null) {
+ throw new UnsupportedOperationException(
+ "Can't convert to ComplexColor: type=0x" + value.type);
+ }
+
+ final String file = value.string.toString();
+
+ if (TRACE_FOR_MISS_PRELOAD) {
+ // Log only framework resources
+ if ((id >>> 24) == 0x1) {
+ final String name = getResourceName(id);
+ if (name != null) {
+ Log.d(TAG, "Loading framework ComplexColor #" + Integer.toHexString(id)
+ + ": " + name + " at " + file);
+ }
+ }
+ }
+
+ if (DEBUG_LOAD) {
+ Log.v(TAG, "Loading ComplexColor for cookie " + value.assetCookie + ": " + file);
+ }
+
+ ComplexColor complexColor = null;
+
+ Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
+ if (file.endsWith(".xml")) {
+ try {
+ final XmlResourceParser parser = loadXmlResourceParser(
+ file, id, value.assetCookie, "ComplexColor");
+
+ final AttributeSet attrs = Xml.asAttributeSet(parser);
+ int type;
+ while ((type = parser.next()) != XmlPullParser.START_TAG
+ && type != XmlPullParser.END_DOCUMENT) {
+ // Seek parser to start tag.
+ }
+ if (type != XmlPullParser.START_TAG) {
+ throw new XmlPullParserException("No start tag found");
+ }
+
+ final String name = parser.getName();
+ if (name.equals("gradient")) {
+ complexColor = GradientColor.createFromXmlInner(wrapper, parser, attrs, theme);
+ } else if (name.equals("selector")) {
+ complexColor = ColorStateList.createFromXmlInner(wrapper, parser, attrs, theme);
+ }
+ parser.close();
+ } catch (Exception e) {
+ Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
+ final NotFoundException rnf = new NotFoundException(
+ "File " + file + " from ComplexColor resource ID #0x"
+ + Integer.toHexString(id));
+ rnf.initCause(e);
+ throw rnf;
+ }
+ } else {
+ Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
+ throw new NotFoundException(
+ "File " + file + " from drawable resource ID #0x"
+ + Integer.toHexString(id) + ": .xml extension required");
+ }
+ Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
+
+ return complexColor;
+ }
+
+ /**
+ * Loads an XML parser for the specified file.
+ *
+ * @param file the path for the XML file to parse
+ * @param id the resource identifier for the file
+ * @param assetCookie the asset cookie for the file
+ * @param type the type of resource (used for logging)
+ * @return a parser for the specified XML file
+ * @throws NotFoundException if the file could not be loaded
+ */
+ @NonNull
+ XmlResourceParser loadXmlResourceParser(@NonNull String file, @AnyRes int id,
+ int assetCookie, @NonNull String type)
+ throws NotFoundException {
+ if (id != 0) {
+ try {
+ synchronized (mCachedXmlBlocks) {
+ final int[] cachedXmlBlockCookies = mCachedXmlBlockCookies;
+ final String[] cachedXmlBlockFiles = mCachedXmlBlockFiles;
+ final XmlBlock[] cachedXmlBlocks = mCachedXmlBlocks;
+ // First see if this block is in our cache.
+ final int num = cachedXmlBlockFiles.length;
+ for (int i = 0; i < num; i++) {
+ if (cachedXmlBlockCookies[i] == assetCookie && cachedXmlBlockFiles[i] != null
+ && cachedXmlBlockFiles[i].equals(file)) {
+ return cachedXmlBlocks[i].newParser();
+ }
+ }
+
+ // Not in the cache, create a new block and put it at
+ // the next slot in the cache.
+ final XmlBlock block = mAssets.openXmlBlockAsset(assetCookie, file);
+ if (block != null) {
+ final int pos = (mLastCachedXmlBlockIndex + 1) % num;
+ mLastCachedXmlBlockIndex = pos;
+ final XmlBlock oldBlock = cachedXmlBlocks[pos];
+ if (oldBlock != null) {
+ oldBlock.close();
+ }
+ cachedXmlBlockCookies[pos] = assetCookie;
+ cachedXmlBlockFiles[pos] = file;
+ cachedXmlBlocks[pos] = block;
+ return block.newParser();
+ }
+ }
+ } catch (Exception e) {
+ final NotFoundException rnf = new NotFoundException("File " + file
+ + " from xml type " + type + " resource ID #0x" + Integer.toHexString(id));
+ rnf.initCause(e);
+ throw rnf;
+ }
+ }
+
+ throw new NotFoundException("File " + file + " from xml type " + type + " resource ID #0x"
+ + Integer.toHexString(id));
+ }
+
+ /**
+ * Start preloading of resource data using this Resources object. Only
+ * for use by the zygote process for loading common system resources.
+ * {@hide}
+ */
+ public final void startPreloading() {
+ synchronized (sSync) {
+ if (sPreloaded) {
+ throw new IllegalStateException("Resources already preloaded");
+ }
+ sPreloaded = true;
+ mPreloading = true;
+ mConfiguration.densityDpi = DisplayMetrics.DENSITY_DEVICE;
+ updateConfiguration(null, null, null);
+ }
+ }
+
+ /**
+ * Called by zygote when it is done preloading resources, to change back
+ * to normal Resources operation.
+ */
+ void finishPreloading() {
+ if (mPreloading) {
+ mPreloading = false;
+ flushLayoutCache();
+ }
+ }
+
+ LongSparseArray<Drawable.ConstantState> getPreloadedDrawables() {
+ return sPreloadedDrawables[0];
+ }
+
+ ThemeImpl newThemeImpl() {
+ return new ThemeImpl();
+ }
+
+ public class ThemeImpl {
+ /**
+ * Unique key for the series of styles applied to this theme.
+ */
+ private final Resources.ThemeKey mKey = new Resources.ThemeKey();
+
+ @SuppressWarnings("hiding")
+ private final AssetManager mAssets;
+ private final long mTheme;
+
+ /**
+ * Resource identifier for the theme.
+ */
+ private int mThemeResId = 0;
+
+ /*package*/ ThemeImpl() {
+ mAssets = ResourcesImpl.this.mAssets;
+ mTheme = mAssets.createTheme();
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ super.finalize();
+ mAssets.releaseTheme(mTheme);
+ }
+
+ /*package*/ Resources.ThemeKey getKey() {
+ return mKey;
+ }
+
+ /*package*/ long getNativeTheme() {
+ return mTheme;
+ }
+
+ /*package*/ int getAppliedStyleResId() {
+ return mThemeResId;
+ }
+
+ void applyStyle(int resId, boolean force) {
+ synchronized (mKey) {
+ AssetManager.applyThemeStyle(mTheme, resId, force);
+
+ mThemeResId = resId;
+ mKey.append(resId, force);
+ }
+ }
+
+ void setTo(ThemeImpl other) {
+ synchronized (mKey) {
+ synchronized (other.mKey) {
+ AssetManager.copyTheme(mTheme, other.mTheme);
+
+ mThemeResId = other.mThemeResId;
+ mKey.setTo(other.getKey());
+ }
+ }
+ }
+
+ @NonNull
+ TypedArray obtainStyledAttributes(@NonNull Resources.Theme wrapper,
+ AttributeSet set,
+ @StyleableRes int[] attrs,
+ @AttrRes int defStyleAttr,
+ @StyleRes int defStyleRes) {
+ synchronized (mKey) {
+ final int len = attrs.length;
+ final TypedArray array = TypedArray.obtain(wrapper.getResources(), len);
+
+ // XXX note that for now we only work with compiled XML files.
+ // To support generic XML files we will need to manually parse
+ // out the attributes from the XML file (applying type information
+ // contained in the resources and such).
+ final XmlBlock.Parser parser = (XmlBlock.Parser) set;
+ AssetManager.applyStyle(mTheme, defStyleAttr, defStyleRes,
+ parser != null ? parser.mParseState : 0,
+ attrs, array.mData, array.mIndices);
+ array.mTheme = wrapper;
+ array.mXml = parser;
+
+ return array;
+ }
+ }
+
+ @NonNull
+ TypedArray resolveAttributes(@NonNull Resources.Theme wrapper,
+ @NonNull int[] values,
+ @NonNull int[] attrs) {
+ synchronized (mKey) {
+ final int len = attrs.length;
+ if (values == null || len != values.length) {
+ throw new IllegalArgumentException(
+ "Base attribute values must the same length as attrs");
+ }
+
+ final TypedArray array = TypedArray.obtain(wrapper.getResources(), len);
+ AssetManager.resolveAttrs(mTheme, 0, 0, values, attrs, array.mData, array.mIndices);
+ array.mTheme = wrapper;
+ array.mXml = null;
+ return array;
+ }
+ }
+
+ boolean resolveAttribute(int resid, TypedValue outValue, boolean resolveRefs) {
+ synchronized (mKey) {
+ return mAssets.getThemeValue(mTheme, resid, outValue, resolveRefs);
+ }
+ }
+
+ int[] getAllAttributes() {
+ return mAssets.getStyleAttributes(getAppliedStyleResId());
+ }
+
+ int getChangingConfigurations() {
+ synchronized (mKey) {
+ final int nativeChangingConfig =
+ AssetManager.getThemeChangingConfigurations(mTheme);
+ return ActivityInfo.activityInfoConfigNativeToJava(nativeChangingConfig);
+ }
+ }
+
+ public void dump(int priority, String tag, String prefix) {
+ synchronized (mKey) {
+ AssetManager.dumpTheme(mTheme, priority, tag, prefix);
+ }
+ }
+
+ String[] getTheme() {
+ synchronized (mKey) {
+ final int N = mKey.mCount;
+ final String[] themes = new String[N * 2];
+ for (int i = 0, j = N - 1; i < themes.length; i += 2, --j) {
+ final int resId = mKey.mResId[j];
+ final boolean forced = mKey.mForce[j];
+ try {
+ themes[i] = getResourceName(resId);
+ } catch (NotFoundException e) {
+ themes[i] = Integer.toHexString(i);
+ }
+ themes[i + 1] = forced ? "forced" : "not forced";
+ }
+ return themes;
+ }
+ }
+
+ /**
+ * Rebases the theme against the parent Resource object's current
+ * configuration by re-applying the styles passed to
+ * {@link #applyStyle(int, boolean)}.
+ */
+ void rebase() {
+ synchronized (mKey) {
+ AssetManager.clearTheme(mTheme);
+
+ // Reapply the same styles in the same order.
+ for (int i = 0; i < mKey.mCount; i++) {
+ final int resId = mKey.mResId[i];
+ final boolean force = mKey.mForce[i];
+ AssetManager.applyThemeStyle(mTheme, resId, force);
+ }
+ }
+ }
+ }
+}
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 6067577..022bdfb 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -426,7 +426,9 @@
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
+ final int attrIndex = index;
index *= AssetManager.STYLE_NUM_ENTRIES;
+
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
if (type == TypedValue.TYPE_NULL) {
@@ -444,13 +446,13 @@
return defValue;
} else if (type == TypedValue.TYPE_ATTRIBUTE) {
final TypedValue value = mValue;
- getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value);
+ getValueAt(index, value);
throw new UnsupportedOperationException(
- "Failed to resolve attribute at index " + index + ": " + value);
+ "Failed to resolve attribute at index " + attrIndex + ": " + value);
}
- throw new UnsupportedOperationException("Can't convert to color: type=0x"
- + Integer.toHexString(type));
+ throw new UnsupportedOperationException("Can't convert value at index " + attrIndex
+ + " to color: type=0x" + Integer.toHexString(type));
}
/**
@@ -541,7 +543,9 @@
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
+ final int attrIndex = index;
index *= AssetManager.STYLE_NUM_ENTRIES;
+
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
if (type == TypedValue.TYPE_NULL) {
@@ -551,13 +555,13 @@
return data[index+AssetManager.STYLE_DATA];
} else if (type == TypedValue.TYPE_ATTRIBUTE) {
final TypedValue value = mValue;
- getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value);
+ getValueAt(index, value);
throw new UnsupportedOperationException(
- "Failed to resolve attribute at index " + index + ": " + value);
+ "Failed to resolve attribute at index " + attrIndex + ": " + value);
}
- throw new UnsupportedOperationException("Can't convert to integer: type=0x"
- + Integer.toHexString(type));
+ throw new UnsupportedOperationException("Can't convert value at index " + attrIndex
+ + " to integer: type=0x" + Integer.toHexString(type));
}
/**
@@ -587,7 +591,9 @@
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
+ final int attrIndex = index;
index *= AssetManager.STYLE_NUM_ENTRIES;
+
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
if (type == TypedValue.TYPE_NULL) {
@@ -597,13 +603,13 @@
data[index + AssetManager.STYLE_DATA], mMetrics);
} else if (type == TypedValue.TYPE_ATTRIBUTE) {
final TypedValue value = mValue;
- getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value);
+ getValueAt(index, value);
throw new UnsupportedOperationException(
- "Failed to resolve attribute at index " + index + ": " + value);
+ "Failed to resolve attribute at index " + attrIndex + ": " + value);
}
- throw new UnsupportedOperationException("Can't convert to dimension: type=0x"
- + Integer.toHexString(type));
+ throw new UnsupportedOperationException("Can't convert value at index " + attrIndex
+ + " to dimension: type=0x" + Integer.toHexString(type));
}
/**
@@ -634,7 +640,9 @@
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
+ final int attrIndex = index;
index *= AssetManager.STYLE_NUM_ENTRIES;
+
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
if (type == TypedValue.TYPE_NULL) {
@@ -644,13 +652,13 @@
data[index + AssetManager.STYLE_DATA], mMetrics);
} else if (type == TypedValue.TYPE_ATTRIBUTE) {
final TypedValue value = mValue;
- getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value);
+ getValueAt(index, value);
throw new UnsupportedOperationException(
- "Failed to resolve attribute at index " + index + ": " + value);
+ "Failed to resolve attribute at index " + attrIndex + ": " + value);
}
- throw new UnsupportedOperationException("Can't convert to dimension: type=0x"
- + Integer.toHexString(type));
+ throw new UnsupportedOperationException("Can't convert value at index " + attrIndex
+ + " to dimension: type=0x" + Integer.toHexString(type));
}
/**
@@ -682,7 +690,9 @@
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
+ final int attrIndex = index;
index *= AssetManager.STYLE_NUM_ENTRIES;
+
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
if (type == TypedValue.TYPE_NULL) {
@@ -692,13 +702,13 @@
data[index+AssetManager.STYLE_DATA], mMetrics);
} else if (type == TypedValue.TYPE_ATTRIBUTE) {
final TypedValue value = mValue;
- getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value);
+ getValueAt(index, value);
throw new UnsupportedOperationException(
- "Failed to resolve attribute at index " + index + ": " + value);
+ "Failed to resolve attribute at index " + attrIndex + ": " + value);
}
- throw new UnsupportedOperationException("Can't convert to dimension: type=0x"
- + Integer.toHexString(type));
+ throw new UnsupportedOperationException("Can't convert value at index " + attrIndex
+ + " to dimension: type=0x" + Integer.toHexString(type));
}
/**
@@ -724,7 +734,9 @@
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
+ final int attrIndex = index;
index *= AssetManager.STYLE_NUM_ENTRIES;
+
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
if (type >= TypedValue.TYPE_FIRST_INT
@@ -735,9 +747,9 @@
data[index+AssetManager.STYLE_DATA], mMetrics);
} else if (type == TypedValue.TYPE_ATTRIBUTE) {
final TypedValue value = mValue;
- getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value);
+ getValueAt(index, value);
throw new UnsupportedOperationException(
- "Failed to resolve attribute at index " + index + ": " + value);
+ "Failed to resolve attribute at index " + attrIndex + ": " + value);
}
throw new UnsupportedOperationException(getPositionDescription()
@@ -800,7 +812,9 @@
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
+ final int attrIndex = index;
index *= AssetManager.STYLE_NUM_ENTRIES;
+
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
if (type == TypedValue.TYPE_NULL) {
@@ -810,13 +824,13 @@
data[index+AssetManager.STYLE_DATA], base, pbase);
} else if (type == TypedValue.TYPE_ATTRIBUTE) {
final TypedValue value = mValue;
- getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value);
+ getValueAt(index, value);
throw new UnsupportedOperationException(
- "Failed to resolve attribute at index " + index + ": " + value);
+ "Failed to resolve attribute at index " + attrIndex + ": " + value);
}
- throw new UnsupportedOperationException("Can't convert to fraction: type=0x"
- + Integer.toHexString(type));
+ throw new UnsupportedOperationException("Can't convert value at index " + attrIndex
+ + " to fraction: type=0x" + Integer.toHexString(type));
}
/**
@@ -1192,8 +1206,8 @@
/*package*/ TypedArray(Resources resources, int[] data, int[] indices, int len) {
mResources = resources;
- mMetrics = mResources.mMetrics;
- mAssets = mResources.mAssets;
+ mMetrics = mResources.getDisplayMetrics();
+ mAssets = mResources.getAssets();
mData = data;
mIndices = indices;
mLength = len;
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 02d4e59..3dbe437 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -19,6 +19,7 @@
import android.app.ActivityThread;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.app.job.JobInfo;
import android.content.Context;
import android.graphics.ImageFormat;
import android.graphics.Point;
@@ -177,19 +178,27 @@
private static final int NO_ERROR = 0;
/**
+ * @deprecated This broadcast is no longer delivered by the system; use
+ * {@link android.app.job.JobInfo.Builder JobInfo.Builder}.{@link android.app.job.JobInfo.Builder#addTriggerContentUri}
+ * instead.
* Broadcast Action: A new picture is taken by the camera, and the entry of
* the picture has been added to the media store.
* {@link android.content.Intent#getData} is URI of the picture.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @Deprecated
public static final String ACTION_NEW_PICTURE = "android.hardware.action.NEW_PICTURE";
/**
+ * @deprecated This broadcast is no longer delivered by the system; use
+ * {@link android.app.job.JobInfo.Builder JobInfo.Builder}.{@link android.app.job.JobInfo.Builder#addTriggerContentUri}
+ * instead.
* Broadcast Action: A new video is recorded by the camera, and the entry
* of the video has been added to the media store.
* {@link android.content.Intent#getData} is URI of the video.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @Deprecated
public static final String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO";
/**
diff --git a/core/java/android/hardware/ConsumerIrManager.java b/core/java/android/hardware/ConsumerIrManager.java
index 6d29212..9fa1c3f 100644
--- a/core/java/android/hardware/ConsumerIrManager.java
+++ b/core/java/android/hardware/ConsumerIrManager.java
@@ -60,8 +60,8 @@
try {
return mService.hasIrEmitter();
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return false;
}
/**
@@ -84,7 +84,7 @@
try {
mService.transmit(mPackageName, carrierFrequency, pattern);
} catch (RemoteException e) {
- Log.w(TAG, "failed to transmit.", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -149,8 +149,7 @@
}
return range;
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return null;
}
-
}
diff --git a/core/java/android/hardware/ICamera.aidl b/core/java/android/hardware/ICamera.aidl
deleted file mode 100644
index d4f64f8..0000000
--- a/core/java/android/hardware/ICamera.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.hardware;
-
-/** @hide */
-interface ICamera
-{
- /**
- * Keep up-to-date with frameworks/av/include/camera/ICamera.h
- */
- void disconnect();
-}
diff --git a/core/java/android/hardware/ICameraService.aidl b/core/java/android/hardware/ICameraService.aidl
deleted file mode 100644
index 0b165cd..0000000
--- a/core/java/android/hardware/ICameraService.aidl
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.hardware;
-
-import android.hardware.ICamera;
-import android.hardware.ICameraClient;
-import android.hardware.camera2.ICameraDeviceUser;
-import android.hardware.camera2.ICameraDeviceCallbacks;
-import android.hardware.camera2.impl.CameraMetadataNative;
-import android.hardware.camera2.utils.BinderHolder;
-import android.hardware.ICameraServiceListener;
-import android.hardware.CameraInfo;
-
-/**
- * Binder interface for the native camera service running in mediaserver.
- *
- * @hide
- */
-interface ICameraService
-{
- /**
- * Keep up-to-date with frameworks/av/include/camera/ICameraService.h
- */
- int getNumberOfCameras(int type);
-
- // rest of 'int' return values in this file are actually status_t
-
- int getCameraInfo(int cameraId, out CameraInfo info);
-
- int connect(ICameraClient client, int cameraId,
- String opPackageName,
- int clientUid,
- // Container for an ICamera object
- out BinderHolder device);
-
- int connectDevice(ICameraDeviceCallbacks callbacks, int cameraId,
- String opPackageName,
- int clientUid,
- // Container for an ICameraDeviceUser object
- out BinderHolder device);
-
- int addListener(ICameraServiceListener listener);
- int removeListener(ICameraServiceListener listener);
-
- int getCameraCharacteristics(int cameraId, out CameraMetadataNative info);
-
- /**
- * The java stubs for this method are not intended to be used. Please use
- * the native stub in frameworks/av/include/camera/ICameraService.h instead.
- * The BinderHolder output is being used as a placeholder, and will not be
- * well-formatted in the generated java method.
- */
- int getCameraVendorTagDescriptor(out BinderHolder desc);
-
- // Writes the camera1 parameters into a single-element array.
- int getLegacyParameters(int cameraId, out String[] parameters);
- // Determines if a particular API version is supported; see ICameraService.h for version defines
- int supportsCameraApi(int cameraId, int apiVersion);
-
- int connectLegacy(ICameraClient client, int cameraId,
- int halVersion,
- String opPackageName,
- int clientUid,
- // Container for an ICamera object
- out BinderHolder device);
-
- int setTorchMode(String CameraId, boolean enabled, IBinder clientBinder);
-
- /**
- * Notify the camera service of a system event. Should only be called from system_server.
- *
- * Callers require the android.permission.CAMERA_SEND_SYSTEM_EVENTS permission.
- */
- oneway void notifySystemEvent(int eventId, in int[] args);
-}
diff --git a/core/java/android/hardware/ICameraServiceProxy.aidl b/core/java/android/hardware/ICameraServiceProxy.aidl
deleted file mode 100644
index 0e654d5..0000000
--- a/core/java/android/hardware/ICameraServiceProxy.aidl
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware;
-
-/**
- * Binder interface for the camera service proxy running in system_server.
- *
- * Keep in sync with frameworks/av/include/camera/ICameraServiceProxy.h
- *
- * @hide
- */
-interface ICameraServiceProxy
-{
- /**
- * Ping the service proxy to update the valid users for the camera service.
- */
- oneway void pingForUserUpdate();
-
- /**
- * Update the status of a camera device
- */
- oneway void notifyCameraState(String cameraId, int newCameraState);
-}
diff --git a/core/java/android/hardware/SensorEventListener.java b/core/java/android/hardware/SensorEventListener.java
index 0d859fb..0c059ba 100644
--- a/core/java/android/hardware/SensorEventListener.java
+++ b/core/java/android/hardware/SensorEventListener.java
@@ -18,28 +18,33 @@
/**
* Used for receiving notifications from the SensorManager when
- * sensor values have changed.
+ * there is new sensor data.
*/
public interface SensorEventListener {
/**
- * Called when sensor values have changed.
+ * Called when there is a new sensor event. Note that "on changed"
+ * is somewhat of a misnomer, as this will also be called if we have a
+ * new reading from a sensor with the exact same sensor values (but a
+ * newer timestamp).
+ *
* <p>See {@link android.hardware.SensorManager SensorManager}
* for details on possible sensor types.
* <p>See also {@link android.hardware.SensorEvent SensorEvent}.
- *
+ *
* <p><b>NOTE:</b> The application doesn't own the
* {@link android.hardware.SensorEvent event}
* object passed as a parameter and therefore cannot hold on to it.
* The object may be part of an internal pool and may be reused by
* the framework.
*
- * @param event the {@link android.hardware.SensorEvent SensorEvent}.
+ * @param event the {@link android.hardware.SensorEvent SensorEvent}.
*/
public void onSensorChanged(SensorEvent event);
/**
- * Called when the accuracy of the registered sensor has changed.
+ * Called when the accuracy of the registered sensor has changed. Unlike
+ * onSensorChanged(), this is only called when this accuracy value changes.
*
* <p>See the SENSOR_STATUS_* constants in
* {@link android.hardware.SensorManager SensorManager} for details.
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index f0b17c30..5684aa5 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -46,7 +46,7 @@
* is an example of a trigger sensor.
* </p>
* <pre class="prettyprint">
- * public class SensorActivity extends Activity, implements SensorEventListener {
+ * public class SensorActivity extends Activity implements SensorEventListener {
* private final SensorManager mSensorManager;
* private final Sensor mAccelerometer;
*
diff --git a/core/java/android/hardware/SerialManager.java b/core/java/android/hardware/SerialManager.java
index e0680bf22..83f7649 100644
--- a/core/java/android/hardware/SerialManager.java
+++ b/core/java/android/hardware/SerialManager.java
@@ -14,13 +14,11 @@
* limitations under the License.
*/
-
package android.hardware;
import android.content.Context;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
-import android.util.Log;
import java.io.IOException;
@@ -50,8 +48,7 @@
try {
return mService.getSerialPorts();
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in getSerialPorts", e);
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -77,8 +74,7 @@
throw new IOException("Could not open serial port " + name);
}
} catch (RemoteException e) {
- Log.e(TAG, "exception in UsbManager.openDevice", e);
+ throw e.rethrowFromSystemServer();
}
- return null;
}
}
diff --git a/core/java/android/hardware/camera2/CameraAccessException.java b/core/java/android/hardware/camera2/CameraAccessException.java
index 933ce0d..f9b659c 100644
--- a/core/java/android/hardware/camera2/CameraAccessException.java
+++ b/core/java/android/hardware/camera2/CameraAccessException.java
@@ -114,12 +114,12 @@
}
public CameraAccessException(@AccessError int problem, String message) {
- super(message);
+ super(getCombinedMessage(problem, message));
mReason = problem;
}
public CameraAccessException(@AccessError int problem, String message, Throwable cause) {
- super(message, cause);
+ super(getCombinedMessage(problem, message), cause);
mReason = problem;
}
@@ -151,4 +151,37 @@
}
return null;
}
+
+ private static String getCombinedMessage(@AccessError int problem, String message) {
+ String problemString = getProblemString(problem);
+ return String.format("%s (%d): %s", problemString, problem, message);
+ }
+
+ private static String getProblemString(int problem) {
+ String problemString;
+ switch (problem) {
+ case CAMERA_IN_USE:
+ problemString = "CAMERA_IN_USE";
+ break;
+ case MAX_CAMERAS_IN_USE:
+ problemString = "MAX_CAMERAS_IN_USE";
+ break;
+ case CAMERA_DISCONNECTED:
+ problemString = "CAMERA_DISCONNECTED";
+ break;
+ case CAMERA_DISABLED:
+ problemString = "CAMERA_DISABLED";
+ break;
+ case CAMERA_ERROR:
+ problemString = "CAMERA_ERROR";
+ break;
+ case CAMERA_DEPRECATED_HAL:
+ problemString = "CAMERA_DEPRECATED_HAL";
+ break;
+ default:
+ problemString = "<UNKNOWN ERROR>";
+ }
+ return problemString;
+ }
+
}
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 51796eb..b3c8e3b 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -26,15 +26,14 @@
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.legacy.CameraDeviceUserShim;
import android.hardware.camera2.legacy.LegacyMetadataMapper;
-import android.hardware.camera2.utils.CameraServiceBinderDecorator;
-import android.hardware.camera2.utils.CameraRuntimeException;
-import android.hardware.camera2.utils.BinderHolder;
import android.os.IBinder;
import android.os.Binder;
+import android.os.DeadObjectException;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
import android.util.Log;
import android.util.ArrayMap;
@@ -240,25 +239,19 @@
if (!supportsCamera2ApiLocked(cameraId)) {
// Legacy backwards compatibility path; build static info from the camera
// parameters
- String[] outParameters = new String[1];
+ String parameters = cameraService.getLegacyParameters(id);
- cameraService.getLegacyParameters(id, /*out*/outParameters);
- String parameters = outParameters[0];
-
- CameraInfo info = new CameraInfo();
- cameraService.getCameraInfo(id, /*out*/info);
+ CameraInfo info = cameraService.getCameraInfo(id);
characteristics = LegacyMetadataMapper.createCharacteristics(parameters, info);
} else {
// Normal path: Get the camera characteristics directly from the camera service
- CameraMetadataNative info = new CameraMetadataNative();
-
- cameraService.getCameraCharacteristics(id, info);
+ CameraMetadataNative info = cameraService.getCameraCharacteristics(id);
characteristics = new CameraCharacteristics(info);
}
- } catch (CameraRuntimeException e) {
- throw e.asChecked();
+ } catch (ServiceSpecificException e) {
+ throwAsPublicException(e);
} catch (RemoteException e) {
// Camera service died - act as if the camera was disconnected
throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
@@ -292,85 +285,83 @@
throws CameraAccessException {
CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
CameraDevice device = null;
- try {
- synchronized (mLock) {
+ synchronized (mLock) {
- ICameraDeviceUser cameraUser = null;
+ ICameraDeviceUser cameraUser = null;
- android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
- new android.hardware.camera2.impl.CameraDeviceImpl(
- cameraId,
- callback,
- handler,
- characteristics);
+ android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
+ new android.hardware.camera2.impl.CameraDeviceImpl(
+ cameraId,
+ callback,
+ handler,
+ characteristics);
- BinderHolder holder = new BinderHolder();
+ ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
- ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
- int id = Integer.parseInt(cameraId);
- try {
- if (supportsCamera2ApiLocked(cameraId)) {
- // Use cameraservice's cameradeviceclient implementation for HAL3.2+ devices
- ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
- if (cameraService == null) {
- throw new CameraRuntimeException(
- CameraAccessException.CAMERA_DISCONNECTED,
- "Camera service is currently unavailable");
- }
- cameraService.connectDevice(callbacks, id,
- mContext.getOpPackageName(), USE_CALLING_UID, holder);
- cameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
- } else {
- // Use legacy camera implementation for HAL1 devices
- Log.i(TAG, "Using legacy camera HAL.");
- cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks, id);
- }
- } catch (CameraRuntimeException e) {
- if (e.getReason() == CameraAccessException.CAMERA_DEPRECATED_HAL) {
- throw new AssertionError("Should've gone down the shim path");
- } else if (e.getReason() == CameraAccessException.CAMERA_IN_USE ||
- e.getReason() == CameraAccessException.MAX_CAMERAS_IN_USE ||
- e.getReason() == CameraAccessException.CAMERA_DISABLED ||
- e.getReason() == CameraAccessException.CAMERA_DISCONNECTED ||
- e.getReason() == CameraAccessException.CAMERA_ERROR) {
- // Received one of the known connection errors
- // The remote camera device cannot be connected to, so
- // set the local camera to the startup error state
- deviceImpl.setRemoteFailure(e);
-
- if (e.getReason() == CameraAccessException.CAMERA_DISABLED ||
- e.getReason() == CameraAccessException.CAMERA_DISCONNECTED ||
- e.getReason() == CameraAccessException.CAMERA_IN_USE) {
- // Per API docs, these failures call onError and throw
- throw e.asChecked();
- }
- } else {
- // Unexpected failure - rethrow
- throw e;
- }
- } catch (RemoteException e) {
- // Camera service died - act as if it's a CAMERA_DISCONNECTED case
- CameraRuntimeException ce = new CameraRuntimeException(
- CameraAccessException.CAMERA_DISCONNECTED,
- "Camera service is currently unavailable", e);
- deviceImpl.setRemoteFailure(ce);
- throw ce.asChecked();
- }
-
- // TODO: factor out callback to be non-nested, then move setter to constructor
- // For now, calling setRemoteDevice will fire initial
- // onOpened/onUnconfigured callbacks.
- deviceImpl.setRemoteDevice(cameraUser);
- device = deviceImpl;
+ int id;
+ try {
+ id = Integer.parseInt(cameraId);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Expected cameraId to be numeric, but it was: "
+ + cameraId);
}
- } catch (NumberFormatException e) {
- throw new IllegalArgumentException("Expected cameraId to be numeric, but it was: "
- + cameraId);
- } catch (CameraRuntimeException e) {
- throw e.asChecked();
+ try {
+ if (supportsCamera2ApiLocked(cameraId)) {
+ // Use cameraservice's cameradeviceclient implementation for HAL3.2+ devices
+ ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
+ if (cameraService == null) {
+ throw new ServiceSpecificException(
+ ICameraService.ERROR_DISCONNECTED,
+ "Camera service is currently unavailable");
+ }
+ cameraUser = cameraService.connectDevice(callbacks, id,
+ mContext.getOpPackageName(), USE_CALLING_UID);
+ } else {
+ // Use legacy camera implementation for HAL1 devices
+ Log.i(TAG, "Using legacy camera HAL.");
+ cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks, id);
+ }
+ } catch (ServiceSpecificException e) {
+ if (e.errorCode == ICameraService.ERROR_DEPRECATED_HAL) {
+ throw new AssertionError("Should've gone down the shim path");
+ } else if (e.errorCode == ICameraService.ERROR_CAMERA_IN_USE ||
+ e.errorCode == ICameraService.ERROR_MAX_CAMERAS_IN_USE ||
+ e.errorCode == ICameraService.ERROR_DISABLED ||
+ e.errorCode == ICameraService.ERROR_DISCONNECTED ||
+ e.errorCode == ICameraService.ERROR_INVALID_OPERATION) {
+ // Received one of the known connection errors
+ // The remote camera device cannot be connected to, so
+ // set the local camera to the startup error state
+ deviceImpl.setRemoteFailure(e);
+
+ if (e.errorCode == ICameraService.ERROR_DISABLED ||
+ e.errorCode == ICameraService.ERROR_DISCONNECTED ||
+ e.errorCode == ICameraService.ERROR_CAMERA_IN_USE) {
+ // Per API docs, these failures call onError and throw
+ throwAsPublicException(e);
+ }
+ } else {
+ // Unexpected failure - rethrow
+ throwAsPublicException(e);
+ }
+ } catch (RemoteException e) {
+ // Camera service died - act as if it's a CAMERA_DISCONNECTED case
+ ServiceSpecificException sse = new ServiceSpecificException(
+ ICameraService.ERROR_DISCONNECTED,
+ "Camera service is currently unavailable");
+ deviceImpl.setRemoteFailure(sse);
+ throwAsPublicException(sse);
+ }
+
+ // TODO: factor out callback to be non-nested, then move setter to constructor
+ // For now, calling setRemoteDevice will fire initial
+ // onOpened/onUnconfigured callbacks.
+ deviceImpl.setRemoteDevice(cameraUser);
+ device = deviceImpl;
}
+
return device;
}
@@ -602,6 +593,56 @@
}
/**
+ * Convert ServiceSpecificExceptions and Binder RemoteExceptions from camera binder interfaces
+ * into the correct public exceptions.
+ *
+ * @hide
+ */
+ public static void throwAsPublicException(Throwable t) throws CameraAccessException {
+ if (t instanceof ServiceSpecificException) {
+ ServiceSpecificException e = (ServiceSpecificException) t;
+ int reason = CameraAccessException.CAMERA_ERROR;
+ switch(e.errorCode) {
+ case ICameraService.ERROR_DISCONNECTED:
+ reason = CameraAccessException.CAMERA_DISCONNECTED;
+ break;
+ case ICameraService.ERROR_DISABLED:
+ reason = CameraAccessException.CAMERA_DISABLED;
+ break;
+ case ICameraService.ERROR_CAMERA_IN_USE:
+ reason = CameraAccessException.CAMERA_IN_USE;
+ break;
+ case ICameraService.ERROR_MAX_CAMERAS_IN_USE:
+ reason = CameraAccessException.MAX_CAMERAS_IN_USE;
+ break;
+ case ICameraService.ERROR_DEPRECATED_HAL:
+ reason = CameraAccessException.CAMERA_DEPRECATED_HAL;
+ break;
+ case ICameraService.ERROR_ILLEGAL_ARGUMENT:
+ case ICameraService.ERROR_ALREADY_EXISTS:
+ throw new IllegalArgumentException(e.getMessage(), e);
+ case ICameraService.ERROR_PERMISSION_DENIED:
+ throw new SecurityException(e.getMessage(), e);
+ case ICameraService.ERROR_TIMED_OUT:
+ case ICameraService.ERROR_INVALID_OPERATION:
+ default:
+ reason = CameraAccessException.CAMERA_ERROR;
+ }
+ throw new CameraAccessException(reason, e.getMessage(), e);
+ } else if (t instanceof DeadObjectException) {
+ throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
+ "Camera service has died unexpectedly",
+ t);
+ } else if (t instanceof RemoteException) {
+ throw new UnsupportedOperationException("An unknown RemoteException was thrown" +
+ " which should never happen.", t);
+ } else if (t instanceof RuntimeException) {
+ RuntimeException e = (RuntimeException) t;
+ throw e;
+ }
+ }
+
+ /**
* Return or create the list of currently connected camera devices.
*
* <p>In case of errors connecting to the camera service, will return an empty list.</p>
@@ -619,34 +660,32 @@
try {
numCameras = cameraService.getNumberOfCameras(CAMERA_TYPE_ALL);
- } catch(CameraRuntimeException e) {
- throw e.asChecked();
+ } catch(ServiceSpecificException e) {
+ throwAsPublicException(e);
} catch (RemoteException e) {
// camera service just died - if no camera service, then no devices
return deviceIdList;
}
- CameraMetadataNative info = new CameraMetadataNative();
for (int i = 0; i < numCameras; ++i) {
// Non-removable cameras use integers starting at 0 for their
// identifiers
boolean isDeviceSupported = false;
try {
- cameraService.getCameraCharacteristics(i, info);
+ CameraMetadataNative info = cameraService.getCameraCharacteristics(i);
if (!info.isEmpty()) {
isDeviceSupported = true;
} else {
throw new AssertionError("Expected to get non-empty characteristics");
}
- } catch(IllegalArgumentException e) {
- // Got a BAD_VALUE from service, meaning that this
- // device is not supported.
- } catch(CameraRuntimeException e) {
+ } catch(ServiceSpecificException e) {
// DISCONNECTED means that the HAL reported an low-level error getting the
- // device info; skip listing the device. Other errors,
+ // device info; ILLEGAL_ARGUMENT means that this devices is not supported.
+ // Skip listing the device. Other errors,
// propagate exception onward
- if (e.getReason() != CameraAccessException.CAMERA_DISCONNECTED) {
- throw e.asChecked();
+ if (e.errorCode != ICameraService.ERROR_DISCONNECTED ||
+ e.errorCode != ICameraService.ERROR_ILLEGAL_ARGUMENT) {
+ throwAsPublicException(e);
}
} catch(RemoteException e) {
// Camera service died - no devices to list
@@ -699,17 +738,7 @@
// If no camera service, no support
if (cameraService == null) return false;
- int res = cameraService.supportsCameraApi(id, apiVersion);
-
- if (res != CameraServiceBinderDecorator.NO_ERROR) {
- throw new AssertionError("Unexpected value " + res);
- }
- return true;
- } catch (CameraRuntimeException e) {
- if (e.getReason() != CameraAccessException.CAMERA_DEPRECATED_HAL) {
- throw e;
- }
- // API level is not supported
+ return cameraService.supportsCameraApi(id, apiVersion);
} catch (RemoteException e) {
// Camera service is now down, no support for any API level
}
@@ -737,21 +766,6 @@
*/
private static final String CAMERA_SERVICE_BINDER_NAME = "media.camera";
- // Keep up-to-date with ICameraServiceListener.h
-
- // Device physically unplugged
- public static final int STATUS_NOT_PRESENT = 0;
- // Device physically has been plugged in
- // and the camera can be used exclusively
- public static final int STATUS_PRESENT = 1;
- // Device physically has been plugged in
- // but it will not be connect-able until enumeration is complete
- public static final int STATUS_ENUMERATING = 2;
- // Camera is in use by another app and cannot be used exclusively
- public static final int STATUS_NOT_AVAILABLE = 0x80000000;
-
- // End enums shared with ICameraServiceListener.h
-
// Camera ID -> Status map
private final ArrayMap<String, Integer> mDeviceStatus = new ArrayMap<String, Integer>();
@@ -759,17 +773,6 @@
private final ArrayMap<AvailabilityCallback, Handler> mCallbackMap =
new ArrayMap<AvailabilityCallback, Handler>();
- // Keep up-to-date with ICameraServiceListener.h
-
- // torch mode has become not available to set via setTorchMode().
- public static final int TORCH_STATUS_NOT_AVAILABLE = 0;
- // torch mode is off and available to be turned on via setTorchMode().
- public static final int TORCH_STATUS_AVAILABLE_OFF = 1;
- // torch mode is on and available to be turned off via setTorchMode().
- public static final int TORCH_STATUS_AVAILABLE_ON = 2;
-
- // End enums shared with ICameraServiceListener.h
-
// torch client binder to set the torch mode with.
private Binder mTorchClientBinder = new Binder();
@@ -839,29 +842,20 @@
return;
}
- ICameraService cameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder);
-
- /**
- * Wrap the camera service in a decorator which automatically translates return codes
- * into exceptions.
- */
- ICameraService cameraService =
- CameraServiceBinderDecorator.newInstance(cameraServiceRaw);
+ ICameraService cameraService = ICameraService.Stub.asInterface(cameraServiceBinder);
try {
- CameraServiceBinderDecorator.throwOnError(
- CameraMetadataNative.nativeSetupGlobalVendorTagDescriptor());
- } catch (CameraRuntimeException e) {
- handleRecoverableSetupErrors(e, "Failed to set up vendor tags");
+ CameraMetadataNative.setupGlobalVendorTagDescriptor();
+ } catch (ServiceSpecificException e) {
+ handleRecoverableSetupErrors(e);
}
try {
cameraService.addListener(this);
mCameraService = cameraService;
- } catch(CameraRuntimeException e) {
+ } catch(ServiceSpecificException e) {
// Unexpected failure
- throw new IllegalStateException("Failed to register a camera service listener",
- e.asChecked());
+ throw new IllegalStateException("Failed to register a camera service listener", e);
} catch (RemoteException e) {
// Camera service is now down, leave mCameraService as null
}
@@ -881,16 +875,9 @@
}
try {
- int status = cameraService.setTorchMode(cameraId, enabled, mTorchClientBinder);
- } catch(CameraRuntimeException e) {
- int problem = e.getReason();
- switch (problem) {
- case CameraAccessException.CAMERA_ERROR:
- throw new IllegalArgumentException(
- "the camera device doesn't have a flash unit.");
- default:
- throw e.asChecked();
- }
+ cameraService.setTorchMode(cameraId, enabled, mTorchClientBinder);
+ } catch(ServiceSpecificException e) {
+ throwAsPublicException(e);
} catch (RemoteException e) {
throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
"Camera service is currently unavailable");
@@ -898,21 +885,19 @@
}
}
- private void handleRecoverableSetupErrors(CameraRuntimeException e, String msg) {
- int problem = e.getReason();
- switch (problem) {
- case CameraAccessException.CAMERA_DISCONNECTED:
- String errorMsg = CameraAccessException.getDefaultMessage(problem);
- Log.w(TAG, msg + ": " + errorMsg);
+ private void handleRecoverableSetupErrors(ServiceSpecificException e) {
+ switch (e.errorCode) {
+ case ICameraService.ERROR_DISCONNECTED:
+ Log.w(TAG, e.getMessage());
break;
default:
- throw new IllegalStateException(msg, e.asChecked());
+ throw new IllegalStateException(e);
}
}
private boolean isAvailable(int status) {
switch (status) {
- case STATUS_PRESENT:
+ case ICameraServiceListener.STATUS_PRESENT:
return true;
default:
return false;
@@ -921,10 +906,10 @@
private boolean validStatus(int status) {
switch (status) {
- case STATUS_NOT_PRESENT:
- case STATUS_PRESENT:
- case STATUS_ENUMERATING:
- case STATUS_NOT_AVAILABLE:
+ case ICameraServiceListener.STATUS_NOT_PRESENT:
+ case ICameraServiceListener.STATUS_PRESENT:
+ case ICameraServiceListener.STATUS_ENUMERATING:
+ case ICameraServiceListener.STATUS_NOT_AVAILABLE:
return true;
default:
return false;
@@ -933,9 +918,9 @@
private boolean validTorchStatus(int status) {
switch (status) {
- case TORCH_STATUS_NOT_AVAILABLE:
- case TORCH_STATUS_AVAILABLE_ON:
- case TORCH_STATUS_AVAILABLE_OFF:
+ case ICameraServiceListener.TORCH_STATUS_NOT_AVAILABLE:
+ case ICameraServiceListener.TORCH_STATUS_AVAILABLE_ON:
+ case ICameraServiceListener.TORCH_STATUS_AVAILABLE_OFF:
return true;
default:
return false;
@@ -966,14 +951,14 @@
private void postSingleTorchUpdate(final TorchCallback callback, final Handler handler,
final String id, final int status) {
switch(status) {
- case TORCH_STATUS_AVAILABLE_ON:
- case TORCH_STATUS_AVAILABLE_OFF:
+ case ICameraServiceListener.TORCH_STATUS_AVAILABLE_ON:
+ case ICameraServiceListener.TORCH_STATUS_AVAILABLE_OFF:
handler.post(
new Runnable() {
@Override
public void run() {
callback.onTorchModeChanged(id, status ==
- TORCH_STATUS_AVAILABLE_ON);
+ ICameraServiceListener.TORCH_STATUS_AVAILABLE_ON);
}
});
break;
@@ -1220,11 +1205,12 @@
// and torch statuses will be updated.
for (int i = 0; i < mDeviceStatus.size(); i++) {
String cameraId = mDeviceStatus.keyAt(i);
- onStatusChangedLocked(STATUS_NOT_PRESENT, cameraId);
+ onStatusChangedLocked(ICameraServiceListener.STATUS_NOT_PRESENT, cameraId);
}
for (int i = 0; i < mTorchStatus.size(); i++) {
String cameraId = mTorchStatus.keyAt(i);
- onTorchStatusChangedLocked(TORCH_STATUS_NOT_AVAILABLE, cameraId);
+ onTorchStatusChangedLocked(ICameraServiceListener.TORCH_STATUS_NOT_AVAILABLE,
+ cameraId);
}
scheduleCameraServiceReconnectionLocked();
diff --git a/core/java/android/hardware/camera2/CaptureRequest.aidl b/core/java/android/hardware/camera2/CaptureRequest.aidl
deleted file mode 100644
index 0b7d5ba..0000000
--- a/core/java/android/hardware/camera2/CaptureRequest.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.hardware.camera2;
-
-/** @hide */
-parcelable CaptureRequest;
diff --git a/core/java/android/hardware/camera2/DngCreator.java b/core/java/android/hardware/camera2/DngCreator.java
index 57a080b..9478dc0 100644
--- a/core/java/android/hardware/camera2/DngCreator.java
+++ b/core/java/android/hardware/camera2/DngCreator.java
@@ -137,6 +137,11 @@
throw new IllegalArgumentException("Orientation " + orientation +
" is not a valid EXIF orientation value");
}
+ // ExifInterface and TIFF/EP spec differ on definition of
+ // "Unknown" orientation; other values map directly
+ if (orientation == ExifInterface.ORIENTATION_UNDEFINED) {
+ orientation = TAG_ORIENTATION_UNKNOWN;
+ }
nativeSetOrientation(orientation);
return this;
}
@@ -443,7 +448,7 @@
private static final String GPS_LONG_REF_WEST = "W";
private static final String GPS_DATE_FORMAT_STR = "yyyy:MM:dd";
- private static final String TIFF_DATETIME_FORMAT = "yyyy:MM:dd kk:mm:ss";
+ private static final String TIFF_DATETIME_FORMAT = "yyyy:MM:dd HH:mm:ss";
private static final DateFormat sExifGPSDateStamp = new SimpleDateFormat(GPS_DATE_FORMAT_STR);
private static final DateFormat sDateTimeStampFormat =
new SimpleDateFormat(TIFF_DATETIME_FORMAT);
@@ -458,6 +463,9 @@
private static final int DEFAULT_PIXEL_STRIDE = 2; // bytes per sample
private static final int BYTES_PER_RGB_PIX = 3; // byts per pixel
+ // TIFF tag values needed to map between public API and TIFF spec
+ private static final int TAG_ORIENTATION_UNKNOWN = 9;
+
/**
* Offset, rowStride, and pixelStride are given in bytes. Height and width are given in pixels.
*/
diff --git a/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl b/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl
deleted file mode 100644
index 151c918..0000000
--- a/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.hardware.camera2;
-
-import android.hardware.camera2.impl.CameraMetadataNative;
-import android.hardware.camera2.impl.CaptureResultExtras;
-
-/** @hide */
-interface ICameraDeviceCallbacks
-{
- /**
- * Keep up-to-date with frameworks/av/include/camera/camera2/ICameraDeviceCallbacks.h
- */
-
- oneway void onDeviceError(int errorCode, in CaptureResultExtras resultExtras);
- oneway void onDeviceIdle();
- oneway void onCaptureStarted(in CaptureResultExtras resultExtras, long timestamp);
- oneway void onResultReceived(in CameraMetadataNative result,
- in CaptureResultExtras resultExtras);
- oneway void onPrepared(int streamId);
-}
diff --git a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl b/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
deleted file mode 100644
index c9c9abc..0000000
--- a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.hardware.camera2;
-
-import android.hardware.camera2.CaptureRequest;
-import android.hardware.camera2.impl.CameraMetadataNative;
-import android.hardware.camera2.params.OutputConfiguration;
-import android.hardware.camera2.utils.LongParcelable;
-import android.view.Surface;
-
-/** @hide */
-interface ICameraDeviceUser
-{
- /**
- * Keep up-to-date with frameworks/av/include/camera/camera2/ICameraDeviceUser.h and
- * frameworks/base/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
- */
- void disconnect();
-
- // ints here are status_t
-
- // non-negative value is the requestId. negative value is status_t
- int submitRequest(in CaptureRequest request, boolean streaming,
- out LongParcelable lastFrameNumber);
-
- int submitRequestList(in List<CaptureRequest> requestList, boolean streaming,
- out LongParcelable lastFrameNumber);
-
- int cancelRequest(int requestId, out LongParcelable lastFrameNumber);
-
- /**
- * Begin the device configuration.
- *
- * <p>
- * beginConfigure must be called before any call to deleteStream, createStream,
- * or endConfigure. It is not valid to call this when the device is not idle.
- * <p>
- */
- int beginConfigure();
-
- /**
- * End the device configuration.
- *
- * <p>
- * endConfigure must be called after stream configuration is complete (i.e. after
- * a call to beginConfigure and subsequent createStream/deleteStream calls). This
- * must be called before any requests can be submitted.
- * <p>
- */
- int endConfigure(boolean isConstrainedHighSpeed);
-
- int deleteStream(int streamId);
-
- // non-negative value is the stream ID. negative value is status_t
- int createStream(in OutputConfiguration outputConfiguration);
-
- /**
- * Create an input stream
- *
- * <p>Create an input stream of width, height, and format</p>
- *
- * @param width Width of the input buffers
- * @param height Height of the input buffers
- * @param format Format of the input buffers. One of HAL_PIXEL_FORMAT_*.
- *
- * @return stream ID if it's a non-negative value. status_t if it's a negative value.
- */
- int createInputStream(int width, int height, int format);
-
- /**
- * Get the surface of the input stream.
- *
- * <p>It's valid to call this method only after a stream configuration is completed
- * successfully and the stream configuration includes a input stream.</p>
- *
- * @param surface An output argument for the surface of the input stream buffer queue.
- */
- int getInputSurface(out Surface surface);
-
- int createDefaultRequest(int templateId, out CameraMetadataNative request);
-
- int getCameraInfo(out CameraMetadataNative info);
-
- int waitUntilIdle();
-
- int flush(out LongParcelable lastFrameNumber);
-
- int prepare(int streamId);
-
- int tearDown(int streamId);
-
- int prepare2(int maxCount, int streamId);
-}
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 3aba0d1..00dd780 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -33,14 +33,14 @@
import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.params.ReprocessFormatsMap;
import android.hardware.camera2.params.StreamConfigurationMap;
-import android.hardware.camera2.utils.CameraBinderDecorator;
-import android.hardware.camera2.utils.CameraRuntimeException;
-import android.hardware.camera2.utils.LongParcelable;
+import android.hardware.camera2.utils.SubmitInfo;
import android.hardware.camera2.utils.SurfaceUtils;
+import android.hardware.ICameraService;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
+import android.os.ServiceSpecificException;
import android.util.Log;
import android.util.Range;
import android.util.Size;
@@ -70,7 +70,7 @@
private static final int REQUEST_ID_NONE = -1;
// TODO: guard every function with if (!mRemoteDevice) check (if it was closed)
- private ICameraDeviceUser mRemoteDevice;
+ private ICameraDeviceUserWrapper mRemoteDevice;
// Lock to synchronize cross-thread access to device public interface
final Object mInterfaceLock = new Object(); // access from this class and Session only!
@@ -267,7 +267,7 @@
// If setRemoteFailure already called, do nothing
if (mInError) return;
- mRemoteDevice = CameraBinderDecorator.newInstance(remoteDevice);
+ mRemoteDevice = new ICameraDeviceUserWrapper(remoteDevice);
mDeviceHandler.post(mCallOnOpened);
mDeviceHandler.post(mCallOnUnconfigured);
@@ -280,28 +280,29 @@
* <p>This places the camera device in the error state and informs the callback.
* Use in place of setRemoteDevice() when startup fails.</p>
*/
- public void setRemoteFailure(final CameraRuntimeException failure) {
+ public void setRemoteFailure(final ServiceSpecificException failure) {
int failureCode = StateCallback.ERROR_CAMERA_DEVICE;
boolean failureIsError = true;
- switch (failure.getReason()) {
- case CameraAccessException.CAMERA_IN_USE:
+ switch (failure.errorCode) {
+ case ICameraService.ERROR_CAMERA_IN_USE:
failureCode = StateCallback.ERROR_CAMERA_IN_USE;
break;
- case CameraAccessException.MAX_CAMERAS_IN_USE:
+ case ICameraService.ERROR_MAX_CAMERAS_IN_USE:
failureCode = StateCallback.ERROR_MAX_CAMERAS_IN_USE;
break;
- case CameraAccessException.CAMERA_DISABLED:
+ case ICameraService.ERROR_DISABLED:
failureCode = StateCallback.ERROR_CAMERA_DISABLED;
break;
- case CameraAccessException.CAMERA_DISCONNECTED:
+ case ICameraService.ERROR_DISCONNECTED:
failureIsError = false;
break;
- case CameraAccessException.CAMERA_ERROR:
+ case ICameraService.ERROR_INVALID_OPERATION:
failureCode = StateCallback.ERROR_CAMERA_DEVICE;
break;
default:
- Log.wtf(TAG, "Unknown failure in opening camera device: " + failure.getReason());
+ Log.e(TAG, "Unexpected failure in opening camera device: " + failure.errorCode +
+ failure.getMessage());
break;
}
final int code = failureCode;
@@ -430,27 +431,20 @@
}
}
- try {
- mRemoteDevice.endConfigure(isConstrainedHighSpeed);
- }
- catch (IllegalArgumentException e) {
- // OK. camera service can reject stream config if it's not supported by HAL
- // This is only the result of a programmer misusing the camera2 api.
- Log.w(TAG, "Stream configuration failed");
- return false;
- }
+ mRemoteDevice.endConfigure(isConstrainedHighSpeed);
success = true;
- } catch (CameraRuntimeException e) {
- if (e.getReason() == CAMERA_IN_USE) {
- throw new IllegalStateException("The camera is currently busy." +
- " You must wait until the previous operation completes.");
- }
-
- throw e.asChecked();
- } catch (RemoteException e) {
- // impossible
+ } catch (IllegalArgumentException e) {
+ // OK. camera service can reject stream config if it's not supported by HAL
+ // This is only the result of a programmer misusing the camera2 api.
+ Log.w(TAG, "Stream configuration failed due to: " + e.getMessage());
return false;
+ } catch (CameraAccessException e) {
+ if (e.getReason() == CameraAccessException.CAMERA_IN_USE) {
+ throw new IllegalStateException("The camera is currently busy." +
+ " You must wait until the previous operation completes.", e);
+ }
+ throw e;
} finally {
if (success && outputs.size() > 0) {
mDeviceHandler.post(mCallOnIdle);
@@ -594,12 +588,7 @@
configureSuccess = configureStreamsChecked(inputConfig, outputConfigurations,
isConstrainedHighSpeed);
if (configureSuccess == true && inputConfig != null) {
- input = new Surface();
- try {
- mRemoteDevice.getInputSurface(/*out*/input);
- } catch (CameraRuntimeException e) {
- e.asChecked();
- }
+ input = mRemoteDevice.getInputSurface();
}
} catch (CameraAccessException e) {
configureSuccess = false;
@@ -608,9 +597,6 @@
if (DEBUG) {
Log.v(TAG, "createCaptureSession - failed with exception ", e);
}
- } catch (RemoteException e) {
- // impossible
- return;
}
List<Surface> outSurfaces = new ArrayList<>(outputConfigurations.size());
@@ -655,16 +641,9 @@
synchronized(mInterfaceLock) {
checkIfCameraClosedOrInError();
- CameraMetadataNative templatedRequest = new CameraMetadataNative();
+ CameraMetadataNative templatedRequest = null;
- try {
- mRemoteDevice.createDefaultRequest(templateType, /*out*/templatedRequest);
- } catch (CameraRuntimeException e) {
- throw e.asChecked();
- } catch (RemoteException e) {
- // impossible
- return null;
- }
+ templatedRequest = mRemoteDevice.createDefaultRequest(templateType);
CaptureRequest.Builder builder = new CaptureRequest.Builder(
templatedRequest, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE);
@@ -701,14 +680,8 @@
if (streamId == -1) {
throw new IllegalArgumentException("Surface is not part of this session");
}
- try {
- mRemoteDevice.prepare(streamId);
- } catch (CameraRuntimeException e) {
- throw e.asChecked();
- } catch (RemoteException e) {
- // impossible
- return;
- }
+
+ mRemoteDevice.prepare(streamId);
}
}
@@ -728,14 +701,8 @@
if (streamId == -1) {
throw new IllegalArgumentException("Surface is not part of this session");
}
- try {
- mRemoteDevice.prepare2(maxCount, streamId);
- } catch (CameraRuntimeException e) {
- throw e.asChecked();
- } catch (RemoteException e) {
- // impossible
- return;
- }
+
+ mRemoteDevice.prepare2(maxCount, streamId);
}
}
@@ -753,14 +720,8 @@
if (streamId == -1) {
throw new IllegalArgumentException("Surface is not part of this session");
}
- try {
- mRemoteDevice.tearDown(streamId);
- } catch (CameraRuntimeException e) {
- throw e.asChecked();
- } catch (RemoteException e) {
- // impossible
- return;
- }
+
+ mRemoteDevice.tearDown(streamId);
}
}
@@ -875,45 +836,37 @@
synchronized(mInterfaceLock) {
checkIfCameraClosedOrInError();
- int requestId;
-
if (repeating) {
stopRepeating();
}
- LongParcelable lastFrameNumberRef = new LongParcelable();
- try {
- requestId = mRemoteDevice.submitRequestList(requestList, repeating,
- /*out*/lastFrameNumberRef);
- if (DEBUG) {
- Log.v(TAG, "last frame number " + lastFrameNumberRef.getNumber());
- }
- } catch (CameraRuntimeException e) {
- throw e.asChecked();
- } catch (RemoteException e) {
- // impossible
- return -1;
+ SubmitInfo requestInfo;
+
+ CaptureRequest[] requestArray = requestList.toArray(new CaptureRequest[requestList.size()]);
+ requestInfo = mRemoteDevice.submitRequestList(requestArray, repeating);
+ if (DEBUG) {
+ Log.v(TAG, "last frame number " + requestInfo.getLastFrameNumber());
}
if (callback != null) {
- mCaptureCallbackMap.put(requestId, new CaptureCallbackHolder(callback,
- requestList, handler, repeating, mNextSessionId - 1));
+ mCaptureCallbackMap.put(requestInfo.getRequestId(),
+ new CaptureCallbackHolder(
+ callback, requestList, handler, repeating, mNextSessionId - 1));
} else {
if (DEBUG) {
- Log.d(TAG, "Listen for request " + requestId + " is null");
+ Log.d(TAG, "Listen for request " + requestInfo.getRequestId() + " is null");
}
}
- long lastFrameNumber = lastFrameNumberRef.getNumber();
-
if (repeating) {
if (mRepeatingRequestId != REQUEST_ID_NONE) {
- checkEarlyTriggerSequenceComplete(mRepeatingRequestId, lastFrameNumber);
+ checkEarlyTriggerSequenceComplete(mRepeatingRequestId,
+ requestInfo.getLastFrameNumber());
}
- mRepeatingRequestId = requestId;
+ mRepeatingRequestId = requestInfo.getRequestId();
} else {
- mRequestLastFrameNumbersList.add(new RequestLastFrameNumbersHolder(requestList,
- requestId, lastFrameNumber));
+ mRequestLastFrameNumbersList.add(
+ new RequestLastFrameNumbersHolder(requestList, requestInfo));
}
if (mIdle) {
@@ -921,7 +874,7 @@
}
mIdle = false;
- return requestId;
+ return requestInfo.getRequestId();
}
}
@@ -949,19 +902,9 @@
int requestId = mRepeatingRequestId;
mRepeatingRequestId = REQUEST_ID_NONE;
- try {
- LongParcelable lastFrameNumberRef = new LongParcelable();
- mRemoteDevice.cancelRequest(requestId, /*out*/lastFrameNumberRef);
- long lastFrameNumber = lastFrameNumberRef.getNumber();
+ long lastFrameNumber = mRemoteDevice.cancelRequest(requestId);
- checkEarlyTriggerSequenceComplete(requestId, lastFrameNumber);
-
- } catch (CameraRuntimeException e) {
- throw e.asChecked();
- } catch (RemoteException e) {
- // impossible
- return;
- }
+ checkEarlyTriggerSequenceComplete(requestId, lastFrameNumber);
}
}
}
@@ -974,14 +917,8 @@
if (mRepeatingRequestId != REQUEST_ID_NONE) {
throw new IllegalStateException("Active repeating request ongoing");
}
- try {
- mRemoteDevice.waitUntilIdle();
- } catch (CameraRuntimeException e) {
- throw e.asChecked();
- } catch (RemoteException e) {
- // impossible
- return;
- }
+
+ mRemoteDevice.waitUntilIdle();
}
}
@@ -997,19 +934,11 @@
mDeviceHandler.post(mCallOnIdle);
return;
}
- try {
- LongParcelable lastFrameNumberRef = new LongParcelable();
- mRemoteDevice.flush(/*out*/lastFrameNumberRef);
- if (mRepeatingRequestId != REQUEST_ID_NONE) {
- long lastFrameNumber = lastFrameNumberRef.getNumber();
- checkEarlyTriggerSequenceComplete(mRepeatingRequestId, lastFrameNumber);
- mRepeatingRequestId = REQUEST_ID_NONE;
- }
- } catch (CameraRuntimeException e) {
- throw e.asChecked();
- } catch (RemoteException e) {
- // impossible
- return;
+
+ long lastFrameNumber = mRemoteDevice.flush();
+ if (mRepeatingRequestId != REQUEST_ID_NONE) {
+ checkEarlyTriggerSequenceComplete(mRepeatingRequestId, lastFrameNumber);
+ mRepeatingRequestId = REQUEST_ID_NONE;
}
}
}
@@ -1021,14 +950,8 @@
return;
}
- try {
- if (mRemoteDevice != null) {
- mRemoteDevice.disconnect();
- }
- } catch (CameraRuntimeException e) {
- Log.e(TAG, "Exception while closing: ", e.asChecked());
- } catch (RemoteException e) {
- // impossible
+ if (mRemoteDevice != null) {
+ mRemoteDevice.disconnect();
}
// Only want to fire the onClosed callback once;
@@ -1297,14 +1220,14 @@
* Create a request-last-frame-numbers holder with a list of requests, request ID, and
* the last frame number returned by camera service.
*/
- public RequestLastFrameNumbersHolder(List<CaptureRequest> requestList, int requestId,
- long lastFrameNumber) {
+ public RequestLastFrameNumbersHolder(List<CaptureRequest> requestList, SubmitInfo requestInfo) {
long lastRegularFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
long lastReprocessFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
- long frameNumber = lastFrameNumber;
+ long frameNumber = requestInfo.getLastFrameNumber();
- if (lastFrameNumber < requestList.size() - 1) {
- throw new IllegalArgumentException("lastFrameNumber: " + lastFrameNumber +
+ if (requestInfo.getLastFrameNumber() < requestList.size() - 1) {
+ throw new IllegalArgumentException(
+ "lastFrameNumber: " + requestInfo.getLastFrameNumber() +
" should be at least " + (requestList.size() - 1) + " for the number of " +
" requests in the list: " + requestList.size());
}
@@ -1330,7 +1253,7 @@
mLastRegularFrameNumber = lastRegularFrameNumber;
mLastReprocessFrameNumber = lastReprocessFrameNumber;
- mRequestId = requestId;
+ mRequestId = requestInfo.getRequestId();
}
/**
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.aidl b/core/java/android/hardware/camera2/impl/CameraMetadataNative.aidl
deleted file mode 100644
index 4a89129..0000000
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.hardware.camera2.impl;
-
-/** @hide */
-parcelable CameraMetadataNative;
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 12a2910..79eac26 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -58,6 +58,7 @@
import android.location.LocationManager;
import android.os.Parcelable;
import android.os.Parcel;
+import android.os.ServiceSpecificException;
import android.util.Log;
import android.util.Size;
@@ -363,13 +364,24 @@
* Set the global client-side vendor tag descriptor to allow use of vendor
* tags in camera applications.
*
- * @return int A native status_t value corresponding to one of the
- * {@link CameraBinderDecorator} integer constants.
- * @see CameraBinderDecorator#throwOnError
- *
+ * @throws ServiceSpecificException
* @hide
*/
- public static native int nativeSetupGlobalVendorTagDescriptor();
+ public static void setupGlobalVendorTagDescriptor() throws ServiceSpecificException {
+ int err = nativeSetupGlobalVendorTagDescriptor();
+ if (err != 0) {
+ throw new ServiceSpecificException(err, "Failure to set up global vendor tags");
+ }
+ }
+
+ /**
+ * Set the global client-side vendor tag descriptor to allow use of vendor
+ * tags in camera applications.
+ *
+ * @return int An error code corresponding to one of the
+ * {@link ICameraService} error constants, or 0 on success.
+ */
+ private static native int nativeSetupGlobalVendorTagDescriptor();
/**
* Set a camera metadata field to a value. The field definitions can be
diff --git a/core/java/android/hardware/camera2/impl/CaptureResultExtras.aidl b/core/java/android/hardware/camera2/impl/CaptureResultExtras.aidl
deleted file mode 100644
index ebc812a..0000000
--- a/core/java/android/hardware/camera2/impl/CaptureResultExtras.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.hardware.camera2.impl;
-
-/** @hide */
-parcelable CaptureResultExtras;
diff --git a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
new file mode 100644
index 0000000..ddc3fd1
--- /dev/null
+++ b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.impl;
+
+import static android.hardware.camera2.CameraAccessException.CAMERA_DISABLED;
+import static android.hardware.camera2.CameraAccessException.CAMERA_DISCONNECTED;
+import static android.hardware.camera2.CameraAccessException.CAMERA_IN_USE;
+import static android.hardware.camera2.CameraAccessException.CAMERA_ERROR;
+import static android.hardware.camera2.CameraAccessException.MAX_CAMERAS_IN_USE;
+import static android.hardware.camera2.CameraAccessException.CAMERA_DEPRECATED_HAL;
+
+import android.hardware.ICameraService;
+import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.ICameraDeviceUser;
+import android.hardware.camera2.impl.CameraMetadataNative;
+import android.hardware.camera2.params.OutputConfiguration;
+import android.hardware.camera2.utils.SubmitInfo;
+import android.os.RemoteException;
+import android.view.Surface;
+
+/**
+ * A wrapper around ICameraDeviceUser.
+ *
+ * Mainly used to convert ServiceSpecificExceptions to the correct
+ * checked / unchecked exception.
+ *
+ * @hide
+ */
+public class ICameraDeviceUserWrapper {
+
+ private final ICameraDeviceUser mRemoteDevice;
+
+ public ICameraDeviceUserWrapper(ICameraDeviceUser remoteDevice) {
+ if (remoteDevice == null) {
+ throw new NullPointerException("Remote device may not be null");
+ }
+ mRemoteDevice = remoteDevice;
+ }
+
+ public void disconnect() {
+ try {
+ mRemoteDevice.disconnect();
+ } catch (RemoteException t) {
+ // ignore binder errors for disconnect
+ }
+ }
+
+ public SubmitInfo submitRequest(CaptureRequest request, boolean streaming)
+ throws CameraAccessException {
+ try {
+ return mRemoteDevice.submitRequest(request, streaming);
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public SubmitInfo submitRequestList(CaptureRequest[] requestList, boolean streaming)
+ throws CameraAccessException {
+ try {
+ return mRemoteDevice.submitRequestList(requestList, streaming);
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public long cancelRequest(int requestId) throws CameraAccessException {
+ try {
+ return mRemoteDevice.cancelRequest(requestId);
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public void beginConfigure() throws CameraAccessException {
+ try {
+ mRemoteDevice.beginConfigure();
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public void endConfigure(boolean isConstrainedHighSpeed) throws CameraAccessException {
+ try {
+ mRemoteDevice.endConfigure(isConstrainedHighSpeed);
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public void deleteStream(int streamId) throws CameraAccessException {
+ try {
+ mRemoteDevice.deleteStream(streamId);
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public int createStream(OutputConfiguration outputConfiguration)
+ throws CameraAccessException {
+ try {
+ return mRemoteDevice.createStream(outputConfiguration);
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public int createInputStream(int width, int height, int format) throws CameraAccessException {
+ try {
+ return mRemoteDevice.createInputStream(width, height, format);
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public Surface getInputSurface() throws CameraAccessException {
+ try {
+ return mRemoteDevice.getInputSurface();
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public CameraMetadataNative createDefaultRequest(int templateId) throws CameraAccessException {
+ try {
+ return mRemoteDevice.createDefaultRequest(templateId);
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public CameraMetadataNative getCameraInfo() throws CameraAccessException {
+ try {
+ return mRemoteDevice.getCameraInfo();
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public void waitUntilIdle() throws CameraAccessException {
+ try {
+ mRemoteDevice.waitUntilIdle();
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public long flush() throws CameraAccessException {
+ try {
+ return mRemoteDevice.flush();
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public void prepare(int streamId) throws CameraAccessException {
+ try {
+ mRemoteDevice.prepare(streamId);
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public void tearDown(int streamId) throws CameraAccessException {
+ try {
+ mRemoteDevice.tearDown(streamId);
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public void prepare2(int maxCount, int streamId) throws CameraAccessException {
+ try {
+ mRemoteDevice.prepare2(maxCount, streamId);
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+
+}
diff --git a/core/java/android/hardware/camera2/legacy/BurstHolder.java b/core/java/android/hardware/camera2/legacy/BurstHolder.java
index e7b3682..23efe15 100644
--- a/core/java/android/hardware/camera2/legacy/BurstHolder.java
+++ b/core/java/android/hardware/camera2/legacy/BurstHolder.java
@@ -35,10 +35,10 @@
*
* @param requestId id of the burst request.
* @param repeating true if this burst is repeating.
- * @param requests a {@link List} of {@link CaptureRequest}s in this burst.
+ * @param requests the array of {@link CaptureRequest}s for this burst.
* @param jpegSurfaceIds a {@link Collection} of IDs for the surfaces that have jpeg outputs.
*/
- public BurstHolder(int requestId, boolean repeating, List<CaptureRequest> requests,
+ public BurstHolder(int requestId, boolean repeating, CaptureRequest[] requests,
Collection<Long> jpegSurfaceIds) {
mRequestBuilders = new ArrayList<>();
int i = 0;
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
index 798c941..d01c275 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
@@ -16,6 +16,7 @@
package android.hardware.camera2.legacy;
+import android.hardware.ICameraService;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.camera2.CameraAccessException;
@@ -23,12 +24,10 @@
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.ICameraDeviceCallbacks;
import android.hardware.camera2.ICameraDeviceUser;
-import android.hardware.camera2.utils.LongParcelable;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.impl.CaptureResultExtras;
import android.hardware.camera2.params.OutputConfiguration;
-import android.hardware.camera2.utils.CameraBinderDecorator;
-import android.hardware.camera2.utils.CameraRuntimeException;
+import android.hardware.camera2.utils.SubmitInfo;
import android.os.ConditionVariable;
import android.os.IBinder;
import android.os.Looper;
@@ -36,6 +35,7 @@
import android.os.HandlerThread;
import android.os.Message;
import android.os.RemoteException;
+import android.os.ServiceSpecificException;
import android.util.Log;
import android.util.SparseArray;
import android.view.Surface;
@@ -93,7 +93,7 @@
private static int translateErrorsFromCamera1(int errorCode) {
if (errorCode == -EACCES) {
- return CameraBinderDecorator.PERMISSION_DENIED;
+ return ICameraService.ERROR_PERMISSION_DENIED;
}
return errorCode;
@@ -173,7 +173,7 @@
*
* @return int error code
*
- * @throws CameraRuntimeException if the camera open times out with ({@code CAMERA_ERROR})
+ * @throws ServiceSpecificException if the camera open times out with ({@code CAMERA_ERROR})
*/
public int waitForOpen(int timeoutMs) {
// Block until the camera is open asynchronously
@@ -186,7 +186,7 @@
Log.e(TAG, "connectBinderShim - Failed to release camera after timeout ", e);
}
- throw new CameraRuntimeException(CameraAccessException.CAMERA_ERROR);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION);
}
return mInitErrors;
@@ -344,7 +344,7 @@
Camera legacyCamera = init.getCamera();
// Check errors old HAL initialization
- CameraBinderDecorator.throwOnError(initErrors);
+ LegacyExceptionUtils.throwOnServiceError(initErrors);
// Disable shutter sounds (this will work unconditionally) for api2 clients
legacyCamera.disableShutterSound();
@@ -356,8 +356,8 @@
try {
legacyParameters = legacyCamera.getParameters();
} catch (RuntimeException e) {
- throw new CameraRuntimeException(CameraAccessException.CAMERA_ERROR,
- "Unable to get initial parameters", e);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION,
+ "Unable to get initial parameters: " + e.getMessage());
}
CameraCharacteristics characteristics =
@@ -386,101 +386,106 @@
}
@Override
- public int submitRequest(CaptureRequest request, boolean streaming,
- /*out*/LongParcelable lastFrameNumber) {
+ public SubmitInfo submitRequest(CaptureRequest request, boolean streaming) {
if (DEBUG) {
Log.d(TAG, "submitRequest called.");
}
if (mLegacyDevice.isClosed()) {
- Log.e(TAG, "Cannot submit request, device has been closed.");
- return -ENODEV;
+ String err = "Cannot submit request, device has been closed.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
synchronized(mConfigureLock) {
if (mConfiguring) {
- Log.e(TAG, "Cannot submit request, configuration change in progress.");
- return CameraBinderDecorator.INVALID_OPERATION;
+ String err = "Cannot submit request, configuration change in progress.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
}
}
- return mLegacyDevice.submitRequest(request, streaming, lastFrameNumber);
+ return mLegacyDevice.submitRequest(request, streaming);
}
@Override
- public int submitRequestList(List<CaptureRequest> request, boolean streaming,
- /*out*/LongParcelable lastFrameNumber) {
+ public SubmitInfo submitRequestList(CaptureRequest[] request, boolean streaming) {
if (DEBUG) {
Log.d(TAG, "submitRequestList called.");
}
if (mLegacyDevice.isClosed()) {
- Log.e(TAG, "Cannot submit request list, device has been closed.");
- return -ENODEV;
+ String err = "Cannot submit request list, device has been closed.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
synchronized(mConfigureLock) {
if (mConfiguring) {
- Log.e(TAG, "Cannot submit request, configuration change in progress.");
- return CameraBinderDecorator.INVALID_OPERATION;
+ String err = "Cannot submit request, configuration change in progress.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
}
}
- return mLegacyDevice.submitRequestList(request, streaming, lastFrameNumber);
+ return mLegacyDevice.submitRequestList(request, streaming);
}
@Override
- public int cancelRequest(int requestId, /*out*/LongParcelable lastFrameNumber) {
+ public long cancelRequest(int requestId) {
if (DEBUG) {
Log.d(TAG, "cancelRequest called.");
}
if (mLegacyDevice.isClosed()) {
- Log.e(TAG, "Cannot cancel request, device has been closed.");
- return -ENODEV;
+ String err = "Cannot cancel request, device has been closed.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
synchronized(mConfigureLock) {
if (mConfiguring) {
- Log.e(TAG, "Cannot cancel request, configuration change in progress.");
- return CameraBinderDecorator.INVALID_OPERATION;
+ String err = "Cannot cancel request, configuration change in progress.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
}
}
- long lastFrame = mLegacyDevice.cancelRequest(requestId);
- lastFrameNumber.setNumber(lastFrame);
- return CameraBinderDecorator.NO_ERROR;
+ return mLegacyDevice.cancelRequest(requestId);
}
@Override
- public int beginConfigure() {
+ public void beginConfigure() {
if (DEBUG) {
Log.d(TAG, "beginConfigure called.");
}
if (mLegacyDevice.isClosed()) {
- Log.e(TAG, "Cannot begin configure, device has been closed.");
- return -ENODEV;
+ String err = "Cannot begin configure, device has been closed.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
synchronized(mConfigureLock) {
if (mConfiguring) {
- Log.e(TAG, "Cannot begin configure, configuration change already in progress.");
- return CameraBinderDecorator.INVALID_OPERATION;
+ String err = "Cannot begin configure, configuration change already in progress.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
}
mConfiguring = true;
}
- return CameraBinderDecorator.NO_ERROR;
}
@Override
- public int endConfigure(boolean isConstrainedHighSpeed) {
+ public void endConfigure(boolean isConstrainedHighSpeed) {
if (DEBUG) {
Log.d(TAG, "endConfigure called.");
}
if (mLegacyDevice.isClosed()) {
- Log.e(TAG, "Cannot end configure, device has been closed.");
- return -ENODEV;
+ String err = "Cannot end configure, device has been closed.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
ArrayList<Surface> surfaces = null;
synchronized(mConfigureLock) {
if (!mConfiguring) {
- Log.e(TAG, "Cannot end configure, no configuration change in progress.");
- return CameraBinderDecorator.INVALID_OPERATION;
+ String err = "Cannot end configure, no configuration change in progress.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
}
int numSurfaces = mSurfaces.size();
if (numSurfaces > 0) {
@@ -491,32 +496,34 @@
}
mConfiguring = false;
}
- return mLegacyDevice.configureOutputs(surfaces);
+ mLegacyDevice.configureOutputs(surfaces);
}
@Override
- public int deleteStream(int streamId) {
+ public void deleteStream(int streamId) {
if (DEBUG) {
Log.d(TAG, "deleteStream called.");
}
if (mLegacyDevice.isClosed()) {
- Log.e(TAG, "Cannot delete stream, device has been closed.");
- return -ENODEV;
+ String err = "Cannot delete stream, device has been closed.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
synchronized(mConfigureLock) {
if (!mConfiguring) {
- Log.e(TAG, "Cannot delete stream, beginConfigure hasn't been called yet.");
- return CameraBinderDecorator.INVALID_OPERATION;
+ String err = "Cannot delete stream, no configuration change in progress.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
}
int index = mSurfaces.indexOfKey(streamId);
if (index < 0) {
- Log.e(TAG, "Cannot delete stream, stream id " + streamId + " doesn't exist.");
- return CameraBinderDecorator.BAD_VALUE;
+ String err = "Cannot delete stream, stream id " + streamId + " doesn't exist.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err);
}
mSurfaces.removeAt(index);
}
- return CameraBinderDecorator.NO_ERROR;
}
@Override
@@ -525,18 +532,21 @@
Log.d(TAG, "createStream called.");
}
if (mLegacyDevice.isClosed()) {
- Log.e(TAG, "Cannot create stream, device has been closed.");
- return -ENODEV;
+ String err = "Cannot create stream, device has been closed.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
synchronized(mConfigureLock) {
if (!mConfiguring) {
- Log.e(TAG, "Cannot create stream, beginConfigure hasn't been called yet.");
- return CameraBinderDecorator.INVALID_OPERATION;
+ String err = "Cannot create stream, beginConfigure hasn't been called yet.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
}
if (outputConfiguration.getRotation() != OutputConfiguration.ROTATION_0) {
- Log.e(TAG, "Cannot create stream, stream rotation is not supported.");
- return CameraBinderDecorator.INVALID_OPERATION;
+ String err = "Cannot create stream, stream rotation is not supported.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err);
}
int id = ++mSurfaceIdCounter;
mSurfaces.put(id, outputConfiguration.getSurface());
@@ -546,24 +556,27 @@
@Override
public int createInputStream(int width, int height, int format) {
- Log.e(TAG, "creating input stream is not supported on legacy devices");
- return CameraBinderDecorator.INVALID_OPERATION;
+ String err = "Creating input stream is not supported on legacy devices";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
}
@Override
- public int getInputSurface(/*out*/ Surface surface) {
- Log.e(TAG, "getting input surface is not supported on legacy devices");
- return CameraBinderDecorator.INVALID_OPERATION;
+ public Surface getInputSurface() {
+ String err = "Getting input surface is not supported on legacy devices";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
}
@Override
- public int createDefaultRequest(int templateId, /*out*/CameraMetadataNative request) {
+ public CameraMetadataNative createDefaultRequest(int templateId) {
if (DEBUG) {
Log.d(TAG, "createDefaultRequest called.");
}
if (mLegacyDevice.isClosed()) {
- Log.e(TAG, "Cannot create default request, device has been closed.");
- return -ENODEV;
+ String err = "Cannot create default request, device has been closed.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
CameraMetadataNative template;
@@ -571,99 +584,96 @@
template =
LegacyMetadataMapper.createRequestTemplate(mCameraCharacteristics, templateId);
} catch (IllegalArgumentException e) {
- Log.e(TAG, "createDefaultRequest - invalid templateId specified");
- return CameraBinderDecorator.BAD_VALUE;
+ String err = "createDefaultRequest - invalid templateId specified";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err);
}
- request.swap(template);
- return CameraBinderDecorator.NO_ERROR;
+ return template;
}
@Override
- public int getCameraInfo(/*out*/CameraMetadataNative info) {
+ public CameraMetadataNative getCameraInfo() {
if (DEBUG) {
Log.d(TAG, "getCameraInfo called.");
}
// TODO: implement getCameraInfo.
Log.e(TAG, "getCameraInfo unimplemented.");
- return CameraBinderDecorator.NO_ERROR;
+ return null;
}
@Override
- public int waitUntilIdle() throws RemoteException {
+ public void waitUntilIdle() throws RemoteException {
if (DEBUG) {
Log.d(TAG, "waitUntilIdle called.");
}
if (mLegacyDevice.isClosed()) {
- Log.e(TAG, "Cannot wait until idle, device has been closed.");
- return -ENODEV;
+ String err = "Cannot wait until idle, device has been closed.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
synchronized(mConfigureLock) {
if (mConfiguring) {
- Log.e(TAG, "Cannot wait until idle, configuration change in progress.");
- return CameraBinderDecorator.INVALID_OPERATION;
+ String err = "Cannot wait until idle, configuration change in progress.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
}
}
mLegacyDevice.waitUntilIdle();
- return CameraBinderDecorator.NO_ERROR;
}
@Override
- public int flush(/*out*/LongParcelable lastFrameNumber) {
+ public long flush() {
if (DEBUG) {
Log.d(TAG, "flush called.");
}
if (mLegacyDevice.isClosed()) {
- Log.e(TAG, "Cannot flush, device has been closed.");
- return -ENODEV;
+ String err = "Cannot flush, device has been closed.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
synchronized(mConfigureLock) {
if (mConfiguring) {
- Log.e(TAG, "Cannot flush, configuration change in progress.");
- return CameraBinderDecorator.INVALID_OPERATION;
+ String err = "Cannot flush, configuration change in progress.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
}
}
- long lastFrame = mLegacyDevice.flush();
- if (lastFrameNumber != null) {
- lastFrameNumber.setNumber(lastFrame);
- }
- return CameraBinderDecorator.NO_ERROR;
+ return mLegacyDevice.flush();
}
- public int prepare(int streamId) {
+ public void prepare(int streamId) {
if (DEBUG) {
Log.d(TAG, "prepare called.");
}
if (mLegacyDevice.isClosed()) {
- Log.e(TAG, "Cannot prepare stream, device has been closed.");
- return -ENODEV;
+ String err = "Cannot prepare stream, device has been closed.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
// LEGACY doesn't support actual prepare, just signal success right away
mCameraCallbacks.onPrepared(streamId);
-
- return CameraBinderDecorator.NO_ERROR;
}
- public int prepare2(int maxCount, int streamId) {
+ public void prepare2(int maxCount, int streamId) {
// We don't support this in LEGACY mode.
- return prepare(streamId);
+ prepare(streamId);
}
- public int tearDown(int streamId) {
+ public void tearDown(int streamId) {
if (DEBUG) {
Log.d(TAG, "tearDown called.");
}
if (mLegacyDevice.isClosed()) {
- Log.e(TAG, "Cannot tear down stream, device has been closed.");
- return -ENODEV;
+ String err = "Cannot tear down stream, device has been closed.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
// LEGACY doesn't support actual teardown, so just a no-op
-
- return CameraBinderDecorator.NO_ERROR;
}
@Override
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index fddfbde..4c4adea 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -26,14 +26,13 @@
import android.hardware.camera2.ICameraDeviceCallbacks;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.hardware.camera2.utils.ArrayUtils;
-import android.hardware.camera2.utils.CameraBinderDecorator;
-import android.hardware.camera2.utils.LongParcelable;
+import android.hardware.camera2.utils.SubmitInfo;
import android.hardware.camera2.impl.CameraMetadataNative;
-import android.hardware.camera2.utils.CameraRuntimeException;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.RemoteException;
+import android.os.ServiceSpecificException;
import android.util.Log;
import android.util.Pair;
import android.util.Size;
@@ -45,7 +44,6 @@
import java.util.List;
import static android.hardware.camera2.legacy.LegacyExceptionUtils.*;
-import static android.hardware.camera2.utils.CameraBinderDecorator.*;
import static com.android.internal.util.Preconditions.*;
/**
@@ -357,9 +355,9 @@
if (success) {
mConfiguredSurfaces = outputs != null ? new ArrayList<>(outputs) : null;
} else {
- return CameraBinderDecorator.INVALID_OPERATION;
+ return LegacyExceptionUtils.INVALID_OPERATION;
}
- return CameraBinderDecorator.NO_ERROR;
+ return LegacyExceptionUtils.NO_ERROR;
}
/**
@@ -367,17 +365,16 @@
*
* @param requestList a list of capture requests to execute.
* @param repeating {@code true} if this burst is repeating.
- * @param frameNumber an output argument that contains either the frame number of the last frame
- * that will be returned for this request, or the frame number of the last
- * frame that will be returned for the current repeating request if this
- * burst is set to be repeating.
- * @return the request id.
+ * @return the submission info, including the new request id, and the last frame number, which
+ * contains either the frame number of the last frame that will be returned for this request,
+ * or the frame number of the last frame that will be returned for the current repeating
+ * request if this burst is set to be repeating.
*/
- public int submitRequestList(List<CaptureRequest> requestList, boolean repeating,
- /*out*/LongParcelable frameNumber) {
- if (requestList == null || requestList.isEmpty()) {
+ public SubmitInfo submitRequestList(CaptureRequest[] requestList, boolean repeating) {
+ if (requestList == null || requestList.length == 0) {
Log.e(TAG, "submitRequestList - Empty/null requests are not allowed");
- return BAD_VALUE;
+ throw new ServiceSpecificException(BAD_VALUE,
+ "submitRequestList - Empty/null requests are not allowed");
}
List<Long> surfaceIds = (mConfiguredSurfaces == null) ? new ArrayList<Long>() :
@@ -388,28 +385,33 @@
if (request.getTargets().isEmpty()) {
Log.e(TAG, "submitRequestList - "
+ "Each request must have at least one Surface target");
- return BAD_VALUE;
+ throw new ServiceSpecificException(BAD_VALUE,
+ "submitRequestList - "
+ + "Each request must have at least one Surface target");
}
for (Surface surface : request.getTargets()) {
if (surface == null) {
Log.e(TAG, "submitRequestList - Null Surface targets are not allowed");
- return BAD_VALUE;
+ throw new ServiceSpecificException(BAD_VALUE,
+ "submitRequestList - Null Surface targets are not allowed");
} else if (mConfiguredSurfaces == null) {
Log.e(TAG, "submitRequestList - must configure " +
" device with valid surfaces before submitting requests");
- return INVALID_OPERATION;
+ throw new ServiceSpecificException(INVALID_OPERATION,
+ "submitRequestList - must configure " +
+ " device with valid surfaces before submitting requests");
} else if (!containsSurfaceId(surface, surfaceIds)) {
Log.e(TAG, "submitRequestList - cannot use a surface that wasn't configured");
- return BAD_VALUE;
+ throw new ServiceSpecificException(BAD_VALUE,
+ "submitRequestList - cannot use a surface that wasn't configured");
}
}
}
// TODO: further validation of request here
mIdle.close();
- return mRequestThreadManager.submitCaptureRequests(requestList, repeating,
- frameNumber);
+ return mRequestThreadManager.submitCaptureRequests(requestList, repeating);
}
/**
@@ -417,17 +419,14 @@
*
* @param request the capture request to execute.
* @param repeating {@code true} if this request is repeating.
- * @param frameNumber an output argument that contains either the frame number of the last frame
- * that will be returned for this request, or the frame number of the last
- * frame that will be returned for the current repeating request if this
- * request is set to be repeating.
- * @return the request id.
+ * @return the submission info, including the new request id, and the last frame number, which
+ * contains either the frame number of the last frame that will be returned for this request,
+ * or the frame number of the last frame that will be returned for the current repeating
+ * request if this burst is set to be repeating.
*/
- public int submitRequest(CaptureRequest request, boolean repeating,
- /*out*/LongParcelable frameNumber) {
- ArrayList<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
- requestList.add(request);
- return submitRequestList(requestList, repeating, frameNumber);
+ public SubmitInfo submitRequest(CaptureRequest request, boolean repeating) {
+ CaptureRequest[] requestList = { request };
+ return submitRequestList(requestList, repeating);
}
/**
@@ -493,7 +492,7 @@
protected void finalize() throws Throwable {
try {
close();
- } catch (CameraRuntimeException e) {
+ } catch (ServiceSpecificException e) {
Log.e(TAG, "Got error while trying to finalize, ignoring: " + e.getMessage());
} finally {
super.finalize();
@@ -615,14 +614,16 @@
return LegacyExceptionUtils.throwOnError(nativeDetectSurfaceDataspace(surface));
}
- static void configureSurface(Surface surface, int width, int height,
- int pixelFormat) throws BufferQueueAbandonedException {
+ static void connectSurface(Surface surface) throws BufferQueueAbandonedException {
checkNotNull(surface);
- checkArgumentPositive(width, "width must be positive.");
- checkArgumentPositive(height, "height must be positive.");
- LegacyExceptionUtils.throwOnError(nativeConfigureSurface(surface, width, height,
- pixelFormat));
+ LegacyExceptionUtils.throwOnError(nativeConnectSurface(surface));
+ }
+
+ static void disconnectSurface(Surface surface) throws BufferQueueAbandonedException {
+ if (surface == null) return;
+
+ LegacyExceptionUtils.throwOnError(nativeDisconnectSurface(surface));
}
static void produceFrame(Surface surface, byte[] pixelBuffer, int width,
@@ -717,8 +718,7 @@
private static native int nativeDetectSurfaceDimens(Surface surface,
/*out*/int[/*2*/] dimens);
- private static native int nativeConfigureSurface(Surface surface, int width, int height,
- int pixelFormat);
+ private static native int nativeConnectSurface(Surface surface);
private static native int nativeProduceFrame(Surface surface, byte[] pixelBuffer, int width,
int height, int pixelFormat);
@@ -741,5 +741,7 @@
private static native int nativeSetScalingMode(Surface surface, int scalingMode);
+ private static native int nativeDisconnectSurface(Surface surface);
+
static native int nativeGetJpegFooterSize();
}
diff --git a/core/java/android/hardware/camera2/legacy/LegacyExceptionUtils.java b/core/java/android/hardware/camera2/legacy/LegacyExceptionUtils.java
index 4501e81..93d6001 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyExceptionUtils.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyExceptionUtils.java
@@ -16,10 +16,11 @@
package android.hardware.camera2.legacy;
-import android.hardware.camera2.utils.CameraBinderDecorator;
+import android.hardware.ICameraService;
+import android.os.ServiceSpecificException;
import android.util.AndroidException;
-import static android.system.OsConstants.ENODEV;
+import static android.system.OsConstants.*;
/**
* Utility class containing exception handling used solely by the compatibility mode shim.
@@ -27,6 +28,14 @@
public class LegacyExceptionUtils {
private static final String TAG = "LegacyExceptionUtils";
+ public static final int NO_ERROR = 0;
+ public static final int PERMISSION_DENIED = -EPERM;
+ public static final int ALREADY_EXISTS = -EEXIST;
+ public static final int BAD_VALUE = -EINVAL;
+ public static final int DEAD_OBJECT = -ENOSYS;
+ public static final int INVALID_OPERATION = -EPIPE;
+ public static final int TIMED_OUT = -ETIMEDOUT;
+
/**
* Checked exception thrown when a BufferQueue has been abandoned by its consumer.
*/
@@ -58,8 +67,8 @@
* @return {@code errorFlag} if the value was non-negative, throws otherwise.
*/
public static int throwOnError(int errorFlag) throws BufferQueueAbandonedException {
- if (errorFlag == CameraBinderDecorator.NO_ERROR) {
- return CameraBinderDecorator.NO_ERROR;
+ if (errorFlag == NO_ERROR) {
+ return NO_ERROR;
} else if (errorFlag == -ENODEV) {
throw new BufferQueueAbandonedException();
}
@@ -70,6 +79,59 @@
return errorFlag;
}
+ /**
+ * Throw error codes returned by the camera service as exceptions.
+ *
+ * @param errorFlag error to throw as an exception.
+ */
+ public static void throwOnServiceError(int errorFlag) {
+ int errorCode = ICameraService.ERROR_INVALID_OPERATION;
+ String errorMsg;
+
+ if (errorFlag >= NO_ERROR) {
+ return;
+ } else if (errorFlag == PERMISSION_DENIED) {
+ errorCode = ICameraService.ERROR_PERMISSION_DENIED;
+ errorMsg = "Lacking privileges to access camera service";
+ } else if (errorFlag == ALREADY_EXISTS) {
+ // This should be handled at the call site. Typically this isn't bad,
+ // just means we tried to do an operation that already completed.
+ return;
+ } else if (errorFlag == BAD_VALUE) {
+ errorCode = ICameraService.ERROR_ILLEGAL_ARGUMENT;
+ errorMsg = "Bad argument passed to camera service";
+ } else if (errorFlag == DEAD_OBJECT) {
+ errorCode = ICameraService.ERROR_DISCONNECTED;
+ errorMsg = "Camera service not available";
+ } else if (errorFlag == TIMED_OUT) {
+ errorCode = ICameraService.ERROR_INVALID_OPERATION;
+ errorMsg = "Operation timed out in camera service";
+ } else if (errorFlag == -EACCES) {
+ errorCode = ICameraService.ERROR_DISABLED;
+ errorMsg = "Camera disabled by policy";
+ } else if (errorFlag == -EBUSY) {
+ errorCode = ICameraService.ERROR_CAMERA_IN_USE;
+ errorMsg = "Camera already in use";
+ } else if (errorFlag == -EUSERS) {
+ errorCode = ICameraService.ERROR_MAX_CAMERAS_IN_USE;
+ errorMsg = "Maximum number of cameras in use";
+ } else if (errorFlag == -ENODEV) {
+ errorCode = ICameraService.ERROR_DISCONNECTED;
+ errorMsg = "Camera device not available";
+ } else if (errorFlag == -EOPNOTSUPP) {
+ errorCode = ICameraService.ERROR_DEPRECATED_HAL;
+ errorMsg = "Deprecated camera HAL does not support this";
+ } else if (errorFlag == INVALID_OPERATION) {
+ errorCode = ICameraService.ERROR_INVALID_OPERATION;
+ errorMsg = "Illegal state encountered in camera service.";
+ } else {
+ errorCode = ICameraService.ERROR_INVALID_OPERATION;
+ errorMsg = "Unknown camera device error " + errorFlag;
+ }
+
+ throw new ServiceSpecificException(errorCode, errorMsg);
+ }
+
private LegacyExceptionUtils() {
throw new AssertionError();
}
diff --git a/core/java/android/hardware/camera2/legacy/RequestQueue.java b/core/java/android/hardware/camera2/legacy/RequestQueue.java
index c995029..8f252a1 100644
--- a/core/java/android/hardware/camera2/legacy/RequestQueue.java
+++ b/core/java/android/hardware/camera2/legacy/RequestQueue.java
@@ -16,7 +16,7 @@
package android.hardware.camera2.legacy;
import android.hardware.camera2.CaptureRequest;
-import android.hardware.camera2.utils.LongParcelable;
+import android.hardware.camera2.utils.SubmitInfo;
import android.util.Log;
import android.util.Pair;
@@ -111,31 +111,29 @@
*
* @param requests the burst of requests to add to the queue.
* @param repeating true if the burst is repeating.
- * @param frameNumber an output argument that contains either the frame number of the last frame
- * that will be returned for this request, or the frame number of the last
- * frame that will be returned for the current repeating request if this
- * burst is set to be repeating.
- * @return the request id.
+ * @return the submission info, including the new request id, and the last frame number, which
+ * contains either the frame number of the last frame that will be returned for this request,
+ * or the frame number of the last frame that will be returned for the current repeating
+ * request if this burst is set to be repeating.
*/
- public synchronized int submit(List<CaptureRequest> requests, boolean repeating,
- /*out*/LongParcelable frameNumber) {
+ public synchronized SubmitInfo submit(CaptureRequest[] requests, boolean repeating) {
int requestId = mCurrentRequestId++;
BurstHolder burst = new BurstHolder(requestId, repeating, requests, mJpegSurfaceIds);
- long ret = INVALID_FRAME;
+ long lastFrame = INVALID_FRAME;
if (burst.isRepeating()) {
Log.i(TAG, "Repeating capture request set.");
if (mRepeatingRequest != null) {
- ret = (mCurrentRepeatingFrameNumber == INVALID_FRAME) ? INVALID_FRAME :
+ lastFrame = (mCurrentRepeatingFrameNumber == INVALID_FRAME) ? INVALID_FRAME :
mCurrentRepeatingFrameNumber - 1;
}
mCurrentRepeatingFrameNumber = INVALID_FRAME;
mRepeatingRequest = burst;
} else {
mRequestQueue.offer(burst);
- ret = calculateLastFrame(burst.getRequestId());
+ lastFrame = calculateLastFrame(burst.getRequestId());
}
- frameNumber.setNumber(ret);
- return requestId;
+ SubmitInfo info = new SubmitInfo(requestId, lastFrame);
+ return info;
}
private long calculateLastFrame(int requestId) {
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index 4866598..e8ce3ec 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -21,7 +21,7 @@
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.impl.CameraDeviceImpl;
-import android.hardware.camera2.utils.LongParcelable;
+import android.hardware.camera2.utils.SubmitInfo;
import android.hardware.camera2.utils.SizeAreaComparator;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.os.ConditionVariable;
@@ -365,6 +365,14 @@
mGLThreadManager.waitUntilIdle();
}
resetJpegSurfaceFormats(mCallbackOutputs);
+
+ for (Surface s : mCallbackOutputs) {
+ try {
+ LegacyCameraDevice.disconnectSurface(s);
+ } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
+ Log.w(TAG, "Surface abandoned, skipping...", e);
+ }
+ }
mPreviewOutputs.clear();
mCallbackOutputs.clear();
mJpegSurfaceIds.clear();
@@ -392,6 +400,10 @@
mJpegSurfaceIds.add(LegacyCameraDevice.getSurfaceId(s));
mCallbackOutputs.add(s);
callbackOutputSizes.add(outSize);
+
+ // LegacyCameraDevice is the producer of JPEG output surfaces
+ // so LegacyCameraDevice needs to connect to the surfaces.
+ LegacyCameraDevice.connectSurface(s);
break;
default:
LegacyCameraDevice.setScalingMode(s, LegacyCameraDevice.
@@ -1008,21 +1020,19 @@
*
* @param requests the burst of requests to add to the queue.
* @param repeating true if the burst is repeating.
- * @param frameNumber an output argument that contains either the frame number of the last frame
- * that will be returned for this request, or the frame number of the last
- * frame that will be returned for the current repeating request if this
- * burst is set to be repeating.
- * @return the request id.
+ * @return the submission info, including the new request id, and the last frame number, which
+ * contains either the frame number of the last frame that will be returned for this request,
+ * or the frame number of the last frame that will be returned for the current repeating
+ * request if this burst is set to be repeating.
*/
- public int submitCaptureRequests(List<CaptureRequest> requests, boolean repeating,
- /*out*/LongParcelable frameNumber) {
+ public SubmitInfo submitCaptureRequests(CaptureRequest[] requests, boolean repeating) {
Handler handler = mRequestThread.waitAndGetHandler();
- int ret;
+ SubmitInfo info;
synchronized (mIdleLock) {
- ret = mRequestQueue.submit(requests, repeating, frameNumber);
+ info = mRequestQueue.submit(requests, repeating);
handler.sendEmptyMessage(MSG_SUBMIT_CAPTURE_REQUEST);
}
- return ret;
+ return info;
}
/**
diff --git a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
index bc80fc1..70bc2fd 100644
--- a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
+++ b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
@@ -401,6 +401,13 @@
private void clearState() {
mSurfaces.clear();
+ for (EGLSurfaceHolder holder : mConversionSurfaces) {
+ try {
+ LegacyCameraDevice.disconnectSurface(holder.surface);
+ } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
+ Log.w(TAG, "Surface abandoned, skipping...", e);
+ }
+ }
mConversionSurfaces.clear();
mPBufferPixels = null;
if (mSurfaceTexture != null) {
@@ -631,6 +638,9 @@
holder.height = surfaceSize.getHeight();
if (LegacyCameraDevice.needsConversion(s)) {
mConversionSurfaces.add(holder);
+ // LegacyCameraDevice is the producer of surfaces if it's not handled by EGL,
+ // so LegacyCameraDevice needs to connect to the surfaces.
+ LegacyCameraDevice.connectSurface(s);
} else {
mSurfaces.add(holder);
}
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.aidl b/core/java/android/hardware/camera2/params/OutputConfiguration.aidl
deleted file mode 100644
index 0921cd8..0000000
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.camera2.params;
-
-/** @hide */
-parcelable OutputConfiguration;
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index 4407e55..cd0c474 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -21,11 +21,11 @@
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.utils.HashCodeHelpers;
import android.hardware.camera2.utils.SurfaceUtils;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
-import android.os.Parcel;
-import android.os.Parcelable;
import static com.android.internal.util.Preconditions.*;
diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
index 8be49e8..6cc7fec 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -1269,6 +1269,11 @@
private Size[] getInternalFormatSizes(int format, int dataspace,
boolean output, boolean highRes) {
+ // All depth formats are non-high-res.
+ if (dataspace == HAL_DATASPACE_DEPTH && highRes) {
+ return new Size[0];
+ }
+
SparseIntArray formatsMap =
!output ? mInputFormats :
dataspace == HAL_DATASPACE_DEPTH ? mDepthOutputFormats :
@@ -1287,6 +1292,8 @@
StreamConfiguration[] configurations =
(dataspace == HAL_DATASPACE_DEPTH) ? mDepthConfigurations : mConfigurations;
+ StreamConfigurationDuration[] minFrameDurations =
+ (dataspace == HAL_DATASPACE_DEPTH) ? mDepthMinFrameDurations : mMinFrameDurations;
for (StreamConfiguration config : configurations) {
int fmt = config.getFormat();
@@ -1295,8 +1302,8 @@
// Filter slow high-res output formats; include for
// highRes, remove for !highRes
long duration = 0;
- for (int i = 0; i < mMinFrameDurations.length; i++) {
- StreamConfigurationDuration d = mMinFrameDurations[i];
+ for (int i = 0; i < minFrameDurations.length; i++) {
+ StreamConfigurationDuration d = minFrameDurations[i];
if (d.getFormat() == fmt &&
d.getWidth() == config.getSize().getWidth() &&
d.getHeight() == config.getSize().getHeight()) {
@@ -1304,7 +1311,8 @@
break;
}
}
- if (highRes != (duration > DURATION_20FPS_NS)) {
+ if (dataspace != HAL_DATASPACE_DEPTH &&
+ highRes != (duration > DURATION_20FPS_NS)) {
continue;
}
}
diff --git a/core/java/android/hardware/camera2/params/VendorTagDescriptor.java b/core/java/android/hardware/camera2/params/VendorTagDescriptor.java
new file mode 100644
index 0000000..ea424e5
--- /dev/null
+++ b/core/java/android/hardware/camera2/params/VendorTagDescriptor.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.params;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * A class for describing the vendor tags declared by a camera HAL module.
+ * Generally only used by the native side of
+ * android.hardware.camera2.impl.CameraMetadataNative
+ *
+ * @hide
+ */
+public final class VendorTagDescriptor implements Parcelable {
+
+ private VendorTagDescriptor(Parcel source) {
+ }
+
+ public static final Parcelable.Creator<VendorTagDescriptor> CREATOR =
+ new Parcelable.Creator<VendorTagDescriptor>() {
+ @Override
+ public VendorTagDescriptor createFromParcel(Parcel source) {
+ try {
+ VendorTagDescriptor vendorDescriptor = new VendorTagDescriptor(source);
+ return vendorDescriptor;
+ } catch (Exception e) {
+ Log.e(TAG, "Exception creating VendorTagDescriptor from parcel", e);
+ return null;
+ }
+ }
+
+ @Override
+ public VendorTagDescriptor[] newArray(int size) {
+ return new VendorTagDescriptor[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ if (dest == null) {
+ throw new IllegalArgumentException("dest must not be null");
+ }
+ }
+
+ private static final String TAG = "VendorTagDescriptor";
+}
diff --git a/core/java/android/hardware/camera2/utils/BinderHolder.aidl b/core/java/android/hardware/camera2/utils/BinderHolder.aidl
deleted file mode 100644
index f39d645..0000000
--- a/core/java/android/hardware/camera2/utils/BinderHolder.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.hardware.camera2.utils;
-
-/** @hide */
-parcelable BinderHolder;
diff --git a/core/java/android/hardware/camera2/utils/BinderHolder.java b/core/java/android/hardware/camera2/utils/BinderHolder.java
deleted file mode 100644
index 9eea390..0000000
--- a/core/java/android/hardware/camera2/utils/BinderHolder.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.hardware.camera2.utils;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.IBinder;
-
-/**
- * @hide
- */
-public class BinderHolder implements Parcelable {
- private IBinder mBinder = null;
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeStrongBinder(mBinder);
- }
-
- public void readFromParcel(Parcel src) {
- mBinder = src.readStrongBinder();
- }
-
- public static final Parcelable.Creator<BinderHolder> CREATOR =
- new Parcelable.Creator<BinderHolder>() {
- @Override
- public BinderHolder createFromParcel(Parcel in) {
- return new BinderHolder(in);
- }
-
- @Override
- public BinderHolder[] newArray(int size) {
- return new BinderHolder[size];
- }
- };
-
- public IBinder getBinder() {
- return mBinder;
- }
-
- public void setBinder(IBinder binder) {
- mBinder = binder;
- }
-
- public BinderHolder() {}
-
- public BinderHolder(IBinder binder) {
- mBinder = binder;
- }
-
- private BinderHolder(Parcel in) {
- mBinder = in.readStrongBinder();
- }
-}
-
diff --git a/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java b/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
deleted file mode 100644
index 162edc9..0000000
--- a/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.hardware.camera2.utils;
-
-import static android.hardware.camera2.CameraAccessException.CAMERA_DISABLED;
-import static android.hardware.camera2.CameraAccessException.CAMERA_DISCONNECTED;
-import static android.hardware.camera2.CameraAccessException.CAMERA_IN_USE;
-import static android.hardware.camera2.CameraAccessException.CAMERA_ERROR;
-import static android.hardware.camera2.CameraAccessException.MAX_CAMERAS_IN_USE;
-import static android.hardware.camera2.CameraAccessException.CAMERA_DEPRECATED_HAL;
-import static android.system.OsConstants.*;
-
-import android.os.DeadObjectException;
-import android.os.RemoteException;
-
-import java.lang.reflect.Method;
-
-/**
- * Translate camera device status_t return values into exceptions.
- *
- * @see android.hardware.camera2.utils.CameraBinderDecorator#newInstance
- * @hide
- */
-public class CameraBinderDecorator {
-
- public static final int NO_ERROR = 0;
- public static final int PERMISSION_DENIED = -EPERM;
- public static final int ALREADY_EXISTS = -EEXIST;
- public static final int BAD_VALUE = -EINVAL;
- public static final int DEAD_OBJECT = -ENOSYS;
- public static final int INVALID_OPERATION = -EPIPE;
- public static final int TIMED_OUT = -ETIMEDOUT;
-
- /**
- * TODO: add as error codes in Errors.h
- * - POLICY_PROHIBITS
- * - RESOURCE_BUSY
- * - NO_SUCH_DEVICE
- * - NOT_SUPPORTED
- * - TOO_MANY_USERS
- */
-
- static class CameraBinderDecoratorListener implements Decorator.DecoratorListener {
-
- @Override
- public void onBeforeInvocation(Method m, Object[] args) {
- }
-
- @Override
- public void onAfterInvocation(Method m, Object[] args, Object result) {
- // int return type => status_t => convert to exception
- if (m.getReturnType() == Integer.TYPE) {
- int returnValue = (Integer) result;
- throwOnError(returnValue);
- }
- }
-
- @Override
- public boolean onCatchException(Method m, Object[] args, Throwable t) {
-
- if (t instanceof DeadObjectException) {
- throw new CameraRuntimeException(CAMERA_DISCONNECTED,
- "Process hosting the camera service has died unexpectedly",
- t);
- } else if (t instanceof RemoteException) {
- throw new UnsupportedOperationException("An unknown RemoteException was thrown" +
- " which should never happen.", t);
- }
-
- return false;
- }
-
- @Override
- public void onFinally(Method m, Object[] args) {
- }
-
- }
-
- /**
- * Throw error codes returned by the camera service as exceptions.
- *
- * @param errorFlag error to throw as an exception.
- */
- public static void throwOnError(int errorFlag) {
- if (errorFlag == NO_ERROR) {
- return;
- } else if (errorFlag == PERMISSION_DENIED) {
- throw new SecurityException("Lacking privileges to access camera service");
- } else if (errorFlag == ALREADY_EXISTS) {
- // This should be handled at the call site. Typically this isn't bad,
- // just means we tried to do an operation that already completed.
- return;
- } else if (errorFlag == BAD_VALUE) {
- throw new IllegalArgumentException("Bad argument passed to camera service");
- } else if (errorFlag == DEAD_OBJECT) {
- throw new CameraRuntimeException(CAMERA_DISCONNECTED);
- } else if (errorFlag == TIMED_OUT) {
- throw new CameraRuntimeException(CAMERA_ERROR,
- "Operation timed out in camera service");
- } else if (errorFlag == -EACCES) {
- throw new CameraRuntimeException(CAMERA_DISABLED);
- } else if (errorFlag == -EBUSY) {
- throw new CameraRuntimeException(CAMERA_IN_USE);
- } else if (errorFlag == -EUSERS) {
- throw new CameraRuntimeException(MAX_CAMERAS_IN_USE);
- } else if (errorFlag == -ENODEV) {
- throw new CameraRuntimeException(CAMERA_DISCONNECTED);
- } else if (errorFlag == -EOPNOTSUPP) {
- throw new CameraRuntimeException(CAMERA_DEPRECATED_HAL);
- } else if (errorFlag == INVALID_OPERATION) {
- throw new CameraRuntimeException(CAMERA_ERROR,
- "Illegal state encountered in camera service.");
- }
-
- /**
- * Trap the rest of the negative return values. If we have known
- * error codes i.e. ALREADY_EXISTS that aren't really runtime
- * errors, then add them to the top switch statement
- */
- if (errorFlag < 0) {
- throw new CameraRuntimeException(CAMERA_ERROR,
- String.format("Unknown camera device error %d", errorFlag));
- }
- }
-
- /**
- * <p>
- * Wraps the type T with a proxy that will check 'status_t' return codes
- * from the native side of the camera service, and throw Java exceptions
- * automatically based on the code.
- * </p>
- * <p>
- * In addition it also rewrites binder's RemoteException into either a
- * CameraAccessException or an UnsupportedOperationException.
- * </p>
- * <p>
- * As a result of calling any method on the proxy, RemoteException is
- * guaranteed never to be thrown.
- * </p>
- *
- * @param obj object that will serve as the target for all method calls
- * @param <T> the type of the element you want to wrap. This must be an interface.
- * @return a proxy that will intercept all invocations to obj
- */
- public static <T> T newInstance(T obj) {
- return Decorator.<T> newInstance(obj, new CameraBinderDecoratorListener());
- }
-}
diff --git a/core/java/android/hardware/camera2/utils/CameraRuntimeException.java b/core/java/android/hardware/camera2/utils/CameraRuntimeException.java
deleted file mode 100644
index 9ed88a9..0000000
--- a/core/java/android/hardware/camera2/utils/CameraRuntimeException.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package android.hardware.camera2.utils;
-
-import android.hardware.camera2.CameraAccessException;
-
-/**
- * @hide
- */
-public class CameraRuntimeException extends RuntimeException {
-
- private final int mReason;
- private String mMessage;
- private Throwable mCause;
-
- public final int getReason() {
- return mReason;
- }
-
- public CameraRuntimeException(int problem) {
- super();
- mReason = problem;
- }
-
- public CameraRuntimeException(int problem, String message) {
- super(message);
- mReason = problem;
- mMessage = message;
- }
-
- public CameraRuntimeException(int problem, String message, Throwable cause) {
- super(message, cause);
- mReason = problem;
- mMessage = message;
- mCause = cause;
- }
-
- public CameraRuntimeException(int problem, Throwable cause) {
- super(cause);
- mReason = problem;
- mCause = cause;
- }
-
- /**
- * Recreate this exception as the CameraAccessException equivalent.
- * @return CameraAccessException
- */
- public CameraAccessException asChecked() {
- CameraAccessException e;
-
- if (mMessage != null && mCause != null) {
- e = new CameraAccessException(mReason, mMessage, mCause);
- } else if (mMessage != null) {
- e = new CameraAccessException(mReason, mMessage);
- } else if (mCause != null) {
- e = new CameraAccessException(mReason, mCause);
- } else {
- e = new CameraAccessException(mReason);
- }
- // throw and catch, so java has a chance to fill out the stack trace
- e.setStackTrace(this.getStackTrace());
-
- return e;
- }
-}
diff --git a/core/java/android/hardware/camera2/utils/CameraServiceBinderDecorator.java b/core/java/android/hardware/camera2/utils/CameraServiceBinderDecorator.java
deleted file mode 100644
index c1fb6b1..0000000
--- a/core/java/android/hardware/camera2/utils/CameraServiceBinderDecorator.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.hardware.camera2.utils;
-
-import android.os.DeadObjectException;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.lang.reflect.Method;
-
-/**
- * Translate camera service status_t return values into exceptions.
- *
- * @see android.hardware.camera2.utils.CameraBinderDecorator#newInstance
- * @hide
- */
-public class CameraServiceBinderDecorator extends CameraBinderDecorator {
-
- private static final String TAG = "CameraServiceBinderDecorator";
-
- static class CameraServiceBinderDecoratorListener
- extends CameraBinderDecorator.CameraBinderDecoratorListener {
-
- // Pass through remote exceptions, unlike CameraBinderDecorator
- @Override
- public boolean onCatchException(Method m, Object[] args, Throwable t) {
-
- if (t instanceof DeadObjectException) {
- // Can sometimes happen (camera service died)
- // Pass on silently
- } else if (t instanceof RemoteException) {
- // Some other kind of remote exception - this is not normal, so let's at least
- // note it before moving on
- Log.e(TAG, "Unexpected RemoteException from camera service call.", t);
- }
- // All other exceptions also get sent onward
- return false;
- }
-
- }
-
- /**
- * <p>
- * Wraps the type T with a proxy that will check 'status_t' return codes
- * from the native side of the camera service, and throw Java exceptions
- * automatically based on the code.
- * </p>
- *
- * @param obj object that will serve as the target for all method calls
- * @param <T> the type of the element you want to wrap. This must be an interface.
- * @return a proxy that will intercept all invocations to obj
- */
- public static <T> T newInstance(T obj) {
- return Decorator.<T> newInstance(obj, new CameraServiceBinderDecoratorListener());
- }
-}
diff --git a/core/java/android/hardware/camera2/utils/Decorator.java b/core/java/android/hardware/camera2/utils/Decorator.java
deleted file mode 100644
index 5826497..0000000
--- a/core/java/android/hardware/camera2/utils/Decorator.java
+++ /dev/null
@@ -1,92 +0,0 @@
-
-package android.hardware.camera2.utils;
-
-import java.lang.reflect.*;
-
-/**
- * This is an implementation of the 'decorator' design pattern using Java's proxy mechanism.
- *
- * @see android.hardware.camera2.utils.Decorator#newInstance
- *
- * @hide
- */
-public class Decorator<T> implements InvocationHandler {
-
- public interface DecoratorListener {
- /**
- * This method is called before the target method is invoked
- * @param args arguments to target method
- * @param m Method being called
- */
- void onBeforeInvocation(Method m, Object[] args);
- /**
- * This function is called after the target method is invoked
- * if there were no uncaught exceptions
- * @param args arguments to target method
- * @param m Method being called
- * @param result return value of target method
- */
- void onAfterInvocation(Method m, Object[] args, Object result);
- /**
- * This method is called only if there was an exception thrown by the target method
- * during its invocation.
- *
- * @param args arguments to target method
- * @param m Method being called
- * @param t Throwable that was thrown
- * @return false to rethrow exception, true if the exception was handled
- */
- boolean onCatchException(Method m, Object[] args, Throwable t);
- /**
- * This is called after the target method is invoked, regardless of whether or not
- * there were any exceptions.
- * @param args arguments to target method
- * @param m Method being called
- */
- void onFinally(Method m, Object[] args);
- }
-
- private final T mObject;
- private final DecoratorListener mListener;
-
- /**
- * Create a decorator wrapping the specified object's method calls.
- *
- * @param obj the object whose method calls you want to intercept
- * @param listener the decorator handler for intercepted method calls
- * @param <T> the type of the element you want to wrap. This must be an interface.
- * @return a wrapped interface-compatible T
- */
- @SuppressWarnings("unchecked")
- public static<T> T newInstance(T obj, DecoratorListener listener) {
- return (T)java.lang.reflect.Proxy.newProxyInstance(
- obj.getClass().getClassLoader(),
- obj.getClass().getInterfaces(),
- new Decorator<T>(obj, listener));
- }
-
- private Decorator(T obj, DecoratorListener listener) {
- this.mObject = obj;
- this.mListener = listener;
- }
-
- @Override
- public Object invoke(Object proxy, Method m, Object[] args)
- throws Throwable
- {
- Object result = null;
- try {
- mListener.onBeforeInvocation(m, args);
- result = m.invoke(mObject, args);
- mListener.onAfterInvocation(m, args, result);
- } catch (InvocationTargetException e) {
- Throwable t = e.getTargetException();
- if (!mListener.onCatchException(m, args, t)) {
- throw t;
- }
- } finally {
- mListener.onFinally(m, args);
- }
- return result;
- }
-}
diff --git a/core/java/android/hardware/camera2/utils/SubmitInfo.java b/core/java/android/hardware/camera2/utils/SubmitInfo.java
new file mode 100644
index 0000000..d1692b5
--- /dev/null
+++ b/core/java/android/hardware/camera2/utils/SubmitInfo.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.camera2.utils;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.hardware.camera2.ICameraDeviceUser;
+
+/**
+ * The status information returned for a successful capture request submission.
+ *
+ * Includes the request ID for the newly submitted capture request, and the
+ * last frame number of either the previous repeating request (for repeating
+ * requests), or of the request(s) just submitted (for single-shot capture).
+ *
+ * @hide
+ */
+public class SubmitInfo implements Parcelable {
+
+ private int mRequestId;
+ private long mLastFrameNumber;
+
+ public SubmitInfo() {
+ mRequestId = -1;
+ mLastFrameNumber = ICameraDeviceUser.NO_IN_FLIGHT_REPEATING_FRAMES;
+ }
+
+ public SubmitInfo(int requestId, long lastFrameNumber) {
+ mRequestId = requestId;
+ mLastFrameNumber = lastFrameNumber;
+ }
+
+ public static final Parcelable.Creator<SubmitInfo> CREATOR =
+ new Parcelable.Creator<SubmitInfo>() {
+ @Override
+ public SubmitInfo createFromParcel(Parcel in) {
+ return new SubmitInfo(in);
+ }
+
+ @Override
+ public SubmitInfo[] newArray(int size) {
+ return new SubmitInfo[size];
+ }
+ };
+
+ private SubmitInfo(Parcel in) {
+ readFromParcel(in);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mRequestId);
+ dest.writeLong(mLastFrameNumber);
+ }
+
+ public void readFromParcel(Parcel in) {
+ mRequestId = in.readInt();
+ mLastFrameNumber = in.readLong();
+ }
+
+ /**
+ * Return the request ID for the submitted capture request/burst.
+ *
+ * This is used to track the completion status of the requested captures,
+ * and to cancel repeating requests.
+ */
+ public int getRequestId() {
+ return mRequestId;
+ }
+
+ /**
+ * Return the last frame number for the submitted capture request/burst.
+ *
+ * For a repeating request, this is the last frame number of the _prior_
+ * repeating request, to indicate when to fire the sequence completion callback
+ * for the prior repeating request.
+ *
+ * For a single-shot capture, this is the last frame number of _this_
+ * burst, to indicate when to fire the sequence completion callback for the request itself.
+ *
+ * For a repeating request, may be NO_IN_FLIGHT_REPEATING_FRAMES, if no
+ * instances of a prior repeating request were actually issued to the camera device.
+ */
+ public long getLastFrameNumber() {
+ return mLastFrameNumber;
+ }
+
+}
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 121a187..93da3e5 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -132,8 +132,7 @@
return info;
}
} catch (RemoteException ex) {
- Log.e(TAG, "Could not get display information from display manager.", ex);
- return null;
+ throw ex.rethrowFromSystemServer();
}
}
@@ -159,8 +158,7 @@
return displayIds;
}
} catch (RemoteException ex) {
- Log.e(TAG, "Could not get display ids from display manager.", ex);
- return new int[] { Display.DEFAULT_DISPLAY };
+ throw ex.rethrowFromSystemServer();
}
}
@@ -237,8 +235,7 @@
try {
mDm.registerCallback(mCallback);
} catch (RemoteException ex) {
- Log.e(TAG, "Failed to register callback with display manager service.", ex);
- mCallback = null;
+ throw ex.rethrowFromSystemServer();
}
}
}
@@ -267,7 +264,7 @@
try {
mDm.startWifiDisplayScan();
} catch (RemoteException ex) {
- Log.e(TAG, "Failed to scan for Wifi displays.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
}
@@ -279,7 +276,7 @@
try {
mDm.stopWifiDisplayScan();
} catch (RemoteException ex) {
- Log.e(TAG, "Failed to scan for Wifi displays.", ex);
+ throw ex.rethrowFromSystemServer();
}
} else if (mWifiDisplayScanNestCount < 0) {
Log.wtf(TAG, "Wifi display scan nest count became negative: "
@@ -297,7 +294,7 @@
try {
mDm.connectWifiDisplay(deviceAddress);
} catch (RemoteException ex) {
- Log.e(TAG, "Failed to connect to Wifi display " + deviceAddress + ".", ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -305,7 +302,7 @@
try {
mDm.pauseWifiDisplay();
} catch (RemoteException ex) {
- Log.e(TAG, "Failed to pause Wifi display.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -313,7 +310,7 @@
try {
mDm.resumeWifiDisplay();
} catch (RemoteException ex) {
- Log.e(TAG, "Failed to resume Wifi display.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -321,7 +318,7 @@
try {
mDm.disconnectWifiDisplay();
} catch (RemoteException ex) {
- Log.e(TAG, "Failed to disconnect from Wifi display.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -333,8 +330,7 @@
try {
mDm.renameWifiDisplay(deviceAddress, alias);
} catch (RemoteException ex) {
- Log.e(TAG, "Failed to rename Wifi display " + deviceAddress
- + " with alias " + alias + ".", ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -346,7 +342,7 @@
try {
mDm.forgetWifiDisplay(deviceAddress);
} catch (RemoteException ex) {
- Log.e(TAG, "Failed to forget Wifi display.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -354,8 +350,7 @@
try {
return mDm.getWifiDisplayStatus();
} catch (RemoteException ex) {
- Log.e(TAG, "Failed to get Wifi display status.", ex);
- return new WifiDisplayStatus();
+ throw ex.rethrowFromSystemServer();
}
}
@@ -363,7 +358,7 @@
try {
mDm.requestColorTransform(displayId, colorTransformId);
} catch (RemoteException ex) {
- Log.e(TAG, "Failed to request color transform.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -385,8 +380,7 @@
displayId = mDm.createVirtualDisplay(callbackWrapper, projectionToken,
context.getPackageName(), name, width, height, densityDpi, surface, flags);
} catch (RemoteException ex) {
- Log.e(TAG, "Could not create virtual display: " + name, ex);
- return null;
+ throw ex.rethrowFromSystemServer();
}
if (displayId < 0) {
Log.e(TAG, "Could not create virtual display: " + name);
@@ -399,6 +393,7 @@
try {
mDm.releaseVirtualDisplay(callbackWrapper);
} catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
}
return null;
}
@@ -409,7 +404,7 @@
try {
mDm.setVirtualDisplaySurface(token, surface);
} catch (RemoteException ex) {
- Log.w(TAG, "Failed to set virtual display surface.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -418,7 +413,7 @@
try {
mDm.resizeVirtualDisplay(token, width, height, densityDpi);
} catch (RemoteException ex) {
- Log.w(TAG, "Failed to resize virtual display.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -426,7 +421,7 @@
try {
mDm.releaseVirtualDisplay(token);
} catch (RemoteException ex) {
- Log.w(TAG, "Failed to release virtual display.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index aa697ea..13ba6cc 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -211,6 +211,9 @@
public int dozeScreenBrightness;
public int dozeScreenState;
+ // If true, use twilight to affect the brightness.
+ public boolean useTwilight;
+
public DisplayPowerRequest() {
policy = POLICY_BRIGHT;
useProximitySensor = false;
@@ -242,6 +245,7 @@
boostScreenBrightness = other.boostScreenBrightness;
dozeScreenBrightness = other.dozeScreenBrightness;
dozeScreenState = other.dozeScreenState;
+ useTwilight = other.useTwilight;
}
@Override
@@ -262,7 +266,8 @@
&& lowPowerMode == other.lowPowerMode
&& boostScreenBrightness == other.boostScreenBrightness
&& dozeScreenBrightness == other.dozeScreenBrightness
- && dozeScreenState == other.dozeScreenState;
+ && dozeScreenState == other.dozeScreenState
+ && useTwilight == other.useTwilight;
}
@Override
@@ -282,7 +287,8 @@
+ ", lowPowerMode=" + lowPowerMode
+ ", boostScreenBrightness=" + boostScreenBrightness
+ ", dozeScreenBrightness=" + dozeScreenBrightness
- + ", dozeScreenState=" + Display.stateToString(dozeScreenState);
+ + ", dozeScreenState=" + Display.stateToString(dozeScreenState)
+ + ", useTwilight=" + useTwilight;
}
public static String policyToString(int policy) {
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 9f8c28e..b8088f3 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -40,6 +40,7 @@
import javax.crypto.Cipher;
import javax.crypto.Mac;
+import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.USE_FINGERPRINT;
import static android.Manifest.permission.MANAGE_FINGERPRINT;
@@ -539,7 +540,7 @@
if (mService != null) try {
result = mService.preEnroll(mToken);
} catch (RemoteException e) {
- Log.w(TAG, "Remote exception in enroll: ", e);
+ throw e.rethrowFromSystemServer();
}
return result;
}
@@ -554,7 +555,7 @@
if (mService != null) try {
result = mService.postEnroll(mToken);
} catch (RemoteException e) {
- Log.w(TAG, "Remote exception in post enroll: ", e);
+ throw e.rethrowFromSystemServer();
}
return result;
}
@@ -570,7 +571,7 @@
if (mService != null) try {
mService.setActiveUser(userId);
} catch (RemoteException e) {
- Log.w(TAG, "Remote exception in setActiveUser: ", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -613,7 +614,7 @@
try {
mService.rename(fpId, userId, newName);
} catch (RemoteException e) {
- Log.v(TAG, "Remote exception in rename(): ", e);
+ throw e.rethrowFromSystemServer();
}
} else {
Log.w(TAG, "rename(): Service not connected!");
@@ -631,7 +632,7 @@
if (mService != null) try {
return mService.getEnrolledFingerprints(userId, mContext.getOpPackageName());
} catch (RemoteException e) {
- Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e);
+ throw e.rethrowFromSystemServer();
}
return null;
}
@@ -655,10 +656,25 @@
@RequiresPermission(USE_FINGERPRINT)
public boolean hasEnrolledFingerprints() {
if (mService != null) try {
- return mService.hasEnrolledFingerprints(UserHandle.myUserId(),
- mContext.getOpPackageName());
+ return mService.hasEnrolledFingerprints(
+ UserHandle.myUserId(), mContext.getOpPackageName());
} catch (RemoteException e) {
- Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e);
+ throw e.rethrowFromSystemServer();
+ }
+ return false;
+ }
+
+ /**
+ * @hide
+ */
+ @RequiresPermission(allOf = {
+ USE_FINGERPRINT,
+ INTERACT_ACROSS_USERS})
+ public boolean hasEnrolledFingerprints(int userId) {
+ if (mService != null) try {
+ return mService.hasEnrolledFingerprints(userId, mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
return false;
}
@@ -675,7 +691,7 @@
long deviceId = 0; /* TODO: plumb hardware id to FPMS */
return mService.isHardwareDetected(deviceId, mContext.getOpPackageName());
} catch (RemoteException e) {
- Log.v(TAG, "Remote exception in isFingerprintHardwareDetected(): ", e);
+ throw e.rethrowFromSystemServer();
}
} else {
Log.w(TAG, "isFingerprintHardwareDetected(): Service not connected!");
@@ -694,7 +710,7 @@
try {
return mService.getAuthenticatorId(mContext.getOpPackageName());
} catch (RemoteException e) {
- Log.v(TAG, "Remote exception in getAuthenticatorId(): ", e);
+ throw e.rethrowFromSystemServer();
}
} else {
Log.w(TAG, "getAuthenticatorId(): Service not connected!");
@@ -714,7 +730,7 @@
try {
mService.resetTimeout(token);
} catch (RemoteException e) {
- Log.v(TAG, "Remote exception in resetTimeout(): ", e);
+ throw e.rethrowFromSystemServer();
}
} else {
Log.w(TAG, "resetTimeout(): Service not connected!");
@@ -749,7 +765,7 @@
}
});
} catch (RemoteException e) {
- Log.v(TAG, "Remote exception in addLockoutResetCallback(): ", e);
+ throw e.rethrowFromSystemServer();
}
} else {
Log.w(TAG, "addLockoutResetCallback(): Service not connected!");
@@ -865,8 +881,7 @@
try {
return ActivityManagerNative.getDefault().getCurrentUser().id;
} catch (RemoteException e) {
- Log.w(TAG, "Failed to get current user id\n");
- return UserHandle.USER_NULL;
+ throw e.rethrowFromSystemServer();
}
}
@@ -874,7 +889,7 @@
if (mService != null) try {
mService.cancelEnrollment(mToken);
} catch (RemoteException e) {
- if (DEBUG) Log.w(TAG, "Remote exception while canceling enrollment");
+ throw e.rethrowFromSystemServer();
}
}
@@ -882,7 +897,7 @@
if (mService != null) try {
mService.cancelAuthentication(mToken, mContext.getOpPackageName());
} catch (RemoteException e) {
- if (DEBUG) Log.w(TAG, "Remote exception while canceling enrollment");
+ throw e.rethrowFromSystemServer();
}
}
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index 6effc0d..ff87b67 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -267,7 +267,7 @@
try {
types = mService.getSupportedTypes();
} catch (RemoteException e) {
- // Do nothing.
+ throw e.rethrowFromSystemServer();
}
}
mHasTvDevice = hasDeviceType(types, HdmiDeviceInfo.DEVICE_TV);
@@ -403,7 +403,7 @@
try {
mService.addHotplugEventListener(wrappedListener);
} catch (RemoteException e) {
- Log.e(TAG, "failed to add hotplug event listener: ", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -425,7 +425,7 @@
try {
mService.removeHotplugEventListener(wrappedListener);
} catch (RemoteException e) {
- Log.e(TAG, "failed to remove hotplug event listener: ", e);
+ throw e.rethrowFromSystemServer();
}
}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index cbe3412..fbac58c 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -252,7 +252,7 @@
try {
inputDevice = mIm.getInputDevice(id);
} catch (RemoteException ex) {
- throw new RuntimeException("Could not get input device information.", ex);
+ throw ex.rethrowFromSystemServer();
}
if (inputDevice != null) {
mInputDevices.setValueAt(index, inputDevice);
@@ -284,7 +284,7 @@
try {
inputDevice = mIm.getInputDevice(id);
} catch (RemoteException ex) {
- // Ignore the problem for the purposes of this method.
+ throw ex.rethrowFromSystemServer();
}
if (inputDevice == null) {
continue;
@@ -384,8 +384,7 @@
try {
return mIm.isInTabletMode();
} catch (RemoteException ex) {
- Log.w(TAG, "Could not get tablet mode state", ex);
- return SWITCH_STATE_UNKNOWN;
+ throw ex.rethrowFromSystemServer();
}
}
@@ -439,7 +438,7 @@
try {
mIm.registerTabletModeChangedListener(listener);
} catch (RemoteException ex) {
- throw new RuntimeException("Could not register tablet mode changed listener", ex);
+ throw ex.rethrowFromSystemServer();
}
mTabletModeChangedListener = listener;
mOnTabletModeChangedListeners = new ArrayList<>();
@@ -471,8 +470,7 @@
try {
return mIm.getKeyboardLayouts();
} catch (RemoteException ex) {
- Log.w(TAG, "Could not get list of keyboard layout informations.", ex);
- return new KeyboardLayout[0];
+ throw ex.rethrowFromSystemServer();
}
}
@@ -494,8 +492,7 @@
try {
return mIm.getKeyboardLayoutsForInputDevice(identifier);
} catch (RemoteException ex) {
- Log.w(TAG, "Could not get list of keyboard layouts for input device.", ex);
- return new KeyboardLayout[0];
+ throw ex.rethrowFromSystemServer();
}
}
@@ -516,8 +513,7 @@
try {
return mIm.getKeyboardLayout(keyboardLayoutDescriptor);
} catch (RemoteException ex) {
- Log.w(TAG, "Could not get keyboard layout information.", ex);
- return null;
+ throw ex.rethrowFromSystemServer();
}
}
@@ -534,8 +530,7 @@
try {
return mIm.getCurrentKeyboardLayoutForInputDevice(identifier);
} catch (RemoteException ex) {
- Log.w(TAG, "Could not get current keyboard layout for input device.", ex);
- return null;
+ throw ex.rethrowFromSystemServer();
}
}
@@ -565,7 +560,7 @@
mIm.setCurrentKeyboardLayoutForInputDevice(identifier,
keyboardLayoutDescriptor);
} catch (RemoteException ex) {
- Log.w(TAG, "Could not set current keyboard layout for input device.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -585,8 +580,7 @@
try {
return mIm.getEnabledKeyboardLayoutsForInputDevice(identifier);
} catch (RemoteException ex) {
- Log.w(TAG, "Could not get keyboard layouts for input device.", ex);
- return ArrayUtils.emptyArray(String.class);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -614,7 +608,7 @@
try {
mIm.addKeyboardLayoutForInputDevice(identifier, keyboardLayoutDescriptor);
} catch (RemoteException ex) {
- Log.w(TAG, "Could not add keyboard layout for input device.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -642,7 +636,7 @@
try {
mIm.removeKeyboardLayoutForInputDevice(identifier, keyboardLayoutDescriptor);
} catch (RemoteException ex) {
- Log.w(TAG, "Could not remove keyboard layout for input device.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -664,8 +658,7 @@
return mIm.getKeyboardLayoutForInputDevice(
identifier, inputMethodInfo, inputMethodSubtype);
} catch (RemoteException ex) {
- Log.w(TAG, "Could not set keyboard layout.", ex);
- return null;
+ throw ex.rethrowFromSystemServer();
}
}
@@ -687,7 +680,7 @@
mIm.setKeyboardLayoutForInputDevice(identifier, inputMethodInfo,
inputMethodSubtype, keyboardLayoutDescriptor);
} catch (RemoteException ex) {
- Log.w(TAG, "Could not set keyboard layout.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -704,8 +697,7 @@
try {
return mIm.getTouchCalibrationForInputDevice(inputDeviceDescriptor, surfaceRotation);
} catch (RemoteException ex) {
- Log.w(TAG, "Could not get calibration matrix for input device.", ex);
- return TouchCalibration.IDENTITY;
+ throw ex.rethrowFromSystemServer();
}
}
@@ -726,7 +718,7 @@
try {
mIm.setTouchCalibrationForInputDevice(inputDeviceDescriptor, surfaceRotation, calibration);
} catch (RemoteException ex) {
- Log.w(TAG, "Could not set calibration matrix for input device.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -793,7 +785,7 @@
try {
mIm.tryPointerSpeed(speed);
} catch (RemoteException ex) {
- Log.w(TAG, "Could not set temporary pointer speed.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -831,7 +823,7 @@
try {
mIm.hasKeys(id, InputDevice.SOURCE_ANY, keyCodes, ret);
} catch (RemoteException e) {
- // no fallback; just return the empty array
+ throw e.rethrowFromSystemServer();
}
return ret;
}
@@ -871,7 +863,7 @@
try {
return mIm.injectInputEvent(event, mode);
} catch (RemoteException ex) {
- return false;
+ throw ex.rethrowFromSystemServer();
}
}
@@ -887,7 +879,7 @@
try {
mIm.setPointerIconShape(iconId);
} catch (RemoteException ex) {
- // Do nothing.
+ throw ex.rethrowFromSystemServer();
}
}
@@ -896,7 +888,7 @@
try {
mIm.setCustomPointerIcon(icon);
} catch (RemoteException ex) {
- // Do nothing.
+ throw ex.rethrowFromSystemServer();
}
}
@@ -914,7 +906,7 @@
try {
mIm.setPointerIconDetached(detached);
} catch (RemoteException ex) {
- // Do nothing.
+ throw ex.rethrowFromSystemServer();
}
}
@@ -924,8 +916,7 @@
try {
mIm.registerInputDevicesChangedListener(listener);
} catch (RemoteException ex) {
- throw new RuntimeException(
- "Could not get register input device changed listener", ex);
+ throw ex.rethrowFromSystemServer();
}
mInputDevicesChangedListener = listener;
}
@@ -935,7 +926,7 @@
try {
ids = mIm.getInputDeviceIds();
} catch (RemoteException ex) {
- throw new RuntimeException("Could not get input device ids.", ex);
+ throw ex.rethrowFromSystemServer();
}
mInputDevices = new SparseArray<InputDevice>();
@@ -1175,7 +1166,7 @@
try {
mIm.vibrate(mDeviceId, pattern, repeat, mToken);
} catch (RemoteException ex) {
- Log.w(TAG, "Failed to vibrate.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -1184,7 +1175,7 @@
try {
mIm.cancelVibrate(mDeviceId, mToken);
} catch (RemoteException ex) {
- Log.w(TAG, "Failed to cancel vibration.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl b/core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl
index 597efa5..dcc3369 100644
--- a/core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl
+++ b/core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl
@@ -26,10 +26,20 @@
* Called when the keyphrase is spoken.
*
* @param recognitionEvent Object containing data relating to the
- * recognition event such as trigger audio data, if it was requested
- * and is available.
+ * keyphrase recognition event such as keyphrase
+ * extras.
*/
- void onDetected(in SoundTrigger.RecognitionEvent recognitionEvent);
+ void onKeyphraseDetected(in SoundTrigger.KeyphraseRecognitionEvent recognitionEvent);
+
+ /**
+ * Called when a generic sound trigger event is witnessed.
+ *
+ * @param recognitionEvent Object containing data relating to the
+ * recognition event such as trigger audio data (if
+ * requested).
+ */
+
+ void onGenericSoundTriggerDetected(in SoundTrigger.GenericRecognitionEvent recognitionEvent);
/**
* Called when the detection fails due to an error.
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.aidl b/core/java/android/hardware/soundtrigger/SoundTrigger.aidl
index fec64ea..325a9ad 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.aidl
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.aidl
@@ -20,7 +20,7 @@
parcelable SoundTrigger.Keyphrase;
parcelable SoundTrigger.RecognitionEvent;
parcelable SoundTrigger.KeyphraseRecognitionEvent;
-parcelable SoundTrigger.GenericSoundRecognitionEvent;
+parcelable SoundTrigger.GenericRecognitionEvent;
parcelable SoundTrigger.KeyphraseRecognitionExtra;
parcelable SoundTrigger.KeyphraseSoundModel;
parcelable SoundTrigger.GenericSoundModel;
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index 882908a..b635088 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -595,7 +595,7 @@
}
};
- private static RecognitionEvent fromParcel(Parcel in) {
+ protected static RecognitionEvent fromParcel(Parcel in) {
int status = in.readInt();
int soundModelHandle = in.readInt();
boolean captureAvailable = in.readByte() == 1;
@@ -689,12 +689,19 @@
return false;
if (triggerInData != other.triggerInData)
return false;
- if (captureFormat.getSampleRate() != other.captureFormat.getSampleRate())
- return false;
- if (captureFormat.getEncoding() != other.captureFormat.getEncoding())
- return false;
- if (captureFormat.getChannelMask() != other.captureFormat.getChannelMask())
- return false;
+ if (captureFormat == null) {
+ if (other.captureFormat != null)
+ return false;
+ } else {
+ if (other.captureFormat == null)
+ return false;
+ if (captureFormat.getSampleRate() != other.captureFormat.getSampleRate())
+ return false;
+ if (captureFormat.getEncoding() != other.captureFormat.getEncoding())
+ return false;
+ if (captureFormat.getChannelMask() != other.captureFormat.getChannelMask())
+ return false;
+ }
return true;
}
@@ -980,7 +987,7 @@
public static final Parcelable.Creator<KeyphraseRecognitionEvent> CREATOR
= new Parcelable.Creator<KeyphraseRecognitionEvent>() {
public KeyphraseRecognitionEvent createFromParcel(Parcel in) {
- return KeyphraseRecognitionEvent.fromParcel(in);
+ return KeyphraseRecognitionEvent.fromParcelForKeyphrase(in);
}
public KeyphraseRecognitionEvent[] newArray(int size) {
@@ -988,7 +995,7 @@
}
};
- private static KeyphraseRecognitionEvent fromParcel(Parcel in) {
+ private static KeyphraseRecognitionEvent fromParcelForKeyphrase(Parcel in) {
int status = in.readInt();
int soundModelHandle = in.readInt();
boolean captureAvailable = in.readByte() == 1;
@@ -1002,10 +1009,10 @@
int encoding = in.readInt();
int channelMask = in.readInt();
captureFormat = (new AudioFormat.Builder())
- .setChannelMask(channelMask)
- .setEncoding(encoding)
- .setSampleRate(sampleRate)
- .build();
+ .setChannelMask(channelMask)
+ .setEncoding(encoding)
+ .setSampleRate(sampleRate)
+ .build();
}
byte[] data = in.readBlob();
KeyphraseRecognitionExtra[] keyphraseExtras =
@@ -1094,6 +1101,40 @@
captureDelayMs, capturePreambleMs, triggerInData, captureFormat,
data);
}
+
+ public static final Parcelable.Creator<GenericRecognitionEvent> CREATOR
+ = new Parcelable.Creator<GenericRecognitionEvent>() {
+ public GenericRecognitionEvent createFromParcel(Parcel in) {
+ return GenericRecognitionEvent.fromParcelForGeneric(in);
+ }
+
+ public GenericRecognitionEvent[] newArray(int size) {
+ return new GenericRecognitionEvent[size];
+ }
+ };
+
+ private static GenericRecognitionEvent fromParcelForGeneric(Parcel in) {
+ RecognitionEvent event = RecognitionEvent.fromParcel(in);
+ return new GenericRecognitionEvent(event.status, event.soundModelHandle,
+ event.captureAvailable, event.captureSession, event.captureDelayMs,
+ event.capturePreambleMs, event.triggerInData, event.captureFormat, event.data);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass()) return false;
+ RecognitionEvent other = (RecognitionEvent) obj;
+ return super.equals(obj);
+ }
+
+ @Override
+ public String toString() {
+ return "GenericRecognitionEvent ::" + super.toString();
+ }
}
/**
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 1e3bcd0..3792e5c 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -302,8 +302,7 @@
}
return result;
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in getDeviceList", e);
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -347,8 +346,7 @@
return new UsbAccessory[] { accessory };
}
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in getAccessoryList", e);
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -362,8 +360,7 @@
try {
return mService.openAccessory(accessory);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in openAccessory", e);
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -380,8 +377,7 @@
try {
return mService.hasDevicePermission(device);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in hasPermission", e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -398,8 +394,7 @@
try {
return mService.hasAccessoryPermission(accessory);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in hasPermission", e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -425,7 +420,7 @@
try {
mService.requestDevicePermission(device, mContext.getPackageName(), pi);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in requestPermission", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -451,7 +446,7 @@
try {
mService.requestAccessoryPermission(accessory, mContext.getPackageName(), pi);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in requestPermission", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -466,7 +461,7 @@
try {
mService.grantDevicePermission(device, Process.myUid());
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in grantPermission", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -486,8 +481,7 @@
try {
return mService.isFunctionEnabled(function);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in setCurrentFunction", e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -517,7 +511,7 @@
try {
mService.setCurrentFunction(function);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in setCurrentFunction", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -533,7 +527,7 @@
try {
mService.setUsbDataUnlocked(unlocked);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in setUsbDataUnlocked", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -554,9 +548,8 @@
try {
return mService.getPorts();
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in getPorts", e);
+ throw e.rethrowFromSystemServer();
}
- return null;
}
/**
@@ -573,9 +566,8 @@
try {
return mService.getPortStatus(port.getId());
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in getPortStatus", e);
+ throw e.rethrowFromSystemServer();
}
- return null;
}
/**
@@ -604,7 +596,7 @@
try {
mService.setPortRoles(port.getId(), powerRole, dataRole);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in setPortRole", e);
+ throw e.rethrowFromSystemServer();
}
}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 7004e97..5f1043b 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -45,10 +45,12 @@
import android.telephony.SubscriptionManager;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.SparseArray;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.Protocol;
+import com.android.internal.util.MessageUtils;
import libcore.net.event.NetworkEventDispatcher;
@@ -79,6 +81,13 @@
public class ConnectivityManager {
private static final String TAG = "ConnectivityManager";
+ private static final SparseArray<String> sMagicDecoderRing = MessageUtils.findMessageNames(
+ new Class[]{ConnectivityManager.class}, new String[]{"CALLBACK_"});
+
+ private static final String whatToString(int what) {
+ return sMagicDecoderRing.get(what, Integer.toString(what));
+ }
+
/**
* A change in network connectivity has occurred. A default connection has either
* been established or lost. The NetworkInfo for the affected network is
@@ -733,7 +742,7 @@
try {
return mService.getActiveNetworkInfo();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -753,7 +762,7 @@
try {
return mService.getActiveNetwork();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -777,7 +786,7 @@
try {
return mService.setAlwaysOnVpnPackage(userId, vpnPackage);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -794,7 +803,7 @@
try {
return mService.getAlwaysOnVpnPackage(userId);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -815,7 +824,7 @@
try {
return mService.getActiveNetworkInfoForUid(uid);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -839,7 +848,7 @@
try {
return mService.getNetworkInfo(networkType);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -859,7 +868,7 @@
try {
return mService.getNetworkInfoForNetwork(network);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -880,7 +889,7 @@
try {
return mService.getAllNetworkInfo();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -900,7 +909,7 @@
try {
return mService.getNetworkForType(networkType);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -916,7 +925,7 @@
try {
return mService.getAllNetworks();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -929,7 +938,7 @@
try {
return mService.getDefaultNetworkCapabilitiesForUser(userId);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -948,7 +957,7 @@
try {
return mService.getActiveLinkProperties();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -972,7 +981,7 @@
try {
return mService.getLinkPropertiesForType(networkType);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -989,7 +998,7 @@
try {
return mService.getLinkProperties(network);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1006,7 +1015,7 @@
try {
return mService.getNetworkCapabilities(network);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1024,7 +1033,7 @@
try {
return mService.getCaptivePortalServerUrl();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1324,7 +1333,9 @@
int type = legacyTypeForNetworkCapabilities(netCap);
try {
delay = mService.getRestoreDefaultNetworkDelay(type);
- } catch (RemoteException e) {}
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
LegacyRequest l = new LegacyRequest();
l.networkCapabilities = netCap;
l.delay = delay;
@@ -1542,7 +1553,7 @@
try {
return mService.requestRouteToHostAddress(networkType, hostAddress.getAddress());
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1598,7 +1609,7 @@
try {
return mService.getActiveNetworkQuotaInfo();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1617,7 +1628,9 @@
Log.d("ConnectivityManager", "getMobileDataEnabled()- subId=" + subId
+ " retVal=" + retVal);
return retVal;
- } catch (RemoteException e) { }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
Log.d("ConnectivityManager", "getMobileDataEnabled()- remote exception retVal=false");
return false;
@@ -1678,6 +1691,7 @@
getNetworkManagementService().registerNetworkActivityListener(rl);
mNetworkActivityListeners.put(l, rl);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1695,6 +1709,7 @@
try {
getNetworkManagementService().unregisterNetworkActivityListener(rl);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1710,8 +1725,8 @@
try {
return getNetworkManagementService().isNetworkActive();
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return false;
}
/**
@@ -1785,7 +1800,7 @@
try {
return mService.getTetherableIfaces();
} catch (RemoteException e) {
- return new String[0];
+ throw e.rethrowFromSystemServer();
}
}
@@ -1802,7 +1817,7 @@
try {
return mService.getTetheredIfaces();
} catch (RemoteException e) {
- return new String[0];
+ throw e.rethrowFromSystemServer();
}
}
@@ -1825,7 +1840,7 @@
try {
return mService.getTetheringErroredIfaces();
} catch (RemoteException e) {
- return new String[0];
+ throw e.rethrowFromSystemServer();
}
}
@@ -1839,7 +1854,7 @@
try {
return mService.getTetheredDhcpRanges();
} catch (RemoteException e) {
- return new String[0];
+ throw e.rethrowFromSystemServer();
}
}
@@ -1871,7 +1886,7 @@
try {
return mService.tether(iface);
} catch (RemoteException e) {
- return TETHER_ERROR_SERVICE_UNAVAIL;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1897,7 +1912,7 @@
try {
return mService.untether(iface);
} catch (RemoteException e) {
- return TETHER_ERROR_SERVICE_UNAVAIL;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1917,7 +1932,7 @@
try {
return mService.isTetheringSupported();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2005,7 +2020,7 @@
try {
mService.stopTethering(type);
} catch (RemoteException e) {
- Log.e(TAG, "Exception trying to stop tethering.", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2025,7 +2040,7 @@
try {
return mService.getTetherableUsbRegexs();
} catch (RemoteException e) {
- return new String[0];
+ throw e.rethrowFromSystemServer();
}
}
@@ -2045,7 +2060,7 @@
try {
return mService.getTetherableWifiRegexs();
} catch (RemoteException e) {
- return new String[0];
+ throw e.rethrowFromSystemServer();
}
}
@@ -2065,7 +2080,7 @@
try {
return mService.getTetherableBluetoothRegexs();
} catch (RemoteException e) {
- return new String[0];
+ throw e.rethrowFromSystemServer();
}
}
@@ -2090,7 +2105,7 @@
try {
return mService.setUsbTethering(enable);
} catch (RemoteException e) {
- return TETHER_ERROR_SERVICE_UNAVAIL;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2135,7 +2150,7 @@
try {
return mService.getLastTetherError(iface);
} catch (RemoteException e) {
- return TETHER_ERROR_SERVICE_UNAVAIL;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2153,6 +2168,7 @@
try {
mService.reportInetCondition(networkType, percentage);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2174,6 +2190,7 @@
mService.reportNetworkConnectivity(network, true);
mService.reportNetworkConnectivity(network, false);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2192,6 +2209,7 @@
try {
mService.reportNetworkConnectivity(network, hasConnectivity);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2211,6 +2229,7 @@
try {
mService.setGlobalProxy(p);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2225,7 +2244,7 @@
try {
return mService.getGlobalProxy();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2247,7 +2266,7 @@
try {
return mService.getProxyForNetwork(network);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2282,8 +2301,9 @@
public boolean isNetworkSupported(int networkType) {
try {
return mService.isNetworkSupported(networkType);
- } catch (RemoteException e) {}
- return false;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -2303,7 +2323,7 @@
try {
return mService.isActiveNetworkMetered();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2320,7 +2340,7 @@
try {
return mService.updateLockdownVpn();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2339,6 +2359,7 @@
try {
timeOutMs = mService.checkMobileProvisioning(suggestedTimeOutMs);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
return timeOutMs;
}
@@ -2351,8 +2372,8 @@
try {
return mService.getMobileProvisioningUrl();
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return null;
}
/**
@@ -2369,6 +2390,7 @@
try {
mService.setProvisioningNotificationVisible(visible, networkType, action);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2385,6 +2407,7 @@
try {
mService.setAirplaneMode(enable);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2392,14 +2415,18 @@
public void registerNetworkFactory(Messenger messenger, String name) {
try {
mService.registerNetworkFactory(messenger, name);
- } catch (RemoteException e) { }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/** {@hide} */
public void unregisterNetworkFactory(Messenger messenger) {
try {
mService.unregisterNetworkFactory(messenger);
- } catch (RemoteException e) { }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -2412,7 +2439,7 @@
try {
return mService.registerNetworkAgent(messenger, ni, lp, nc, score, misc);
} catch (RemoteException e) {
- return NETID_UNSET;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2563,9 +2590,11 @@
@Override
public void handleMessage(Message message) {
- if (DBG) Log.d(TAG, "CM callback handler got msg " + message.what);
NetworkRequest request = (NetworkRequest) getObject(message, NetworkRequest.class);
Network network = (Network) getObject(message, Network.class);
+ if (DBG) {
+ Log.d(TAG, whatToString(message.what) + " for network " + network);
+ }
switch (message.what) {
case CALLBACK_PRECHECK: {
NetworkCallback callback = getCallback(request, "PRECHECK");
@@ -2730,7 +2759,9 @@
sNetworkCallback.put(networkCallback.networkRequest, networkCallback);
}
}
- } catch (RemoteException e) {}
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
if (networkCallback.networkRequest == null) decCallbackHandlerRefCount();
return networkCallback.networkRequest;
}
@@ -2893,7 +2924,9 @@
checkPendingIntent(operation);
try {
mService.pendingRequestForNetwork(request.networkCapabilities, operation);
- } catch (RemoteException e) {}
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -2911,7 +2944,9 @@
checkPendingIntent(operation);
try {
mService.releasePendingNetworkRequest(operation);
- } catch (RemoteException e) {}
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
private void checkPendingIntent(PendingIntent intent) {
@@ -2970,7 +3005,9 @@
checkPendingIntent(operation);
try {
mService.pendingListenForNetwork(request.networkCapabilities, operation);
- } catch (RemoteException e) {}
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -2988,7 +3025,7 @@
try {
return mService.requestBandwidthUpdate(network);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -3008,7 +3045,9 @@
}
try {
mService.releaseNetworkRequest(networkCallback.networkRequest);
- } catch (RemoteException e) {}
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -3044,7 +3083,9 @@
public void setAcceptUnvalidated(Network network, boolean accept, boolean always) {
try {
mService.setAcceptUnvalidated(network, accept, always);
- } catch (RemoteException e) {}
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -3055,6 +3096,7 @@
try {
mService.factoryReset();
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -3262,7 +3304,7 @@
try {
return getNetworkPolicyManager().getRestrictBackgroundByCaller();
} catch (RemoteException e) {
- return RESTRICT_BACKGROUND_STATUS_DISABLED;
+ throw e.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/hardware/CameraInfo.aidl b/core/java/android/net/ConnectivityMetricsEvent.aidl
similarity index 82%
rename from core/java/android/hardware/CameraInfo.aidl
rename to core/java/android/net/ConnectivityMetricsEvent.aidl
index e21e694..da17561 100644
--- a/core/java/android/hardware/CameraInfo.aidl
+++ b/core/java/android/net/ConnectivityMetricsEvent.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-package android.hardware;
+package android.net;
-/** @hide */
-parcelable CameraInfo;
+parcelable ConnectivityMetricsEvent;
diff --git a/core/java/android/net/ConnectivityMetricsEvent.java b/core/java/android/net/ConnectivityMetricsEvent.java
new file mode 100644
index 0000000..098f1e6
--- /dev/null
+++ b/core/java/android/net/ConnectivityMetricsEvent.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/** {@hide} */
+public final class ConnectivityMetricsEvent implements Parcelable {
+
+ /** The time when this event was collected, as returned by System.currentTimeMillis(). */
+ final public long timestamp;
+
+ /** The subsystem that generated the event. One of the COMPONENT_TAG_xxx constants. */
+ final public int componentTag;
+
+ /** The subsystem-specific event ID. */
+ final public int eventTag;
+
+ /** Opaque event-specific data. */
+ final public Parcelable data;
+
+ public ConnectivityMetricsEvent(long timestamp, int componentTag,
+ int eventTag, Parcelable data) {
+ this.timestamp = timestamp;
+ this.componentTag = componentTag;
+ this.eventTag = eventTag;
+ this.data = data;
+ }
+
+ /** Implement the Parcelable interface */
+ public static final Parcelable.Creator<ConnectivityMetricsEvent> CREATOR
+ = new Parcelable.Creator<ConnectivityMetricsEvent> (){
+ public ConnectivityMetricsEvent createFromParcel(Parcel source) {
+ final long timestamp = source.readLong();
+ final int componentTag = source.readInt();
+ final int eventTag = source.readInt();
+ final Parcelable data = source.readParcelable(null);
+ return new ConnectivityMetricsEvent(timestamp, componentTag,
+ eventTag, data);
+ }
+
+ public ConnectivityMetricsEvent[] newArray(int size) {
+ return new ConnectivityMetricsEvent[size];
+ }
+ };
+
+ /** Implement the Parcelable interface */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(timestamp);
+ dest.writeInt(componentTag);
+ dest.writeInt(eventTag);
+ dest.writeParcelable(data, 0);
+ }
+
+ public String toString() {
+ return String.format("ConnectivityMetricsEvent(%d, %d, %d)", timestamp,
+ componentTag, eventTag);
+ }
+}
diff --git a/core/java/android/net/ConnectivityMetricsLogger.java b/core/java/android/net/ConnectivityMetricsLogger.java
new file mode 100644
index 0000000..3ef8050
--- /dev/null
+++ b/core/java/android/net/ConnectivityMetricsLogger.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.net;
+
+import android.os.Parcelable;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+/** {@hide} */
+public class ConnectivityMetricsLogger {
+ private static String TAG = "ConnectivityMetricsLogger";
+ private static final boolean DBG = true;
+
+ public static final String CONNECTIVITY_METRICS_LOGGER_SERVICE = "connectivity_metrics_logger";
+
+ // Component Tags
+ public static final int COMPONENT_TAG_CONNECTIVITY = 1;
+ public static final int COMPONENT_TAG_BLUETOOTH = 2;
+ public static final int COMPONENT_TAG_WIFI = 3;
+ public static final int COMPONENT_TAG_TELECOM = 4;
+ public static final int COMPONENT_TAG_TELEPHONY = 5;
+
+ private IConnectivityMetricsLogger mService;
+
+ public ConnectivityMetricsLogger() {
+ mService = IConnectivityMetricsLogger.Stub.asInterface(ServiceManager.getService(
+ CONNECTIVITY_METRICS_LOGGER_SERVICE));
+ }
+
+ public void logEvent(long timestamp, int componentTag, int eventTag, Parcelable data) {
+ if (mService == null) {
+ if (DBG) {
+ Log.d(TAG, "logEvent(" + componentTag + "," + eventTag + ") Service not ready");
+ }
+ } else {
+ try {
+ mService.logEvent(new ConnectivityMetricsEvent(timestamp, componentTag, eventTag, data));
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error logging event " + e.getMessage());
+ }
+ }
+ }
+}
diff --git a/core/java/android/net/DataUsageRequest.java b/core/java/android/net/DataUsageRequest.java
index 5e96cc1..8526584 100644
--- a/core/java/android/net/DataUsageRequest.java
+++ b/core/java/android/net/DataUsageRequest.java
@@ -29,7 +29,7 @@
* If no {@code uid}s are set, callbacks are restricted to device-owners,
* carrier-privileged apps, or system apps.
*/
-public class DataUsageRequest implements Parcelable {
+public final class DataUsageRequest implements Parcelable {
/**
* @hide
diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
index f45737a..664b7b4 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/core/java/android/net/EthernetManager.java
@@ -87,8 +87,8 @@
public IpConfiguration getConfiguration() {
try {
return mService.getConfiguration();
- } catch (NullPointerException | RemoteException e) {
- return new IpConfiguration();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -98,7 +98,8 @@
public void setConfiguration(IpConfiguration config) {
try {
mService.setConfiguration(config);
- } catch (NullPointerException | RemoteException e) {
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -109,8 +110,8 @@
public boolean isAvailable() {
try {
return mService.isAvailable();
- } catch (NullPointerException | RemoteException e) {
- return false;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -127,7 +128,8 @@
if (mListeners.size() == 1) {
try {
mService.addListener(mServiceListener);
- } catch (NullPointerException | RemoteException e) {
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -145,7 +147,8 @@
if (mListeners.isEmpty()) {
try {
mService.removeListener(mServiceListener);
- } catch (NullPointerException | RemoteException e) {
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/net/IConnectivityMetricsLogger.aidl b/core/java/android/net/IConnectivityMetricsLogger.aidl
new file mode 100644
index 0000000..2778671
--- /dev/null
+++ b/core/java/android/net/IConnectivityMetricsLogger.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.net.ConnectivityMetricsEvent;
+import android.net.IConnectivityMetricsLoggerSubscriber;
+
+/** {@hide} */
+interface IConnectivityMetricsLogger {
+
+ void logEvent(in ConnectivityMetricsEvent event);
+ void logEvents(in ConnectivityMetricsEvent[] events);
+
+ boolean subscribe(in IConnectivityMetricsLoggerSubscriber subscriber);
+ void unsubscribe(in IConnectivityMetricsLoggerSubscriber subscriber);
+}
diff --git a/core/java/android/hardware/ICameraClient.aidl b/core/java/android/net/IConnectivityMetricsLoggerSubscriber.aidl
similarity index 69%
rename from core/java/android/hardware/ICameraClient.aidl
rename to core/java/android/net/IConnectivityMetricsLoggerSubscriber.aidl
index d7877b4..a2c62cd 100644
--- a/core/java/android/hardware/ICameraClient.aidl
+++ b/core/java/android/net/IConnectivityMetricsLoggerSubscriber.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,13 +14,12 @@
* limitations under the License.
*/
-package android.hardware;
+package android.net;
-/** @hide */
-interface ICameraClient
-{
- /**
- * Keep up-to-date with frameworks/av/include/camera/ICameraClient.h
- */
- // TODO: consider implementing this.
+import android.net.ConnectivityMetricsEvent;
+
+/** {@hide} */
+oneway interface IConnectivityMetricsLoggerSubscriber {
+
+ void onEvents(in ConnectivityMetricsEvent[] events);
}
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 20c2168..9e360e1 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -200,6 +200,14 @@
*/
public static final int CMD_PREVENT_AUTOMATIC_RECONNECT = BASE + 15;
+ /**
+ * Sent by ConnectivityService to the NetworkAgent to install an APF program in the network
+ * chipset for use to filter packets.
+ *
+ * obj = byte[] containing the APF program bytecode.
+ */
+ public static final int CMD_PUSH_APF_PROGRAM = BASE + 16;
+
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
NetworkCapabilities nc, LinkProperties lp, int score) {
this(looper, context, logTag, ni, nc, lp, score, null);
@@ -319,6 +327,10 @@
preventAutomaticReconnect();
break;
}
+ case CMD_PUSH_APF_PROGRAM: {
+ installPacketFilter((byte[]) msg.obj);
+ break;
+ }
}
}
@@ -494,6 +506,15 @@
protected void preventAutomaticReconnect() {
}
+ /**
+ * Install a packet filter.
+ * @param filter an APF program to filter incoming packets.
+ * @return {@code true} if filter successfully installed, {@code false} otherwise.
+ */
+ protected boolean installPacketFilter(byte[] filter) {
+ return false;
+ }
+
protected void log(String s) {
Log.d(LOG_TAG, "NetworkAgent: " + s);
}
diff --git a/core/java/android/net/NetworkMisc.java b/core/java/android/net/NetworkMisc.java
index 5511a24..748699e 100644
--- a/core/java/android/net/NetworkMisc.java
+++ b/core/java/android/net/NetworkMisc.java
@@ -56,6 +56,22 @@
*/
public String subscriberId;
+ /**
+ * Version of APF instruction set supported for packet filtering. 0 indicates no support for
+ * packet filtering using APF programs.
+ */
+ public int apfVersionSupported;
+
+ /**
+ * Maximum size of APF program allowed.
+ */
+ public int maximumApfProgramSize;
+
+ /**
+ * Format of packets passed to APF filter. Should be one of ARPHRD_*
+ */
+ public int apfPacketFormat;
+
public NetworkMisc() {
}
@@ -65,6 +81,9 @@
explicitlySelected = nm.explicitlySelected;
acceptUnvalidated = nm.acceptUnvalidated;
subscriberId = nm.subscriberId;
+ apfVersionSupported = nm.apfVersionSupported;
+ maximumApfProgramSize = nm.maximumApfProgramSize;
+ apfPacketFormat = nm.apfPacketFormat;
}
}
@@ -79,6 +98,9 @@
out.writeInt(explicitlySelected ? 1 : 0);
out.writeInt(acceptUnvalidated ? 1 : 0);
out.writeString(subscriberId);
+ out.writeInt(apfVersionSupported);
+ out.writeInt(maximumApfProgramSize);
+ out.writeInt(apfPacketFormat);
}
public static final Creator<NetworkMisc> CREATOR = new Creator<NetworkMisc>() {
@@ -89,6 +111,9 @@
networkMisc.explicitlySelected = in.readInt() != 0;
networkMisc.acceptUnvalidated = in.readInt() != 0;
networkMisc.subscriberId = in.readString();
+ networkMisc.apfVersionSupported = in.readInt();
+ networkMisc.maximumApfProgramSize = in.readInt();
+ networkMisc.apfPacketFormat = in.readInt();
return networkMisc;
}
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index a83e722..8738424 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -68,10 +68,12 @@
public static final int FIREWALL_CHAIN_NONE = 0;
public static final int FIREWALL_CHAIN_DOZABLE = 1;
public static final int FIREWALL_CHAIN_STANDBY = 2;
+ public static final int FIREWALL_CHAIN_POWERSAVE = 3;
public static final String FIREWALL_CHAIN_NAME_NONE = "none";
public static final String FIREWALL_CHAIN_NAME_DOZABLE = "dozable";
public static final String FIREWALL_CHAIN_NAME_STANDBY = "standby";
+ public static final String FIREWALL_CHAIN_NAME_POWERSAVE = "powersave";
private static final boolean ALLOW_PLATFORM_APP_POLICY = true;
@@ -106,6 +108,7 @@
try {
mService.setUidPolicy(uid, policy);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -118,6 +121,7 @@
try {
mService.addUidPolicy(uid, policy);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -130,6 +134,7 @@
try {
mService.removeUidPolicy(uid, policy);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -137,7 +142,7 @@
try {
return mService.getUidPolicy(uid);
} catch (RemoteException e) {
- return POLICY_NONE;
+ throw e.rethrowFromSystemServer();
}
}
@@ -145,7 +150,7 @@
try {
return mService.getUidsWithPolicy(policy);
} catch (RemoteException e) {
- return new int[0];
+ throw e.rethrowFromSystemServer();
}
}
@@ -153,6 +158,7 @@
try {
mService.registerListener(listener);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -160,6 +166,7 @@
try {
mService.unregisterListener(listener);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -167,6 +174,7 @@
try {
mService.setNetworkPolicies(policies);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -174,7 +182,7 @@
try {
return mService.getNetworkPolicies(mContext.getOpPackageName());
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -182,6 +190,7 @@
try {
mService.setRestrictBackground(restrictBackground);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -189,7 +198,7 @@
try {
return mService.getRestrictBackground();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -202,6 +211,7 @@
try {
mService.factoryReset(subscriber);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index b6fe68a..01c160f 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -166,7 +166,7 @@
try {
return mService.updateScores(networks);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -186,7 +186,7 @@
try {
return mService.clearScores();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -206,7 +206,7 @@
try {
return mService.setActiveScorer(packageName);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -221,6 +221,7 @@
try {
mService.disableScoring();
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -265,6 +266,7 @@
try {
mService.registerNetworkScoreCache(networkType, scoreCache);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 4487cab..555032d 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -57,95 +57,18 @@
public native static int resetConnections(String interfaceName, int mask);
/**
- * Start the DHCP client daemon, in order to have it request addresses
- * for the named interface. This returns {@code true} if the DHCPv4 daemon
- * starts, {@code false} otherwise. This call blocks until such time as a
- * result is available or the default discovery timeout has been reached.
- * Callers should check {@link #getDhcpResults} to determine whether DHCP
- * succeeded or failed, and if it succeeded, to fetch the {@link DhcpResults}.
- * @param interfaceName the name of the interface to configure
- * @return {@code true} for success, {@code false} for failure
- */
- public native static boolean startDhcp(String interfaceName);
-
- /**
- * Initiate renewal on the DHCP client daemon for the named interface. This
- * returns {@code true} if the DHCPv4 daemon has been notified, {@code false}
- * otherwise. This call blocks until such time as a result is available or
- * the default renew timeout has been reached. Callers should check
- * {@link #getDhcpResults} to determine whether DHCP succeeded or failed,
- * and if it succeeded, to fetch the {@link DhcpResults}.
- * @param interfaceName the name of the interface to configure
- * @return {@code true} for success, {@code false} for failure
- */
- public native static boolean startDhcpRenew(String interfaceName);
-
- /**
- * Start the DHCP client daemon, in order to have it request addresses
- * for the named interface, and then configure the interface with those
- * addresses. This call blocks until it obtains a result (either success
- * or failure) from the daemon.
- * @param interfaceName the name of the interface to configure
- * @param dhcpResults if the request succeeds, this object is filled in with
- * the IP address information.
- * @return {@code true} for success, {@code false} for failure
- */
- public static boolean runDhcp(String interfaceName, DhcpResults dhcpResults) {
- return startDhcp(interfaceName) && getDhcpResults(interfaceName, dhcpResults);
- }
-
- /**
- * Initiate renewal on the DHCP client daemon. This call blocks until it obtains
- * a result (either success or failure) from the daemon.
- * @param interfaceName the name of the interface to configure
- * @param dhcpResults if the request succeeds, this object is filled in with
- * the IP address information.
- * @return {@code true} for success, {@code false} for failure
- */
- public static boolean runDhcpRenew(String interfaceName, DhcpResults dhcpResults) {
- return startDhcpRenew(interfaceName) && getDhcpResults(interfaceName, dhcpResults);
- }
-
- /**
- * Fetch results from the DHCP client daemon. This call returns {@code true} if
- * if there are results available to be read, {@code false} otherwise.
- * @param interfaceName the name of the interface to configure
- * @param dhcpResults if the request succeeds, this object is filled in with
- * the IP address information.
- * @return {@code true} for success, {@code false} for failure
- */
- public native static boolean getDhcpResults(String interfaceName, DhcpResults dhcpResults);
-
- /**
- * Shut down the DHCP client daemon.
- * @param interfaceName the name of the interface for which the daemon
- * should be stopped
- * @return {@code true} for success, {@code false} for failure
- */
- public native static boolean stopDhcp(String interfaceName);
-
- /**
- * Release the current DHCP lease.
- * @param interfaceName the name of the interface for which the lease should
- * be released
- * @return {@code true} for success, {@code false} for failure
- */
- public native static boolean releaseDhcpLease(String interfaceName);
-
- /**
- * Return the last DHCP-related error message that was recorded.
- * <p/>NOTE: This string is not localized, but currently it is only
- * used in logging.
- * @return the most recent error message, if any
- */
- public native static String getDhcpError();
-
- /**
* Attaches a socket filter that accepts DHCP packets to the given socket.
*/
public native static void attachDhcpFilter(FileDescriptor fd) throws SocketException;
/**
+ * Attaches a socket filter that accepts ICMP6 router advertisement packets to the given socket.
+ * @param fd the socket's {@link FileDescriptor}.
+ * @param packetType the hardware address type, one of ARPHRD_*.
+ */
+ public native static void attachRaFilter(FileDescriptor fd, int packetType) throws SocketException;
+
+ /**
* Binds the current process to the network designated by {@code netId}. All sockets created
* in the future (and not explicitly bound via a bound {@link SocketFactory} (see
* {@link Network#getSocketFactory}) will be bound to this network. Note that if this
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index e82485d..ba8bd34 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -310,7 +310,7 @@
try {
getStatsService().incrementOperationCount(uid, tag, operationCount);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -653,7 +653,7 @@
try {
return getStatsService().getDataLayerSnapshotForUid(uid);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -666,7 +666,7 @@
try {
return getStatsService().getMobileIfaces();
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java
index 377ed88..86bd502 100644
--- a/core/java/android/net/nsd/NsdManager.java
+++ b/core/java/android/net/nsd/NsdManager.java
@@ -619,7 +619,9 @@
public void setEnabled(boolean enabled) {
try {
mService.setEnabled(enabled);
- } catch (RemoteException e) { }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -632,7 +634,7 @@
try {
return mService.getMessenger();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 56cb250..e40ebf7 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -221,7 +221,7 @@
try {
return mBatteryStats.isCharging();
} catch (RemoteException e) {
- return true;
+ throw e.rethrowFromSystemServer();
}
}
@@ -246,7 +246,7 @@
else
ret = Long.MIN_VALUE;
} catch (RemoteException e) {
- ret = Long.MIN_VALUE;
+ throw e.rethrowFromSystemServer();
}
return ret;
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index b33e807..8281279 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -623,7 +623,7 @@
/**
* The statistics associated with a particular service.
*/
- public abstract class Serv {
+ public static abstract class Serv {
/**
* Returns the amount of time spent started.
@@ -2827,7 +2827,7 @@
final long wifiOnTime = getWifiOnTime(rawRealtime, which);
final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
dumpLine(pw, 0 /* uid */, category, GLOBAL_WIFI_DATA, wifiOnTime / 1000,
- wifiRunningTime / 1000, /* legacy fields follow, keep at 0 */ 0, 0, 0, 0);
+ wifiRunningTime / 1000, /* legacy fields follow, keep at 0 */ 0, 0, 0);
dumpControllerActivityLine(pw, 0 /* uid */, category, GLOBAL_WIFI_CONTROLLER_DATA,
getWifiControllerActivity(), which);
diff --git a/core/java/android/os/CpuUsageInfo.aidl b/core/java/android/os/CpuUsageInfo.aidl
new file mode 100644
index 0000000..f81aefe
--- /dev/null
+++ b/core/java/android/os/CpuUsageInfo.aidl
@@ -0,0 +1,18 @@
+/* Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.os;
+
+parcelable CpuUsageInfo;
diff --git a/media/mca/effect/java/android/media/effect/package-info.java b/core/java/android/os/DeadSystemException.java
similarity index 63%
copy from media/mca/effect/java/android/media/effect/package-info.java
copy to core/java/android/os/DeadSystemException.java
index b2c14ff..595365c 100644
--- a/media/mca/effect/java/android/media/effect/package-info.java
+++ b/core/java/android/os/DeadSystemException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,15 +14,14 @@
* limitations under the License.
*/
-
-package android.media.effect;
+package android.os;
/**
- * <h1>Effect Framework</h1>
- *
- * This package includes a collection of high-performance visual effects that make use of the
- * mobile filter framework subsystem.
- *
- * TODO: More Documentation
- *
+ * The core Android system has died and is going through a runtime restart. All
+ * running apps will be promptly be killed.
*/
+public class DeadSystemException extends DeadObjectException {
+ public DeadSystemException() {
+ super();
+ }
+}
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index e58744b..f382241 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -98,13 +98,15 @@
/**
* Default trace file path and file
*/
- private static final String DEFAULT_TRACE_PATH_PREFIX =
- Environment.getLegacyExternalStorageDirectory().getPath() + "/";
private static final String DEFAULT_TRACE_BODY = "dmtrace";
private static final String DEFAULT_TRACE_EXTENSION = ".trace";
- private static final String DEFAULT_TRACE_FILE_PATH =
- DEFAULT_TRACE_PATH_PREFIX + DEFAULT_TRACE_BODY
- + DEFAULT_TRACE_EXTENSION;
+ private static class NoPreloadHolder {
+ private static final String DEFAULT_TRACE_PATH_PREFIX =
+ Environment.getLegacyExternalStorageDirectory().getPath() + "/";
+ private static final String DEFAULT_TRACE_FILE_PATH =
+ DEFAULT_TRACE_PATH_PREFIX + DEFAULT_TRACE_BODY
+ + DEFAULT_TRACE_EXTENSION;
+ }
/**
@@ -942,7 +944,7 @@
* tracing.
*/
public static void startMethodTracing() {
- VMDebug.startMethodTracing(DEFAULT_TRACE_FILE_PATH, 0, 0, false, 0);
+ VMDebug.startMethodTracing(fixTraceName(null), 0, 0, false, 0);
}
/**
@@ -1032,9 +1034,9 @@
*/
private static String fixTraceName(String traceName) {
if (traceName == null)
- traceName = DEFAULT_TRACE_FILE_PATH;
+ traceName = NoPreloadHolder.DEFAULT_TRACE_FILE_PATH;
if (traceName.charAt(0) != '/')
- traceName = DEFAULT_TRACE_PATH_PREFIX + traceName;
+ traceName = NoPreloadHolder.DEFAULT_TRACE_PATH_PREFIX + traceName;
if (!traceName.endsWith(DEFAULT_TRACE_EXTENSION))
traceName = traceName + DEFAULT_TRACE_EXTENSION;
@@ -2158,6 +2160,14 @@
public static native void dumpNativeBacktraceToFile(int pid, String file);
/**
+ * Get description of unreachable native memory.
+ * @param limit the number of leaks to provide info on, 0 to only get a summary.
+ * @param contents true to include a hex dump of the contents of unreachable memory.
+ * @return the String containing a description of unreachable memory.
+ * @hide */
+ public static native String getUnreachableMemory(int limit, boolean contents);
+
+ /**
* Return a String describing the calling method and location at a particular stack depth.
* @param callStack the Thread stack
* @param depth the depth of stack to return information for.
diff --git a/core/java/android/os/DropBoxManager.java b/core/java/android/os/DropBoxManager.java
index 2b14468..0d94072 100644
--- a/core/java/android/os/DropBoxManager.java
+++ b/core/java/android/os/DropBoxManager.java
@@ -267,7 +267,11 @@
* @param data value to store
*/
public void addText(String tag, String data) {
- try { mService.add(new Entry(tag, 0, data)); } catch (RemoteException e) {}
+ try {
+ mService.add(new Entry(tag, 0, data));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -279,7 +283,11 @@
*/
public void addData(String tag, byte[] data, int flags) {
if (data == null) throw new NullPointerException("data == null");
- try { mService.add(new Entry(tag, 0, data, flags)); } catch (RemoteException e) {}
+ try {
+ mService.add(new Entry(tag, 0, data, flags));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -297,7 +305,7 @@
try {
mService.add(entry);
} catch (RemoteException e) {
- // ignore
+ throw e.rethrowFromSystemServer();
} finally {
entry.close();
}
@@ -312,7 +320,11 @@
* @return whether events with that tag would be accepted
*/
public boolean isTagEnabled(String tag) {
- try { return mService.isTagEnabled(tag); } catch (RemoteException e) { return false; }
+ try {
+ return mService.isTagEnabled(tag);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -325,7 +337,11 @@
* @return the next entry, or null if there are no more entries
*/
public Entry getNextEntry(String tag, long msec) {
- try { return mService.getNextEntry(tag, msec); } catch (RemoteException e) { return null; }
+ try {
+ return mService.getNextEntry(tag, msec);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
// TODO: It may be useful to have some sort of notification mechanism
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 1085b1e..307bd2d 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -258,6 +258,20 @@
return buildPath(getDataDirectory(), "misc_de", String.valueOf(userId));
}
+ private static File getDataProfilesDeDirectory(int userId) {
+ return buildPath(getDataDirectory(), "misc", "profiles", "cur", String.valueOf(userId));
+ }
+
+ /** {@hide} */
+ public static File getDataProfilesDePackageDirectory(int userId, String packageName) {
+ return buildPath(getDataProfilesDeDirectory(userId), packageName);
+ }
+
+ /** {@hide} */
+ public static File getDataProfilesDeForeignDexDirectory(int userId) {
+ return buildPath(getDataProfilesDeDirectory(userId), "foreign-dex");
+ }
+
/** {@hide} */
public static File getDataAppDirectory(String volumeUuid) {
return new File(getDataDirectory(volumeUuid), "app");
@@ -493,7 +507,7 @@
* </ul>
* @hide
*/
- private static final String[] STANDARD_DIRECTORIES = {
+ public static final String[] STANDARD_DIRECTORIES = {
DIRECTORY_MUSIC,
DIRECTORY_PODCASTS,
DIRECTORY_RINGTONES,
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index c2aca41..1b79497 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -307,7 +307,11 @@
}
}
- /**
+ public static void stringToFile(File file, String string) throws IOException {
+ stringToFile(file.getAbsolutePath(), string);
+ }
+
+ /**
* Writes string to file. Basically same as "echo -n $string > $filename"
*
* @param filename
diff --git a/core/java/android/os/HardwarePropertiesManager.java b/core/java/android/os/HardwarePropertiesManager.java
index bc317b6..9ca1dcd 100644
--- a/core/java/android/os/HardwarePropertiesManager.java
+++ b/core/java/android/os/HardwarePropertiesManager.java
@@ -17,10 +17,12 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.content.Context;
+import android.util.Log;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-
/**
* The HardwarePropertiesManager class provides a mechanism of accessing hardware state of a
* device: CPU, GPU and battery temperatures, CPU usage per core, fan speed, etc.
@@ -29,11 +31,7 @@
private static final String TAG = HardwarePropertiesManager.class.getSimpleName();
- private static native void nativeInit();
-
- private static native float[] nativeGetFanSpeeds();
- private static native float[] nativeGetDeviceTemperatures(int type);
- private static native CpuUsageInfo[] nativeGetCpuUsages();
+ private final IHardwarePropertiesManager mService;
@Retention(RetentionPolicy.SOURCE)
@IntDef({
@@ -54,9 +52,13 @@
/** Temperature of battery in Celsius. */
public static final int DEVICE_TEMPERATURE_BATTERY = 2;
+ /** Calling app context. */
+ private final Context mContext;
+
/** @hide */
- public HardwarePropertiesManager() {
- nativeInit();
+ public HardwarePropertiesManager(Context context, IHardwarePropertiesManager service) {
+ mContext = context;
+ mService = service;
}
/**
@@ -67,16 +69,21 @@
* @return an array of requested float device temperatures.
* Empty if platform doesn't provide the queried temperature.
*
- * @throws IllegalArgumentException if an incorrect temperature type is queried.
+ * @throws SecurityException if a non profile or device owner tries to call this method.
*/
public @NonNull float[] getDeviceTemperatures(@DeviceTemperatureType int type) {
switch (type) {
case DEVICE_TEMPERATURE_CPU:
case DEVICE_TEMPERATURE_GPU:
case DEVICE_TEMPERATURE_BATTERY:
- return nativeGetDeviceTemperatures(type);
+ try {
+ return mService.getDeviceTemperatures(mContext.getOpPackageName(), type);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
default:
- throw new IllegalArgumentException();
+ Log.w(TAG, "Unknown device temperature type.");
+ return new float[0];
}
}
@@ -85,18 +92,30 @@
*
* @return an array of {@link android.os.CpuUsageInfo} for each core.
* Empty if CPU usage is not supported on this system.
+ *
+ * @throws SecurityException if a non profile or device owner tries to call this method.
*/
public @NonNull CpuUsageInfo[] getCpuUsages() {
- return nativeGetCpuUsages();
+ try {
+ return mService.getCpuUsages(mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
* Return an array of fan speeds in RPM.
*
- * @return an arrat of float fan speeds. Empty if there is no fans or fan speed
- * not supported on this system.
+ * @return an array of float fan speeds in RPM. Empty if there are no fans or fan speed is not
+ * supported on this system.
+ *
+ * @throws SecurityException if a non profile or device owner tries to call this method.
*/
public @NonNull float[] getFanSpeeds() {
- return nativeGetFanSpeeds();
+ try {
+ return mService.getFanSpeeds(mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
}
diff --git a/core/java/android/os/IHardwarePropertiesManager.aidl b/core/java/android/os/IHardwarePropertiesManager.aidl
new file mode 100644
index 0000000..bcf0dc8
--- /dev/null
+++ b/core/java/android/os/IHardwarePropertiesManager.aidl
@@ -0,0 +1,28 @@
+/*
+**
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.os;
+
+import android.os.CpuUsageInfo;
+
+/** @hide */
+
+interface IHardwarePropertiesManager {
+ float[] getDeviceTemperatures(String callingPackage, int type);
+ CpuUsageInfo[] getCpuUsages(String callingPackage);
+ float[] getFanSpeeds(String callingPackage);
+}
diff --git a/core/java/android/os/IRecoverySystem.aidl b/core/java/android/os/IRecoverySystem.aidl
new file mode 100644
index 0000000..12830a4
--- /dev/null
+++ b/core/java/android/os/IRecoverySystem.aidl
@@ -0,0 +1,28 @@
+/* //device/java/android/android/os/IRecoverySystem.aidl
+**
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.os;
+
+import android.os.IRecoverySystemProgressListener;
+
+/** @hide */
+
+interface IRecoverySystem {
+ boolean uncrypt(in String packageFile, IRecoverySystemProgressListener listener);
+ boolean setupBcb(in String command);
+ boolean clearBcb();
+}
diff --git a/core/java/android/os/IRecoverySystemProgressListener.aidl b/core/java/android/os/IRecoverySystemProgressListener.aidl
new file mode 100644
index 0000000..d6f712e
--- /dev/null
+++ b/core/java/android/os/IRecoverySystemProgressListener.aidl
@@ -0,0 +1,24 @@
+/* //device/java/android/android/os/IRecoverySystemProgressListener.aidl
+**
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.os;
+
+/** @hide */
+
+oneway interface IRecoverySystemProgressListener {
+ void onProgress(int progress);
+}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 314b7d5..2a4507c 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -224,6 +224,8 @@
* This is used by Gaming and VR applications to ensure the device provides
* will provide consistent performance over a large amount of time.
* </p>
+ *
+ * {@hide}
*/
public static final int SUSTAINED_PERFORMANCE_WAKE_LOCK = 0x00000100;
@@ -385,9 +387,9 @@
public static final int GO_TO_SLEEP_FLAG_NO_DOZE = 1 << 0;
/**
- * The value to pass as the 'reason' argument to reboot() to
- * reboot into recovery mode (for applying system updates, doing
- * factory resets, etc.).
+ * The value to pass as the 'reason' argument to reboot() to reboot into
+ * recovery mode for tasks other than applying system updates, such as
+ * doing factory resets.
* <p>
* Requires the {@link android.Manifest.permission#RECOVERY}
* permission (in addition to
@@ -398,6 +400,18 @@
public static final String REBOOT_RECOVERY = "recovery";
/**
+ * The value to pass as the 'reason' argument to reboot() to reboot into
+ * recovery mode for applying system updates.
+ * <p>
+ * Requires the {@link android.Manifest.permission#RECOVERY}
+ * permission (in addition to
+ * {@link android.Manifest.permission#REBOOT}).
+ * </p>
+ * @hide
+ */
+ public static final String REBOOT_RECOVERY_UPDATE = "recovery-update";
+
+ /**
* The value to pass as the 'reason' argument to reboot() when device owner requests a reboot on
* the device.
* @hide
@@ -606,6 +620,7 @@
try {
mService.userActivity(when, event, flags);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -657,6 +672,7 @@
try {
mService.goToSleep(time, reason, flags);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -683,6 +699,7 @@
try {
mService.wakeUp(time, "wakeUp", mContext.getOpPackageName());
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -693,6 +710,7 @@
try {
mService.wakeUp(time, reason, mContext.getOpPackageName());
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -721,6 +739,7 @@
try {
mService.nap(time);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -743,6 +762,7 @@
try {
mService.boostScreenBrightness(time);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -758,7 +778,7 @@
try {
return mService.isScreenBrightnessBoosted();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -776,6 +796,7 @@
try {
mService.setTemporaryScreenBrightnessSettingOverride(brightness);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -789,7 +810,7 @@
try {
return mService.isWakeLockLevelSupported(level);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -853,7 +874,7 @@
try {
return mService.isInteractive();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -870,6 +891,7 @@
try {
mService.reboot(false, reason, true);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -885,7 +907,7 @@
try {
return mService.isPowerSaveMode();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -902,7 +924,7 @@
try {
return mService.setPowerSaveMode(mode);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -922,7 +944,7 @@
try {
return mService.isDeviceIdleMode();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -942,7 +964,7 @@
try {
return mService.isLightDeviceIdleMode();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -961,7 +983,7 @@
try {
return mIDeviceIdleController.isPowerSaveWhitelistApp(packageName);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -978,6 +1000,7 @@
try {
mService.shutdown(confirm, reason, wait);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1104,6 +1127,7 @@
try {
mService.releaseWakeLock(mToken, 0);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1172,6 +1196,7 @@
mService.acquireWakeLock(mToken, mFlags, mTag, mPackageName, mWorkSource,
mHistoryTag);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
mHeld = true;
}
@@ -1210,6 +1235,7 @@
try {
mService.releaseWakeLock(mToken, flags);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
mHeld = false;
}
@@ -1266,6 +1292,7 @@
try {
mService.updateWakeLockWorkSource(mToken, mWorkSource, mHistoryTag);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 9984755..8fd3b0c 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -383,6 +383,9 @@
public static final int SIGNAL_KILL = 9;
public static final int SIGNAL_USR1 = 10;
+ private static long sStartElapsedRealtime;
+ private static long sStartUptimeMillis;
+
/**
* State for communicating with the zygote process.
*
@@ -772,6 +775,26 @@
public static final native long getElapsedCpuTime();
/**
+ * Return the {@link SystemClock#elapsedRealtime()} at which this process was started.
+ */
+ public static final long getStartElapsedRealtime() {
+ return sStartElapsedRealtime;
+ }
+
+ /**
+ * Return the {@link SystemClock#uptimeMillis()} at which this process was started.
+ */
+ public static final long getStartUptimeMillis() {
+ return sStartUptimeMillis;
+ }
+
+ /** @hide */
+ public static final void setStartTimes(long elapsedRealtime, long uptimeMillis) {
+ sStartElapsedRealtime = elapsedRealtime;
+ sStartUptimeMillis = uptimeMillis;
+ }
+
+ /**
* Returns true if the current process is a 64-bit runtime.
*/
public static final boolean is64Bit() {
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 154c9bb..ddcd635 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -16,6 +16,7 @@
package android.os;
+import android.annotation.SystemApi;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -66,15 +67,34 @@
private static final long PUBLISH_PROGRESS_INTERVAL_MS = 500;
/** Used to communicate with recovery. See bootable/recovery/recovery.cpp. */
- private static File RECOVERY_DIR = new File("/cache/recovery");
- private static File BLOCK_MAP_FILE = new File(RECOVERY_DIR, "block.map");
- private static File COMMAND_FILE = new File(RECOVERY_DIR, "command");
- private static File UNCRYPT_FILE = new File(RECOVERY_DIR, "uncrypt_file");
- private static File LOG_FILE = new File(RECOVERY_DIR, "log");
- private static String LAST_PREFIX = "last_";
+ private static final File RECOVERY_DIR = new File("/cache/recovery");
+ private static final File LOG_FILE = new File(RECOVERY_DIR, "log");
+ private static final String LAST_PREFIX = "last_";
+
+ /**
+ * The recovery image uses this file to identify the location (i.e. blocks)
+ * of an OTA package on the /data partition. The block map file is
+ * generated by uncrypt.
+ *
+ * @hide
+ */
+ public static final File BLOCK_MAP_FILE = new File(RECOVERY_DIR, "block.map");
+
+ /**
+ * UNCRYPT_PACKAGE_FILE stores the filename to be uncrypt'd, which will be
+ * read by uncrypt.
+ *
+ * @hide
+ */
+ public static final File UNCRYPT_PACKAGE_FILE = new File(RECOVERY_DIR, "uncrypt_file");
// Length limits for reading files.
- private static int LOG_FILE_MAX_LENGTH = 64 * 1024;
+ private static final int LOG_FILE_MAX_LENGTH = 64 * 1024;
+
+ // Prevent concurrent execution of requests.
+ private static final Object sRequestLock = new Object();
+
+ private final IRecoverySystem mService;
/**
* Interface definition for a callback to be invoked regularly as
@@ -287,6 +307,89 @@
}
/**
+ * Process a given package with uncrypt. No-op if the package is not on the
+ * /data partition.
+ *
+ * @param Context the Context to use
+ * @param packageFile the package to be processed
+ * @param listener an object to receive periodic progress updates as
+ * processing proceeds. May be null.
+ * @param handler the Handler upon which the callbacks will be
+ * executed.
+ *
+ * @throws IOException if there were any errors processing the package file.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static void processPackage(Context context,
+ File packageFile,
+ final ProgressListener listener,
+ final Handler handler)
+ throws IOException {
+ String filename = packageFile.getCanonicalPath();
+ if (!filename.startsWith("/data/")) {
+ return;
+ }
+
+ RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE);
+ IRecoverySystemProgressListener progressListener = null;
+ if (listener != null) {
+ final Handler progressHandler;
+ if (handler != null) {
+ progressHandler = handler;
+ } else {
+ progressHandler = new Handler(context.getMainLooper());
+ }
+ progressListener = new IRecoverySystemProgressListener.Stub() {
+ int lastProgress = 0;
+ long lastPublishTime = System.currentTimeMillis();
+
+ @Override
+ public void onProgress(final int progress) {
+ final long now = System.currentTimeMillis();
+ progressHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (progress > lastProgress &&
+ now - lastPublishTime > PUBLISH_PROGRESS_INTERVAL_MS) {
+ lastProgress = progress;
+ lastPublishTime = now;
+ listener.onProgress(progress);
+ }
+ }
+ });
+ }
+ };
+ }
+
+ if (!rs.uncrypt(filename, progressListener)) {
+ throw new IOException("process package failed");
+ }
+ }
+
+ /**
+ * Process a given package with uncrypt. No-op if the package is not on the
+ * /data partition.
+ *
+ * @param Context the Context to use
+ * @param packageFile the package to be processed
+ * @param listener an object to receive periodic progress updates as
+ * processing proceeds. May be null.
+ *
+ * @throws IOException if there were any errors processing the package file.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static void processPackage(Context context,
+ File packageFile,
+ final ProgressListener listener)
+ throws IOException {
+ processPackage(context, packageFile, listener, null);
+ }
+
+ /**
* Reboots the device in order to install the given update
* package.
* Requires the {@link android.Manifest.permission#REBOOT} permission.
@@ -301,30 +404,127 @@
* fails, or if the reboot itself fails.
*/
public static void installPackage(Context context, File packageFile)
- throws IOException {
+ throws IOException {
+ installPackage(context, packageFile, false);
+ }
+
+ /**
+ * If the package hasn't been processed (i.e. uncrypt'd), set up
+ * UNCRYPT_PACKAGE_FILE and delete BLOCK_MAP_FILE to trigger uncrypt during the
+ * reboot.
+ *
+ * @param context the Context to use
+ * @param packageFile the update package to install. Must be on a
+ * partition mountable by recovery.
+ * @param processed if the package has been processed (uncrypt'd).
+ *
+ * @throws IOException if writing the recovery command file fails, or if
+ * the reboot itself fails.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static void installPackage(Context context, File packageFile, boolean processed)
+ throws IOException {
+ synchronized (sRequestLock) {
+ LOG_FILE.delete();
+ // Must delete the file in case it was created by system server.
+ UNCRYPT_PACKAGE_FILE.delete();
+
+ String filename = packageFile.getCanonicalPath();
+ Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");
+
+ if (!processed && filename.startsWith("/data/")) {
+ FileWriter uncryptFile = new FileWriter(UNCRYPT_PACKAGE_FILE);
+ try {
+ uncryptFile.write(filename + "\n");
+ } finally {
+ uncryptFile.close();
+ }
+ // UNCRYPT_PACKAGE_FILE needs to be readable and writable by system server.
+ if (!UNCRYPT_PACKAGE_FILE.setReadable(true, false)
+ || !UNCRYPT_PACKAGE_FILE.setWritable(true, false)) {
+ Log.e(TAG, "Error setting permission for " + UNCRYPT_PACKAGE_FILE);
+ }
+
+ BLOCK_MAP_FILE.delete();
+ }
+
+ // If the package is on the /data partition, use the block map file as
+ // the package name instead.
+ if (filename.startsWith("/data/")) {
+ filename = "@/cache/recovery/block.map";
+ }
+
+ final String filenameArg = "--update_package=" + filename + "\n";
+ final String localeArg = "--locale=" + Locale.getDefault().toString() + "\n";
+ final String command = filenameArg + localeArg;
+
+ RecoverySystem rs = (RecoverySystem) context.getSystemService(
+ Context.RECOVERY_SERVICE);
+ if (!rs.setupBcb(command)) {
+ throw new IOException("Setup BCB failed");
+ }
+
+ // Having set up the BCB (bootloader control block), go ahead and reboot
+ PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ pm.reboot(PowerManager.REBOOT_RECOVERY_UPDATE);
+
+ throw new IOException("Reboot failed (no permissions?)");
+ }
+ }
+
+ /**
+ * Schedule to install the given package on next boot. The caller needs to
+ * ensure that the package must have been processed (uncrypt'd) if needed.
+ * It sets up the command in BCB (bootloader control block), which will
+ * be read by the bootloader and the recovery image.
+ *
+ * @param Context the Context to use.
+ * @param packageFile the package to be installed.
+ *
+ * @throws IOException if there were any errors setting up the BCB.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static void scheduleUpdateOnBoot(Context context, File packageFile)
+ throws IOException {
String filename = packageFile.getCanonicalPath();
- FileWriter uncryptFile = new FileWriter(UNCRYPT_FILE);
- try {
- uncryptFile.write(filename + "\n");
- } finally {
- uncryptFile.close();
- }
- // UNCRYPT_FILE needs to be readable by system server on bootup.
- if (!UNCRYPT_FILE.setReadable(true, false)) {
- Log.e(TAG, "Error setting readable for " + UNCRYPT_FILE.getCanonicalPath());
- }
- Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");
-
- // If the package is on the /data partition, write the block map file
- // into COMMAND_FILE instead.
+ // If the package is on the /data partition, use the block map file as
+ // the package name instead.
if (filename.startsWith("/data/")) {
filename = "@/cache/recovery/block.map";
}
- final String filenameArg = "--update_package=" + filename;
- final String localeArg = "--locale=" + Locale.getDefault().toString();
- bootCommand(context, filenameArg, localeArg);
+ final String filenameArg = "--update_package=" + filename + "\n";
+ final String localeArg = "--locale=" + Locale.getDefault().toString() + "\n";
+ final String command = filenameArg + localeArg;
+
+ RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE);
+ if (!rs.setupBcb(command)) {
+ throw new IOException("schedule update on boot failed");
+ }
+ }
+
+ /**
+ * Cancel any scheduled update by clearing up the BCB (bootloader control
+ * block).
+ *
+ * @param Context the Context to use.
+ *
+ * @throws IOException if there were any errors clearing up the BCB.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static void cancelScheduledUpdate(Context context)
+ throws IOException {
+ RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE);
+ if (!rs.clearBcb()) {
+ throw new IOException("cancel scheduled update failed");
+ }
}
/**
@@ -434,27 +634,28 @@
* @throws IOException if something goes wrong.
*/
private static void bootCommand(Context context, String... args) throws IOException {
- RECOVERY_DIR.mkdirs(); // In case we need it
- COMMAND_FILE.delete(); // In case it's not writable
- LOG_FILE.delete();
+ synchronized (sRequestLock) {
+ LOG_FILE.delete();
- FileWriter command = new FileWriter(COMMAND_FILE);
- try {
+ StringBuilder command = new StringBuilder();
for (String arg : args) {
if (!TextUtils.isEmpty(arg)) {
- command.write(arg);
- command.write("\n");
+ command.append(arg);
+ command.append("\n");
}
}
- } finally {
- command.close();
+
+ // Write the command into BCB (bootloader control block).
+ RecoverySystem rs = (RecoverySystem) context.getSystemService(
+ Context.RECOVERY_SERVICE);
+ rs.setupBcb(command.toString());
+
+ // Having set up the BCB, go ahead and reboot.
+ PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ pm.reboot(PowerManager.REBOOT_RECOVERY);
+
+ throw new IOException("Reboot failed (no permissions?)");
}
-
- // Having written the command file, go ahead and reboot
- PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- pm.reboot(PowerManager.REBOOT_RECOVERY);
-
- throw new IOException("Reboot failed (no permissions?)");
}
/**
@@ -476,10 +677,10 @@
// Only remove the OTA package if it's partially processed (uncrypt'd).
boolean reservePackage = BLOCK_MAP_FILE.exists();
- if (!reservePackage && UNCRYPT_FILE.exists()) {
+ if (!reservePackage && UNCRYPT_PACKAGE_FILE.exists()) {
String filename = null;
try {
- filename = FileUtils.readTextFile(UNCRYPT_FILE, 0, null);
+ filename = FileUtils.readTextFile(UNCRYPT_PACKAGE_FILE, 0, null);
} catch (IOException e) {
Log.e(TAG, "Error reading uncrypt file", e);
}
@@ -487,7 +688,7 @@
// Remove the OTA package on /data that has been (possibly
// partially) processed. (Bug: 24973532)
if (filename != null && filename.startsWith("/data")) {
- if (UNCRYPT_FILE.delete()) {
+ if (UNCRYPT_PACKAGE_FILE.delete()) {
Log.i(TAG, "Deleted: " + filename);
} else {
Log.e(TAG, "Can't delete: " + filename);
@@ -499,13 +700,13 @@
// the block map file (BLOCK_MAP_FILE) for a package. BLOCK_MAP_FILE
// will be created at the end of a successful uncrypt. If seeing this
// file, we keep the block map file and the file that contains the
- // package name (UNCRYPT_FILE). This is to reduce the work for GmsCore
- // to avoid re-downloading everything again.
+ // package name (UNCRYPT_PACKAGE_FILE). This is to reduce the work for
+ // GmsCore to avoid re-downloading everything again.
String[] names = RECOVERY_DIR.list();
for (int i = 0; names != null && i < names.length; i++) {
if (names[i].startsWith(LAST_PREFIX)) continue;
if (reservePackage && names[i].equals(BLOCK_MAP_FILE.getName())) continue;
- if (reservePackage && names[i].equals(UNCRYPT_FILE.getName())) continue;
+ if (reservePackage && names[i].equals(UNCRYPT_PACKAGE_FILE.getName())) continue;
recursiveDelete(new File(RECOVERY_DIR, names[i]));
}
@@ -533,6 +734,39 @@
}
/**
+ * Talks to RecoverySystemService via Binder to trigger uncrypt.
+ */
+ private boolean uncrypt(String packageFile, IRecoverySystemProgressListener listener) {
+ try {
+ return mService.uncrypt(packageFile, listener);
+ } catch (RemoteException unused) {
+ }
+ return false;
+ }
+
+ /**
+ * Talks to RecoverySystemService via Binder to set up the BCB.
+ */
+ private boolean setupBcb(String command) {
+ try {
+ return mService.setupBcb(command);
+ } catch (RemoteException unused) {
+ }
+ return false;
+ }
+
+ /**
+ * Talks to RecoverySystemService via Binder to clear up the BCB.
+ */
+ private boolean clearBcb() {
+ try {
+ return mService.clearBcb();
+ } catch (RemoteException unused) {
+ }
+ return false;
+ }
+
+ /**
* Internally, recovery treats each line of the command file as a separate
* argv, so we only need to protect against newlines and nulls.
*/
@@ -546,5 +780,14 @@
/**
* @removed Was previously made visible by accident.
*/
- public RecoverySystem() { }
+ public RecoverySystem() {
+ mService = null;
+ }
+
+ /**
+ * @hide
+ */
+ public RecoverySystem(IRecoverySystem service) {
+ mService = service;
+ }
}
diff --git a/core/java/android/os/RemoteException.java b/core/java/android/os/RemoteException.java
index 98d7523..6d25fc1 100644
--- a/core/java/android/os/RemoteException.java
+++ b/core/java/android/os/RemoteException.java
@@ -15,6 +15,7 @@
*/
package android.os;
+
import android.util.AndroidException;
/**
@@ -33,4 +34,25 @@
public RuntimeException rethrowAsRuntimeException() {
throw new RuntimeException(this);
}
+
+ /**
+ * Rethrow this exception when we know it came from the system server. This
+ * gives us an opportunity to throw a nice clean
+ * {@link DeadSystemException} signal to avoid spamming logs with
+ * misleading stack traces.
+ * <p>
+ * Apps making calls into the system server may end up persisting internal
+ * state or making security decisions based on the perceived success or
+ * failure of a call, or any default values returned. For this reason, we
+ * want to strongly throw when there was trouble with the transaction.
+ *
+ * @hide
+ */
+ public RuntimeException rethrowFromSystemServer() {
+ if (this instanceof DeadObjectException) {
+ throw new RuntimeException(new DeadSystemException());
+ } else {
+ throw new RuntimeException(this);
+ }
+ }
}
diff --git a/core/java/android/os/ServiceSpecificException.java b/core/java/android/os/ServiceSpecificException.java
index 20f237a5..04fca19 100644
--- a/core/java/android/os/ServiceSpecificException.java
+++ b/core/java/android/os/ServiceSpecificException.java
@@ -20,20 +20,23 @@
*
* <p>This exception includes an error code specific to the throwing
* service. This is mostly used by system services to indicate
- * domain specific error conditions.
+ * domain specific error conditions.</p>
+ *
+ * <p>Since these exceptions are designed to be passed through Binder
+ * interfaces, and to be generated by native-code Binder services,
+ * they do not support exception chaining.</p>
*
* @hide
*/
public class ServiceSpecificException extends RuntimeException {
public final int errorCode;
- ServiceSpecificException(int errorCode, String message) {
+ public ServiceSpecificException(int errorCode, String message) {
super(message);
this.errorCode = errorCode;
}
- ServiceSpecificException(int errorCode) {
+ public ServiceSpecificException(int errorCode) {
this.errorCode = errorCode;
}
}
-
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 91d88da..e4a76db 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -1517,7 +1517,11 @@
violationMaskSubset,
info);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
+ if (e instanceof DeadObjectException) {
+ // System process is dead; ignore
+ } else {
+ Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
+ }
} finally {
// Restore the policy.
setThreadPolicyMask(savedPolicyMask);
@@ -1569,7 +1573,11 @@
info);
}
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException handling StrictMode violation", e);
+ if (e instanceof DeadObjectException) {
+ // System process is dead; ignore
+ } else {
+ Log.e(TAG, "RemoteException handling StrictMode violation", e);
+ }
}
int outstanding = sDropboxCallsInFlight.decrementAndGet();
if (LOG_V) Log.d(TAG, "Dropbox complete; in-flight=" + outstanding);
@@ -1897,7 +1905,11 @@
violationMaskSubset,
info);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
+ if (e instanceof DeadObjectException) {
+ // System process is dead; ignore
+ } else {
+ Log.e(TAG, "RemoteException trying to handle StrictMode violation", e);
+ }
} finally {
// Restore the policy.
setThreadPolicyMask(savedPolicyMask);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 69d564f..7223dfb 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -36,7 +36,7 @@
import android.graphics.drawable.Drawable;
import android.os.storage.StorageManager;
import android.provider.Settings;
-import android.util.Log;
+import android.telephony.TelephonyManager;
import android.view.WindowManager.LayoutParams;
import com.android.internal.R;
@@ -379,8 +379,7 @@
* Specifies that the user is not allowed to make outgoing
* phone calls. Emergency calls are still permitted.
* The default value is <code>false</code>.
- * <p>This restriction has no effect on managed profiles since call intents are normally
- * forwarded to the primary user.
+ * <p>This restriction has no effect on managed profiles.
*
* <p>Key for user restrictions.
* <p>Type: Boolean
@@ -682,6 +681,22 @@
}
/**
+ * Returns whether switching users is currently allowed.
+ * <p>For instance switching users is not allowed if the current user is in a phone call,
+ * or system user hasn't been unlocked yet
+ * @hide
+ */
+ public boolean canSwitchUsers() {
+ boolean allowUserSwitchingWhenSystemUserLocked = Settings.Global.getInt(
+ mContext.getContentResolver(),
+ Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED, 0) != 0;
+ boolean isSystemUserUnlocked = isUserUnlocked(UserHandle.SYSTEM);
+ boolean inCall = TelephonyManager.getDefault().getCallState()
+ != TelephonyManager.CALL_STATE_IDLE;
+ return (allowUserSwitchingWhenSystemUserLocked || isSystemUserUnlocked) && !inCall;
+ }
+
+ /**
* Returns the user handle for the user that this process is running under.
*
* @return the user handle of this process.
@@ -701,8 +716,7 @@
try {
return mService.getUserInfo(getUserHandle()).name;
} catch (RemoteException re) {
- Log.w(TAG, "Could not get user name", re);
- return "";
+ throw re.rethrowFromSystemServer();
}
}
@@ -772,8 +786,7 @@
try {
return mService.isRestricted();
} catch (RemoteException re) {
- Log.w(TAG, "Could not check if user is limited ", re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -785,8 +798,7 @@
try {
return mService.canHaveRestrictedProfile(userId);
} catch (RemoteException re) {
- Log.w(TAG, "Could not check if user can have restricted profile", re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -848,8 +860,8 @@
public boolean isUserRunning(int userId) {
try {
return ActivityManagerNative.getDefault().isUserRunning(userId, 0);
- } catch (RemoteException e) {
- return false;
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
}
}
@@ -865,8 +877,8 @@
// TODO: reconcile stopped vs stopping?
return ActivityManagerNative.getDefault().isUserRunning(
user.getIdentifier(), ActivityManager.FLAG_OR_STOPPED);
- } catch (RemoteException e) {
- return false;
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
}
}
@@ -894,8 +906,8 @@
try {
return ActivityManagerNative.getDefault().isUserRunning(
user.getIdentifier(), ActivityManager.FLAG_AND_LOCKED);
- } catch (RemoteException e) {
- return false;
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
}
}
@@ -923,8 +935,8 @@
try {
return ActivityManagerNative.getDefault().isUserRunning(
user.getIdentifier(), ActivityManager.FLAG_AND_UNLOCKED);
- } catch (RemoteException e) {
- return false;
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
}
}
@@ -969,8 +981,7 @@
try {
return mService.getUserInfo(userHandle);
} catch (RemoteException re) {
- Log.w(TAG, "Could not get user info", re);
- return null;
+ throw re.rethrowFromSystemServer();
}
}
@@ -991,8 +1002,7 @@
try {
return mService.getUserRestrictions(userHandle.getIdentifier());
} catch (RemoteException re) {
- Log.w(TAG, "Could not get user restrictions", re);
- return Bundle.EMPTY;
+ throw re.rethrowFromSystemServer();
}
}
@@ -1008,9 +1018,7 @@
try {
return mService.hasBaseUserRestriction(restrictionKey, userHandle.getIdentifier());
} catch (RemoteException re) {
- Log.w(TAG, "Could not get base user restrictions for user " +
- userHandle.getIdentifier(), re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -1066,7 +1074,7 @@
try {
mService.setUserRestriction(key, value, userHandle.getIdentifier());
} catch (RemoteException re) {
- Log.w(TAG, "Could not set user restriction", re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -1093,8 +1101,7 @@
return mService.hasUserRestriction(restrictionKey,
userHandle.getIdentifier());
} catch (RemoteException re) {
- Log.w(TAG, "Could not check user restrictions", re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -1148,7 +1155,7 @@
mService.setUserRestriction(DISALLOW_OUTGOING_CALLS, true, user.id);
}
} catch (RemoteException re) {
- Log.w(TAG, "Could not create a user", re);
+ throw re.rethrowFromSystemServer();
}
return user;
}
@@ -1168,7 +1175,7 @@
Settings.Secure.SKIP_FIRST_USE_HINTS, "1", guest.id);
}
} catch (RemoteException re) {
- Log.w(TAG, "Could not create a user", re);
+ throw re.rethrowFromSystemServer();
}
return guest;
}
@@ -1189,8 +1196,7 @@
try {
return mService.createProfileForUser(name, flags, userHandle);
} catch (RemoteException re) {
- Log.w(TAG, "Could not create a user", re);
- return null;
+ throw re.rethrowFromSystemServer();
}
}
@@ -1212,10 +1218,9 @@
UserHandle.of(user.id));
}
return user;
- } catch (RemoteException e) {
- Log.w(TAG, "Could not create a restricted profile", e);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
}
- return null;
}
/**
@@ -1283,8 +1288,7 @@
try {
return mService.getSeedAccountName();
} catch (RemoteException re) {
- Log.w(TAG, "Could not get the seed account name", re);
- return null;
+ throw re.rethrowFromSystemServer();
}
}
@@ -1298,8 +1302,7 @@
try {
return mService.getSeedAccountType();
} catch (RemoteException re) {
- Log.w(TAG, "Could not get the seed account type", re);
- return null;
+ throw re.rethrowFromSystemServer();
}
}
@@ -1315,8 +1318,7 @@
try {
return mService.getSeedAccountOptions();
} catch (RemoteException re) {
- Log.w(TAG, "Could not get the seed account options", re);
- return null;
+ throw re.rethrowFromSystemServer();
}
}
@@ -1337,7 +1339,7 @@
mService.setSeedAccountData(userId, accountName, accountType, accountOptions,
/* persist= */ true);
} catch (RemoteException re) {
- Log.w(TAG, "Could not set the seed account data", re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -1350,7 +1352,7 @@
try {
mService.clearSeedAccountData();
} catch (RemoteException re) {
- Log.w(TAG, "Could not clear the seed account data", re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -1365,15 +1367,18 @@
try {
return mService.markGuestForDeletion(userHandle);
} catch (RemoteException re) {
- Log.w(TAG, "Could not mark guest for deletion", re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
/**
* Sets the user as enabled, if such an user exists.
- * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
- * Note that the default is true, it's only that managed profiles might not be enabled.
+ *
+ * <p>Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+ *
+ * <p>Note that the default is true, it's only that managed profiles might not be enabled.
+ * Also ephemeral users can be disabled to indicate that their removal is in progress and they
+ * shouldn't be re-entered. Therefore ephemeral users should not be re-enabled once disabled.
*
* @param userHandle the id of the profile to enable
* @hide
@@ -1381,8 +1386,8 @@
public void setUserEnabled(@UserIdInt int userHandle) {
try {
mService.setUserEnabled(userHandle);
- } catch (RemoteException e) {
- Log.w(TAG, "Could not enable the profile", e);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
}
}
@@ -1404,8 +1409,7 @@
try {
return mService.getUsers(false);
} catch (RemoteException re) {
- Log.w(TAG, "Could not get user list", re);
- return null;
+ throw re.rethrowFromSystemServer();
}
}
@@ -1427,8 +1431,7 @@
}
return result;
} catch (RemoteException re) {
- Log.w(TAG, "Could not get users list", re);
- return null;
+ throw re.rethrowFromSystemServer();
}
}
@@ -1444,8 +1447,7 @@
try {
return mService.getUserAccount(userHandle);
} catch (RemoteException re) {
- Log.w(TAG, "Could not get user account", re);
- return null;
+ throw re.rethrowFromSystemServer();
}
}
@@ -1461,7 +1463,7 @@
try {
mService.setUserAccount(userHandle, accountName);
} catch (RemoteException re) {
- Log.w(TAG, "Could not set user account", re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -1476,8 +1478,7 @@
try {
return mService.getPrimaryUser();
} catch (RemoteException re) {
- Log.w(TAG, "Could not get Primary user", re);
- return null;
+ throw re.rethrowFromSystemServer();
}
}
@@ -1514,8 +1515,7 @@
try {
return mService.canAddMoreManagedProfiles(userId, allowedToRemoveOne);
} catch (RemoteException re) {
- Log.w(TAG, "Could not check if we can add more managed profiles", re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -1534,8 +1534,7 @@
try {
return mService.getProfiles(userHandle, false /* enabledOnly */);
} catch (RemoteException re) {
- Log.w(TAG, "Could not get user list", re);
- return null;
+ throw re.rethrowFromSystemServer();
}
}
@@ -1550,8 +1549,7 @@
try {
return mService.isSameProfileGroup(userId, otherUserId);
} catch (RemoteException re) {
- Log.w(TAG, "Could not get user list", re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -1569,8 +1567,7 @@
try {
return mService.getProfiles(userHandle, true /* enabledOnly */);
} catch (RemoteException re) {
- Log.w(TAG, "Could not get user list", re);
- return null;
+ throw re.rethrowFromSystemServer();
}
}
@@ -1586,8 +1583,7 @@
try {
users = mService.getProfiles(UserHandle.myUserId(), true /* enabledOnly */);
} catch (RemoteException re) {
- Log.w(TAG, "Could not get user list", re);
- return null;
+ throw re.rethrowFromSystemServer();
}
for (UserInfo info : users) {
UserHandle userHandle = new UserHandle(info.id);
@@ -1607,8 +1603,7 @@
try {
return mService.getCredentialOwnerProfile(userHandle);
} catch (RemoteException re) {
- Log.w(TAG, "Could not get credential owner", re);
- return -1;
+ throw re.rethrowFromSystemServer();
}
}
@@ -1622,8 +1617,7 @@
try {
return mService.getProfileParent(userHandle);
} catch (RemoteException re) {
- Log.w(TAG, "Could not get profile parent", re);
- return null;
+ throw re.rethrowFromSystemServer();
}
}
@@ -1637,8 +1631,8 @@
public void setQuietModeEnabled(@UserIdInt int userHandle, boolean enableQuietMode) {
try {
mService.setQuietModeEnabled(userHandle, enableQuietMode);
- } catch (RemoteException e) {
- Log.w(TAG, "Could not change the profile's quiet mode", e);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
}
}
@@ -1651,10 +1645,9 @@
public boolean isQuietModeEnabled(UserHandle userHandle) {
try {
return mService.isQuietModeEnabled(userHandle.getIdentifier());
- } catch (RemoteException e) {
- Log.w(TAG, "Could not query the profile's quiet mode", e);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
}
- return false;
}
/**
@@ -1665,7 +1658,7 @@
* android.graphics.drawable.Drawable, UserHandle, android.graphics.Rect, int)}.
* <p>
* If the original drawable is a BitmapDrawable and the backing bitmap is
- * mutable as per {@link android.graphics.Bitmap#isMutable()}, the bading
+ * mutable as per {@link android.graphics.Bitmap#isMutable()}, the badging
* is performed in place and the original drawable is returned.
* </p>
*
@@ -1688,17 +1681,17 @@
* badge to be used.
* <p>
* If the original drawable is a BitmapDrawable and the backing bitmap is
- * mutable as per {@link android.graphics.Bitmap#isMutable()}, the bading
+ * mutable as per {@link android.graphics.Bitmap#isMutable()}, the badging
* is performed in place and the original drawable is returned.
* </p>
*
* @param badgedDrawable The drawable to badge.
* @param user The target user.
* @param badgeLocation Where in the bounds of the badged drawable to place
- * the badge. If not provided, the badge is applied on top of the entire
+ * the badge. If it's {@code null}, the badge is applied on top of the entire
* drawable being badged.
* @param badgeDensity The optional desired density for the badge as per
- * {@link android.util.DisplayMetrics#densityDpi}. If not provided,
+ * {@link android.util.DisplayMetrics#densityDpi}. If it's not positive,
* the density of the display is used.
* @return A drawable that combines the original drawable and a badge as
* determined by the system.
@@ -1739,8 +1732,7 @@
try {
return mService.getUsers(excludeDying);
} catch (RemoteException re) {
- Log.w(TAG, "Could not get user list", re);
- return null;
+ throw re.rethrowFromSystemServer();
}
}
@@ -1754,8 +1746,7 @@
try {
return mService.removeUser(userHandle);
} catch (RemoteException re) {
- Log.w(TAG, "Could not remove user ", re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -1771,7 +1762,7 @@
try {
mService.setUserName(userHandle, name);
} catch (RemoteException re) {
- Log.w(TAG, "Could not set the user name ", re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -1785,7 +1776,7 @@
try {
mService.setUserIcon(userHandle, icon);
} catch (RemoteException re) {
- Log.w(TAG, "Could not set the user icon ", re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -1810,7 +1801,7 @@
}
}
} catch (RemoteException re) {
- Log.w(TAG, "Could not get the user icon ", re);
+ throw re.rethrowFromSystemServer();
}
return null;
}
@@ -1866,9 +1857,8 @@
try {
return mService.getUserSerialNumber(userHandle);
} catch (RemoteException re) {
- Log.w(TAG, "Could not get serial number for user " + userHandle);
+ throw re.rethrowFromSystemServer();
}
- return -1;
}
/**
@@ -1884,9 +1874,8 @@
try {
return mService.getUserHandle(userSerialNumber);
} catch (RemoteException re) {
- Log.w(TAG, "Could not get userHandle for user " + userSerialNumber);
+ throw re.rethrowFromSystemServer();
}
- return -1;
}
/**
@@ -1912,9 +1901,8 @@
try {
return mService.getApplicationRestrictions(packageName);
} catch (RemoteException re) {
- Log.w(TAG, "Could not get application restrictions for package " + packageName);
+ throw re.rethrowFromSystemServer();
}
- return null;
}
/**
@@ -1924,9 +1912,8 @@
try {
return mService.getApplicationRestrictionsForUser(packageName, user.getIdentifier());
} catch (RemoteException re) {
- Log.w(TAG, "Could not get application restrictions for user " + user.getIdentifier());
+ throw re.rethrowFromSystemServer();
}
- return null;
}
/**
@@ -1937,7 +1924,7 @@
try {
mService.setApplicationRestrictions(packageName, restrictions, user.getIdentifier());
} catch (RemoteException re) {
- Log.w(TAG, "Could not set application restrictions for user " + user.getIdentifier());
+ throw re.rethrowFromSystemServer();
}
}
@@ -1961,7 +1948,7 @@
try {
mService.setDefaultGuestRestrictions(restrictions);
} catch (RemoteException re) {
- Log.w(TAG, "Could not set guest restrictions");
+ throw re.rethrowFromSystemServer();
}
}
@@ -1973,9 +1960,8 @@
try {
return mService.getDefaultGuestRestrictions();
} catch (RemoteException re) {
- Log.w(TAG, "Could not set guest restrictions");
+ throw re.rethrowFromSystemServer();
}
- return new Bundle();
}
/**
@@ -1988,8 +1974,7 @@
try {
return mService.getUserCreationTime(userHandle.getIdentifier());
} catch (RemoteException re) {
- Log.w(TAG, "Could not get user creation time", re);
- return 0;
+ throw re.rethrowFromSystemServer();
}
}
@@ -2005,8 +1990,7 @@
try {
return mService.someUserHasSeedAccount(accountName, accountType);
} catch (RemoteException re) {
- Log.w(TAG, "Could not check seed accounts", re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/os/UserManagerInternal.java b/core/java/android/os/UserManagerInternal.java
index d2ece8b..f399719 100644
--- a/core/java/android/os/UserManagerInternal.java
+++ b/core/java/android/os/UserManagerInternal.java
@@ -109,6 +109,17 @@
public abstract void removeAllUsers();
/**
+ * Called by the activity manager when the ephemeral user goes to background and its removal
+ * starts as a result.
+ *
+ * <p>It marks the ephemeral user as disabled in order to prevent it from being re-entered
+ * before its removal finishes.
+ *
+ * @param userId the ID of the ephemeral user.
+ */
+ public abstract void onEphemeralUserStop(int userId);
+
+ /**
* Same as UserManager.createUser(), but bypasses the check for DISALLOW_ADD_USER.
*
* <p>Called by the {@link com.android.server.devicepolicy.DevicePolicyManagerService} when
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 97ee90d..17df708 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -332,7 +332,7 @@
try {
mMountService.registerListener(delegate);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
mDelegates.add(delegate);
}
@@ -353,7 +353,7 @@
try {
mMountService.unregisterListener(delegate);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
i.remove();
}
@@ -434,10 +434,8 @@
} catch (IOException e) {
throw new IllegalArgumentException("Failed to resolve path: " + rawPath, e);
} catch (RemoteException e) {
- Log.e(TAG, "Failed to mount OBB", e);
+ throw e.rethrowFromSystemServer();
}
-
- return false;
}
/**
@@ -469,10 +467,8 @@
mMountService.unmountObb(rawPath, force, mObbActionListener, nonce);
return true;
} catch (RemoteException e) {
- Log.e(TAG, "Failed to mount OBB", e);
+ throw e.rethrowFromSystemServer();
}
-
- return false;
}
/**
@@ -487,10 +483,8 @@
try {
return mMountService.isObbMounted(rawPath);
} catch (RemoteException e) {
- Log.e(TAG, "Failed to check if OBB is mounted", e);
+ throw e.rethrowFromSystemServer();
}
-
- return false;
}
/**
@@ -508,10 +502,8 @@
try {
return mMountService.getMountedObbPath(rawPath);
} catch (RemoteException e) {
- Log.e(TAG, "Failed to find mounted path for OBB", e);
+ throw e.rethrowFromSystemServer();
}
-
- return null;
}
/** {@hide} */
@@ -519,7 +511,7 @@
try {
return Arrays.asList(mMountService.getDisks());
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -605,7 +597,7 @@
try {
return Arrays.asList(mMountService.getVolumes(0));
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -620,7 +612,7 @@
}
return res;
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -629,7 +621,7 @@
try {
return Arrays.asList(mMountService.getVolumeRecords(0));
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -672,7 +664,7 @@
try {
mMountService.mount(volId);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -681,7 +673,7 @@
try {
mMountService.unmount(volId);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -690,7 +682,7 @@
try {
mMountService.format(volId);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -699,7 +691,7 @@
try {
return mMountService.benchmark(volId);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -708,7 +700,7 @@
try {
mMountService.partitionPublic(diskId);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -717,7 +709,7 @@
try {
mMountService.partitionPrivate(diskId);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -726,7 +718,7 @@
try {
mMountService.partitionMixed(diskId, ratio);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -759,7 +751,7 @@
try {
mMountService.setVolumeNickname(fsUuid, nickname);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -769,7 +761,7 @@
mMountService.setVolumeUserFlags(fsUuid, inited ? VolumeRecord.USER_FLAG_INITED : 0,
VolumeRecord.USER_FLAG_INITED);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -779,7 +771,7 @@
mMountService.setVolumeUserFlags(fsUuid, snoozed ? VolumeRecord.USER_FLAG_SNOOZED : 0,
VolumeRecord.USER_FLAG_SNOOZED);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -788,7 +780,7 @@
try {
mMountService.forgetVolume(fsUuid);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -802,7 +794,7 @@
try {
return mMountService.getPrimaryStorageUuid();
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -816,7 +808,7 @@
try {
mMountService.setPrimaryStorageUuid(volumeUuid, callback);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -900,7 +892,7 @@
}
return mountService.getVolumeList(uid, packageName, flags);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -984,7 +976,7 @@
try {
mMountService.createUserKey(userId, serialNumber, ephemeral);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -993,7 +985,7 @@
try {
mMountService.destroyUserKey(userId);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -1002,7 +994,7 @@
try {
mMountService.unlockUserKey(userId, serialNumber, token, secret);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -1011,7 +1003,7 @@
try {
mMountService.lockUserKey(userId);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -1020,7 +1012,7 @@
try {
mMountService.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -1029,7 +1021,7 @@
try {
return mMountService.isUserKeyUnlocked(userId);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
@@ -1064,7 +1056,8 @@
}
}
}
- } catch (RemoteException ignored) {
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
return path;
}
@@ -1074,7 +1067,7 @@
try {
return mMountService.mountAppFuse(name);
} catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ throw e.rethrowFromSystemServer();
}
}
diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java
index d860c7d..54d20d3 100644
--- a/core/java/android/os/storage/StorageVolume.java
+++ b/core/java/android/os/storage/StorageVolume.java
@@ -76,7 +76,7 @@
*/
// NOTE: This is a legacy specialization of VolumeInfo which describes the volume for a specific
// user, but is now part of the public API.
-public class StorageVolume implements Parcelable {
+public final class StorageVolume implements Parcelable {
private final String mId;
private final int mStorageId;
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index 4b70649..ea0597d 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -438,10 +438,6 @@
final Intent intent = new Intent(DocumentsContract.ACTION_BROWSE);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(uri);
-
- // note that docsui treats this as *force* show advanced. So sending
- // false permits advanced to be shown based on user preferences.
- intent.putExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, isPrimary());
intent.putExtra(DocumentsContract.EXTRA_SHOW_FILESIZE, true);
return intent;
}
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index 5d64af5..d41bc07 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -1494,11 +1494,9 @@
* @return True if the Preference is persistent. (This is not whether the
* value was persisted, since we may not necessarily commit if there
* will be a batch commit later.)
- * @see #getPersistedString(Set)
- *
- * @hide Pending API approval
+ * @see #getPersistedStringSet(Set)
*/
- protected boolean persistStringSet(Set<String> values) {
+ public boolean persistStringSet(Set<String> values) {
if (shouldPersist()) {
// Shouldn't store null
if (values.equals(getPersistedStringSet(null))) {
@@ -1527,10 +1525,8 @@
* @return The value from the SharedPreferences or the default return
* value.
* @see #persistStringSet(Set)
- *
- * @hide Pending API approval
*/
- protected Set<String> getPersistedStringSet(Set<String> defaultReturnValue) {
+ public Set<String> getPersistedStringSet(Set<String> defaultReturnValue) {
if (!shouldPersist()) {
return defaultReturnValue;
}
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index 58f260c..0540036 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -232,9 +232,8 @@
try {
return mService.getPrintJobInfo(printJobId, mAppId, mUserId);
} catch (RemoteException re) {
- Log.e(LOG_TAG, "Error getting a print job info:" + printJobId, re);
+ throw re.rethrowFromSystemServer();
}
- return null;
}
/**
@@ -258,7 +257,7 @@
mService.addPrintJobStateChangeListener(wrappedListener, mAppId, mUserId);
mPrintJobStateChangeListeners.put(listener, wrappedListener);
} catch (RemoteException re) {
- Log.e(LOG_TAG, "Error adding print job state change listener", re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -288,7 +287,7 @@
try {
mService.removePrintJobStateChangeListener(wrappedListener, mUserId);
} catch (RemoteException re) {
- Log.e(LOG_TAG, "Error removing print job state change listener", re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -311,7 +310,7 @@
return new PrintJob(printJob, this);
}
} catch (RemoteException re) {
- Log.e(LOG_TAG, "Error getting print job", re);
+ throw re.rethrowFromSystemServer();
}
return null;
}
@@ -334,9 +333,8 @@
try {
return mService.getCustomPrinterIcon(printerId, mUserId);
} catch (RemoteException re) {
- Log.e(LOG_TAG, "Error getting custom printer icon", re);
+ throw re.rethrowFromSystemServer();
}
- return null;
}
/**
@@ -362,9 +360,8 @@
}
return printJobs;
} catch (RemoteException re) {
- Log.e(LOG_TAG, "Error getting print jobs", re);
+ throw re.rethrowFromSystemServer();
}
- return Collections.emptyList();
}
void cancelPrintJob(PrintJobId printJobId) {
@@ -375,7 +372,7 @@
try {
mService.cancelPrintJob(printJobId, mAppId, mUserId);
} catch (RemoteException re) {
- Log.e(LOG_TAG, "Error canceling a print job: " + printJobId, re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -387,7 +384,7 @@
try {
mService.restartPrintJob(printJobId, mAppId, mUserId);
} catch (RemoteException re) {
- Log.e(LOG_TAG, "Error restarting a print job: " + printJobId, re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -475,7 +472,7 @@
}
}
} catch (RemoteException re) {
- Log.e(LOG_TAG, "Error creating a print job", re);
+ throw re.rethrowFromSystemServer();
}
return null;
}
@@ -497,7 +494,7 @@
return enabledServices;
}
} catch (RemoteException re) {
- Log.e(LOG_TAG, "Error getting the enabled print services", re);
+ throw re.rethrowFromSystemServer();
}
return Collections.emptyList();
}
@@ -519,7 +516,7 @@
return installedServices;
}
} catch (RemoteException re) {
- Log.e(LOG_TAG, "Error getting the installed print services", re);
+ throw re.rethrowFromSystemServer();
}
return Collections.emptyList();
}
diff --git a/core/java/android/provider/BlockedNumberContract.java b/core/java/android/provider/BlockedNumberContract.java
index 4d3bea4..0439fe2 100644
--- a/core/java/android/provider/BlockedNumberContract.java
+++ b/core/java/android/provider/BlockedNumberContract.java
@@ -29,8 +29,11 @@
* <p>
* The content provider exposes a table containing blocked numbers. The columns and URIs for
* accessing this table are defined by the {@link BlockedNumbers} class. Messages, and calls from
- * blocked numbers are discarded by the platform. Notifications upon provider changes can be
- * received using a {@link android.database.ContentObserver}.
+ * blocked numbers are discarded by the platform. If the user contacts emergency
+ * services, number blocking is disabled by the platform for a duration defined by
+ * {@link android.telephony.CarrierConfigManager#KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT}.
+ * Notifications upon provider changes can be received using a
+ * {@link android.database.ContentObserver}.
* </p>
*
* <h3> Permissions </h3>
@@ -141,25 +144,26 @@
/**
* Content URI for the blocked numbers.
- *
- * Supported operations
- * blocked
- * - query
- * - delete
- * - insert
- *
- * blocked/ID
- * - query (selection is not supported)
- * - delete (selection is not supported)
+ * <h3> Supported operations </h3>
+ * <p> blocked
+ * <ul>
+ * <li> query
+ * <li> delete
+ * <li> insert
+ * </ul>
+ * <p> blocked/ID
+ * <ul>
+ * <li> query (selection is not supported)
+ * <li> delete (selection is not supported)
+ * </ul>
*/
- public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI,
- "blocked");
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "blocked");
/**
* The MIME type of {@link #CONTENT_URI} itself providing a directory of blocked phone
* numbers.
*/
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_numbers";
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_number";
/**
* The MIME type of a blocked phone number under {@link #CONTENT_URI}.
@@ -215,7 +219,7 @@
/**
* Returns {@code true} if blocking numbers is supported for the current user.
- * <p> Typically, blocking numbers is only supported for the primary user.
+ * <p> Typically, blocking numbers is only supported for one user at a time.
*/
public static boolean canCurrentUserBlockNumbers(Context context) {
final Bundle res = context.getContentResolver().call(
@@ -239,20 +243,20 @@
public static class SystemContract {
/**
* A protected broadcast intent action for letting components with
- * {@link android.Manifest.permission#READ_BLOCKED_NUMBERS} know that the block suppressal
- * status as returned by {@link #getBlockSuppressalStatus(Context)} has been updated.
+ * {@link android.Manifest.permission#READ_BLOCKED_NUMBERS} know that the block suppression
+ * status as returned by {@link #getBlockSuppressionStatus(Context)} has been updated.
*/
- public static final String ACTION_BLOCK_SUPPRESSAL_STATE_CHANGED =
- "android.provider.action.BLOCK_SUPPRESSAL_STATE_CHANGED";
+ public static final String ACTION_BLOCK_SUPPRESSION_STATE_CHANGED =
+ "android.provider.action.BLOCK_SUPPRESSION_STATE_CHANGED";
public static final String METHOD_NOTIFY_EMERGENCY_CONTACT = "notify_emergency_contact";
- public static final String METHOD_END_BLOCK_SUPPRESSAL = "end_block_suppressal";
+ public static final String METHOD_END_BLOCK_SUPPRESSION = "end_block_suppression";
public static final String METHOD_SHOULD_SYSTEM_BLOCK_NUMBER = "should_system_block_number";
- public static final String METHOD_GET_BLOCK_SUPPRESSAL_STATUS =
- "get_block_suppresal_status";
+ public static final String METHOD_GET_BLOCK_SUPPRESSION_STATUS =
+ "get_block_suppression_status";
public static final String RES_IS_BLOCKING_SUPPRESSED = "blocking_suppressed";
@@ -264,7 +268,7 @@
* <p> This results in {@link #shouldSystemBlockNumber} returning {@code false} independent
* of the contents of the provider for a duration defined by
* {@link android.telephony.CarrierConfigManager#KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT}
- * the provider unless {@link #endBlockSuppressal(Context)} is called.
+ * the provider unless {@link #endBlockSuppression(Context)} is called.
*/
public static void notifyEmergencyContact(Context context) {
context.getContentResolver().call(
@@ -275,9 +279,9 @@
* Notifies the provider to disable suppressing blocking. If emergency services were not
* contacted recently at all, calling this method is a no-op.
*/
- public static void endBlockSuppressal(Context context) {
+ public static void endBlockSuppression(Context context) {
context.getContentResolver().call(
- AUTHORITY_URI, METHOD_END_BLOCK_SUPPRESSAL, null, null);
+ AUTHORITY_URI, METHOD_END_BLOCK_SUPPRESSION, null, null);
}
/**
@@ -292,26 +296,29 @@
return res != null && res.getBoolean(RES_NUMBER_IS_BLOCKED, false);
}
- public static BlockSuppressalStatus getBlockSuppressalStatus(Context context) {
+ /**
+ * Returns the current status of block suppression.
+ */
+ public static BlockSuppressionStatus getBlockSuppressionStatus(Context context) {
final Bundle res = context.getContentResolver().call(
- AUTHORITY_URI, METHOD_GET_BLOCK_SUPPRESSAL_STATUS, null, null);
- return new BlockSuppressalStatus(res.getBoolean(RES_IS_BLOCKING_SUPPRESSED, false),
+ AUTHORITY_URI, METHOD_GET_BLOCK_SUPPRESSION_STATUS, null, null);
+ return new BlockSuppressionStatus(res.getBoolean(RES_IS_BLOCKING_SUPPRESSED, false),
res.getLong(RES_BLOCKING_SUPPRESSED_UNTIL_TIMESTAMP, 0));
}
/**
* Represents the current status of {@link #shouldSystemBlockNumber(Context, String)}. If
* emergency services have been contacted recently, {@link #isSuppressed} is {@code true},
- * and blocking is disabled until the timestamp {@link #untilTimestampMillis}.
+ * and blocking is disabled until the timestamp {@link #untilTimestampMillis}.
*/
- public static class BlockSuppressalStatus {
+ public static class BlockSuppressionStatus {
public final boolean isSuppressed;
/**
* Timestamp in milliseconds from epoch.
*/
public final long untilTimestampMillis;
- BlockSuppressalStatus(boolean isSuppressed, long untilTimestampMillis) {
+ public BlockSuppressionStatus(boolean isSuppressed, long untilTimestampMillis) {
this.isSuppressed = isSuppressed;
this.untilTimestampMillis = untilTimestampMillis;
}
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 904b393..4b43f53 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -8763,6 +8763,15 @@
* <li><em>Note: Some apps may choose to use phone number as the unique contact ID in DATA1.
* If this applies to you and you’d like phone number to be shown below the Contact Name by
* the Voice Assistant, then you may choose to leave DATA3 empty.</em></li>
+ * <li><em>Note: If your app also uses DATA3 to display contact details in the Contacts App,
+ * make sure it does not include prefix text such as "Message +<phone>" or "Free Message
+ * +<phone>", etc. If you must show the prefix text in the Contacts App, please use a
+ * different DATA# column, and update your contacts.xml to point to this new column. </em>
+ * </li>
+ * <li>Everytime the user sends a message to a contact, your app may choose to update the
+ * {@link ContactOptionsColumns#TIMES_CONTACTED} entry through DataUsageFeedback class.
+ * Doing this will allow Voice Assistant to bias speech recognition to contacts frequently
+ * contacted, this is particularly useful for contact names that are hard to pronounce.</li>
* </ul>
* <p>
* Input: {@link android.content.Intent#getType} is the MIME type of the data being sent.
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 3700098..0065cd9 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -93,9 +93,6 @@
public static final String EXTRA_PACKAGE_NAME = "android.content.extra.PACKAGE_NAME";
/** {@hide} */
- public static final String EXTRA_SHOW_ADVANCED = "android.content.extra.SHOW_ADVANCED";
-
- /** {@hide} */
public static final String EXTRA_SHOW_FILESIZE = "android.content.extra.SHOW_FILESIZE";
/** {@hide} */
@@ -481,7 +478,6 @@
/**
* Capacity of a root in bytes. This column is optional, and may be
* {@code null} if unknown or unbounded.
- * {@hide}
* <p>
* Type: INTEGER (long)
*/
@@ -564,22 +560,29 @@
public static final int FLAG_EMPTY = 1 << 16;
/**
- * Flag indicating that this root should only be visible to advanced
- * users.
- *
- * @see #COLUMN_FLAGS
- * @hide
- */
- public static final int FLAG_ADVANCED = 1 << 17;
-
- /**
* Flag indicating that this root has settings.
*
* @see #COLUMN_FLAGS
* @see DocumentsContract#ACTION_DOCUMENT_ROOT_SETTINGS
* @hide
*/
- public static final int FLAG_HAS_SETTINGS = 1 << 18;
+ public static final int FLAG_HAS_SETTINGS = 1 << 17;
+
+ /**
+ * Flag indicating that this root is on removable SD card storage.
+ *
+ * @see #COLUMN_FLAGS
+ * @hide
+ */
+ public static final int FLAG_REMOVABLE_SD = 1 << 18;
+
+ /**
+ * Flag indicating that this root is on removable USB storage.
+ *
+ * @see #COLUMN_FLAGS
+ * @hide
+ */
+ public static final int FLAG_REMOVABLE_USB = 1 << 19;
}
/**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 9632ff7..a40cf96 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -58,6 +58,7 @@
import android.util.AndroidException;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.LocaleList;
import android.util.Log;
import com.android.internal.util.ArrayUtils;
@@ -114,6 +115,21 @@
"android.settings.LOCATION_SOURCE_SETTINGS";
/**
+ * Activity Action: Show settings to allow configuration of users.
+ * <p>
+ * In some cases, a matching Activity may not exist, so ensure you
+ * safeguard against this.
+ * <p>
+ * Input: Nothing.
+ * <p>
+ * Output: Nothing.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_USER_SETTINGS =
+ "android.settings.USER_SETTINGS";
+
+ /**
* Activity Action: Show settings to allow configuration of wireless controls
* such as Wi-Fi, Bluetooth and Mobile networks.
* <p>
@@ -1225,6 +1241,19 @@
public static final String ACTION_SHOW_ADMIN_SUPPORT_DETAILS
= "android.settings.SHOW_ADMIN_SUPPORT_DETAILS";
+ /**
+ * Activity Action: Show a dialog for remote bugreport flow.
+ * <p>
+ * Input: Nothing.
+ * <p>
+ * Output: Nothing.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_SHOW_REMOTE_BUGREPORT_DIALOG
+ = "android.settings.SHOW_REMOTE_BUGREPORT_DIALOG";
+
// End of Intent actions for Settings
/**
@@ -2056,6 +2085,8 @@
if (outConfig.fontScale < 0) {
outConfig.fontScale = 1;
}
+ outConfig.setLocales(LocaleList.forLanguageTags(
+ Settings.System.getStringForUser(cr, SYSTEM_LOCALES, userHandle)));
}
/**
@@ -2064,6 +2095,9 @@
*/
public static void clearConfiguration(Configuration inoutConfig) {
inoutConfig.fontScale = 0;
+ if (!inoutConfig.userSetLocale) {
+ inoutConfig.setLocales(LocaleList.getEmptyLocaleList());
+ }
}
/**
@@ -2081,12 +2115,15 @@
/** @hide */
public static boolean putConfigurationForUser(ContentResolver cr, Configuration config,
int userHandle) {
- return Settings.System.putFloatForUser(cr, FONT_SCALE, config.fontScale, userHandle);
+ return Settings.System.putFloatForUser(cr, FONT_SCALE, config.fontScale, userHandle) &&
+ Settings.System.putStringForUser(
+ cr, SYSTEM_LOCALES, config.getLocales().toLanguageTags(), userHandle);
}
/** @hide */
public static boolean hasInterestingConfigurationChanges(int changes) {
- return (changes&ActivityInfo.CONFIG_FONT_SCALE) != 0;
+ return (changes & ActivityInfo.CONFIG_FONT_SCALE) != 0 ||
+ (changes & ActivityInfo.CONFIG_LOCALE) != 0;
}
/** @deprecated - Do not use */
@@ -2465,6 +2502,18 @@
};
/**
+ * The serialized system locale value.
+ *
+ * Do not use this value directory.
+ * To get system locale, use {@link android.util.LocaleList#getDefault} instead.
+ * To update system locale, use {@link com.android.internal.app.LocalePicker#updateLocales}
+ * instead.
+ * @hide
+ */
+ public static final String SYSTEM_LOCALES = "system_locales";
+
+
+ /**
* Name of an application package to be debugged.
*
* @deprecated Use {@link Global#DEBUG_APP} instead
@@ -2765,6 +2814,11 @@
*/
public static final Uri DEFAULT_RINGTONE_URI = getUriFor(RINGTONE);
+ /** {@hide} */
+ public static final String RINGTONE_CACHE = "ringtone_cache";
+ /** {@hide} */
+ public static final Uri RINGTONE_CACHE_URI = getUriFor(RINGTONE_CACHE);
+
/**
* Persistent store for the system-wide default notification sound.
*
@@ -2783,6 +2837,11 @@
*/
public static final Uri DEFAULT_NOTIFICATION_URI = getUriFor(NOTIFICATION_SOUND);
+ /** {@hide} */
+ public static final String NOTIFICATION_SOUND_CACHE = "notification_sound_cache";
+ /** {@hide} */
+ public static final Uri NOTIFICATION_SOUND_CACHE_URI = getUriFor(NOTIFICATION_SOUND_CACHE);
+
/**
* Persistent store for the system-wide default alarm alert.
*
@@ -2801,6 +2860,11 @@
*/
public static final Uri DEFAULT_ALARM_ALERT_URI = getUriFor(ALARM_ALERT);
+ /** {@hide} */
+ public static final String ALARM_ALERT_CACHE = "alarm_alert_cache";
+ /** {@hide} */
+ public static final Uri ALARM_ALERT_CACHE_URI = getUriFor(ALARM_ALERT_CACHE);
+
/**
* Persistent store for the system default media button event receiver.
*
@@ -4471,6 +4535,13 @@
public static final String USER_SETUP_COMPLETE = "user_setup_complete";
/**
+ * Prefix for category name that marks whether a suggested action from that category was
+ * completed.
+ * @hide
+ */
+ public static final String COMPLETED_CATEGORY_PREFIX = "suggested.completed_category.";
+
+ /**
* List of input methods that are currently enabled. This is a string
* containing the IDs of all enabled input methods, each ID separated
* by ':'.
@@ -5924,6 +5995,52 @@
"camera_double_tap_power_gesture_disabled";
/**
+
+ /**
+ * Behavior of twilight on the device.
+ * One of {@link #TWILIGHT_MODE_LOCKED_OFF}, {@link #TWILIGHT_MODE_LOCKED_ON}
+ * or {@link #TWILIGHT_MODE_AUTO}.
+ * @hide
+ */
+ public static final String TWILIGHT_MODE = "twilight_mode";
+
+ /**
+ * Twilight mode always off.
+ * @hide
+ */
+ public static final int TWILIGHT_MODE_LOCKED_OFF = 0;
+
+ /**
+ * Twilight mode always on.
+ * @hide
+ */
+ public static final int TWILIGHT_MODE_LOCKED_ON = 1;
+
+ /**
+ * Twilight mode auto.
+ * @hide
+ */
+ public static final int TWILIGHT_MODE_AUTO = 2;
+
+ /**
+ * Twilight mode auto, temporarily overriden to on.
+ * @hide
+ */
+ public static final int TWILIGHT_MODE_AUTO_OVERRIDE_OFF = 3;
+
+ /**
+ * Twilight mode auto, temporarily overriden to off.
+ * @hide
+ */
+ public static final int TWILIGHT_MODE_AUTO_OVERRIDE_ON = 4;
+
+ /**
+ * Whether brightness should automatically adjust based on twilight state.
+ * @hide
+ */
+ public static final String BRIGHTNESS_USE_TWILIGHT = "brightness_use_twilight";
+
+ /**
* This are the settings to be backed up.
*
* NOTE: Settings are backed up and restored in the order they appear
@@ -6297,6 +6414,18 @@
public static final String BLUETOOTH_DISABLED_PROFILES = "bluetooth_disabled_profiles";
/**
+ * A semi-colon separated list of Bluetooth interoperability workarounds.
+ * Each entry is a partial Bluetooth device address string and an integer representing
+ * the feature to be disabled, separated by a comma. The integer must correspond
+ * to a interoperability feature as defined in "interop.h" in /system/bt.
+ * <p>
+ * Example: <br/>
+ * "00:11:22,0;01:02:03:04,2"
+ * @hide
+ */
+ public static final String BLUETOOTH_INTEROPERABILITY_LIST = "bluetooth_interoperability_list";
+
+ /**
* The policy for deciding when Wi-Fi should go to sleep (which will in
* turn switch to using the mobile data as an Internet connection).
* <p>
@@ -6960,12 +7089,27 @@
"webview_data_reduction_proxy_key";
/**
+ * Whether or not the WebView fallback mechanism should be enabled.
+ * 0=disabled, 1=enabled.
+ * @hide
+ */
+ public static final String WEBVIEW_FALLBACK_LOGIC_ENABLED =
+ "webview_fallback_logic_enabled";
+
+ /**
* Name of the package used as WebView provider (if unset the provider is instead determined
* by the system).
* @hide
*/
public static final String WEBVIEW_PROVIDER = "webview_provider";
+ /**
+ * Developer setting to enable WebView multiprocess rendering.
+ * @hide
+ */
+ @SystemApi
+ public static final String WEBVIEW_MULTIPROCESS = "webview_multiprocess";
+
/**
* Whether Wifi display is enabled/disabled
* 0=disabled. 1=enabled.
@@ -7765,13 +7909,20 @@
public static final String LOW_POWER_MODE_TRIGGER_LEVEL = "low_power_trigger_level";
/**
- * If 1, the activity manager will aggressively finish activities and
+ * If not 0, the activity manager will aggressively finish activities and
* processes as soon as they are no longer needed. If 0, the normal
* extended lifetime is used.
*/
public static final String ALWAYS_FINISH_ACTIVITIES = "always_finish_activities";
/**
+ * @hide
+ * If not 0, the activity manager will implement a looser version of background
+ * check that is more compatible with existing apps.
+ */
+ public static final String LENIENT_BACKGROUND_CHECK = "lenient_background_check";
+
+ /**
* Use Dock audio output for media:
* 0 = disabled
* 1 = enabled
@@ -7780,6 +7931,52 @@
public static final String DOCK_AUDIO_MEDIA_ENABLED = "dock_audio_media_enabled";
/**
+ * The surround sound formats AC3, DTS or IEC61937 are
+ * available for use if they are detected.
+ * This is the default mode.
+ *
+ * Note that AUTO is equivalent to ALWAYS for Android TVs and other
+ * devices that have an S/PDIF output. This is because S/PDIF
+ * is unidirectional and the TV cannot know if a decoder is
+ * connected. So it assumes they are always available.
+ * @hide
+ */
+ public static final int ENCODED_SURROUND_OUTPUT_AUTO = 0;
+
+ /**
+ * AC3, DTS or IEC61937 are NEVER available, even if they
+ * are detected by the hardware. Those formats will not be
+ * reported.
+ *
+ * An example use case would be an AVR reports that it is capable of
+ * surround sound decoding but is broken. If NEVER is chosen
+ * then apps must use PCM output instead of encoded output.
+ * @hide
+ */
+ public static final int ENCODED_SURROUND_OUTPUT_NEVER = 1;
+
+ /**
+ * AC3, DTS or IEC61937 are ALWAYS available, even if they
+ * are not detected by the hardware. Those formats will be
+ * reported as part of the HDMI output capability. Applications
+ * are then free to use either PCM or encoded output.
+ *
+ * An example use case would be a when TV was connected over
+ * TOS-link to an AVR. But the TV could not see it because TOS-link
+ * is unidirectional.
+ * @hide
+ */
+ public static final int ENCODED_SURROUND_OUTPUT_ALWAYS = 2;
+
+ /**
+ * Set to ENCODED_SURROUND_OUTPUT_AUTO,
+ * ENCODED_SURROUND_OUTPUT_NEVER or
+ * ENCODED_SURROUND_OUTPUT_ALWAYS
+ * @hide
+ */
+ public static final String ENCODED_SURROUND_OUTPUT = "encoded_surround_output";
+
+ /**
* Persisted safe headphone volume management state by AudioService
* @hide
*/
@@ -8054,6 +8251,15 @@
"uninstalled_ephemeral_app_cache_duration_millis";
/**
+ * Allows switching users when system user is locked.
+ * <p>
+ * Type: int
+ * @hide
+ */
+ public static final String ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED =
+ "allow_user_switching_when_system_user_locked";
+
+ /**
* Settings to backup. This is here so that it's in the same place as the settings
* keys and easy to update.
*
@@ -8086,6 +8292,7 @@
EMERGENCY_TONE,
CALL_AUTO_RETRY,
DOCK_AUDIO_MEDIA_ENABLED,
+ ENCODED_SURROUND_OUTPUT,
LOW_POWER_MODE_TRIGGER_LEVEL
};
diff --git a/core/java/android/security/net/config/ManifestConfigSource.java b/core/java/android/security/net/config/ManifestConfigSource.java
index 0e137cd..be0821c 100644
--- a/core/java/android/security/net/config/ManifestConfigSource.java
+++ b/core/java/android/security/net/config/ManifestConfigSource.java
@@ -61,6 +61,7 @@
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException("Failed to look up ApplicationInfo", e);
}
+ int targetSdkVersion = info.targetSdkVersion;
int configResourceId = 0;
if (info != null && info.metaData != null) {
configResourceId = info.metaData.getInt(META_DATA_NETWORK_SECURITY_CONFIG);
@@ -74,14 +75,15 @@
+ mContext.getResources().getResourceEntryName(configResourceId)
+ " debugBuild: " + debugBuild);
}
- source = new XmlConfigSource(mContext, configResourceId, debugBuild);
+ source = new XmlConfigSource(mContext, configResourceId, debugBuild,
+ targetSdkVersion);
} else {
if (DBG) {
Log.d(LOG_TAG, "No Network Security Config specified, using platform default");
}
boolean usesCleartextTraffic =
(info.flags & ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC) != 0;
- source = new DefaultConfigSource(usesCleartextTraffic);
+ source = new DefaultConfigSource(usesCleartextTraffic, targetSdkVersion);
}
mConfigSource = source;
return mConfigSource;
@@ -92,11 +94,11 @@
private final NetworkSecurityConfig mDefaultConfig;
- public DefaultConfigSource(boolean usesCleartextTraffic) {
- mDefaultConfig = NetworkSecurityConfig.getDefaultBuilder()
+ public DefaultConfigSource(boolean usesCleartextTraffic, int targetSdkVersion) {
+ mDefaultConfig = NetworkSecurityConfig.getDefaultBuilder(targetSdkVersion)
.setCleartextTrafficPermitted(usesCleartextTraffic)
.build();
- }
+ }
@Override
public NetworkSecurityConfig getDefaultConfig() {
diff --git a/core/java/android/security/net/config/NetworkSecurityConfig.java b/core/java/android/security/net/config/NetworkSecurityConfig.java
index ebe14691..6d6a92a 100644
--- a/core/java/android/security/net/config/NetworkSecurityConfig.java
+++ b/core/java/android/security/net/config/NetworkSecurityConfig.java
@@ -16,6 +16,7 @@
package android.security.net.config;
+import android.os.Build;
import android.util.ArrayMap;
import android.util.ArraySet;
import java.security.cert.X509Certificate;
@@ -37,7 +38,6 @@
public static final boolean DEFAULT_CLEARTEXT_TRAFFIC_PERMITTED = true;
/** @hide */
public static final boolean DEFAULT_HSTS_ENFORCED = false;
- public static final NetworkSecurityConfig DEFAULT = getDefaultBuilder().build();
private final boolean mCleartextTrafficPermitted;
private final boolean mHstsEnforced;
@@ -163,21 +163,28 @@
* <li>Cleartext traffic is permitted.</li>
* <li>HSTS is not enforced.</li>
* <li>No certificate pinning is used.</li>
- * <li>The system and user added trusted certificate stores are trusted for connections.</li>
+ * <li>The system certificate store is trusted for connections.</li>
+ * <li>If the application targets API level 23 (Android M) or lower then the user certificate
+ * store is trusted by default as well.</li>
* </ol>
*
* @hide
*/
- public static final Builder getDefaultBuilder() {
- return new Builder()
+ public static final Builder getDefaultBuilder(int targetSdkVersion) {
+ Builder builder = new Builder()
.setCleartextTrafficPermitted(DEFAULT_CLEARTEXT_TRAFFIC_PERMITTED)
.setHstsEnforced(DEFAULT_HSTS_ENFORCED)
// System certificate store, does not bypass static pins.
.addCertificatesEntryRef(
- new CertificatesEntryRef(SystemCertificateSource.getInstance(), false))
- // User certificate store, does not bypass static pins.
- .addCertificatesEntryRef(
- new CertificatesEntryRef(UserCertificateSource.getInstance(), false));
+ new CertificatesEntryRef(SystemCertificateSource.getInstance(), false));
+ // Applications targeting N and above must opt in into trusting the user added certificate
+ // store.
+ if (targetSdkVersion <= Build.VERSION_CODES.M) {
+ // User certificate store, does not bypass static pins.
+ builder.addCertificatesEntryRef(
+ new CertificatesEntryRef(UserCertificateSource.getInstance(), false));
+ }
+ return builder;
}
/**
diff --git a/core/java/android/security/net/config/ResourceCertificateSource.java b/core/java/android/security/net/config/ResourceCertificateSource.java
index 8803c4b..22fbee2 100644
--- a/core/java/android/security/net/config/ResourceCertificateSource.java
+++ b/core/java/android/security/net/config/ResourceCertificateSource.java
@@ -44,7 +44,7 @@
public ResourceCertificateSource(int resourceId, Context context) {
mResourceId = resourceId;
- mContext = context.getApplicationContext();
+ mContext = context;
}
private void ensureInitialized() {
diff --git a/core/java/android/security/net/config/XmlConfigSource.java b/core/java/android/security/net/config/XmlConfigSource.java
index 1706e95..2a8773c 100644
--- a/core/java/android/security/net/config/XmlConfigSource.java
+++ b/core/java/android/security/net/config/XmlConfigSource.java
@@ -3,9 +3,11 @@
import android.content.Context;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
+import android.os.Build;
import android.util.ArraySet;
import android.util.Base64;
import android.util.Pair;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
@@ -34,20 +36,29 @@
private final Object mLock = new Object();
private final int mResourceId;
private final boolean mDebugBuild;
+ private final int mTargetSdkVersion;
private boolean mInitialized;
private NetworkSecurityConfig mDefaultConfig;
private Set<Pair<Domain, NetworkSecurityConfig>> mDomainMap;
private Context mContext;
+ @VisibleForTesting
public XmlConfigSource(Context context, int resourceId) {
this(context, resourceId, false);
}
+ @VisibleForTesting
public XmlConfigSource(Context context, int resourceId, boolean debugBuild) {
+ this(context, resourceId, debugBuild, Build.VERSION_CODES.CUR_DEVELOPMENT);
+ }
+
+ public XmlConfigSource(Context context, int resourceId, boolean debugBuild,
+ int targetSdkVersion) {
mResourceId = resourceId;
mContext = context;
mDebugBuild = debugBuild;
+ mTargetSdkVersion = targetSdkVersion;
}
public Set<Pair<Domain, NetworkSecurityConfig>> getPerDomainConfigs() {
@@ -341,7 +352,7 @@
// Use the platform default as the parent of the base config for any values not provided
// there. If there is no base config use the platform default.
NetworkSecurityConfig.Builder platformDefaultBuilder =
- NetworkSecurityConfig.getDefaultBuilder();
+ NetworkSecurityConfig.getDefaultBuilder(mTargetSdkVersion);
addDebugAnchorsIfNeeded(debugConfigBuilder, platformDefaultBuilder);
if (baseConfigBuilder != null) {
baseConfigBuilder.setParent(platformDefaultBuilder);
diff --git a/core/java/android/service/carrier/CarrierMessagingService.java b/core/java/android/service/carrier/CarrierMessagingService.java
index f5396a3..140341c 100644
--- a/core/java/android/service/carrier/CarrierMessagingService.java
+++ b/core/java/android/service/carrier/CarrierMessagingService.java
@@ -51,6 +51,30 @@
= "android.service.carrier.CarrierMessagingService";
/**
+ * The default bitmask value passed to the callback of {@link #onReceiveTextSms} with all
+ * {@code RECEIVE_OPTIONS_x} flags cleared to indicate that the message should be kept and a
+ * new message notification should be shown.
+ *
+ * @see #RECEIVE_OPTIONS_DROP
+ * @see #RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE
+ */
+ public static final int RECEIVE_OPTIONS_DEFAULT = 0;
+
+ /**
+ * Used to set the flag in the bitmask passed to the callback of {@link #onReceiveTextSms} to
+ * indicate that the inbound SMS should be dropped.
+ */
+ public static final int RECEIVE_OPTIONS_DROP = 0x1;
+
+ /**
+ * Used to set the flag in the bitmask passed to the callback of {@link #onReceiveTextSms} to
+ * indicate that a new message notification should not be shown to the user when the
+ * credential-encrypted storage of the device is not available before the user unlocks the
+ * phone. It is only applicable to devices that support file-based encryption.
+ */
+ public static final int RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE = 0x2;
+
+ /**
* Indicates that an SMS or MMS message was successfully sent.
*/
public static final int SEND_STATUS_OK = 0;
@@ -96,7 +120,9 @@
* @param subId SMS subscription ID of the SIM
* @param callback result callback. Call with {@code true} to keep an inbound SMS message and
* deliver to SMS apps, and {@code false} to drop the message.
+ * @deprecated Use {@link #onReceiveTextSms} instead.
*/
+ @Deprecated
public void onFilterSms(@NonNull MessagePdu pdu, @NonNull String format, int destPort,
int subId, @NonNull ResultCallback<Boolean> callback) {
// optional
@@ -107,6 +133,36 @@
}
/**
+ * Override this method to filter inbound SMS messages.
+ *
+ * <p>This method will be called once for every incoming text SMS. You can invoke the callback
+ * with a bitmask to tell the platform how to handle the SMS. For a SMS received on a
+ * file-based encryption capable device while the credential-encrypted storage is not available,
+ * this method will be called for the second time when the credential-encrypted storage becomes
+ * available after the user unlocks the phone, if the bit {@link #RECEIVE_OPTIONS_DROP} is not
+ * set when invoking the callback.
+ *
+ * @param pdu the PDUs of the message
+ * @param format the format of the PDUs, typically "3gpp" or "3gpp2"
+ * @param destPort the destination port of a binary SMS, this will be -1 for text SMS
+ * @param subId SMS subscription ID of the SIM
+ * @param callback result callback. Call with a bitmask integer to indicate how the incoming
+ * text SMS should be handled by the platform. Use {@link #RECEIVE_OPTIONS_DROP} and
+ * {@link #RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE}
+ * to set the flags in the bitmask.
+ */
+ public void onReceiveTextSms(@NonNull MessagePdu pdu, @NonNull String format,
+ int destPort, int subId, @NonNull final ResultCallback<Integer> callback) {
+ onFilterSms(pdu, format, destPort, subId, new ResultCallback<Boolean>() {
+ @Override
+ public void onReceiveResult(Boolean result) throws RemoteException {
+ callback.onReceiveResult(result ? RECEIVE_OPTIONS_DEFAULT : RECEIVE_OPTIONS_DROP
+ | RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE);
+ }
+ });
+ }
+
+ /**
* Override this method to intercept text SMSs sent from the device.
* @deprecated Override {@link #onSendTextSms} below instead.
*
@@ -408,10 +464,11 @@
@Override
public void filterSms(MessagePdu pdu, String format, int destPort,
int subId, final ICarrierMessagingCallback callback) {
- onFilterSms(pdu, format, destPort, subId, new ResultCallback<Boolean>() {
+ onReceiveTextSms(pdu, format, destPort, subId,
+ new ResultCallback<Integer>() {
@Override
- public void onReceiveResult(final Boolean result) throws RemoteException {
- callback.onFilterComplete(result);
+ public void onReceiveResult(Integer options) throws RemoteException {
+ callback.onFilterComplete(options);
}
});
}
diff --git a/core/java/android/service/carrier/ICarrierMessagingCallback.aidl b/core/java/android/service/carrier/ICarrierMessagingCallback.aidl
index 6118a20..2753669 100644
--- a/core/java/android/service/carrier/ICarrierMessagingCallback.aidl
+++ b/core/java/android/service/carrier/ICarrierMessagingCallback.aidl
@@ -22,7 +22,7 @@
* @hide
*/
oneway interface ICarrierMessagingCallback {
- void onFilterComplete(boolean keepMessage);
+ void onFilterComplete(int result);
void onSendSmsComplete(int result, int messageRef);
void onSendMultipartSmsComplete(int result, in int[] messageRefs);
void onSendMmsComplete(int result, in byte[] sendConfPdu);
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index fb58f4e..41af837 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -18,18 +18,17 @@
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
-import android.app.INotificationManager;
-import android.app.Notification;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import android.os.Handler;
import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
+import android.os.Looper;
+import android.os.Message;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.util.Log;
+import com.android.internal.os.SomeArgs;
/**
* A service that helps the user manage notifications by modifying the
@@ -97,14 +96,11 @@
/** Notification was canceled because it was an invisible member of a group. */
public static final int REASON_GROUP_OPTIMIZATION = 13;
- /** Notification was canceled by the user banning the topic. */
- public static final int REASON_TOPIC_BANNED = 14;
-
/** Notification was canceled by the device administrator suspending the package. */
- public static final int REASON_PACKAGE_SUSPENDED = 15;
+ public static final int REASON_PACKAGE_SUSPENDED = 14;
/** Notification was canceled by the owning managed profile being turned off. */
- public static final int REASON_PROFILE_TURNED_OFF = 16;
+ public static final int REASON_PROFILE_TURNED_OFF = 15;
public class Adjustment {
int mImportance;
@@ -128,8 +124,24 @@
}
}
+ private Handler mHandler;
+
+ /** @hide */
@Override
- public IBinder onBind(Intent intent) {
+ public void registerAsSystemService(Context context, ComponentName componentName,
+ int currentUser) throws RemoteException {
+ super.registerAsSystemService(context, componentName, currentUser);
+ mHandler = new MyHandler(getContext().getMainLooper());
+ }
+
+ @Override
+ protected void attachBaseContext(Context base) {
+ super.attachBaseContext(base);
+ mHandler = new MyHandler(getContext().getMainLooper());
+ }
+
+ @Override
+ public final IBinder onBind(Intent intent) {
if (mWrapper == null) {
mWrapper = new NotificationAssistantWrapper();
}
@@ -201,8 +213,7 @@
* @param key the notification key
* @param adjustment the new importance with an explanation
*/
- public final void adjustImportance(String key, Adjustment adjustment)
- {
+ public final void adjustImportance(String key, Adjustment adjustment) {
if (!isBound()) return;
try {
getNotificationInterface().setImportanceFromAssistant(mWrapper, key,
@@ -215,7 +226,7 @@
private class NotificationAssistantWrapper extends NotificationListenerWrapper {
@Override
public void onNotificationEnqueued(IStatusBarNotificationHolder sbnHolder,
- int importance, boolean user) throws RemoteException {
+ int importance, boolean user) {
StatusBarNotification sbn;
try {
sbn = sbnHolder.get();
@@ -224,54 +235,114 @@
return;
}
- try {
- Adjustment adjustment =
- NotificationAssistantService.this.onNotificationEnqueued(sbn, importance, user);
- if (adjustment != null) {
- adjustImportance(sbn.getKey(), adjustment);
- }
- } catch (Throwable t) {
- Log.w(TAG, "Error running onNotificationEnqueued", t);
- }
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = sbn;
+ args.argi1 = importance;
+ args.argi2 = user ? 1 : 0;
+ mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_ENQUEUED,
+ args).sendToTarget();
}
@Override
- public void onNotificationVisibilityChanged(String key, long time, boolean visible)
- throws RemoteException {
- try {
- NotificationAssistantService.this.onNotificationVisibilityChanged(key, time,
- visible);
- } catch (Throwable t) {
- Log.w(TAG, "Error running onNotificationVisibilityChanged", t);
- }
+ public void onNotificationVisibilityChanged(String key, long time, boolean visible) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = key;
+ args.arg2 = time;
+ args.argi1 = visible ? 1 : 0;
+ mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_VISIBILITY_CHANGED,
+ args).sendToTarget();
}
@Override
- public void onNotificationClick(String key, long time) throws RemoteException {
- try {
- NotificationAssistantService.this.onNotificationClick(key, time);
- } catch (Throwable t) {
- Log.w(TAG, "Error running onNotificationClick", t);
- }
+ public void onNotificationClick(String key, long time) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = key;
+ args.arg2 = time;
+ mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_CLICK,
+ args).sendToTarget();
}
@Override
- public void onNotificationActionClick(String key, long time, int actionIndex)
- throws RemoteException {
- try {
- NotificationAssistantService.this.onNotificationActionClick(key, time, actionIndex);
- } catch (Throwable t) {
- Log.w(TAG, "Error running onNotificationActionClick", t);
- }
+ public void onNotificationActionClick(String key, long time, int actionIndex) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = key;
+ args.arg2 = time;
+ args.argi1 = actionIndex;
+ mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_ACTION_CLICK,
+ args).sendToTarget();
}
@Override
- public void onNotificationRemovedReason(String key, long time, int reason)
- throws RemoteException {
- try {
- NotificationAssistantService.this.onNotificationRemoved(key, time, reason);
- } catch (Throwable t) {
- Log.w(TAG, "Error running onNotificationRemoved", t);
+ public void onNotificationRemovedReason(String key, long time, int reason) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = key;
+ args.arg2 = time;
+ args.argi1 = reason;
+ mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_REMOVED_REASON,
+ args).sendToTarget();
+ }
+ }
+
+ private final class MyHandler extends Handler {
+ public static final int MSG_ON_NOTIFICATION_ENQUEUED = 1;
+ public static final int MSG_ON_NOTIFICATION_VISIBILITY_CHANGED = 2;
+ public static final int MSG_ON_NOTIFICATION_CLICK = 3;
+ public static final int MSG_ON_NOTIFICATION_ACTION_CLICK = 4;
+ public static final int MSG_ON_NOTIFICATION_REMOVED_REASON = 5;
+
+ public MyHandler(Looper looper) {
+ super(looper, null, false);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_ON_NOTIFICATION_ENQUEUED: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ StatusBarNotification sbn = (StatusBarNotification) args.arg1;
+ final int importance = args.argi1;
+ final boolean user = args.argi2 == 1;
+ args.recycle();
+ Adjustment adjustment = onNotificationEnqueued(sbn, importance, user);
+ if (adjustment != null) {
+ adjustImportance(sbn.getKey(), adjustment);
+ }
+ } break;
+
+ case MSG_ON_NOTIFICATION_VISIBILITY_CHANGED: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ final String key = (String) args.arg1;
+ final long time = (long) args.arg2;
+ final boolean visible = args.argi1 == 1;
+ args.recycle();
+ onNotificationVisibilityChanged(key, time, visible);
+ } break;
+
+ case MSG_ON_NOTIFICATION_CLICK: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ final String key = (String) args.arg1;
+ final long time = (long) args.arg2;
+ args.recycle();
+ onNotificationClick(key, time);
+ } break;
+
+ case MSG_ON_NOTIFICATION_ACTION_CLICK: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ final String key = (String) args.arg1;
+ final long time = (long) args.arg2;
+ final int actionIndex = args.argi1;
+ args.recycle();
+ onNotificationActionClick(key, time, actionIndex);
+ } break;
+
+ case MSG_ON_NOTIFICATION_REMOVED_REASON: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ final String key = (String) args.arg1;
+ final long time = (long) args.arg2;
+ final int reason = args.argi1;
+ args.recycle();
+ onNotificationRemoved(key, time, reason);
+ } break;
}
}
}
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 7b461b1..73a890f 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -15,8 +15,12 @@
*/
package android.service.notification;
-import android.service.notification.IStatusBarNotificationHolder;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+
+import android.annotation.IntDef;
import android.annotation.SystemApi;
import android.annotation.SdkConstant;
import android.app.INotificationManager;
@@ -42,7 +46,11 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
-
+import android.widget.RemoteViews;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.SomeArgs;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -160,8 +168,14 @@
@SystemApi
public static final int TRIM_LIGHT = 1;
+ private final Object mLock = new Object();
+
+ private Handler mHandler;
+
/** @hide */
protected NotificationListenerWrapper mWrapper = null;
+
+ @GuardedBy("mLock")
private RankingMap mRankingMap;
private INotificationManager mNoMan;
@@ -192,6 +206,12 @@
public static final String CATEGORY_VR_NOTIFICATIONS =
"android.intent.category.vr.notifications";
+ @Override
+ protected void attachBaseContext(Context base) {
+ super.attachBaseContext(base);
+ mHandler = new MyHandler(getMainLooper());
+ }
+
/**
* Implement this method to learn about new notifications as they are posted by apps.
*
@@ -639,7 +659,9 @@
* @return A {@link RankingMap} object providing access to ranking information
*/
public RankingMap getCurrentRanking() {
- return mRankingMap;
+ synchronized (mLock) {
+ return mRankingMap;
+ }
}
@Override
@@ -681,6 +703,7 @@
INotificationManager noMan = getNotificationInterface();
noMan.registerListener(mWrapper, componentName, currentUser);
mCurrentUser = currentUser;
+ mHandler = new MyHandler(context.getMainLooper());
}
/**
@@ -707,7 +730,7 @@
* <P>The service should wait for the {@link #onListenerConnected()} event
* before performing any operations.
*/
- public static final void requestRebind(ComponentName componentName)
+ public static void requestRebind(ComponentName componentName)
throws RemoteException {
INotificationManager noMan = INotificationManager.Stub.asInterface(
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
@@ -752,9 +775,16 @@
private void maybePopulateRemoteViews(Notification notification) {
if (getContext().getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) {
Builder builder = Builder.recoverBuilder(getContext(), notification);
- notification.contentView = builder.makeContentView();
- notification.bigContentView = builder.makeBigContentView();
- notification.headsUpContentView = builder.makeHeadsUpContentView();
+
+ // Some styles wrap Notification's contentView, bigContentView and headsUpContentView.
+ // First inflate them all, only then set them to avoid recursive wrapping.
+ RemoteViews content = builder.createContentView();
+ RemoteViews big = builder.createBigContentView();
+ RemoteViews headsUp = builder.createHeadsUpContentView();
+
+ notification.contentView = content;
+ notification.bigContentView = big;
+ notification.headsUpContentView = headsUp;
}
}
@@ -772,7 +802,6 @@
}
try {
- Notification notification = sbn.getNotification();
// convert icon metadata to legacy format for older clients
createLegacyIconExtras(sbn.getNotification());
maybePopulateRemoteViews(sbn.getNotification());
@@ -784,20 +813,23 @@
}
// protect subclass from concurrent modifications of (@link mNotificationKeys}.
- synchronized (mWrapper) {
- applyUpdate(update);
- try {
- if (sbn != null) {
- NotificationListenerService.this.onNotificationPosted(sbn, mRankingMap);
- } else {
- // still pass along the ranking map, it may contain other information
- NotificationListenerService.this.onNotificationRankingUpdate(mRankingMap);
- }
- } catch (Throwable t) {
- Log.w(TAG, "Error running onNotificationPosted", t);
+ synchronized (mLock) {
+ applyUpdateLocked(update);
+ if (sbn != null) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = sbn;
+ args.arg2 = mRankingMap;
+ mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_POSTED,
+ args).sendToTarget();
+ } else {
+ // still pass along the ranking map, it may contain other information
+ mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_RANKING_UPDATE,
+ mRankingMap).sendToTarget();
}
}
+
}
+
@Override
public void onNotificationRemoved(IStatusBarNotificationHolder sbnHolder,
NotificationRankingUpdate update) {
@@ -809,56 +841,48 @@
return;
}
// protect subclass from concurrent modifications of (@link mNotificationKeys}.
- synchronized (mWrapper) {
- applyUpdate(update);
- try {
- NotificationListenerService.this.onNotificationRemoved(sbn, mRankingMap);
- } catch (Throwable t) {
- Log.w(TAG, "Error running onNotificationRemoved", t);
- }
+ synchronized (mLock) {
+ applyUpdateLocked(update);
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = sbn;
+ args.arg2 = mRankingMap;
+ mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_REMOVED,
+ args).sendToTarget();
}
+
}
+
@Override
public void onListenerConnected(NotificationRankingUpdate update) {
// protect subclass from concurrent modifications of (@link mNotificationKeys}.
- synchronized (mWrapper) {
- applyUpdate(update);
- try {
- NotificationListenerService.this.onListenerConnected();
- } catch (Throwable t) {
- Log.w(TAG, "Error running onListenerConnected", t);
- }
+ synchronized (mLock) {
+ applyUpdateLocked(update);
}
+ mHandler.obtainMessage(MyHandler.MSG_ON_LISTENER_CONNECTED).sendToTarget();
}
+
@Override
public void onNotificationRankingUpdate(NotificationRankingUpdate update)
throws RemoteException {
// protect subclass from concurrent modifications of (@link mNotificationKeys}.
- synchronized (mWrapper) {
- applyUpdate(update);
- try {
- NotificationListenerService.this.onNotificationRankingUpdate(mRankingMap);
- } catch (Throwable t) {
- Log.w(TAG, "Error running onNotificationRankingUpdate", t);
- }
+ synchronized (mLock) {
+ applyUpdateLocked(update);
+ mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_RANKING_UPDATE,
+ mRankingMap).sendToTarget();
}
+
}
+
@Override
public void onListenerHintsChanged(int hints) throws RemoteException {
- try {
- NotificationListenerService.this.onListenerHintsChanged(hints);
- } catch (Throwable t) {
- Log.w(TAG, "Error running onListenerHintsChanged", t);
- }
+ mHandler.obtainMessage(MyHandler.MSG_ON_LISTENER_HINTS_CHANGED,
+ hints, 0).sendToTarget();
}
@Override
public void onInterruptionFilterChanged(int interruptionFilter) throws RemoteException {
- try {
- NotificationListenerService.this.onInterruptionFilterChanged(interruptionFilter);
- } catch (Throwable t) {
- Log.w(TAG, "Error running onInterruptionFilterChanged", t);
- }
+ mHandler.obtainMessage(MyHandler.MSG_ON_INTERRUPTION_FILTER_CHANGED,
+ interruptionFilter, 0).sendToTarget();
}
@Override
@@ -891,11 +915,12 @@
}
}
- private void applyUpdate(NotificationRankingUpdate update) {
+ private void applyUpdateLocked(NotificationRankingUpdate update) {
mRankingMap = new RankingMap(update);
}
- private Context getContext() {
+ /** @hide */
+ protected Context getContext() {
if (mSystemContext != null) {
return mSystemContext;
}
@@ -911,6 +936,14 @@
* current {@link RankingMap}.
*/
public static class Ranking {
+
+ /** @hide */
+ @IntDef({VISIBILITY_NO_OVERRIDE, IMPORTANCE_UNSPECIFIED, IMPORTANCE_NONE,
+ IMPORTANCE_MIN, IMPORTANCE_LOW, IMPORTANCE_DEFAULT, IMPORTANCE_HIGH,
+ IMPORTANCE_MAX})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Importance {}
+
/** Value signifying that the user has not expressed a per-app visibility override value.
* @hide */
public static final int VISIBILITY_NO_OVERRIDE = -1000;
@@ -929,26 +962,31 @@
public static final int IMPORTANCE_NONE = 0;
/**
- * Low notification importance: only shows in the shade, below the fold.
+ * Min notification importance: only shows in the shade, below the fold.
*/
- public static final int IMPORTANCE_LOW = 1;
+ public static final int IMPORTANCE_MIN = 1;
/**
- * Default notification importance: shows everywhere, but is not intrusive.
+ * Low notification importance: shows everywhere, but is not intrusive.
*/
- public static final int IMPORTANCE_DEFAULT = 2;
+ public static final int IMPORTANCE_LOW = 2;
/**
- * Higher notification importance: shows everywhere, makes noise,
+ * Default notification importance: shows everywhere, allowed to makes noise,
* but does not visually intrude.
*/
- public static final int IMPORTANCE_HIGH = 3;
+ public static final int IMPORTANCE_DEFAULT = 3;
/**
- * Highest notification importance: shows everywhere, makes noise,
- * and also visually intrudes.
+ * Higher notification importance: shows everywhere, allowed to makes noise and peek.
*/
- public static final int IMPORTANCE_MAX = 4;
+ public static final int IMPORTANCE_HIGH = 4;
+
+ /**
+ * Highest notification importance: shows everywhere, allowed to makes noise, peek, and
+ * use full screen intents.
+ */
+ public static final int IMPORTANCE_MAX = 5;
private String mKey;
private int mRank = -1;
@@ -956,7 +994,7 @@
private boolean mMatchesInterruptionFilter;
private int mVisibilityOverride;
private int mSuppressedVisualEffects;
- private int mImportance;
+ private @Importance int mImportance;
private CharSequence mImportanceExplanation;
public Ranking() {}
@@ -1022,7 +1060,7 @@
*
* @return the rank of the notification
*/
- public int getImportance() {
+ public @Importance int getImportance() {
return mImportance;
}
@@ -1041,7 +1079,7 @@
CharSequence explanation) {
mKey = key;
mRank = rank;
- mIsAmbient = importance < IMPORTANCE_DEFAULT;
+ mIsAmbient = importance < IMPORTANCE_LOW;
mMatchesInterruptionFilter = matchesInterruptionFilter;
mVisibilityOverride = visibilityOverride;
mSuppressedVisualEffects = suppressedVisualEffects;
@@ -1058,6 +1096,8 @@
return "UNSPECIFIED";
case IMPORTANCE_NONE:
return "NONE";
+ case IMPORTANCE_MIN:
+ return "MIN";
case IMPORTANCE_LOW:
return "LOW";
case IMPORTANCE_DEFAULT:
@@ -1264,4 +1304,57 @@
}
};
}
+
+ private final class MyHandler extends Handler {
+ public static final int MSG_ON_NOTIFICATION_POSTED = 1;
+ public static final int MSG_ON_NOTIFICATION_REMOVED = 2;
+ public static final int MSG_ON_LISTENER_CONNECTED = 3;
+ public static final int MSG_ON_NOTIFICATION_RANKING_UPDATE = 4;
+ public static final int MSG_ON_LISTENER_HINTS_CHANGED = 5;
+ public static final int MSG_ON_INTERRUPTION_FILTER_CHANGED = 6;
+
+ public MyHandler(Looper looper) {
+ super(looper, null, false);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_ON_NOTIFICATION_POSTED: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ StatusBarNotification sbn = (StatusBarNotification) args.arg1;
+ RankingMap rankingMap = (RankingMap) args.arg2;
+ args.recycle();
+ onNotificationPosted(sbn, rankingMap);
+ } break;
+
+ case MSG_ON_NOTIFICATION_REMOVED: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ StatusBarNotification sbn = (StatusBarNotification) args.arg1;
+ RankingMap rankingMap = (RankingMap) args.arg2;
+ args.recycle();
+ onNotificationRemoved(sbn, rankingMap);
+ } break;
+
+ case MSG_ON_LISTENER_CONNECTED: {
+ onListenerConnected();
+ } break;
+
+ case MSG_ON_NOTIFICATION_RANKING_UPDATE: {
+ RankingMap rankingMap = (RankingMap) msg.obj;
+ onNotificationRankingUpdate(rankingMap);
+ } break;
+
+ case MSG_ON_LISTENER_HINTS_CHANGED: {
+ final int hints = msg.arg1;
+ onListenerHintsChanged(hints);
+ } break;
+
+ case MSG_ON_INTERRUPTION_FILTER_CHANGED: {
+ final int interruptionFilter = msg.arg1;
+ onInterruptionFilterChanged(interruptionFilter);
+ } break;
+ }
+ }
+ }
}
diff --git a/core/java/android/service/notification/ZenModeConfig.aidl b/core/java/android/service/notification/ZenModeConfig.aidl
index c73b75e..4644103 100644
--- a/core/java/android/service/notification/ZenModeConfig.aidl
+++ b/core/java/android/service/notification/ZenModeConfig.aidl
@@ -17,4 +17,5 @@
package android.service.notification;
parcelable ZenModeConfig;
+parcelable ZenModeConfig.ZenRule;
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 97939a9..27315ee 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -1017,7 +1017,7 @@
public static class ZenRule implements Parcelable {
public boolean enabled;
public boolean snoozing; // user manually disabled this instance
- public String name; // required for automatic (unique)
+ public String name; // required for automatic
public int zenMode;
public Uri conditionId; // required for automatic
public Condition condition; // optional
diff --git a/core/java/android/service/persistentdata/IPersistentDataBlockService.aidl b/core/java/android/service/persistentdata/IPersistentDataBlockService.aidl
index 52db223..626b408 100644
--- a/core/java/android/service/persistentdata/IPersistentDataBlockService.aidl
+++ b/core/java/android/service/persistentdata/IPersistentDataBlockService.aidl
@@ -35,4 +35,6 @@
void setOemUnlockEnabled(boolean enabled);
boolean getOemUnlockEnabled();
+ int getFlashLockState();
}
+
diff --git a/core/java/android/service/persistentdata/PersistentDataBlockManager.java b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
index 0ffdf68..cfeed51 100644
--- a/core/java/android/service/persistentdata/PersistentDataBlockManager.java
+++ b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
@@ -17,9 +17,13 @@
package android.service.persistentdata;
import android.annotation.SystemApi;
+import android.annotation.IntDef;
import android.os.RemoteException;
import android.util.Slog;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Interface for reading and writing data blocks to a persistent partition.
*
@@ -43,6 +47,27 @@
private static final String TAG = PersistentDataBlockManager.class.getSimpleName();
private IPersistentDataBlockService sService;
+ /**
+ * Indicates that the device's bootloader lock state is UNKNOWN.
+ */
+ public static final int FLASH_LOCK_UNKNOWN = -1;
+ /**
+ * Indicates that the device's bootloader is UNLOCKED.
+ */
+ public static final int FLASH_LOCK_UNLOCKED = 0;
+ /**
+ * Indicates that the device's bootloader is LOCKED.
+ */
+ public static final int FLASH_LOCK_LOCKED = 1;
+
+ @IntDef({
+ FLASH_LOCK_UNKNOWN,
+ FLASH_LOCK_LOCKED,
+ FLASH_LOCK_UNLOCKED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface FlashLockState {}
+
public PersistentDataBlockManager(IPersistentDataBlockService service) {
sService = service;
}
@@ -60,8 +85,7 @@
try {
return sService.write(data);
} catch (RemoteException e) {
- onError("writing data");
- return -1;
+ throw e.rethrowFromSystemServer();
}
}
@@ -72,8 +96,7 @@
try {
return sService.read();
} catch (RemoteException e) {
- onError("reading data");
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -86,8 +109,7 @@
try {
return sService.getDataBlockSize();
} catch (RemoteException e) {
- onError("getting data block size");
- return -1;
+ throw e.rethrowFromSystemServer();
}
}
@@ -100,8 +122,7 @@
try {
return sService.getMaximumDataBlockSize();
} catch (RemoteException e) {
- onError("getting maximum data block size");
- return -1;
+ throw e.rethrowFromSystemServer();
}
}
@@ -113,7 +134,7 @@
try {
sService.wipe();
} catch (RemoteException e) {
- onError("wiping persistent partition");
+ throw e.rethrowFromSystemServer();
}
}
@@ -124,7 +145,7 @@
try {
sService.setOemUnlockEnabled(enabled);
} catch (RemoteException e) {
- onError("setting OEM unlock enabled to " + enabled);
+ throw e.rethrowFromSystemServer();
}
}
@@ -135,12 +156,24 @@
try {
return sService.getOemUnlockEnabled();
} catch (RemoteException e) {
- onError("getting OEM unlock enabled bit");
- return false;
+ throw e.rethrowFromSystemServer();
}
}
- private void onError(String msg) {
- Slog.v(TAG, "Remote exception while " + msg);
+ /**
+ * Retrieves available information about this device's flash lock state.
+ *
+ * @return FLASH_LOCK_STATE_LOCKED if device bootloader is locked,
+ * FLASH_LOCK_STATE_UNLOCKED if device bootloader is unlocked,
+ * or FLASH_LOCK_STATE unknown if this information cannot be ascertained
+ * on this device.
+ */
+ @FlashLockState
+ public int getFlashLockState() {
+ try {
+ return sService.getFlashLockState();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
}
diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java
index 0cf1175..553d539 100644
--- a/core/java/android/service/quicksettings/TileService.java
+++ b/core/java/android/service/quicksettings/TileService.java
@@ -16,6 +16,8 @@
package android.service.quicksettings;
import android.Manifest;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.app.Dialog;
import android.app.Service;
@@ -74,6 +76,14 @@
public class TileService extends Service {
/**
+ * An activity that provides a user interface for adjusting TileService preferences.
+ * Optional but recommended for apps that implement a TileService.
+ */
+ @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+ public static final String ACTION_QS_TILE_PREFERENCES
+ = "android.service.quicksettings.action.QS_TILE_PREFERENCES";
+
+ /**
* Action that identifies a Service as being a TileService.
*/
public static final String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE";
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 76a401d..9464a87 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -617,11 +617,7 @@
}
@Override
- public void onDetected(RecognitionEvent event) {
- if (! (event instanceof KeyphraseRecognitionEvent)) {
- Slog.e(TAG, "onDetected() called for a soundtrigger event.");
- return;
- }
+ public void onKeyphraseDetected(KeyphraseRecognitionEvent event) {
if (DBG) {
Slog.d(TAG, "onDetected(" + event + ")");
} else {
@@ -632,6 +628,10 @@
event.captureFormat, event.captureSession, event.data))
.sendToTarget();
}
+ @Override
+ public void onGenericSoundTriggerDetected(SoundTrigger.GenericRecognitionEvent event) {
+ Slog.w(TAG, "Generic sound trigger event detected at AOHD: " + event);
+ }
@Override
public void onError(int status) {
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index a985517..de8133b 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -271,7 +271,8 @@
@Override
public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,
Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
- Configuration newConfig, Rect backDropRect, boolean forceLayout) {
+ Configuration newConfig, Rect backDropRect, boolean forceLayout,
+ boolean alwaysConsumeNavBar) {
Message msg = mCaller.obtainMessageIO(MSG_WINDOW_RESIZED,
reportDraw ? 1 : 0, outsets);
mCaller.sendMessage(msg);
@@ -790,7 +791,7 @@
mFinalStableInsets.set(mDispatchedStableInsets);
WindowInsets insets = new WindowInsets(mFinalSystemInsets,
null, mFinalStableInsets,
- getResources().getConfiguration().isScreenRound());
+ getResources().getConfiguration().isScreenRound(), false);
if (DEBUG) {
Log.v(TAG, "dispatching insets=" + insets);
}
diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java
index 0f65f80..bfe5c3f 100644
--- a/core/java/android/text/BoringLayout.java
+++ b/core/java/android/text/BoringLayout.java
@@ -423,9 +423,6 @@
private float mMax;
private int mEllipsizedWidth, mEllipsizedStart, mEllipsizedCount;
- private static final TextPaint sTemp =
- new TextPaint();
-
public static class Metrics extends Paint.FontMetricsInt {
public int width;
diff --git a/core/java/android/text/Emoji.java b/core/java/android/text/Emoji.java
index b437f48..c0f0663 100644
--- a/core/java/android/text/Emoji.java
+++ b/core/java/android/text/Emoji.java
@@ -23,15 +23,17 @@
* @hide
*/
public class Emoji {
- // See http://www.unicode.org/Public/emoji/2.0//emoji-data.txt
+ // See http://www.unicode.org/Public/emoji/3.0/emoji-data.txt
private static int[] EMOJI_MODIFIER_BASE = {
0x261D, 0x26F9, 0x270A, 0x270B, 0x270C, 0x270D, 0x1F385, 0x1F3C3, 0x1F3C4, 0x1F3CA,
0x1F3CB, 0x1F442, 0x1F443, 0x1F446, 0x1F447, 0x1F448, 0x1F449, 0x1F44A, 0x1F44B, 0x1F44C,
0x1F44D, 0x1F44E, 0x1F44F, 0x1F450, 0x1F466, 0x1F467, 0x1F468, 0x1F469, 0x1F46E, 0x1F470,
- 0x1F471, 0x1F472, 0x1F473, 0x1F474, 0x1F475, 0x1F476, 0x1F474, 0x1F478, 0x1F47C, 0x1F481,
- 0x1F482, 0x1F483, 0x1F485, 0x1F486, 0x1F487, 0x1F4AA, 0x1F575, 0x1F590, 0x1F595, 0x1F596,
- 0x1F645, 0x1F646, 0x1F647, 0x1F64B, 0x1F64C, 0x1F64D, 0x1F64E, 0x1F64F, 0x1F6A3, 0x1F6B4,
- 0x1F6B5, 0x1F6B6, 0x1F6C0, 0x1F918
+ 0x1F471, 0x1F472, 0x1F473, 0x1F474, 0x1F475, 0x1F476, 0x1F477, 0x1F478, 0x1F47C, 0x1F481,
+ 0x1F482, 0x1F483, 0x1F485, 0x1F486, 0x1F487, 0x1F4AA, 0x1F575, 0x1F57A, 0x1F590, 0x1F595,
+ 0x1F596, 0x1F645, 0x1F646, 0x1F647, 0x1F64B, 0x1F64C, 0x1F64D, 0x1F64E, 0x1F64F, 0x1F6A3,
+ 0x1F6B4, 0x1F6B5, 0x1F6B6, 0x1F6C0, 0x1F918, 0x1F919, 0x1F91A, 0x1F91B, 0x1F91C, 0x1F91D,
+ 0x1F91E, 0x1F926, 0x1F930, 0x1F933, 0x1F934, 0x1F935, 0x1F936, 0x1F937, 0x1F938, 0x1F939,
+ 0x1F93B, 0x1F93C, 0x1F93D, 0x1F93E
};
// See http://www.unicode.org/emoji/charts/emoji-zwj-sequences.html
diff --git a/core/java/android/text/method/BaseKeyListener.java b/core/java/android/text/method/BaseKeyListener.java
index 367c9fb..3564e11 100644
--- a/core/java/android/text/method/BaseKeyListener.java
+++ b/core/java/android/text/method/BaseKeyListener.java
@@ -16,6 +16,7 @@
package android.text.method;
+import android.graphics.Paint;
import android.icu.lang.UCharacter;
import android.icu.lang.UProperty;
import android.view.KeyEvent;
@@ -25,6 +26,8 @@
import android.text.style.ReplacementSpan;
import android.widget.TextView;
+import com.android.internal.annotations.GuardedBy;
+
import java.text.BreakIterator;
import java.util.Arrays;
import java.util.Collections;
@@ -45,6 +48,11 @@
implements KeyListener {
/* package */ static final Object OLD_SEL_START = new NoCopySpan.Concrete();
+ private final Object mLock = new Object();
+
+ @GuardedBy("mLock")
+ static Paint sCachedPaint = null;
+
/**
* Performs the action that happens when you press the {@link KeyEvent#KEYCODE_DEL} key in
* a {@link TextView}. If there is a selection, deletes the selection; otherwise,
@@ -258,20 +266,15 @@
}
// Returns the end offset to be deleted by a forward delete key from the given offset.
- private static int getOffsetForForwardDeleteKey(CharSequence text, int offset) {
+ private static int getOffsetForForwardDeleteKey(CharSequence text, int offset, Paint paint) {
final int len = text.length();
if (offset >= len - 1) {
return len;
}
- int codePoint = Character.codePointAt(text, offset);
- offset += Character.charCount(codePoint);
- if (offset == len) {
- return len;
- }
-
- // TODO: Handle emoji, combining chars, etc.
+ offset = paint.getTextRunCursor(text, offset, len, Paint.DIRECTION_LTR /* not used */,
+ offset, Paint.CURSOR_AFTER);
return adjustReplacementSpan(text, offset, false /* move to the end */);
}
@@ -311,7 +314,18 @@
final int start = Selection.getSelectionEnd(content);
final int end;
if (isForwardDelete) {
- end = getOffsetForForwardDeleteKey(content, start);
+ final Paint paint;
+ if (view instanceof TextView) {
+ paint = ((TextView)view).getPaint();
+ } else {
+ synchronized (mLock) {
+ if (sCachedPaint == null) {
+ sCachedPaint = new Paint();
+ }
+ paint = sCachedPaint;
+ }
+ }
+ end = getOffsetForForwardDeleteKey(content, start, paint);
} else {
end = getOffsetForBackspaceKey(content, start);
}
@@ -437,6 +451,7 @@
if (handled) {
adjustMetaAfterKeypress(content);
+ return true;
}
return super.onKeyDown(view, content, keyCode, event);
@@ -470,4 +485,3 @@
return true;
}
}
-
diff --git a/core/java/android/text/style/ReplacementSpan.java b/core/java/android/text/style/ReplacementSpan.java
index 26c725f..07190b2 100644
--- a/core/java/android/text/style/ReplacementSpan.java
+++ b/core/java/android/text/style/ReplacementSpan.java
@@ -16,18 +16,49 @@
package android.text.style;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.graphics.Paint;
import android.graphics.Canvas;
import android.text.TextPaint;
public abstract class ReplacementSpan extends MetricAffectingSpan {
- public abstract int getSize(Paint paint, CharSequence text,
- int start, int end,
- Paint.FontMetricsInt fm);
- public abstract void draw(Canvas canvas, CharSequence text,
- int start, int end, float x,
- int top, int y, int bottom, Paint paint);
+ /**
+ * Returns the width of the span. Extending classes can set the height of the span by updating
+ * attributes of {@link android.graphics.Paint.FontMetricsInt}. If the span covers the whole
+ * text, and the height is not set,
+ * {@link #draw(Canvas, CharSequence, int, int, float, int, int, int, Paint)} will not be
+ * called for the span.
+ *
+ * @param paint Paint instance.
+ * @param text Current text.
+ * @param start Start character index for span.
+ * @param end End character index for span.
+ * @param fm Font metrics, can be null.
+ * @return Width of the span.
+ */
+ public abstract int getSize(@NonNull Paint paint, CharSequence text,
+ @IntRange(from = 0) int start, @IntRange(from = 0) int end,
+ @Nullable Paint.FontMetricsInt fm);
+
+ /**
+ * Draws the span into the canvas.
+ *
+ * @param canvas Canvas into which the span should be rendered.
+ * @param text Current text.
+ * @param start Start character index for span.
+ * @param end End character index for span.
+ * @param x Edge of the replacement closest to the leading margin.
+ * @param top Top of the line.
+ * @param y Baseline.
+ * @param bottom Bottom of the line.
+ * @param paint Paint instance.
+ */
+ public abstract void draw(@NonNull Canvas canvas, CharSequence text,
+ @IntRange(from = 0) int start, @IntRange(from = 0) int end, float x,
+ int top, int y, int bottom, @NonNull Paint paint);
/**
* This method does nothing, since ReplacementSpans are measured
diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java
index fbd9924..bd376ea 100644
--- a/core/java/android/text/util/Linkify.java
+++ b/core/java/android/text/util/Linkify.java
@@ -224,7 +224,7 @@
}
if ((mask & EMAIL_ADDRESSES) != 0) {
- gatherLinks(links, text, Patterns.EMAIL_ADDRESS,
+ gatherLinks(links, text, Patterns.AUTOLINK_EMAIL_ADDRESS,
new String[] { "mailto:" },
null, null);
}
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index bdb1fdc..92a5803 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -67,7 +67,7 @@
/**
* @hide Special immutable empty ArrayMap.
*/
- public static final ArrayMap EMPTY = new ArrayMap(true);
+ public static final ArrayMap EMPTY = new ArrayMap<>(-1);
/**
* Caches of small array objects to avoid spamming garbage. The cache
@@ -80,6 +80,7 @@
static Object[] mTwiceBaseCache;
static int mTwiceBaseCacheSize;
+ final boolean mIdentityHashCode;
int[] mHashes;
Object[] mArray;
int mSize;
@@ -236,16 +237,27 @@
* will grow once items are added to it.
*/
public ArrayMap() {
- mHashes = EmptyArray.INT;
- mArray = EmptyArray.OBJECT;
- mSize = 0;
+ this(0, false);
}
/**
* Create a new ArrayMap with a given initial capacity.
*/
public ArrayMap(int capacity) {
- if (capacity == 0) {
+ this(capacity, false);
+ }
+
+ /** {@hide} */
+ public ArrayMap(int capacity, boolean identityHashCode) {
+ mIdentityHashCode = identityHashCode;
+
+ // If this is immutable, use the sentinal EMPTY_IMMUTABLE_INTS
+ // instance instead of the usual EmptyArray.INT. The reference
+ // is checked later to see if the array is allowed to grow.
+ if (capacity < 0) {
+ mHashes = EMPTY_IMMUTABLE_INTS;
+ mArray = EmptyArray.OBJECT;
+ } else if (capacity == 0) {
mHashes = EmptyArray.INT;
mArray = EmptyArray.OBJECT;
} else {
@@ -254,15 +266,6 @@
mSize = 0;
}
- private ArrayMap(boolean immutable) {
- // If this is immutable, use the sentinal EMPTY_IMMUTABLE_INTS
- // instance instead of the usual EmptyArray.INT. The reference
- // is checked later to see if the array is allowed to grow.
- mHashes = immutable ? EMPTY_IMMUTABLE_INTS : EmptyArray.INT;
- mArray = EmptyArray.OBJECT;
- mSize = 0;
- }
-
/**
* Create a new ArrayMap with the mappings from the given ArrayMap.
*/
@@ -336,7 +339,8 @@
* @return Returns the index of the key if it exists, else a negative integer.
*/
public int indexOfKey(Object key) {
- return key == null ? indexOfNull() : indexOf(key, key.hashCode());
+ return key == null ? indexOfNull()
+ : indexOf(key, mIdentityHashCode ? System.identityHashCode(key) : key.hashCode());
}
int indexOfValue(Object value) {
@@ -437,7 +441,7 @@
hash = 0;
index = indexOfNull();
} else {
- hash = key.hashCode();
+ hash = mIdentityHashCode ? System.identityHashCode(key) : key.hashCode();
index = indexOf(key, hash);
}
if (index >= 0) {
@@ -488,7 +492,8 @@
*/
public void append(K key, V value) {
int index = mSize;
- final int hash = key == null ? 0 : key.hashCode();
+ final int hash = key == null ? 0
+ : (mIdentityHashCode ? System.identityHashCode(key) : key.hashCode());
if (index >= mHashes.length) {
throw new IllegalStateException("Array is full");
}
diff --git a/core/java/android/util/ArraySet.java b/core/java/android/util/ArraySet.java
index b7a3c42..9e9314f 100644
--- a/core/java/android/util/ArraySet.java
+++ b/core/java/android/util/ArraySet.java
@@ -69,6 +69,7 @@
static Object[] mTwiceBaseCache;
static int mTwiceBaseCacheSize;
+ final boolean mIdentityHashCode;
int[] mHashes;
Object[] mArray;
int mSize;
@@ -222,15 +223,19 @@
* will grow once items are added to it.
*/
public ArraySet() {
- mHashes = EmptyArray.INT;
- mArray = EmptyArray.OBJECT;
- mSize = 0;
+ this(0, false);
}
/**
* Create a new ArraySet with a given initial capacity.
*/
public ArraySet(int capacity) {
+ this(capacity, false);
+ }
+
+ /** {@hide} */
+ public ArraySet(int capacity, boolean identityHashCode) {
+ mIdentityHashCode = identityHashCode;
if (capacity == 0) {
mHashes = EmptyArray.INT;
mArray = EmptyArray.OBJECT;
@@ -306,7 +311,8 @@
* @return Returns the index of the value if it exists, else a negative integer.
*/
public int indexOf(Object key) {
- return key == null ? indexOfNull() : indexOf(key, key.hashCode());
+ return key == null ? indexOfNull()
+ : indexOf(key, mIdentityHashCode ? System.identityHashCode(key) : key.hashCode());
}
/**
@@ -343,7 +349,7 @@
hash = 0;
index = indexOfNull();
} else {
- hash = value.hashCode();
+ hash = mIdentityHashCode ? System.identityHashCode(value) : value.hashCode();
index = indexOf(value, hash);
}
if (index >= 0) {
diff --git a/core/java/android/util/LocaleList.java b/core/java/android/util/LocaleList.java
index fc39004..fa3921c 100644
--- a/core/java/android/util/LocaleList.java
+++ b/core/java/android/util/LocaleList.java
@@ -478,8 +478,6 @@
/**
* Returns the default locale list, adjusted by moving the default locale to its first
* position.
- *
- * {@hide}
*/
@NonNull @Size(min=1)
public static LocaleList getAdjustedDefault() {
diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java
index 544444d..5bc6c94 100644
--- a/core/java/android/util/Log.java
+++ b/core/java/android/util/Log.java
@@ -16,6 +16,8 @@
package android.util;
+import android.os.DeadSystemException;
+
import com.android.internal.os.RuntimeInit;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.LineBreakBufferedWriter;
@@ -377,8 +379,9 @@
* Helper function for long messages. Uses the LineBreakBufferedWriter to break
* up long messages and stacktraces along newlines, but tries to write in large
* chunks. This is to avoid truncation.
+ * @hide
*/
- private static int printlns(int bufID, int priority, String tag, String msg,
+ public static int printlns(int bufID, int priority, String tag, String msg,
Throwable tr) {
ImmediateLogWriter logWriter = new ImmediateLogWriter(bufID, priority, tag);
// Acceptable buffer size. Get the native buffer size, subtract two zero terminators,
@@ -404,6 +407,11 @@
if (t instanceof UnknownHostException) {
break;
}
+ if (t instanceof DeadSystemException) {
+ lbbw.println("DeadSystemException: The system died; "
+ + "earlier logs will point to the root cause");
+ break;
+ }
t = t.getCause();
}
if (t == null) {
diff --git a/core/java/android/util/Patterns.java b/core/java/android/util/Patterns.java
index 9f2bcfd..9ed4850 100644
--- a/core/java/android/util/Patterns.java
+++ b/core/java/android/util/Patterns.java
@@ -394,6 +394,36 @@
public static final Pattern AUTOLINK_WEB_URL = Pattern.compile(
"(" + WEB_URL_WITH_PROTOCOL + "|" + WEB_URL_WITHOUT_PROTOCOL + ")");
+ /**
+ * Regular expression for valid email characters. Does not include some of the valid characters
+ * defined in RFC5321: #&~!^`{}/=$*?|
+ */
+ private static final String EMAIL_CHAR = LABEL_CHAR + "\\+\\-_%'";
+
+ /**
+ * Regular expression for local part of an email address. RFC5321 section 4.5.3.1.1 limits
+ * the local part to be at most 64 octets.
+ */
+ private static final String EMAIL_ADDRESS_LOCAL_PART =
+ "[" + EMAIL_CHAR + "]" + "(?:[" + EMAIL_CHAR + "\\.]{1,62}[" + EMAIL_CHAR + "])?";
+
+ /**
+ * Regular expression for the domain part of an email address. RFC5321 section 4.5.3.1.2 limits
+ * the domain to be at most 255 octets.
+ */
+ private static final String EMAIL_ADDRESS_DOMAIN =
+ "(?=.{1,255}(?:\\s|$|^))" + HOST_NAME;
+
+ /**
+ * Regular expression pattern to match email addresses. It excludes double quoted local parts
+ * and the special characters #&~!^`{}/=$*?| that are included in RFC5321.
+ * @hide
+ */
+ public static final Pattern AUTOLINK_EMAIL_ADDRESS = Pattern.compile("(" + WORD_BOUNDARY +
+ "(?:" + EMAIL_ADDRESS_LOCAL_PART + "@" + EMAIL_ADDRESS_DOMAIN + ")" +
+ WORD_BOUNDARY + ")"
+ );
+
public static final Pattern EMAIL_ADDRESS
= Pattern.compile(
"[a-zA-Z0-9\\+\\.\\_\\%\\-\\+]{1,256}" +
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
index 728f723..60c7270 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
@@ -75,6 +75,36 @@
public static final int SF_ATTRIBUTE_ANDROID_APK_SIGNED_ID = 2;
/**
+ * Returns {@code true} if the provided APK contains an APK Signature Scheme V2
+ * signature. The signature will not be verified.
+ */
+ public static boolean hasSignature(String apkFile) throws IOException {
+ try (RandomAccessFile apk = new RandomAccessFile(apkFile, "r")) {
+ long fileSize = apk.length();
+ if (fileSize > Integer.MAX_VALUE) {
+ return false;
+ }
+ MappedByteBuffer apkContents =
+ apk.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, fileSize);
+ // ZipUtils and APK Signature Scheme v2 verifier expect little-endian byte order.
+ apkContents.order(ByteOrder.LITTLE_ENDIAN);
+
+ final int centralDirOffset =
+ (int) getCentralDirOffset(apkContents, getEocdOffset(apkContents));
+ // Find the APK Signing Block.
+ int apkSigningBlockOffset = findApkSigningBlock(apkContents, centralDirOffset);
+ ByteBuffer apkSigningBlock =
+ sliceFromTo(apkContents, apkSigningBlockOffset, centralDirOffset);
+
+ // Find the APK Signature Scheme v2 Block inside the APK Signing Block.
+ findApkSignatureSchemeV2Block(apkSigningBlock);
+ return true;
+ } catch (SignatureNotFoundException e) {
+ }
+ return false;
+ }
+
+ /**
* Verifies APK Signature Scheme v2 signatures of the provided APK and returns the certificates
* associated with each signer.
*
@@ -130,31 +160,8 @@
// ZipUtils and APK Signature Scheme v2 verifier expect little-endian byte order.
apkContents.order(ByteOrder.LITTLE_ENDIAN);
- // Find the offset of ZIP End of Central Directory (EoCD)
- int eocdOffset = ZipUtils.findZipEndOfCentralDirectoryRecord(apkContents);
- if (eocdOffset == -1) {
- throw new SignatureNotFoundException(
- "Not an APK file: ZIP End of Central Directory record not found");
- }
- if (ZipUtils.isZip64EndOfCentralDirectoryLocatorPresent(apkContents, eocdOffset)) {
- throw new SignatureNotFoundException("ZIP64 APK not supported");
- }
- ByteBuffer eocd = sliceFromTo(apkContents, eocdOffset, apkContents.capacity());
-
- // Look up the offset of ZIP Central Directory.
- long centralDirOffsetLong = ZipUtils.getZipEocdCentralDirectoryOffset(eocd);
- if (centralDirOffsetLong >= eocdOffset) {
- throw new SignatureNotFoundException(
- "ZIP Central Directory offset out of range: " + centralDirOffsetLong
- + ". ZIP End of Central Directory offset: " + eocdOffset);
- }
- long centralDirSizeLong = ZipUtils.getZipEocdCentralDirectorySizeBytes(eocd);
- if (centralDirOffsetLong + centralDirSizeLong != eocdOffset) {
- throw new SignatureNotFoundException(
- "ZIP Central Directory is not immediately followed by End of Central"
- + " Directory");
- }
- int centralDirOffset = (int) centralDirOffsetLong;
+ final int eocdOffset = getEocdOffset(apkContents);
+ final int centralDirOffset = (int) getCentralDirOffset(apkContents, eocdOffset);
// Find the APK Signing Block.
int apkSigningBlockOffset = findApkSigningBlock(apkContents, centralDirOffset);
@@ -499,6 +506,43 @@
return result;
}
+ /**
+ * Finds the offset of ZIP End of Central Directory (EoCD).
+ *
+ * @throws SignatureNotFoundException If the EoCD could not be found
+ */
+ private static int getEocdOffset(ByteBuffer apkContents) throws SignatureNotFoundException {
+ int eocdOffset = ZipUtils.findZipEndOfCentralDirectoryRecord(apkContents);
+ if (eocdOffset == -1) {
+ throw new SignatureNotFoundException(
+ "Not an APK file: ZIP End of Central Directory record not found");
+ }
+ return eocdOffset;
+ }
+
+ private static long getCentralDirOffset(ByteBuffer apkContents, int eocdOffset)
+ throws SignatureNotFoundException {
+ if (ZipUtils.isZip64EndOfCentralDirectoryLocatorPresent(apkContents, eocdOffset)) {
+ throw new SignatureNotFoundException("ZIP64 APK not supported");
+ }
+ ByteBuffer eocd = sliceFromTo(apkContents, eocdOffset, apkContents.capacity());
+
+ // Look up the offset of ZIP Central Directory.
+ long centralDirOffsetLong = ZipUtils.getZipEocdCentralDirectoryOffset(eocd);
+ if (centralDirOffsetLong >= eocdOffset) {
+ throw new SignatureNotFoundException(
+ "ZIP Central Directory offset out of range: " + centralDirOffsetLong
+ + ". ZIP End of Central Directory offset: " + eocdOffset);
+ }
+ long centralDirSizeLong = ZipUtils.getZipEocdCentralDirectorySizeBytes(eocd);
+ if (centralDirOffsetLong + centralDirSizeLong != eocdOffset) {
+ throw new SignatureNotFoundException(
+ "ZIP Central Directory is not immediately followed by End of Central"
+ + " Directory");
+ }
+ return centralDirOffsetLong;
+ }
+
private static final int getChunkCount(int inputSizeBytes) {
return (inputSizeBytes + CHUNK_SIZE_BYTES - 1) / CHUNK_SIZE_BYTES;
}
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 664c02a..c7b1d03 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -1053,6 +1053,7 @@
private void prefetchPredecessorsOfVirtualNode(AccessibilityNodeInfo root,
View providerHost, AccessibilityNodeProvider provider,
List<AccessibilityNodeInfo> outInfos) {
+ final int initialResultSize = outInfos.size();
long parentNodeId = root.getParentNodeId();
int accessibilityViewId = AccessibilityNodeInfo.getAccessibilityViewId(parentNodeId);
while (accessibilityViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
@@ -1071,6 +1072,12 @@
AccessibilityNodeProvider.HOST_VIEW_ID);
}
if (parent == null) {
+ // Going up the parent relation we found a null predecessor,
+ // so remove these disconnected nodes form the result.
+ final int currentResultSize = outInfos.size();
+ for (int i = currentResultSize - 1; i >= initialResultSize; i--) {
+ outInfos.remove(i);
+ }
// Couldn't obtain the parent, which means we have a
// disconnected sub-tree. Abort prefetch immediately.
return;
diff --git a/core/java/android/view/IDockedStackListener.aidl b/core/java/android/view/IDockedStackListener.aidl
index 77fa7e2..cbc8dbd 100644
--- a/core/java/android/view/IDockedStackListener.aidl
+++ b/core/java/android/view/IDockedStackListener.aidl
@@ -33,4 +33,13 @@
* Called when the docked stack gets created or removed.
*/
void onDockedStackExistsChanged(boolean exists);
+
+ /**
+ * Called when window manager decides to minimize the docked stack. The divider should make
+ * itself not interactable and shrink a bit in this state.
+ *
+ * @param minimized Whether the docked stack is currently minimized.
+ * @param animDuration The duration of the animation for changing the minimized state.
+ */
+ void onDockedStackMinimizedChanged(boolean minimized, long animDuration);
}
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 3688d50..70d0513 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -49,7 +49,8 @@
void resized(in Rect frame, in Rect overscanInsets, in Rect contentInsets,
in Rect visibleInsets, in Rect stableInsets, in Rect outsets, boolean reportDraw,
- in Configuration newConfig, in Rect backDropFrame, boolean forceLayout);
+ in Configuration newConfig, in Rect backDropFrame, boolean forceLayout,
+ boolean alwaysConsumeNavBar);
void moved(int newX, int newY);
void dispatchAppVisibility(boolean visible);
void dispatchGetNewSurface();
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 5b9930b..8048301 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -20,6 +20,7 @@
import com.android.internal.os.IResultReceiver;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
+import com.android.internal.policy.IShortcutService;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
@@ -166,7 +167,7 @@
in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
int icon, int logo, int windowFlags, IBinder transferFrom, boolean createIfNeeded);
void setAppVisibility(IBinder token, boolean visible);
- void notifyAppStopped(IBinder token);
+ void notifyAppStopped(IBinder token, boolean stopped);
void startAppFreezingScreen(IBinder token, int configChanges);
void stopAppFreezingScreen(IBinder token, boolean force);
void removeAppToken(IBinder token);
@@ -387,4 +388,11 @@
* Retrieves the current stable insets from the primary display.
*/
void getStableInsets(out Rect outInsets);
+
+ /**
+ * Register shortcut key. Shortcut code is packed as:
+ * (MetaState << Integer.SIZE) | KeyCode
+ * @hide
+ */
+ void registerShortcutKey(in long shortcutCode, IShortcutService keySubscriber);
}
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 51e1f4b..e0c6770 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -1780,6 +1780,7 @@
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
case KeyEvent.KEYCODE_SPACE:
+ case KeyEvent.KEYCODE_NUMPAD_ENTER:
return true;
default:
return false;
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index 7017ff5..a45c18d 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -775,7 +775,11 @@
mOwningView.mAttachInfo.mViewRootImpl.registerAnimatingRenderNode(this);
}
- public void addAnimator(AnimatedVectorDrawable.VectorDrawableAnimator animatorSet) {
+ public boolean isAttached() {
+ return mOwningView != null && mOwningView.mAttachInfo != null;
+ }
+
+ public void addAnimator(AnimatedVectorDrawable.VectorDrawableAnimatorRT animatorSet) {
if (mOwningView == null || mOwningView.mAttachInfo == null) {
throw new IllegalStateException("Cannot start this animator on a detached view!");
}
diff --git a/core/java/android/view/Surface.aidl b/core/java/android/view/Surface.aidl
deleted file mode 100644
index 90bf37a..0000000
--- a/core/java/android/view/Surface.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/view/Surface.aidl
-**
-** Copyright 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.view;
-
-parcelable Surface;
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index b58c68f..aa86c03 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -36,6 +36,7 @@
throws OutOfResourcesException;
private static native void nativeRelease(long nativeObject);
private static native void nativeDestroy(long nativeObject);
+ private static native void nativeDisconnect(long nativeObject);
private static native Bitmap nativeScreenshot(IBinder displayToken,
Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
@@ -341,6 +342,15 @@
mCloseGuard.close();
}
+ /**
+ * Disconnect any client still connected to the surface.
+ */
+ public void disconnect() {
+ if (mNativeObject != 0) {
+ nativeDisconnect(mNativeObject);
+ }
+ }
+
private void checkNotReleased() {
if (mNativeObject == 0) throw new NullPointerException(
"mNativeObject is null. Have you called release() already?");
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 152dd66..2c9d691 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -743,7 +743,8 @@
@Override
public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,
Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
- Configuration newConfig, Rect backDropRect, boolean forceLayout) {
+ Configuration newConfig, Rect backDropRect, boolean forceLayout,
+ boolean alwaysConsumeNavBar) {
SurfaceView surfaceView = mSurfaceView.get();
if (surfaceView != null) {
if (DEBUG) Log.v(
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index ca41d78..c972476 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -380,7 +380,7 @@
void destroy() {
mInitialized = false;
updateEnabledState(null);
- nDestroy(mNativeProxy);
+ nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
}
/**
@@ -994,7 +994,7 @@
float lightX, float lightY, float lightZ);
private static native void nSetOpaque(long nativeProxy, boolean opaque);
private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
- private static native void nDestroy(long nativeProxy);
+ private static native void nDestroy(long nativeProxy, long rootRenderNode);
private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode);
private static native void nInvokeFunctor(long functor, boolean waitForCompletion);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 70a0e01..9bd3df0 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10270,6 +10270,27 @@
}
/**
+ * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
+ * is currently in without any insets.
+ *
+ * @hide
+ */
+ public void getWindowDisplayFrame(Rect outRect) {
+ if (mAttachInfo != null) {
+ try {
+ mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
+ } catch (RemoteException e) {
+ return;
+ }
+ return;
+ }
+ // The view is not attached to a display so we don't have a context.
+ // Make a best guess about the display size.
+ Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
+ d.getRectSize(outRect);
+ }
+
+ /**
* Dispatch a notification about a resource configuration change down
* the view hierarchy.
* ViewGroups should override to route to their children.
@@ -18916,7 +18937,8 @@
transformFromViewToWindowSpace(outLocation);
}
- void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
+ /** @hide */
+ public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
if (inOutLocation == null || inOutLocation.length < 2) {
throw new IllegalArgumentException("inOutLocation must be an array of two integers");
}
@@ -22517,6 +22539,13 @@
final Rect mOutsets = new Rect();
/**
+ * In multi-window we force show the navigation bar. Because we don't want that the surface
+ * size changes in this mode, we instead have a flag whether the navigation bar size should
+ * always be consumed, so the app is treated like there is no virtual navigation bar at all.
+ */
+ boolean mAlwaysConsumeNavBar;
+
+ /**
* The internal insets given by this window. This value is
* supplied by the client (through
* {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 0517788..afe2f10 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -313,6 +313,7 @@
final Rect mPendingContentInsets = new Rect();
final Rect mPendingOutsets = new Rect();
final Rect mPendingBackDropFrame = new Rect();
+ boolean mPendingAlwaysConsumeNavBar;
final ViewTreeObserver.InternalInsetsInfo mLastGivenInsets
= new ViewTreeObserver.InternalInsetsInfo();
@@ -623,6 +624,9 @@
mPendingContentInsets.set(mAttachInfo.mContentInsets);
mPendingStableInsets.set(mAttachInfo.mStableInsets);
mPendingVisibleInsets.set(0, 0, 0, 0);
+ mAttachInfo.mAlwaysConsumeNavBar =
+ (res & WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR) != 0;
+ mPendingAlwaysConsumeNavBar = mAttachInfo.mAlwaysConsumeNavBar;
if (DEBUG_LAYOUT) Log.v(mTag, "Added window " + mWindow);
if (res < WindowManagerGlobal.ADD_OKAY) {
mAttachInfo.mRootView = null;
@@ -1072,6 +1076,13 @@
mStopped = stopped;
if (!mStopped) {
scheduleTraversals();
+ } else {
+ if (mAttachInfo.mHardwareRenderer != null) {
+ // TODO: Temporary to help track down b/27286867
+ Log.d(mTag, "WindowStopped on " + getTitle());
+ mAttachInfo.mHardwareRenderer.updateSurface(null);
+ mAttachInfo.mHardwareRenderer.destroyHardwareResources(mView);
+ }
}
}
}
@@ -1343,7 +1354,8 @@
}
mLastWindowInsets = new WindowInsets(contentInsets,
null /* windowDecorInsets */, stableInsets,
- mContext.getResources().getConfiguration().isScreenRound());
+ mContext.getResources().getConfiguration().isScreenRound(),
+ mAttachInfo.mAlwaysConsumeNavBar);
}
return mLastWindowInsets;
}
@@ -1510,6 +1522,9 @@
if (!mPendingOutsets.equals(mAttachInfo.mOutsets)) {
insetsChanged = true;
}
+ if (mPendingAlwaysConsumeNavBar != mAttachInfo.mAlwaysConsumeNavBar) {
+ insetsChanged = true;
+ }
if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT
|| lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
windowSizeMayChange = true;
@@ -1694,6 +1709,8 @@
final boolean outsetsChanged = !mPendingOutsets.equals(mAttachInfo.mOutsets);
final boolean surfaceSizeChanged = (relayoutResult
& WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED) != 0;
+ final boolean alwaysConsumeNavBarChanged =
+ mPendingAlwaysConsumeNavBar != mAttachInfo.mAlwaysConsumeNavBar;
if (contentInsetsChanged) {
mAttachInfo.mContentInsets.set(mPendingContentInsets);
if (DEBUG_LAYOUT) Log.v(mTag, "Content insets changing to: "
@@ -1713,6 +1730,10 @@
// Need to relayout with content insets.
contentInsetsChanged = true;
}
+ if (alwaysConsumeNavBarChanged) {
+ mAttachInfo.mAlwaysConsumeNavBar = mPendingAlwaysConsumeNavBar;
+ contentInsetsChanged = true;
+ }
if (contentInsetsChanged || mLastSystemUiVisibility !=
mAttachInfo.mSystemUiVisibility || mApplyInsetsRequested
|| mLastOverscanRequested != mAttachInfo.mOverscanRequested
@@ -1966,7 +1987,7 @@
boolean triggerGlobalLayoutListener = didLayout
|| mAttachInfo.mRecomputeGlobalAttributes;
if (didLayout) {
- performLayout(lp, desiredWindowWidth, desiredWindowHeight);
+ performLayout(lp, mWidth, mHeight);
// By this point all views have been sized and positioned
// We can compute the transparent area
@@ -3389,6 +3410,7 @@
mPendingOutsets.set((Rect) args.arg7);
mPendingBackDropFrame.set((Rect) args.arg8);
mForceNextWindowRelayout = args.argi1 != 0;
+ mPendingAlwaysConsumeNavBar = args.argi2 != 0;
args.recycle();
@@ -3797,7 +3819,8 @@
return true;
} else if ((!mAttachInfo.mHasWindowFocus
&& !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) || mStopped
- || mIsAmbientMode || (mPausedForTransition && !isBack(q.mEvent))) {
+ || (mIsAmbientMode && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_BUTTON))
+ || (mPausedForTransition && !isBack(q.mEvent))) {
// This is a focus event and the window doesn't currently have input focus or
// has stopped. This could be an event that came back from the previous stage
// but the window has lost focus or stopped in the meantime.
@@ -4375,8 +4398,14 @@
private boolean updatePointerIcon(MotionEvent event) {
final float x = event.getX();
final float y = event.getY();
+ if (mView == null) {
+ // E.g. click outside a popup to dismiss it
+ Slog.d(mTag, "updatePointerIcon called after view was removed");
+ return false;
+ }
if (x < 0 || x >= mView.getWidth() || y < 0 || y >= mView.getHeight()) {
- Slog.e(mTag, "updatePointerIcon called with position out of bounds");
+ // E.g. when moving window divider with mouse
+ Slog.d(mTag, "updatePointerIcon called with position out of bounds");
return false;
}
final PointerIcon pointerIcon = mView.getPointerIcon(event, x, y);
@@ -5567,6 +5596,10 @@
mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingConfiguration,
mSurface);
+
+ mPendingAlwaysConsumeNavBar =
+ (relayoutResult & WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR) != 0;
+
//Log.d(mTag, "<<<<<< BACK FROM relayout");
if (restore) {
params.restore();
@@ -5838,7 +5871,8 @@
public void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets,
Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
- Configuration newConfig, Rect backDropFrame, boolean forceLayout) {
+ Configuration newConfig, Rect backDropFrame, boolean forceLayout,
+ boolean alwaysConsumeNavBar) {
if (DEBUG_LAYOUT) Log.v(mTag, "Resizing " + this + ": frame=" + frame.toShortString()
+ " contentInsets=" + contentInsets.toShortString()
+ " visibleInsets=" + visibleInsets.toShortString()
@@ -5875,6 +5909,7 @@
args.arg7 = sameProcessCall ? new Rect(outsets) : outsets;
args.arg8 = sameProcessCall ? new Rect(backDropFrame) : backDropFrame;
args.argi1 = forceLayout ? 1 : 0;
+ args.argi2 = alwaysConsumeNavBar ? 1 : 0;
msg.obj = args;
mHandler.sendMessage(msg);
}
@@ -6876,12 +6911,13 @@
@Override
public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,
Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
- Configuration newConfig, Rect backDropFrame, boolean forceLayout) {
+ Configuration newConfig, Rect backDropFrame, boolean forceLayout,
+ boolean alwaysConsumeNavBar) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
viewAncestor.dispatchResized(frame, overscanInsets, contentInsets,
visibleInsets, stableInsets, outsets, reportDraw, newConfig, backDropFrame,
- forceLayout);
+ forceLayout, alwaysConsumeNavBar);
}
}
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 997e7e8..929fdac 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -37,6 +37,13 @@
private Rect mTempRect;
private boolean mIsRound;
+ /**
+ * In multi-window we force show the navigation bar. Because we don't want that the surface size
+ * changes in this mode, we instead have a flag whether the navigation bar size should always
+ * be consumed, so the app is treated like there is no virtual navigation bar at all.
+ */
+ private boolean mAlwaysConsumeNavBar;
+
private boolean mSystemWindowInsetsConsumed = false;
private boolean mWindowDecorInsetsConsumed = false;
private boolean mStableInsetsConsumed = false;
@@ -52,12 +59,12 @@
public static final WindowInsets CONSUMED;
static {
- CONSUMED = new WindowInsets(null, null, null, false);
+ CONSUMED = new WindowInsets(null, null, null, false, false);
}
/** @hide */
public WindowInsets(Rect systemWindowInsets, Rect windowDecorInsets, Rect stableInsets,
- boolean isRound) {
+ boolean isRound, boolean alwaysConsumeNavBar) {
mSystemWindowInsetsConsumed = systemWindowInsets == null;
mSystemWindowInsets = mSystemWindowInsetsConsumed ? EMPTY_RECT : systemWindowInsets;
@@ -68,6 +75,7 @@
mStableInsets = mStableInsetsConsumed ? EMPTY_RECT : stableInsets;
mIsRound = isRound;
+ mAlwaysConsumeNavBar = alwaysConsumeNavBar;
}
/**
@@ -87,7 +95,7 @@
/** @hide */
public WindowInsets(Rect systemWindowInsets) {
- this(systemWindowInsets, null, null, false);
+ this(systemWindowInsets, null, null, false, false);
}
/**
@@ -475,6 +483,13 @@
return result;
}
+ /**
+ * @hide
+ */
+ public boolean shouldAlwaysConsumeNavBar() {
+ return mAlwaysConsumeNavBar;
+ }
+
@Override
public String toString() {
return "WindowInsets{systemWindowInsets=" + mSystemWindowInsets
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 18dfdfd..6e02516 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -30,7 +30,7 @@
import android.util.Log;
import java.util.List;
-
+import java.util.Objects;
/**
* The interface that apps use to talk to the window manager.
@@ -1950,7 +1950,7 @@
// already have one.
packageName = o.packageName;
}
- if (o.mTitle != null) {
+ if (!Objects.equals(mTitle, o.mTitle) && o.mTitle != null) {
// NOTE: mTitle only copied if the originator set one.
mTitle = o.mTitle;
changes |= TITLE_CHANGED;
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 1530b47..a1cbc1d 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -90,6 +90,13 @@
public static final int RELAYOUT_RES_SURFACE_RESIZED = 0x20;
/**
+ * In multi-window we force show the navigation bar. Because we don't want that the surface size
+ * changes in this mode, we instead have a flag whether the navigation bar size should always be
+ * consumed, so the app is treated like there is no virtual navigation bar at all.
+ */
+ public static final int RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR = 0x40;
+
+ /**
* Flag for relayout: the client will be later giving
* internal insets; as a result, the window will not impact other window
* layouts until the insets are given.
@@ -107,6 +114,11 @@
public static final int ADD_FLAG_APP_VISIBLE = 0x2;
public static final int ADD_FLAG_IN_TOUCH_MODE = RELAYOUT_RES_IN_TOUCH_MODE;
+ /**
+ * Like {@link #RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR}, but as a "hint" when adding the window.
+ */
+ public static final int ADD_FLAG_ALWAYS_CONSUME_NAV_BAR = 0x4;
+
public static final int ADD_OKAY = 0;
public static final int ADD_BAD_APP_TOKEN = -1;
public static final int ADD_BAD_SUBWINDOW_TOKEN = -2;
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 609c471..b011414 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -29,7 +29,9 @@
import android.os.Bundle;
import android.os.IBinder;
import android.os.Looper;
+import android.os.RemoteException;
import android.view.animation.Animation;
+import com.android.internal.policy.IShortcutService;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -121,6 +123,14 @@
public final static int ACTION_PASS_TO_USER = 0x00000001;
/**
+ * Register shortcuts for window manager to dispatch.
+ * Shortcut code is packed as (metaState << Integer.SIZE) | keyCode
+ * @hide
+ */
+ void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)
+ throws RemoteException;
+
+ /**
* Interface to the Window Manager state associated with a particular
* window. You can hold on to an instance of this interface from the call
* to prepareAddWindow() until removeWindow().
@@ -631,7 +641,7 @@
/**
* Return the display width available after excluding any screen
- * decorations that can never be removed. That is, system bar or
+ * decorations that could never be removed in Honeycomb. That is, system bar or
* button bar.
*/
public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation,
@@ -639,7 +649,7 @@
/**
* Return the display height available after excluding any screen
- * decorations that can never be removed. That is, system bar or
+ * decorations that could never be removed in Honeycomb. That is, system bar or
* button bar.
*/
public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation,
@@ -920,9 +930,10 @@
* @param outStableInsets The areas covered by stable system windows irrespective of their
* current visibility. Expressed as positive insets.
* @param outOutsets The areas that are not real display, but we would like to treat as such.
- *
+ * @return Whether to always consume the navigation bar.
+ * See {@link #isNavBarForcedShownLw(WindowState)}.
*/
- public void getInsetHintLw(WindowManager.LayoutParams attrs, int rotation,
+ public boolean getInsetHintLw(WindowManager.LayoutParams attrs, int rotation,
Rect outContentInsets, Rect outStableInsets, Rect outOutsets);
/**
@@ -1350,4 +1361,29 @@
*/
public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
Rect outInsets);
+
+
+ /**
+ * @return true if the navigation bar is forced to stay visible
+ */
+ public boolean isNavBarForcedShownLw(WindowState win);
+
+ /**
+ * Calculates the insets for the areas that could never be removed in Honeycomb, i.e. system
+ * bar or button bar. See {@link #getNonDecorDisplayWidth}.
+ *
+ * @param displayRotation the current display rotation
+ * @param displayWidth the current display width
+ * @param displayHeight the current display height
+ * @param outInsets the insets to return
+ */
+ public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
+ Rect outInsets);
+
+ /**
+ * @return True if a specified {@param dockSide} is allowed on the current device, or false
+ * otherwise. It is guaranteed that at least one dock side for a particular orientation
+ * is allowed, so for example, if DOCKED_RIGHT is not allowed, DOCKED_LEFT is allowed.
+ */
+ public boolean isDockSideAllowed(int dockSide);
}
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
index a75e8a7..ad78b68 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
@@ -64,6 +64,12 @@
*/
public static final int TYPE_ACCESSIBILITY_OVERLAY = 4;
+ /**
+ * Window type: A system window used to divide the screen in split-screen mode.
+ * This type of window is present only in split-screen mode.
+ */
+ public static final int TYPE_SPLIT_SCREEN_DIVIDER = 5;
+
private static final int UNDEFINED = -1;
private static final int BOOLEAN_PROPERTY_ACTIVE = 1 << 0;
@@ -551,6 +557,9 @@
case TYPE_ACCESSIBILITY_OVERLAY: {
return "TYPE_ACCESSIBILITY_OVERLAY";
}
+ case TYPE_SPLIT_SCREEN_DIVIDER: {
+ return "TYPE_SPLIT_SCREEN_DIVIDER";
+ }
default:
return "<UNKNOWN>";
}
diff --git a/core/java/android/view/animation/ClipRectTBAnimation.java b/core/java/android/view/animation/ClipRectTBAnimation.java
deleted file mode 100644
index 06f86ce..0000000
--- a/core/java/android/view/animation/ClipRectTBAnimation.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.animation;
-
-import android.graphics.Rect;
-
-/**
- * Special case of ClipRectAnimation that animates only the top/bottom
- * dimensions of the clip, picking up the other dimensions from whatever is
- * set on the transform already.
- *
- * @hide
- */
-public class ClipRectTBAnimation extends ClipRectAnimation {
-
- /**
- * Constructor. Passes in 0 for Left/Right parameters of ClipRectAnimation
- */
- public ClipRectTBAnimation(int fromT, int fromB, int toT, int toB) {
- super(0, fromT, 0, fromB, 0, toT, 0, toB);
- }
-
- /**
- * Calculates and sets clip rect on given transformation. It uses existing values
- * on the Transformation for Left/Right clip parameters.
- */
- @Override
- protected void applyTransformation(float it, Transformation tr) {
- Rect oldClipRect = tr.getClipRect();
- tr.setClipRect(oldClipRect.left, mFromRect.top + (int) ((mToRect.top - mFromRect.top) * it),
- oldClipRect.right,
- mFromRect.bottom + (int) ((mToRect.bottom - mFromRect.bottom) * it));
- }
-
-}
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index a10f792..6a830f8 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Bundle;
+import android.os.Handler;
import android.os.SystemClock;
import android.text.Editable;
import android.text.NoCopySpan;
@@ -602,6 +603,10 @@
return false;
}
+ public Handler getHandler() {
+ return null;
+ }
+
/**
* The default implementation places the given text into the editable,
* replacing any existing composing text. The new text is marked as
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index eb773e2..2a9706d 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -17,6 +17,7 @@
package android.view.inputmethod;
import android.os.Bundle;
+import android.os.Handler;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
@@ -786,4 +787,15 @@
* {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)}.
*/
public boolean requestCursorUpdates(int cursorUpdateMode);
+
+ /**
+ * Called by the {@link InputMethodManager} to enable application developers to specify a
+ * dedicated {@link Handler} on which incoming IPC method calls from input methods will be
+ * dispatched.
+ *
+ * <p>Note: This does nothing when called from input methods.</p>
+ *
+ * @return {@code null} to use the default {@link Handler}.
+ */
+ public Handler getHandler();
}
diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java
index e5ae422..42d1442 100644
--- a/core/java/android/view/inputmethod/InputConnectionWrapper.java
+++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java
@@ -17,16 +17,26 @@
package android.view.inputmethod;
import android.os.Bundle;
+import android.os.Handler;
import android.view.KeyEvent;
/**
- * <p>Wrapper class for proxying calls to another InputConnection. Subclass
- * and have fun!
+ * <p>Wrapper class for proxying calls to another InputConnection. Subclass and have fun!
*/
public class InputConnectionWrapper implements InputConnection {
private InputConnection mTarget;
final boolean mMutable;
-
+
+ /**
+ * Initializes a wrapper.
+ *
+ * <p><b>Caveat:</b> Although the system can accept {@code (InputConnection) null} in some
+ * places, you cannot emulate such a behavior by non-null {@link InputConnectionWrapper} that
+ * has {@code null} in {@code target}.</p>
+ * @param target the {@link InputConnection} to be proxied.
+ * @param mutable set {@code true} to protect this object from being reconfigured to target
+ * another {@link InputConnection}. Note that this is ignored while the target is {@code null}.
+ */
public InputConnectionWrapper(InputConnection target, boolean mutable) {
mMutable = mutable;
mTarget = target;
@@ -34,6 +44,12 @@
/**
* Change the target of the input connection.
+ *
+ * <p><b>Caveat:</b> Although the system can accept {@code (InputConnection) null} in some
+ * places, you cannot emulate such a behavior by non-null {@link InputConnectionWrapper} that
+ * has {@code null} in {@code target}.</p>
+ * @param target the {@link InputConnection} to be proxied.
+ * @throws SecurityException when this wrapper has non-null target and is immutable.
*/
public void setTarget(InputConnection target) {
if (mTarget != null && !mMutable) {
@@ -41,96 +57,196 @@
}
mTarget = target;
}
-
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public CharSequence getTextBeforeCursor(int n, int flags) {
return mTarget.getTextBeforeCursor(n, flags);
}
-
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public CharSequence getTextAfterCursor(int n, int flags) {
return mTarget.getTextAfterCursor(n, flags);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public CharSequence getSelectedText(int flags) {
return mTarget.getSelectedText(flags);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public int getCursorCapsMode(int reqModes) {
return mTarget.getCursorCapsMode(reqModes);
}
-
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
return mTarget.getExtractedText(request, flags);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean deleteSurroundingTextInCodePoints(int beforeLength, int afterLength) {
return mTarget.deleteSurroundingTextInCodePoints(beforeLength, afterLength);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
return mTarget.deleteSurroundingText(beforeLength, afterLength);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean setComposingText(CharSequence text, int newCursorPosition) {
return mTarget.setComposingText(text, newCursorPosition);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean setComposingRegion(int start, int end) {
return mTarget.setComposingRegion(start, end);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean finishComposingText() {
return mTarget.finishComposingText();
}
-
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean commitText(CharSequence text, int newCursorPosition) {
return mTarget.commitText(text, newCursorPosition);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean commitCompletion(CompletionInfo text) {
return mTarget.commitCompletion(text);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean commitCorrection(CorrectionInfo correctionInfo) {
return mTarget.commitCorrection(correctionInfo);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean setSelection(int start, int end) {
return mTarget.setSelection(start, end);
}
-
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean performEditorAction(int editorAction) {
return mTarget.performEditorAction(editorAction);
}
-
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean performContextMenuAction(int id) {
return mTarget.performContextMenuAction(id);
}
-
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean beginBatchEdit() {
return mTarget.beginBatchEdit();
}
-
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean endBatchEdit() {
return mTarget.endBatchEdit();
}
-
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean sendKeyEvent(KeyEvent event) {
return mTarget.sendKeyEvent(event);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean clearMetaKeyStates(int states) {
return mTarget.clearMetaKeyStates(states);
}
-
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean reportFullscreenMode(boolean enabled) {
return mTarget.reportFullscreenMode(enabled);
}
-
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean performPrivateCommand(String action, Bundle data) {
return mTarget.performPrivateCommand(action, data);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean requestCursorUpdates(int cursorUpdateMode) {
return mTarget.requestCursorUpdates(cursorUpdateMode);
}
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
+ public Handler getHandler() {
+ return mTarget.getHandler();
+ }
}
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index d97f8af..281babe 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -428,18 +428,6 @@
}
}
- /**
- * @return {@code true} if the {@link android.inputmethodservice.InputMethodService} is marked
- * to be Encryption-Aware.
- * @hide
- */
- public boolean isEncryptionAware() {
- if (mService == null || mService.serviceInfo == null) {
- return false;
- }
- return mService.serviceInfo.encryptionAware;
- }
-
public void dump(Printer pw, String prefix) {
pw.println(prefix + "mId=" + mId
+ " mSettingsActivityName=" + mSettingsActivityName
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 0ed2299..859df43 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -664,7 +664,7 @@
try {
return mService.getInputMethodList();
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -672,7 +672,7 @@
try {
return mService.getEnabledInputMethodList();
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -689,7 +689,7 @@
return mService.getEnabledInputMethodSubtypeList(
imi == null ? null : imi.getId(), allowsImplicitlySelectedSubtypes);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -697,7 +697,7 @@
try {
mService.updateStatusIcon(imeToken, packageName, iconId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -705,7 +705,7 @@
try {
mService.updateStatusIcon(imeToken, null, 0);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -714,7 +714,7 @@
try {
mService.setImeWindowStatus(imeToken, vis, backDisposition);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -728,7 +728,7 @@
try {
mService.registerSuggestionSpansForNotification(spans);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -737,7 +737,7 @@
try {
mService.notifySuggestionPicked(span, originalString, index);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -833,6 +833,7 @@
try {
mService.finishInput(mClient);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
notifyInputConnectionFinished();
@@ -996,9 +997,8 @@
try {
return mService.showSoftInput(mClient, flags, resultReceiver);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
-
- return false;
}
}
@@ -1007,6 +1007,7 @@
try {
mService.showSoftInput(mClient, flags, resultReceiver);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1065,8 +1066,8 @@
try {
return mService.hideSoftInput(mClient, flags, resultReceiver);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return false;
}
}
@@ -1215,7 +1216,7 @@
if (mCurrentTextBoxAttribute == null) {
controlFlags |= CONTROL_START_INITIAL;
}
-
+
// Hook 'em up and let 'er rip.
mCurrentTextBoxAttribute = tba;
mServedConnecting = false;
@@ -1230,7 +1231,9 @@
mCursorCandEnd = -1;
mCursorRect.setEmpty();
mCursorAnchorInfo = null;
- servedContext = new ControlledInputConnectionWrapper(vh.getLooper(), ic, this);
+ final Handler icHandler = ic.getHandler();
+ servedContext = new ControlledInputConnectionWrapper(
+ icHandler != null ? icHandler.getLooper() : vh.getLooper(), ic, this);
} else {
servedContext = null;
}
@@ -1238,20 +1241,14 @@
mServedInputConnectionWrapper.deactivate();
}
mServedInputConnectionWrapper = servedContext;
-
+
try {
if (DEBUG) Log.v(TAG, "START INPUT: " + view + " ic="
+ ic + " tba=" + tba + " controlFlags=#"
+ Integer.toHexString(controlFlags));
- InputBindResult res;
- if (windowGainingFocus != null) {
- res = mService.windowGainedFocus(startInputReason, mClient, windowGainingFocus,
- controlFlags, softInputMode, windowFlags,
- tba, servedContext);
- } else {
- res = mService.startInput(startInputReason, mClient,
- servedContext, tba, controlFlags);
- }
+ final InputBindResult res = mService.startInputOrWindowGainedFocus(
+ startInputReason, mClient, windowGainingFocus, controlFlags, softInputMode,
+ windowFlags, tba, servedContext);
if (DEBUG) Log.v(TAG, "Starting input: Bind result=" + res);
if (res != null) {
if (res.id != null) {
@@ -1425,6 +1422,7 @@
try {
mService.hideSoftInput(mClient, HIDE_NOT_ALWAYS, null);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1469,17 +1467,18 @@
return;
}
}
-
+
// For some reason we didn't do a startInput + windowFocusGain, so
// we'll just do a window focus gain and call it a day.
synchronized (mH) {
try {
if (DEBUG) Log.v(TAG, "Reporting focus gain, without startInput");
- mService.windowGainedFocus(
+ mService.startInputOrWindowGainedFocus(
InputMethodClient.START_INPUT_REASON_WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient,
rootView.getWindowToken(), controlFlags, softInputMode, windowFlags, null,
null);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1720,7 +1719,7 @@
try {
mService.setInputMethod(token, id);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1737,7 +1736,7 @@
try {
mService.setInputMethodAndSubtype(token, id, subtype);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1757,7 +1756,7 @@
try {
mService.hideMySoftInput(token, flags);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1778,7 +1777,7 @@
try {
mService.showMySoftInput(token, flags);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1984,7 +1983,7 @@
SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES;
mService.showInputMethodPickerFromClient(mClient, mode);
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1993,7 +1992,7 @@
try {
mService.showInputMethodPickerFromClient(mClient, SHOW_IM_PICKER_MODE_AUTO);
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2007,7 +2006,7 @@
try {
mService.showInputMethodAndSubtypeEnablerFromClient(mClient, imiId);
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2022,8 +2021,7 @@
try {
return mService.getCurrentInputMethodSubtype();
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
- return null;
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2040,8 +2038,7 @@
try {
return mService.setCurrentInputMethodSubtype(subtype);
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2075,7 +2072,7 @@
mLastSentUserActionNotificationSequenceNumber =
mNextUserActionNotificationSequenceNumber;
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2108,7 +2105,7 @@
}
}
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
+ throw e.rethrowFromSystemServer();
}
return ret;
}
@@ -2123,8 +2120,7 @@
try {
return mService.getInputMethodWindowVisibleHeight();
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
- return 0;
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2143,8 +2139,7 @@
try {
return mService.switchToLastInputMethod(imeToken);
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2164,8 +2159,7 @@
try {
return mService.switchToNextInputMethod(imeToken, onlyCurrentIme);
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2186,8 +2180,7 @@
try {
return mService.shouldOfferSwitchingToNextInputMethod(imeToken);
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2222,7 +2215,7 @@
try {
mService.setAdditionalInputMethodSubtypes(imiId, subtypes);
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2232,8 +2225,7 @@
try {
return mService.getLastInputMethodSubtype();
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
- return null;
+ throw e.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/webkit/IWebViewUpdateService.aidl b/core/java/android/webkit/IWebViewUpdateService.aidl
index 89d5d69..5697dfc 100644
--- a/core/java/android/webkit/IWebViewUpdateService.aidl
+++ b/core/java/android/webkit/IWebViewUpdateService.aidl
@@ -38,10 +38,14 @@
WebViewProviderResponse waitForAndGetProvider();
/**
- * DevelopmentSettings uses this to notify WebViewUpdateService that a
- * new provider has been selected by the user.
+ * DevelopmentSettings uses this to notify WebViewUpdateService that a new provider has been
+ * selected by the user. Returns the provider we end up switching to, this could be different to
+ * the one passed as argument to this method since the Dev Setting calling this method could be
+ * stale. I.e. the Dev setting could be letting the user choose uninstalled/disabled packages,
+ * it would then try to update the provider to such a package while in reality the update
+ * service would switch to another one.
*/
- void changeProviderAndSetting(String newProvider);
+ String changeProviderAndSetting(String newProvider);
/**
* DevelopmentSettings uses this to get the current available WebView
@@ -53,4 +57,15 @@
* Used by DevelopmentSetting to get the name of the WebView provider currently in use.
*/
String getCurrentWebViewPackageName();
+
+ /**
+ * Used by Settings to determine whether a certain package can be enabled/disabled by the user -
+ * the package should not be modifiable in this way if it is a fallback package.
+ */
+ boolean isFallbackPackage(String packageName);
+
+ /**
+ * Enable or disable the WebView package fallback mechanism.
+ */
+ void enableFallbackLogic(boolean enable);
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 0f58ba3..2eb258f 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -39,6 +39,7 @@
import android.security.KeyChain;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.DragEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
@@ -287,11 +288,11 @@
* helps Google improve WebView. Data is collected on a per-app basis for each app which has
* instantiated a WebView. An individual app can opt out of this feature by putting the following
* tag in its manifest:
- * </p>
* <pre>
- * <meta-data android:name="android.webkit.WebView.MetricsOptOut"
- * android:value="true" />
+ * <meta-data android:name="android.webkit.WebView.MetricsOptOut"
+ * android:value="true" />
* </pre>
+ * </p>
* <p>
* Data will only be uploaded for a given app if the user has consented AND the app has not opted
* out.
@@ -2528,6 +2529,11 @@
}
@Override
+ public boolean onDragEvent(DragEvent event) {
+ return mProvider.getViewDelegate().onDragEvent(event);
+ }
+
+ @Override
protected void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
// This method may be called in the constructor chain, before the WebView provider is
diff --git a/core/java/android/webkit/WebViewDelegate.java b/core/java/android/webkit/WebViewDelegate.java
index 23af384..94dc03c 100644
--- a/core/java/android/webkit/WebViewDelegate.java
+++ b/core/java/android/webkit/WebViewDelegate.java
@@ -156,7 +156,7 @@
* Adds the WebView asset path to {@link android.content.res.AssetManager}.
*/
public void addWebViewAssetPath(Context context) {
- context.getAssets().addAssetPath(
+ context.getAssets().addAssetPathAsSharedLibrary(
WebViewFactory.getLoadedPackageInfo().applicationInfo.sourceDir);
}
}
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index b04b4c0..ad50ff6 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -21,6 +21,7 @@
import android.app.AppGlobals;
import android.app.Application;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -134,6 +135,7 @@
// Whether or not the provider must be explicitly chosen by the user to be used.
private static String TAG_AVAILABILITY = "availableByDefault";
private static String TAG_SIGNATURE = "signature";
+ private static String TAG_FALLBACK = "isFallback";
/**
* Reads all signatures at the current depth (within the current provider) from the XML parser.
@@ -159,6 +161,7 @@
* @hide
* */
public static WebViewProviderInfo[] getWebViewPackages() {
+ int numFallbackPackages = 0;
XmlResourceParser parser = null;
List<WebViewProviderInfo> webViewProviders = new ArrayList<WebViewProviderInfo>();
try {
@@ -182,13 +185,21 @@
throw new MissingWebViewPackageException(
"WebView provider in framework resources missing description");
}
- String availableByDefault = parser.getAttributeValue(null, TAG_AVAILABILITY);
- if (availableByDefault == null) {
- availableByDefault = "false";
- }
- webViewProviders.add(
+ boolean availableByDefault = "true".equals(
+ parser.getAttributeValue(null, TAG_AVAILABILITY));
+ boolean isFallback = "true".equals(
+ parser.getAttributeValue(null, TAG_FALLBACK));
+ WebViewProviderInfo currentProvider =
new WebViewProviderInfo(packageName, description, availableByDefault,
- readSignatures(parser)));
+ isFallback, readSignatures(parser));
+ if (currentProvider.isFallbackPackage()) {
+ numFallbackPackages++;
+ if (numFallbackPackages > 1) {
+ throw new AndroidRuntimeException(
+ "There can be at most one webview fallback package.");
+ }
+ }
+ webViewProviders.add(currentProvider);
}
else {
Log.e(LOGTAG, "Found an element that is not a webview provider");
@@ -641,6 +652,18 @@
return result;
}
+ /**
+ * Returns whether the entire package from an ACTION_PACKAGE_CHANGED intent was changed (rather
+ * than just one of its components).
+ * @hide
+ */
+ public static boolean entirePackageChanged(Intent intent) {
+ String[] componentList =
+ intent.getStringArrayExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
+ return Arrays.asList(componentList).contains(
+ intent.getDataString().substring("package:".length()));
+ }
+
private static IWebViewUpdateService getUpdateService() {
return IWebViewUpdateService.Stub.asInterface(ServiceManager.getService("webviewupdate"));
}
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 3ce034c..94d231c 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -30,6 +30,7 @@
import android.os.Bundle;
import android.os.Message;
import android.print.PrintDocumentAdapter;
+import android.view.DragEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
@@ -334,6 +335,8 @@
public InputConnection onCreateInputConnection(EditorInfo outAttrs);
+ public boolean onDragEvent(DragEvent event);
+
public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event);
public boolean onKeyDown(int keyCode, KeyEvent event);
diff --git a/core/java/android/webkit/WebViewProviderInfo.java b/core/java/android/webkit/WebViewProviderInfo.java
index 94e8b70..64c2caa 100644
--- a/core/java/android/webkit/WebViewProviderInfo.java
+++ b/core/java/android/webkit/WebViewProviderInfo.java
@@ -40,11 +40,12 @@
public WebViewPackageNotFoundException(Exception e) { super(e); }
}
- public WebViewProviderInfo(String packageName, String description, String availableByDefault,
- String[] signatures) {
+ public WebViewProviderInfo(String packageName, String description, boolean availableByDefault,
+ boolean isFallback, String[] signatures) {
this.packageName = packageName;
this.description = description;
- this.availableByDefault = availableByDefault.equals("true");
+ this.availableByDefault = availableByDefault;
+ this.isFallback = isFallback;
this.signatures = signatures;
}
@@ -114,6 +115,10 @@
return availableByDefault;
}
+ public boolean isFallbackPackage() {
+ return isFallback;
+ }
+
private void updatePackageInfo() {
try {
PackageManager pm = AppGlobals.getInitialApplication().getPackageManager();
@@ -165,6 +170,7 @@
public String packageName;
public String description;
private boolean availableByDefault;
+ private boolean isFallback;
private String[] signatures;
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index b689564..d2aef0a 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -28,6 +28,7 @@
import android.graphics.drawable.TransitionDrawable;
import android.os.Bundle;
import android.os.Debug;
+import android.os.Handler;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.StrictMode;
@@ -3077,7 +3078,8 @@
final int motionPosition = mClickMotionPosition;
if (adapter != null && mItemCount > 0 &&
motionPosition != INVALID_POSITION &&
- motionPosition < adapter.getCount() && sameWindow()) {
+ motionPosition < adapter.getCount() && sameWindow() &&
+ adapter.isEnabled(motionPosition)) {
final View view = getChildAt(motionPosition - mFirstPosition);
// If there is no view, something bad happened (the view scrolled off the
// screen, etc.) and we should cancel the click
@@ -5930,6 +5932,11 @@
public boolean requestCursorUpdates(int cursorUpdateMode) {
return getTarget().requestCursorUpdates(cursorUpdateMode);
}
+
+ @Override
+ public Handler getHandler() {
+ return getTarget().getHandler();
+ }
}
/**
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index 9a68593..34f3a47 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -694,7 +694,7 @@
final int halfH = h >= 0 ? h / 2 : 1;
mTickMark.setBounds(-halfW, -halfH, halfW, halfH);
- final int spacing = (getWidth() - mPaddingLeft - mPaddingRight) / count;
+ final float spacing = (getWidth() - mPaddingLeft - mPaddingRight) / (float) count;
final int saveCount = canvas.save();
canvas.translate(mPaddingLeft, getHeight() / 2);
for (int i = 0; i <= count; i++) {
diff --git a/core/java/android/widget/Chronometer.java b/core/java/android/widget/Chronometer.java
index 4d707e3..3421790 100644
--- a/core/java/android/widget/Chronometer.java
+++ b/core/java/android/widget/Chronometer.java
@@ -19,15 +19,14 @@
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
-import android.os.Handler;
-import android.os.Message;
import android.os.SystemClock;
import android.text.format.DateUtils;
import android.util.AttributeSet;
import android.util.Log;
-import android.view.accessibility.AccessibilityEvent;
import android.widget.RemoteViews.RemoteView;
+import com.android.internal.R;
+
import java.util.Formatter;
import java.util.IllegalFormatException;
import java.util.Locale;
@@ -37,11 +36,17 @@
* <p>
* You can give it a start time in the {@link SystemClock#elapsedRealtime} timebase,
* and it counts up from that, or if you don't give it a base time, it will use the
- * time at which you call {@link #start}. By default it will display the current
+ * time at which you call {@link #start}.
+ *
+ * <p>The timer can also count downward towards the base time by
+ * setting {@link #setCountDown(boolean)} to true.
+ *
+ * <p>By default it will display the current
* timer value in the form "MM:SS" or "H:MM:SS", or you can use {@link #setFormat}
* to format the timer value into an arbitrary string.
*
* @attr ref android.R.styleable#Chronometer_format
+ * @attr ref android.R.styleable#Chronometer_countDown
*/
@RemoteView
public class Chronometer extends TextView {
@@ -72,6 +77,7 @@
private StringBuilder mFormatBuilder;
private OnChronometerTickListener mOnChronometerTickListener;
private StringBuilder mRecycle = new StringBuilder(8);
+ private boolean mCountDown;
/**
* Initialize this Chronometer object.
@@ -102,7 +108,8 @@
final TypedArray a = context.obtainStyledAttributes(
attrs, com.android.internal.R.styleable.Chronometer, defStyleAttr, defStyleRes);
- setFormat(a.getString(com.android.internal.R.styleable.Chronometer_format));
+ setFormat(a.getString(R.styleable.Chronometer_format));
+ setCountDown(a.getBoolean(R.styleable.Chronometer_countDown, false));
a.recycle();
init();
@@ -114,6 +121,27 @@
}
/**
+ * Set this view to count down to the base instead of counting up from it.
+ *
+ * @param countDown whether this view should count down
+ *
+ * @see #setBase(long)
+ */
+ @android.view.RemotableViewMethod
+ public void setCountDown(boolean countDown) {
+ mCountDown = countDown;
+ }
+
+ /**
+ * @return whether this view counts down
+ *
+ * @see #setCountDown(boolean)
+ */
+ public boolean isCountDown() {
+ return mCountDown;
+ }
+
+ /**
* Set the time that the count-up timer is in reference to.
*
* @param base Use the {@link SystemClock#elapsedRealtime} time base.
@@ -226,9 +254,17 @@
private synchronized void updateText(long now) {
mNow = now;
- long seconds = now - mBase;
+ long seconds = mCountDown ? mBase - now : now - mBase;
seconds /= 1000;
+ boolean negative = false;
+ if (seconds < 0) {
+ seconds = -seconds;
+ negative = true;
+ }
String text = DateUtils.formatElapsedTime(mRecycle, seconds);
+ if (negative) {
+ text = getResources().getString(R.string.negative_duration, text);
+ }
if (mFormat != null) {
Locale loc = Locale.getDefault();
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 87bee44..6e3dbd8 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -23,32 +23,17 @@
import android.content.res.TypedArray;
import android.os.Parcel;
import android.os.Parcelable;
-import android.text.TextUtils;
-import android.text.InputType;
-import android.text.format.DateFormat;
-import android.text.format.DateUtils;
import android.util.AttributeSet;
-import android.util.Log;
import android.util.SparseArray;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.NumberPicker.OnValueChangeListener;
import com.android.internal.R;
-import java.text.DateFormatSymbols;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Arrays;
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;
-import libcore.icu.ICU;
-
/**
* Provides a widget for selecting a date.
* <p>
@@ -527,6 +512,114 @@
protected void onLocaleChanged(Locale locale) {
// Stub.
}
+
+ /**
+ * Class for managing state storing/restoring.
+ */
+ static class SavedState extends View.BaseSavedState {
+ private final int mSelectedYear;
+ private final int mSelectedMonth;
+ private final int mSelectedDay;
+ private final long mMinDate;
+ private final long mMaxDate;
+ private final int mCurrentView;
+ private final int mListPosition;
+ private final int mListPositionOffset;
+
+ public SavedState(Parcelable superState, int year, int month, int day, long minDate,
+ long maxDate) {
+ this(superState, year, month, day, minDate, maxDate, 0, 0, 0);
+ }
+
+ /**
+ * Constructor called from {@link DatePicker#onSaveInstanceState()}
+ */
+ public SavedState(Parcelable superState, int year, int month, int day, long minDate,
+ long maxDate, int currentView, int listPosition, int listPositionOffset) {
+ super(superState);
+ mSelectedYear = year;
+ mSelectedMonth = month;
+ mSelectedDay = day;
+ mMinDate = minDate;
+ mMaxDate = maxDate;
+ mCurrentView = currentView;
+ mListPosition = listPosition;
+ mListPositionOffset = listPositionOffset;
+ }
+
+ /**
+ * Constructor called from {@link #CREATOR}
+ */
+ private SavedState(Parcel in) {
+ super(in);
+ mSelectedYear = in.readInt();
+ mSelectedMonth = in.readInt();
+ mSelectedDay = in.readInt();
+ mMinDate = in.readLong();
+ mMaxDate = in.readLong();
+ mCurrentView = in.readInt();
+ mListPosition = in.readInt();
+ mListPositionOffset = in.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(mSelectedYear);
+ dest.writeInt(mSelectedMonth);
+ dest.writeInt(mSelectedDay);
+ dest.writeLong(mMinDate);
+ dest.writeLong(mMaxDate);
+ dest.writeInt(mCurrentView);
+ dest.writeInt(mListPosition);
+ dest.writeInt(mListPositionOffset);
+ }
+
+ public int getSelectedDay() {
+ return mSelectedDay;
+ }
+
+ public int getSelectedMonth() {
+ return mSelectedMonth;
+ }
+
+ public int getSelectedYear() {
+ return mSelectedYear;
+ }
+
+ public long getMinDate() {
+ return mMinDate;
+ }
+
+ public long getMaxDate() {
+ return mMaxDate;
+ }
+
+ public int getCurrentView() {
+ return mCurrentView;
+ }
+
+ public int getListPosition() {
+ return mListPosition;
+ }
+
+ public int getListPositionOffset() {
+ return mListPositionOffset;
+ }
+
+ @SuppressWarnings("all")
+ // suppress unused and hiding
+ public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {
+
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
}
/**
@@ -535,666 +628,7 @@
*
* @hide
*/
- public static interface ValidationCallback {
+ public interface ValidationCallback {
void onValidationChanged(boolean valid);
}
-
- /**
- * A delegate implementing the basic DatePicker
- */
- private static class DatePickerSpinnerDelegate extends AbstractDatePickerDelegate {
-
- private static final String DATE_FORMAT = "MM/dd/yyyy";
-
- private static final int DEFAULT_START_YEAR = 1900;
-
- private static final int DEFAULT_END_YEAR = 2100;
-
- private static final boolean DEFAULT_CALENDAR_VIEW_SHOWN = true;
-
- private static final boolean DEFAULT_SPINNERS_SHOWN = true;
-
- private static final boolean DEFAULT_ENABLED_STATE = true;
-
- private final LinearLayout mSpinners;
-
- private final NumberPicker mDaySpinner;
-
- private final NumberPicker mMonthSpinner;
-
- private final NumberPicker mYearSpinner;
-
- private final EditText mDaySpinnerInput;
-
- private final EditText mMonthSpinnerInput;
-
- private final EditText mYearSpinnerInput;
-
- private final CalendarView mCalendarView;
-
- private String[] mShortMonths;
-
- private final java.text.DateFormat mDateFormat = new SimpleDateFormat(DATE_FORMAT);
-
- private int mNumberOfMonths;
-
- private Calendar mTempDate;
-
- private Calendar mMinDate;
-
- private Calendar mMaxDate;
-
- private Calendar mCurrentDate;
-
- private boolean mIsEnabled = DEFAULT_ENABLED_STATE;
-
- DatePickerSpinnerDelegate(DatePicker delegator, Context context, AttributeSet attrs,
- int defStyleAttr, int defStyleRes) {
- super(delegator, context);
-
- mDelegator = delegator;
- mContext = context;
-
- // initialization based on locale
- setCurrentLocale(Locale.getDefault());
-
- final TypedArray attributesArray = context.obtainStyledAttributes(attrs,
- R.styleable.DatePicker, defStyleAttr, defStyleRes);
- boolean spinnersShown = attributesArray.getBoolean(R.styleable.DatePicker_spinnersShown,
- DEFAULT_SPINNERS_SHOWN);
- boolean calendarViewShown = attributesArray.getBoolean(
- R.styleable.DatePicker_calendarViewShown, DEFAULT_CALENDAR_VIEW_SHOWN);
- int startYear = attributesArray.getInt(R.styleable.DatePicker_startYear,
- DEFAULT_START_YEAR);
- int endYear = attributesArray.getInt(R.styleable.DatePicker_endYear, DEFAULT_END_YEAR);
- String minDate = attributesArray.getString(R.styleable.DatePicker_minDate);
- String maxDate = attributesArray.getString(R.styleable.DatePicker_maxDate);
- int layoutResourceId = attributesArray.getResourceId(
- R.styleable.DatePicker_legacyLayout, R.layout.date_picker_legacy);
- attributesArray.recycle();
-
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- inflater.inflate(layoutResourceId, mDelegator, true);
-
- OnValueChangeListener onChangeListener = new OnValueChangeListener() {
- public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
- updateInputState();
- mTempDate.setTimeInMillis(mCurrentDate.getTimeInMillis());
- // take care of wrapping of days and months to update greater fields
- if (picker == mDaySpinner) {
- int maxDayOfMonth = mTempDate.getActualMaximum(Calendar.DAY_OF_MONTH);
- if (oldVal == maxDayOfMonth && newVal == 1) {
- mTempDate.add(Calendar.DAY_OF_MONTH, 1);
- } else if (oldVal == 1 && newVal == maxDayOfMonth) {
- mTempDate.add(Calendar.DAY_OF_MONTH, -1);
- } else {
- mTempDate.add(Calendar.DAY_OF_MONTH, newVal - oldVal);
- }
- } else if (picker == mMonthSpinner) {
- if (oldVal == 11 && newVal == 0) {
- mTempDate.add(Calendar.MONTH, 1);
- } else if (oldVal == 0 && newVal == 11) {
- mTempDate.add(Calendar.MONTH, -1);
- } else {
- mTempDate.add(Calendar.MONTH, newVal - oldVal);
- }
- } else if (picker == mYearSpinner) {
- mTempDate.set(Calendar.YEAR, newVal);
- } else {
- throw new IllegalArgumentException();
- }
- // now set the date to the adjusted one
- setDate(mTempDate.get(Calendar.YEAR), mTempDate.get(Calendar.MONTH),
- mTempDate.get(Calendar.DAY_OF_MONTH));
- updateSpinners();
- updateCalendarView();
- notifyDateChanged();
- }
- };
-
- mSpinners = (LinearLayout) mDelegator.findViewById(R.id.pickers);
-
- // calendar view day-picker
- mCalendarView = (CalendarView) mDelegator.findViewById(R.id.calendar_view);
- mCalendarView.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
- public void onSelectedDayChange(CalendarView view, int year, int month, int monthDay) {
- setDate(year, month, monthDay);
- updateSpinners();
- notifyDateChanged();
- }
- });
-
- // day
- mDaySpinner = (NumberPicker) mDelegator.findViewById(R.id.day);
- mDaySpinner.setFormatter(NumberPicker.getTwoDigitFormatter());
- mDaySpinner.setOnLongPressUpdateInterval(100);
- mDaySpinner.setOnValueChangedListener(onChangeListener);
- mDaySpinnerInput = (EditText) mDaySpinner.findViewById(R.id.numberpicker_input);
-
- // month
- mMonthSpinner = (NumberPicker) mDelegator.findViewById(R.id.month);
- mMonthSpinner.setMinValue(0);
- mMonthSpinner.setMaxValue(mNumberOfMonths - 1);
- mMonthSpinner.setDisplayedValues(mShortMonths);
- mMonthSpinner.setOnLongPressUpdateInterval(200);
- mMonthSpinner.setOnValueChangedListener(onChangeListener);
- mMonthSpinnerInput = (EditText) mMonthSpinner.findViewById(R.id.numberpicker_input);
-
- // year
- mYearSpinner = (NumberPicker) mDelegator.findViewById(R.id.year);
- mYearSpinner.setOnLongPressUpdateInterval(100);
- mYearSpinner.setOnValueChangedListener(onChangeListener);
- mYearSpinnerInput = (EditText) mYearSpinner.findViewById(R.id.numberpicker_input);
-
- // show only what the user required but make sure we
- // show something and the spinners have higher priority
- if (!spinnersShown && !calendarViewShown) {
- setSpinnersShown(true);
- } else {
- setSpinnersShown(spinnersShown);
- setCalendarViewShown(calendarViewShown);
- }
-
- // set the min date giving priority of the minDate over startYear
- mTempDate.clear();
- if (!TextUtils.isEmpty(minDate)) {
- if (!parseDate(minDate, mTempDate)) {
- mTempDate.set(startYear, 0, 1);
- }
- } else {
- mTempDate.set(startYear, 0, 1);
- }
- setMinDate(mTempDate.getTimeInMillis());
-
- // set the max date giving priority of the maxDate over endYear
- mTempDate.clear();
- if (!TextUtils.isEmpty(maxDate)) {
- if (!parseDate(maxDate, mTempDate)) {
- mTempDate.set(endYear, 11, 31);
- }
- } else {
- mTempDate.set(endYear, 11, 31);
- }
- setMaxDate(mTempDate.getTimeInMillis());
-
- // initialize to current date
- mCurrentDate.setTimeInMillis(System.currentTimeMillis());
- init(mCurrentDate.get(Calendar.YEAR), mCurrentDate.get(Calendar.MONTH), mCurrentDate
- .get(Calendar.DAY_OF_MONTH), null);
-
- // re-order the number spinners to match the current date format
- reorderSpinners();
-
- // accessibility
- setContentDescriptions();
-
- // If not explicitly specified this view is important for accessibility.
- if (mDelegator.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
- mDelegator.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
- }
- }
-
- @Override
- public void init(int year, int monthOfYear, int dayOfMonth,
- OnDateChangedListener onDateChangedListener) {
- setDate(year, monthOfYear, dayOfMonth);
- updateSpinners();
- updateCalendarView();
- mOnDateChangedListener = onDateChangedListener;
- }
-
- @Override
- public void updateDate(int year, int month, int dayOfMonth) {
- if (!isNewDate(year, month, dayOfMonth)) {
- return;
- }
- setDate(year, month, dayOfMonth);
- updateSpinners();
- updateCalendarView();
- notifyDateChanged();
- }
-
- @Override
- public int getYear() {
- return mCurrentDate.get(Calendar.YEAR);
- }
-
- @Override
- public int getMonth() {
- return mCurrentDate.get(Calendar.MONTH);
- }
-
- @Override
- public int getDayOfMonth() {
- return mCurrentDate.get(Calendar.DAY_OF_MONTH);
- }
-
- @Override
- public void setFirstDayOfWeek(int firstDayOfWeek) {
- mCalendarView.setFirstDayOfWeek(firstDayOfWeek);
- }
-
- @Override
- public int getFirstDayOfWeek() {
- return mCalendarView.getFirstDayOfWeek();
- }
-
- @Override
- public void setMinDate(long minDate) {
- mTempDate.setTimeInMillis(minDate);
- if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)
- && mTempDate.get(Calendar.DAY_OF_YEAR) != mMinDate.get(Calendar.DAY_OF_YEAR)) {
- return;
- }
- mMinDate.setTimeInMillis(minDate);
- mCalendarView.setMinDate(minDate);
- if (mCurrentDate.before(mMinDate)) {
- mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
- updateCalendarView();
- }
- updateSpinners();
- }
-
- @Override
- public Calendar getMinDate() {
- final Calendar minDate = Calendar.getInstance();
- minDate.setTimeInMillis(mCalendarView.getMinDate());
- return minDate;
- }
-
- @Override
- public void setMaxDate(long maxDate) {
- mTempDate.setTimeInMillis(maxDate);
- if (mTempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR)
- && mTempDate.get(Calendar.DAY_OF_YEAR) != mMaxDate.get(Calendar.DAY_OF_YEAR)) {
- return;
- }
- mMaxDate.setTimeInMillis(maxDate);
- mCalendarView.setMaxDate(maxDate);
- if (mCurrentDate.after(mMaxDate)) {
- mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
- updateCalendarView();
- }
- updateSpinners();
- }
-
- @Override
- public Calendar getMaxDate() {
- final Calendar maxDate = Calendar.getInstance();
- maxDate.setTimeInMillis(mCalendarView.getMaxDate());
- return maxDate;
- }
-
- @Override
- public void setEnabled(boolean enabled) {
- mDaySpinner.setEnabled(enabled);
- mMonthSpinner.setEnabled(enabled);
- mYearSpinner.setEnabled(enabled);
- mCalendarView.setEnabled(enabled);
- mIsEnabled = enabled;
- }
-
- @Override
- public boolean isEnabled() {
- return mIsEnabled;
- }
-
- @Override
- public CalendarView getCalendarView() {
- return mCalendarView;
- }
-
- @Override
- public void setCalendarViewShown(boolean shown) {
- mCalendarView.setVisibility(shown ? VISIBLE : GONE);
- }
-
- @Override
- public boolean getCalendarViewShown() {
- return (mCalendarView.getVisibility() == View.VISIBLE);
- }
-
- @Override
- public void setSpinnersShown(boolean shown) {
- mSpinners.setVisibility(shown ? VISIBLE : GONE);
- }
-
- @Override
- public boolean getSpinnersShown() {
- return mSpinners.isShown();
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- setCurrentLocale(newConfig.locale);
- }
-
- @Override
- public Parcelable onSaveInstanceState(Parcelable superState) {
- return new SavedState(superState, getYear(), getMonth(), getDayOfMonth());
- }
-
- @Override
- public void onRestoreInstanceState(Parcelable state) {
- SavedState ss = (SavedState) state;
- setDate(ss.mYear, ss.mMonth, ss.mDay);
- updateSpinners();
- updateCalendarView();
- }
-
- @Override
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- onPopulateAccessibilityEvent(event);
- return true;
- }
-
- @Override
- public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
- final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR;
- String selectedDateUtterance = DateUtils.formatDateTime(mContext,
- mCurrentDate.getTimeInMillis(), flags);
- event.getText().add(selectedDateUtterance);
- }
-
- /**
- * Sets the current locale.
- *
- * @param locale The current locale.
- */
- @Override
- protected void setCurrentLocale(Locale locale) {
- super.setCurrentLocale(locale);
-
- mTempDate = getCalendarForLocale(mTempDate, locale);
- mMinDate = getCalendarForLocale(mMinDate, locale);
- mMaxDate = getCalendarForLocale(mMaxDate, locale);
- mCurrentDate = getCalendarForLocale(mCurrentDate, locale);
-
- mNumberOfMonths = mTempDate.getActualMaximum(Calendar.MONTH) + 1;
- mShortMonths = new DateFormatSymbols().getShortMonths();
-
- if (usingNumericMonths()) {
- // We're in a locale where a date should either be all-numeric, or all-text.
- // All-text would require custom NumberPicker formatters for day and year.
- mShortMonths = new String[mNumberOfMonths];
- for (int i = 0; i < mNumberOfMonths; ++i) {
- mShortMonths[i] = String.format("%d", i + 1);
- }
- }
- }
-
- /**
- * Tests whether the current locale is one where there are no real month names,
- * such as Chinese, Japanese, or Korean locales.
- */
- private boolean usingNumericMonths() {
- return Character.isDigit(mShortMonths[Calendar.JANUARY].charAt(0));
- }
-
- /**
- * Gets a calendar for locale bootstrapped with the value of a given calendar.
- *
- * @param oldCalendar The old calendar.
- * @param locale The locale.
- */
- private Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) {
- if (oldCalendar == null) {
- return Calendar.getInstance(locale);
- } else {
- final long currentTimeMillis = oldCalendar.getTimeInMillis();
- Calendar newCalendar = Calendar.getInstance(locale);
- newCalendar.setTimeInMillis(currentTimeMillis);
- return newCalendar;
- }
- }
-
- /**
- * Reorders the spinners according to the date format that is
- * explicitly set by the user and if no such is set fall back
- * to the current locale's default format.
- */
- private void reorderSpinners() {
- mSpinners.removeAllViews();
- // We use numeric spinners for year and day, but textual months. Ask icu4c what
- // order the user's locale uses for that combination. http://b/7207103.
- String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), "yyyyMMMdd");
- char[] order = ICU.getDateFormatOrder(pattern);
- final int spinnerCount = order.length;
- for (int i = 0; i < spinnerCount; i++) {
- switch (order[i]) {
- case 'd':
- mSpinners.addView(mDaySpinner);
- setImeOptions(mDaySpinner, spinnerCount, i);
- break;
- case 'M':
- mSpinners.addView(mMonthSpinner);
- setImeOptions(mMonthSpinner, spinnerCount, i);
- break;
- case 'y':
- mSpinners.addView(mYearSpinner);
- setImeOptions(mYearSpinner, spinnerCount, i);
- break;
- default:
- throw new IllegalArgumentException(Arrays.toString(order));
- }
- }
- }
-
- /**
- * Parses the given <code>date</code> and in case of success sets the result
- * to the <code>outDate</code>.
- *
- * @return True if the date was parsed.
- */
- private boolean parseDate(String date, Calendar outDate) {
- try {
- outDate.setTime(mDateFormat.parse(date));
- return true;
- } catch (ParseException e) {
- Log.w(LOG_TAG, "Date: " + date + " not in format: " + DATE_FORMAT);
- return false;
- }
- }
-
- private boolean isNewDate(int year, int month, int dayOfMonth) {
- return (mCurrentDate.get(Calendar.YEAR) != year
- || mCurrentDate.get(Calendar.MONTH) != month
- || mCurrentDate.get(Calendar.DAY_OF_MONTH) != dayOfMonth);
- }
-
- private void setDate(int year, int month, int dayOfMonth) {
- mCurrentDate.set(year, month, dayOfMonth);
- if (mCurrentDate.before(mMinDate)) {
- mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
- } else if (mCurrentDate.after(mMaxDate)) {
- mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
- }
- }
-
- private void updateSpinners() {
- // set the spinner ranges respecting the min and max dates
- if (mCurrentDate.equals(mMinDate)) {
- mDaySpinner.setMinValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
- mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
- mDaySpinner.setWrapSelectorWheel(false);
- mMonthSpinner.setDisplayedValues(null);
- mMonthSpinner.setMinValue(mCurrentDate.get(Calendar.MONTH));
- mMonthSpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.MONTH));
- mMonthSpinner.setWrapSelectorWheel(false);
- } else if (mCurrentDate.equals(mMaxDate)) {
- mDaySpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.DAY_OF_MONTH));
- mDaySpinner.setMaxValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
- mDaySpinner.setWrapSelectorWheel(false);
- mMonthSpinner.setDisplayedValues(null);
- mMonthSpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.MONTH));
- mMonthSpinner.setMaxValue(mCurrentDate.get(Calendar.MONTH));
- mMonthSpinner.setWrapSelectorWheel(false);
- } else {
- mDaySpinner.setMinValue(1);
- mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
- mDaySpinner.setWrapSelectorWheel(true);
- mMonthSpinner.setDisplayedValues(null);
- mMonthSpinner.setMinValue(0);
- mMonthSpinner.setMaxValue(11);
- mMonthSpinner.setWrapSelectorWheel(true);
- }
-
- // make sure the month names are a zero based array
- // with the months in the month spinner
- String[] displayedValues = Arrays.copyOfRange(mShortMonths,
- mMonthSpinner.getMinValue(), mMonthSpinner.getMaxValue() + 1);
- mMonthSpinner.setDisplayedValues(displayedValues);
-
- // year spinner range does not change based on the current date
- mYearSpinner.setMinValue(mMinDate.get(Calendar.YEAR));
- mYearSpinner.setMaxValue(mMaxDate.get(Calendar.YEAR));
- mYearSpinner.setWrapSelectorWheel(false);
-
- // set the spinner values
- mYearSpinner.setValue(mCurrentDate.get(Calendar.YEAR));
- mMonthSpinner.setValue(mCurrentDate.get(Calendar.MONTH));
- mDaySpinner.setValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
-
- if (usingNumericMonths()) {
- mMonthSpinnerInput.setRawInputType(InputType.TYPE_CLASS_NUMBER);
- }
- }
-
- /**
- * Updates the calendar view with the current date.
- */
- private void updateCalendarView() {
- mCalendarView.setDate(mCurrentDate.getTimeInMillis(), false, false);
- }
-
-
- /**
- * Notifies the listener, if such, for a change in the selected date.
- */
- private void notifyDateChanged() {
- mDelegator.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
- if (mOnDateChangedListener != null) {
- mOnDateChangedListener.onDateChanged(mDelegator, getYear(), getMonth(),
- getDayOfMonth());
- }
- }
-
- /**
- * Sets the IME options for a spinner based on its ordering.
- *
- * @param spinner The spinner.
- * @param spinnerCount The total spinner count.
- * @param spinnerIndex The index of the given spinner.
- */
- private void setImeOptions(NumberPicker spinner, int spinnerCount, int spinnerIndex) {
- final int imeOptions;
- if (spinnerIndex < spinnerCount - 1) {
- imeOptions = EditorInfo.IME_ACTION_NEXT;
- } else {
- imeOptions = EditorInfo.IME_ACTION_DONE;
- }
- TextView input = (TextView) spinner.findViewById(R.id.numberpicker_input);
- input.setImeOptions(imeOptions);
- }
-
- private void setContentDescriptions() {
- // Day
- trySetContentDescription(mDaySpinner, R.id.increment,
- R.string.date_picker_increment_day_button);
- trySetContentDescription(mDaySpinner, R.id.decrement,
- R.string.date_picker_decrement_day_button);
- // Month
- trySetContentDescription(mMonthSpinner, R.id.increment,
- R.string.date_picker_increment_month_button);
- trySetContentDescription(mMonthSpinner, R.id.decrement,
- R.string.date_picker_decrement_month_button);
- // Year
- trySetContentDescription(mYearSpinner, R.id.increment,
- R.string.date_picker_increment_year_button);
- trySetContentDescription(mYearSpinner, R.id.decrement,
- R.string.date_picker_decrement_year_button);
- }
-
- private void trySetContentDescription(View root, int viewId, int contDescResId) {
- View target = root.findViewById(viewId);
- if (target != null) {
- target.setContentDescription(mContext.getString(contDescResId));
- }
- }
-
- private void updateInputState() {
- // Make sure that if the user changes the value and the IME is active
- // for one of the inputs if this widget, the IME is closed. If the user
- // changed the value via the IME and there is a next input the IME will
- // be shown, otherwise the user chose another means of changing the
- // value and having the IME up makes no sense.
- InputMethodManager inputMethodManager = InputMethodManager.peekInstance();
- if (inputMethodManager != null) {
- if (inputMethodManager.isActive(mYearSpinnerInput)) {
- mYearSpinnerInput.clearFocus();
- inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
- } else if (inputMethodManager.isActive(mMonthSpinnerInput)) {
- mMonthSpinnerInput.clearFocus();
- inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
- } else if (inputMethodManager.isActive(mDaySpinnerInput)) {
- mDaySpinnerInput.clearFocus();
- inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
- }
- }
- }
- }
-
- /**
- * Class for managing state storing/restoring.
- */
- private static class SavedState extends BaseSavedState {
-
- private final int mYear;
-
- private final int mMonth;
-
- private final int mDay;
-
- /**
- * Constructor called from {@link DatePicker#onSaveInstanceState()}
- */
- private SavedState(Parcelable superState, int year, int month, int day) {
- super(superState);
- mYear = year;
- mMonth = month;
- mDay = day;
- }
-
- /**
- * Constructor called from {@link #CREATOR}
- */
- private SavedState(Parcel in) {
- super(in);
- mYear = in.readInt();
- mMonth = in.readInt();
- mDay = in.readInt();
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeInt(mYear);
- dest.writeInt(mMonth);
- dest.writeInt(mDay);
- }
-
- @SuppressWarnings("all")
- // suppress unused and hiding
- public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {
-
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
}
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index cbb6109..5adac01 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -16,13 +16,14 @@
package android.widget;
+import com.android.internal.R;
+
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
-import android.os.Parcel;
import android.os.Parcelable;
import android.text.format.DateFormat;
import android.text.format.DateUtils;
@@ -37,8 +38,6 @@
import android.widget.DayPickerView.OnDaySelectedListener;
import android.widget.YearPickerView.OnYearSelectedListener;
-import com.android.internal.R;
-
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
@@ -550,25 +549,27 @@
@Override
public void onRestoreInstanceState(Parcelable state) {
- final SavedState ss = (SavedState) state;
+ if (state instanceof SavedState) {
+ final SavedState ss = (SavedState) state;
- // TODO: Move instance state into DayPickerView, YearPickerView.
- mCurrentDate.set(ss.getSelectedYear(), ss.getSelectedMonth(), ss.getSelectedDay());
- mMinDate.setTimeInMillis(ss.getMinDate());
- mMaxDate.setTimeInMillis(ss.getMaxDate());
+ // TODO: Move instance state into DayPickerView, YearPickerView.
+ mCurrentDate.set(ss.getSelectedYear(), ss.getSelectedMonth(), ss.getSelectedDay());
+ mMinDate.setTimeInMillis(ss.getMinDate());
+ mMaxDate.setTimeInMillis(ss.getMaxDate());
- onCurrentDateChanged(false);
+ onCurrentDateChanged(false);
- final int currentView = ss.getCurrentView();
- setCurrentView(currentView);
+ final int currentView = ss.getCurrentView();
+ setCurrentView(currentView);
- final int listPosition = ss.getListPosition();
- if (listPosition != -1) {
- if (currentView == VIEW_MONTH_DAY) {
- mDayPickerView.setPosition(listPosition);
- } else if (currentView == VIEW_YEAR) {
- final int listPositionOffset = ss.getListPositionOffset();
- mYearPickerView.setSelectionFromTop(listPosition, listPositionOffset);
+ final int listPosition = ss.getListPosition();
+ if (listPosition != -1) {
+ if (currentView == VIEW_MONTH_DAY) {
+ mDayPickerView.setPosition(listPosition);
+ } else if (currentView == VIEW_YEAR) {
+ final int listPositionOffset = ss.getListPositionOffset();
+ mYearPickerView.setSelectionFromTop(listPosition, listPositionOffset);
+ }
}
}
}
@@ -613,108 +614,4 @@
private void tryVibrate() {
mDelegator.performHapticFeedback(HapticFeedbackConstants.CALENDAR_DATE);
}
-
- /**
- * Class for managing state storing/restoring.
- */
- private static class SavedState extends View.BaseSavedState {
- private final int mSelectedYear;
- private final int mSelectedMonth;
- private final int mSelectedDay;
- private final long mMinDate;
- private final long mMaxDate;
- private final int mCurrentView;
- private final int mListPosition;
- private final int mListPositionOffset;
-
- /**
- * Constructor called from {@link DatePicker#onSaveInstanceState()}
- */
- private SavedState(Parcelable superState, int year, int month, int day,
- long minDate, long maxDate, int currentView, int listPosition,
- int listPositionOffset) {
- super(superState);
- mSelectedYear = year;
- mSelectedMonth = month;
- mSelectedDay = day;
- mMinDate = minDate;
- mMaxDate = maxDate;
- mCurrentView = currentView;
- mListPosition = listPosition;
- mListPositionOffset = listPositionOffset;
- }
-
- /**
- * Constructor called from {@link #CREATOR}
- */
- private SavedState(Parcel in) {
- super(in);
- mSelectedYear = in.readInt();
- mSelectedMonth = in.readInt();
- mSelectedDay = in.readInt();
- mMinDate = in.readLong();
- mMaxDate = in.readLong();
- mCurrentView = in.readInt();
- mListPosition = in.readInt();
- mListPositionOffset = in.readInt();
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeInt(mSelectedYear);
- dest.writeInt(mSelectedMonth);
- dest.writeInt(mSelectedDay);
- dest.writeLong(mMinDate);
- dest.writeLong(mMaxDate);
- dest.writeInt(mCurrentView);
- dest.writeInt(mListPosition);
- dest.writeInt(mListPositionOffset);
- }
-
- public int getSelectedDay() {
- return mSelectedDay;
- }
-
- public int getSelectedMonth() {
- return mSelectedMonth;
- }
-
- public int getSelectedYear() {
- return mSelectedYear;
- }
-
- public long getMinDate() {
- return mMinDate;
- }
-
- public long getMaxDate() {
- return mMaxDate;
- }
-
- public int getCurrentView() {
- return mCurrentView;
- }
-
- public int getListPosition() {
- return mListPosition;
- }
-
- public int getListPositionOffset() {
- return mListPositionOffset;
- }
-
- @SuppressWarnings("all")
- // suppress unused and hiding
- public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {
-
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
}
diff --git a/core/java/android/widget/DatePickerSpinnerDelegate.java b/core/java/android/widget/DatePickerSpinnerDelegate.java
new file mode 100644
index 0000000..255de79
--- /dev/null
+++ b/core/java/android/widget/DatePickerSpinnerDelegate.java
@@ -0,0 +1,652 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.TypedArray;
+import android.os.Parcelable;
+import android.text.InputType;
+import android.text.TextUtils;
+import android.text.format.DateFormat;
+import android.text.format.DateUtils;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.DatePicker.AbstractDatePickerDelegate;
+import android.widget.NumberPicker.OnValueChangeListener;
+
+import java.text.DateFormatSymbols;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Locale;
+
+import libcore.icu.ICU;
+
+/**
+ * A delegate implementing the basic DatePicker
+ */
+class DatePickerSpinnerDelegate extends AbstractDatePickerDelegate {
+
+ private static final String DATE_FORMAT = "MM/dd/yyyy";
+
+ private static final int DEFAULT_START_YEAR = 1900;
+
+ private static final int DEFAULT_END_YEAR = 2100;
+
+ private static final boolean DEFAULT_CALENDAR_VIEW_SHOWN = true;
+
+ private static final boolean DEFAULT_SPINNERS_SHOWN = true;
+
+ private static final boolean DEFAULT_ENABLED_STATE = true;
+
+ private final LinearLayout mSpinners;
+
+ private final NumberPicker mDaySpinner;
+
+ private final NumberPicker mMonthSpinner;
+
+ private final NumberPicker mYearSpinner;
+
+ private final EditText mDaySpinnerInput;
+
+ private final EditText mMonthSpinnerInput;
+
+ private final EditText mYearSpinnerInput;
+
+ private final CalendarView mCalendarView;
+
+ private String[] mShortMonths;
+
+ private final java.text.DateFormat mDateFormat = new SimpleDateFormat(DATE_FORMAT);
+
+ private int mNumberOfMonths;
+
+ private Calendar mTempDate;
+
+ private Calendar mMinDate;
+
+ private Calendar mMaxDate;
+
+ private Calendar mCurrentDate;
+
+ private boolean mIsEnabled = DEFAULT_ENABLED_STATE;
+
+ DatePickerSpinnerDelegate(DatePicker delegator, Context context, AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+ super(delegator, context);
+
+ mDelegator = delegator;
+ mContext = context;
+
+ // initialization based on locale
+ setCurrentLocale(Locale.getDefault());
+
+ final TypedArray attributesArray = context.obtainStyledAttributes(attrs,
+ com.android.internal.R.styleable.DatePicker, defStyleAttr, defStyleRes);
+ boolean spinnersShown = attributesArray.getBoolean(com.android.internal.R.styleable.DatePicker_spinnersShown,
+ DEFAULT_SPINNERS_SHOWN);
+ boolean calendarViewShown = attributesArray.getBoolean(
+ com.android.internal.R.styleable.DatePicker_calendarViewShown, DEFAULT_CALENDAR_VIEW_SHOWN);
+ int startYear = attributesArray.getInt(com.android.internal.R.styleable.DatePicker_startYear,
+ DEFAULT_START_YEAR);
+ int endYear = attributesArray.getInt(com.android.internal.R.styleable.DatePicker_endYear, DEFAULT_END_YEAR);
+ String minDate = attributesArray.getString(com.android.internal.R.styleable.DatePicker_minDate);
+ String maxDate = attributesArray.getString(com.android.internal.R.styleable.DatePicker_maxDate);
+ int layoutResourceId = attributesArray.getResourceId(
+ com.android.internal.R.styleable.DatePicker_legacyLayout, com.android.internal.R.layout.date_picker_legacy);
+ attributesArray.recycle();
+
+ LayoutInflater inflater = (LayoutInflater) context
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ inflater.inflate(layoutResourceId, mDelegator, true);
+
+ OnValueChangeListener onChangeListener = new OnValueChangeListener() {
+ public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
+ updateInputState();
+ mTempDate.setTimeInMillis(mCurrentDate.getTimeInMillis());
+ // take care of wrapping of days and months to update greater fields
+ if (picker == mDaySpinner) {
+ int maxDayOfMonth = mTempDate.getActualMaximum(Calendar.DAY_OF_MONTH);
+ if (oldVal == maxDayOfMonth && newVal == 1) {
+ mTempDate.add(Calendar.DAY_OF_MONTH, 1);
+ } else if (oldVal == 1 && newVal == maxDayOfMonth) {
+ mTempDate.add(Calendar.DAY_OF_MONTH, -1);
+ } else {
+ mTempDate.add(Calendar.DAY_OF_MONTH, newVal - oldVal);
+ }
+ } else if (picker == mMonthSpinner) {
+ if (oldVal == 11 && newVal == 0) {
+ mTempDate.add(Calendar.MONTH, 1);
+ } else if (oldVal == 0 && newVal == 11) {
+ mTempDate.add(Calendar.MONTH, -1);
+ } else {
+ mTempDate.add(Calendar.MONTH, newVal - oldVal);
+ }
+ } else if (picker == mYearSpinner) {
+ mTempDate.set(Calendar.YEAR, newVal);
+ } else {
+ throw new IllegalArgumentException();
+ }
+ // now set the date to the adjusted one
+ setDate(mTempDate.get(Calendar.YEAR), mTempDate.get(Calendar.MONTH),
+ mTempDate.get(Calendar.DAY_OF_MONTH));
+ updateSpinners();
+ updateCalendarView();
+ notifyDateChanged();
+ }
+ };
+
+ mSpinners = (LinearLayout) mDelegator.findViewById(com.android.internal.R.id.pickers);
+
+ // calendar view day-picker
+ mCalendarView = (CalendarView) mDelegator.findViewById(com.android.internal.R.id.calendar_view);
+ mCalendarView.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
+ public void onSelectedDayChange(CalendarView view, int year, int month, int monthDay) {
+ setDate(year, month, monthDay);
+ updateSpinners();
+ notifyDateChanged();
+ }
+ });
+
+ // day
+ mDaySpinner = (NumberPicker) mDelegator.findViewById(com.android.internal.R.id.day);
+ mDaySpinner.setFormatter(NumberPicker.getTwoDigitFormatter());
+ mDaySpinner.setOnLongPressUpdateInterval(100);
+ mDaySpinner.setOnValueChangedListener(onChangeListener);
+ mDaySpinnerInput = (EditText) mDaySpinner.findViewById(com.android.internal.R.id.numberpicker_input);
+
+ // month
+ mMonthSpinner = (NumberPicker) mDelegator.findViewById(com.android.internal.R.id.month);
+ mMonthSpinner.setMinValue(0);
+ mMonthSpinner.setMaxValue(mNumberOfMonths - 1);
+ mMonthSpinner.setDisplayedValues(mShortMonths);
+ mMonthSpinner.setOnLongPressUpdateInterval(200);
+ mMonthSpinner.setOnValueChangedListener(onChangeListener);
+ mMonthSpinnerInput = (EditText) mMonthSpinner.findViewById(com.android.internal.R.id.numberpicker_input);
+
+ // year
+ mYearSpinner = (NumberPicker) mDelegator.findViewById(com.android.internal.R.id.year);
+ mYearSpinner.setOnLongPressUpdateInterval(100);
+ mYearSpinner.setOnValueChangedListener(onChangeListener);
+ mYearSpinnerInput = (EditText) mYearSpinner.findViewById(com.android.internal.R.id.numberpicker_input);
+
+ // show only what the user required but make sure we
+ // show something and the spinners have higher priority
+ if (!spinnersShown && !calendarViewShown) {
+ setSpinnersShown(true);
+ } else {
+ setSpinnersShown(spinnersShown);
+ setCalendarViewShown(calendarViewShown);
+ }
+
+ // set the min date giving priority of the minDate over startYear
+ mTempDate.clear();
+ if (!TextUtils.isEmpty(minDate)) {
+ if (!parseDate(minDate, mTempDate)) {
+ mTempDate.set(startYear, 0, 1);
+ }
+ } else {
+ mTempDate.set(startYear, 0, 1);
+ }
+ setMinDate(mTempDate.getTimeInMillis());
+
+ // set the max date giving priority of the maxDate over endYear
+ mTempDate.clear();
+ if (!TextUtils.isEmpty(maxDate)) {
+ if (!parseDate(maxDate, mTempDate)) {
+ mTempDate.set(endYear, 11, 31);
+ }
+ } else {
+ mTempDate.set(endYear, 11, 31);
+ }
+ setMaxDate(mTempDate.getTimeInMillis());
+
+ // initialize to current date
+ mCurrentDate.setTimeInMillis(System.currentTimeMillis());
+ init(mCurrentDate.get(Calendar.YEAR), mCurrentDate.get(Calendar.MONTH), mCurrentDate
+ .get(Calendar.DAY_OF_MONTH), null);
+
+ // re-order the number spinners to match the current date format
+ reorderSpinners();
+
+ // accessibility
+ setContentDescriptions();
+
+ // If not explicitly specified this view is important for accessibility.
+ if (mDelegator.getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
+ mDelegator.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+ }
+ }
+
+ @Override
+ public void init(int year, int monthOfYear, int dayOfMonth,
+ DatePicker.OnDateChangedListener onDateChangedListener) {
+ setDate(year, monthOfYear, dayOfMonth);
+ updateSpinners();
+ updateCalendarView();
+ mOnDateChangedListener = onDateChangedListener;
+ }
+
+ @Override
+ public void updateDate(int year, int month, int dayOfMonth) {
+ if (!isNewDate(year, month, dayOfMonth)) {
+ return;
+ }
+ setDate(year, month, dayOfMonth);
+ updateSpinners();
+ updateCalendarView();
+ notifyDateChanged();
+ }
+
+ @Override
+ public int getYear() {
+ return mCurrentDate.get(Calendar.YEAR);
+ }
+
+ @Override
+ public int getMonth() {
+ return mCurrentDate.get(Calendar.MONTH);
+ }
+
+ @Override
+ public int getDayOfMonth() {
+ return mCurrentDate.get(Calendar.DAY_OF_MONTH);
+ }
+
+ @Override
+ public void setFirstDayOfWeek(int firstDayOfWeek) {
+ mCalendarView.setFirstDayOfWeek(firstDayOfWeek);
+ }
+
+ @Override
+ public int getFirstDayOfWeek() {
+ return mCalendarView.getFirstDayOfWeek();
+ }
+
+ @Override
+ public void setMinDate(long minDate) {
+ mTempDate.setTimeInMillis(minDate);
+ if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)
+ && mTempDate.get(Calendar.DAY_OF_YEAR) != mMinDate.get(Calendar.DAY_OF_YEAR)) {
+ return;
+ }
+ mMinDate.setTimeInMillis(minDate);
+ mCalendarView.setMinDate(minDate);
+ if (mCurrentDate.before(mMinDate)) {
+ mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
+ updateCalendarView();
+ }
+ updateSpinners();
+ }
+
+ @Override
+ public Calendar getMinDate() {
+ final Calendar minDate = Calendar.getInstance();
+ minDate.setTimeInMillis(mCalendarView.getMinDate());
+ return minDate;
+ }
+
+ @Override
+ public void setMaxDate(long maxDate) {
+ mTempDate.setTimeInMillis(maxDate);
+ if (mTempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR)
+ && mTempDate.get(Calendar.DAY_OF_YEAR) != mMaxDate.get(Calendar.DAY_OF_YEAR)) {
+ return;
+ }
+ mMaxDate.setTimeInMillis(maxDate);
+ mCalendarView.setMaxDate(maxDate);
+ if (mCurrentDate.after(mMaxDate)) {
+ mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
+ updateCalendarView();
+ }
+ updateSpinners();
+ }
+
+ @Override
+ public Calendar getMaxDate() {
+ final Calendar maxDate = Calendar.getInstance();
+ maxDate.setTimeInMillis(mCalendarView.getMaxDate());
+ return maxDate;
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ mDaySpinner.setEnabled(enabled);
+ mMonthSpinner.setEnabled(enabled);
+ mYearSpinner.setEnabled(enabled);
+ mCalendarView.setEnabled(enabled);
+ mIsEnabled = enabled;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return mIsEnabled;
+ }
+
+ @Override
+ public CalendarView getCalendarView() {
+ return mCalendarView;
+ }
+
+ @Override
+ public void setCalendarViewShown(boolean shown) {
+ mCalendarView.setVisibility(shown ? View.VISIBLE : View.GONE);
+ }
+
+ @Override
+ public boolean getCalendarViewShown() {
+ return (mCalendarView.getVisibility() == View.VISIBLE);
+ }
+
+ @Override
+ public void setSpinnersShown(boolean shown) {
+ mSpinners.setVisibility(shown ? View.VISIBLE : View.GONE);
+ }
+
+ @Override
+ public boolean getSpinnersShown() {
+ return mSpinners.isShown();
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ setCurrentLocale(newConfig.locale);
+ }
+
+ @Override
+ public Parcelable onSaveInstanceState(Parcelable superState) {
+ return new SavedState(superState, getYear(), getMonth(), getDayOfMonth(),
+ getMinDate().getTimeInMillis(), getMaxDate().getTimeInMillis());
+ }
+
+ @Override
+ public void onRestoreInstanceState(Parcelable state) {
+ if (state instanceof SavedState) {
+ final SavedState ss = (SavedState) state;
+ setDate(ss.getSelectedYear(), ss.getSelectedMonth(), ss.getSelectedDay());
+ updateSpinners();
+ updateCalendarView();
+ }
+ }
+
+ @Override
+ public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ onPopulateAccessibilityEvent(event);
+ return true;
+ }
+
+ @Override
+ public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+ final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR;
+ String selectedDateUtterance = DateUtils.formatDateTime(mContext,
+ mCurrentDate.getTimeInMillis(), flags);
+ event.getText().add(selectedDateUtterance);
+ }
+
+ /**
+ * Sets the current locale.
+ *
+ * @param locale The current locale.
+ */
+ @Override
+ protected void setCurrentLocale(Locale locale) {
+ super.setCurrentLocale(locale);
+
+ mTempDate = getCalendarForLocale(mTempDate, locale);
+ mMinDate = getCalendarForLocale(mMinDate, locale);
+ mMaxDate = getCalendarForLocale(mMaxDate, locale);
+ mCurrentDate = getCalendarForLocale(mCurrentDate, locale);
+
+ mNumberOfMonths = mTempDate.getActualMaximum(Calendar.MONTH) + 1;
+ mShortMonths = new DateFormatSymbols().getShortMonths();
+
+ if (usingNumericMonths()) {
+ // We're in a locale where a date should either be all-numeric, or all-text.
+ // All-text would require custom NumberPicker formatters for day and year.
+ mShortMonths = new String[mNumberOfMonths];
+ for (int i = 0; i < mNumberOfMonths; ++i) {
+ mShortMonths[i] = String.format("%d", i + 1);
+ }
+ }
+ }
+
+ /**
+ * Tests whether the current locale is one where there are no real month names,
+ * such as Chinese, Japanese, or Korean locales.
+ */
+ private boolean usingNumericMonths() {
+ return Character.isDigit(mShortMonths[Calendar.JANUARY].charAt(0));
+ }
+
+ /**
+ * Gets a calendar for locale bootstrapped with the value of a given calendar.
+ *
+ * @param oldCalendar The old calendar.
+ * @param locale The locale.
+ */
+ private Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) {
+ if (oldCalendar == null) {
+ return Calendar.getInstance(locale);
+ } else {
+ final long currentTimeMillis = oldCalendar.getTimeInMillis();
+ Calendar newCalendar = Calendar.getInstance(locale);
+ newCalendar.setTimeInMillis(currentTimeMillis);
+ return newCalendar;
+ }
+ }
+
+ /**
+ * Reorders the spinners according to the date format that is
+ * explicitly set by the user and if no such is set fall back
+ * to the current locale's default format.
+ */
+ private void reorderSpinners() {
+ mSpinners.removeAllViews();
+ // We use numeric spinners for year and day, but textual months. Ask icu4c what
+ // order the user's locale uses for that combination. http://b/7207103.
+ String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), "yyyyMMMdd");
+ char[] order = ICU.getDateFormatOrder(pattern);
+ final int spinnerCount = order.length;
+ for (int i = 0; i < spinnerCount; i++) {
+ switch (order[i]) {
+ case 'd':
+ mSpinners.addView(mDaySpinner);
+ setImeOptions(mDaySpinner, spinnerCount, i);
+ break;
+ case 'M':
+ mSpinners.addView(mMonthSpinner);
+ setImeOptions(mMonthSpinner, spinnerCount, i);
+ break;
+ case 'y':
+ mSpinners.addView(mYearSpinner);
+ setImeOptions(mYearSpinner, spinnerCount, i);
+ break;
+ default:
+ throw new IllegalArgumentException(Arrays.toString(order));
+ }
+ }
+ }
+
+ /**
+ * Parses the given <code>date</code> and in case of success sets the result
+ * to the <code>outDate</code>.
+ *
+ * @return True if the date was parsed.
+ */
+ private boolean parseDate(String date, Calendar outDate) {
+ try {
+ outDate.setTime(mDateFormat.parse(date));
+ return true;
+ } catch (ParseException e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ private boolean isNewDate(int year, int month, int dayOfMonth) {
+ return (mCurrentDate.get(Calendar.YEAR) != year
+ || mCurrentDate.get(Calendar.MONTH) != month
+ || mCurrentDate.get(Calendar.DAY_OF_MONTH) != dayOfMonth);
+ }
+
+ private void setDate(int year, int month, int dayOfMonth) {
+ mCurrentDate.set(year, month, dayOfMonth);
+ if (mCurrentDate.before(mMinDate)) {
+ mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
+ } else if (mCurrentDate.after(mMaxDate)) {
+ mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
+ }
+ }
+
+ private void updateSpinners() {
+ // set the spinner ranges respecting the min and max dates
+ if (mCurrentDate.equals(mMinDate)) {
+ mDaySpinner.setMinValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
+ mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
+ mDaySpinner.setWrapSelectorWheel(false);
+ mMonthSpinner.setDisplayedValues(null);
+ mMonthSpinner.setMinValue(mCurrentDate.get(Calendar.MONTH));
+ mMonthSpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.MONTH));
+ mMonthSpinner.setWrapSelectorWheel(false);
+ } else if (mCurrentDate.equals(mMaxDate)) {
+ mDaySpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.DAY_OF_MONTH));
+ mDaySpinner.setMaxValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
+ mDaySpinner.setWrapSelectorWheel(false);
+ mMonthSpinner.setDisplayedValues(null);
+ mMonthSpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.MONTH));
+ mMonthSpinner.setMaxValue(mCurrentDate.get(Calendar.MONTH));
+ mMonthSpinner.setWrapSelectorWheel(false);
+ } else {
+ mDaySpinner.setMinValue(1);
+ mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
+ mDaySpinner.setWrapSelectorWheel(true);
+ mMonthSpinner.setDisplayedValues(null);
+ mMonthSpinner.setMinValue(0);
+ mMonthSpinner.setMaxValue(11);
+ mMonthSpinner.setWrapSelectorWheel(true);
+ }
+
+ // make sure the month names are a zero based array
+ // with the months in the month spinner
+ String[] displayedValues = Arrays.copyOfRange(mShortMonths,
+ mMonthSpinner.getMinValue(), mMonthSpinner.getMaxValue() + 1);
+ mMonthSpinner.setDisplayedValues(displayedValues);
+
+ // year spinner range does not change based on the current date
+ mYearSpinner.setMinValue(mMinDate.get(Calendar.YEAR));
+ mYearSpinner.setMaxValue(mMaxDate.get(Calendar.YEAR));
+ mYearSpinner.setWrapSelectorWheel(false);
+
+ // set the spinner values
+ mYearSpinner.setValue(mCurrentDate.get(Calendar.YEAR));
+ mMonthSpinner.setValue(mCurrentDate.get(Calendar.MONTH));
+ mDaySpinner.setValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
+
+ if (usingNumericMonths()) {
+ mMonthSpinnerInput.setRawInputType(InputType.TYPE_CLASS_NUMBER);
+ }
+ }
+
+ /**
+ * Updates the calendar view with the current date.
+ */
+ private void updateCalendarView() {
+ mCalendarView.setDate(mCurrentDate.getTimeInMillis(), false, false);
+ }
+
+
+ /**
+ * Notifies the listener, if such, for a change in the selected date.
+ */
+ private void notifyDateChanged() {
+ mDelegator.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
+ if (mOnDateChangedListener != null) {
+ mOnDateChangedListener.onDateChanged(mDelegator, getYear(), getMonth(),
+ getDayOfMonth());
+ }
+ }
+
+ /**
+ * Sets the IME options for a spinner based on its ordering.
+ *
+ * @param spinner The spinner.
+ * @param spinnerCount The total spinner count.
+ * @param spinnerIndex The index of the given spinner.
+ */
+ private void setImeOptions(NumberPicker spinner, int spinnerCount, int spinnerIndex) {
+ final int imeOptions;
+ if (spinnerIndex < spinnerCount - 1) {
+ imeOptions = EditorInfo.IME_ACTION_NEXT;
+ } else {
+ imeOptions = EditorInfo.IME_ACTION_DONE;
+ }
+ TextView input = (TextView) spinner.findViewById(com.android.internal.R.id.numberpicker_input);
+ input.setImeOptions(imeOptions);
+ }
+
+ private void setContentDescriptions() {
+ // Day
+ trySetContentDescription(mDaySpinner, com.android.internal.R.id.increment,
+ com.android.internal.R.string.date_picker_increment_day_button);
+ trySetContentDescription(mDaySpinner, com.android.internal.R.id.decrement,
+ com.android.internal.R.string.date_picker_decrement_day_button);
+ // Month
+ trySetContentDescription(mMonthSpinner, com.android.internal.R.id.increment,
+ com.android.internal.R.string.date_picker_increment_month_button);
+ trySetContentDescription(mMonthSpinner, com.android.internal.R.id.decrement,
+ com.android.internal.R.string.date_picker_decrement_month_button);
+ // Year
+ trySetContentDescription(mYearSpinner, com.android.internal.R.id.increment,
+ com.android.internal.R.string.date_picker_increment_year_button);
+ trySetContentDescription(mYearSpinner, com.android.internal.R.id.decrement,
+ com.android.internal.R.string.date_picker_decrement_year_button);
+ }
+
+ private void trySetContentDescription(View root, int viewId, int contDescResId) {
+ View target = root.findViewById(viewId);
+ if (target != null) {
+ target.setContentDescription(mContext.getString(contDescResId));
+ }
+ }
+
+ private void updateInputState() {
+ // Make sure that if the user changes the value and the IME is active
+ // for one of the inputs if this widget, the IME is closed. If the user
+ // changed the value via the IME and there is a next input the IME will
+ // be shown, otherwise the user chose another means of changing the
+ // value and having the IME up makes no sense.
+ InputMethodManager inputMethodManager = InputMethodManager.peekInstance();
+ if (inputMethodManager != null) {
+ if (inputMethodManager.isActive(mYearSpinnerInput)) {
+ mYearSpinnerInput.clearFocus();
+ inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
+ } else if (inputMethodManager.isActive(mMonthSpinnerInput)) {
+ mMonthSpinnerInput.clearFocus();
+ inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
+ } else if (inputMethodManager.isActive(mDaySpinnerInput)) {
+ mDaySpinnerInput.clearFocus();
+ inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
+ }
+ }
+ }
+}
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
index 1d242d3..434e3eb 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -117,6 +117,16 @@
Selection.extendSelection(getText(), index);
}
+ /**
+ * Causes words in the text that are longer than the view's width to be ellipsized instead of
+ * broken in the middle. {@link TextUtils.TruncateAt#MARQUEE
+ * TextUtils.TruncateAt#MARQUEE} is not supported.
+ *
+ * @param ellipsis Type of ellipsis to be applied.
+ * @throws IllegalArgumentException When the value of <code>ellipsis</code> parameter is
+ * {@link TextUtils.TruncateAt#MARQUEE}.
+ * @see TextView#setEllipsize(TextUtils.TruncateAt)
+ */
@Override
public void setEllipsize(TextUtils.TruncateAt ellipsis) {
if (ellipsis == TextUtils.TruncateAt.MARQUEE) {
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index f693ce7..0e34067 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -962,20 +962,21 @@
private int getNextCursorOffset(int offset, boolean findAfterGivenOffset) {
final Layout layout = mTextView.getLayout();
if (layout == null) return offset;
- final CharSequence text = mTextView.getText();
- final int nextOffset = layout.getPaint().getTextRunCursor(text, 0, text.length(),
- layout.isRtlCharAt(offset) ? Paint.DIRECTION_RTL : Paint.DIRECTION_LTR,
- offset, findAfterGivenOffset ? Paint.CURSOR_AFTER : Paint.CURSOR_BEFORE);
- return nextOffset == -1 ? offset : nextOffset;
+ return findAfterGivenOffset == layout.isRtlCharAt(offset) ?
+ layout.getOffsetToLeftOf(offset) : layout.getOffsetToRightOf(offset);
}
private long getCharClusterRange(int offset) {
final int textLength = mTextView.getText().length();
if (offset < textLength) {
- return TextUtils.packRangeInLong(offset, getNextCursorOffset(offset, true));
+ final int clusterEndOffset = getNextCursorOffset(offset, true);
+ return TextUtils.packRangeInLong(
+ getNextCursorOffset(clusterEndOffset, false), clusterEndOffset);
}
if (offset - 1 >= 0) {
- return TextUtils.packRangeInLong(getNextCursorOffset(offset, false), offset);
+ final int clusterStartOffset = getNextCursorOffset(offset, false);
+ return TextUtils.packRangeInLong(clusterStartOffset,
+ getNextCursorOffset(clusterStartOffset, true));
}
return TextUtils.packRangeInLong(offset, offset);
}
@@ -1086,7 +1087,7 @@
CharSequence selectedText = mTextView.getTransformedText(start, end);
ClipData data = ClipData.newPlainText(null, selectedText);
DragLocalState localState = new DragLocalState(mTextView, start, end);
- mTextView.startDragAndDrop(data, getTextThumbnailBuilder(selectedText), localState,
+ mTextView.startDragAndDrop(data, getTextThumbnailBuilder(start, end), localState,
View.DRAG_FLAG_GLOBAL);
stopTextActionMode();
if (hasSelectionController()) {
@@ -2307,7 +2308,7 @@
}
}
- private DragShadowBuilder getTextThumbnailBuilder(CharSequence text) {
+ private DragShadowBuilder getTextThumbnailBuilder(int start, int end) {
TextView shadowView = (TextView) View.inflate(mTextView.getContext(),
com.android.internal.R.layout.text_drag_thumbnail, null);
@@ -2315,9 +2316,11 @@
throw new IllegalArgumentException("Unable to inflate text drag thumbnail");
}
- if (text.length() > DRAG_SHADOW_MAX_TEXT_LENGTH) {
- text = text.subSequence(0, DRAG_SHADOW_MAX_TEXT_LENGTH);
+ if (end - start > DRAG_SHADOW_MAX_TEXT_LENGTH) {
+ final long range = getCharClusterRange(start + DRAG_SHADOW_MAX_TEXT_LENGTH);
+ end = TextUtils.unpackRangeEndFromLong(range);
}
+ final CharSequence text = mTextView.getTransformedText(start, end);
shadowView.setText(text);
shadowView.setTextColor(mTextView.getTextColors());
@@ -3199,6 +3202,7 @@
mTextView.getContext(), mTextView.mTextEditSuggestionHighlightStyle);
private TextView mAddToDictionaryButton;
private TextView mDeleteButton;
+ private ListView mSuggestionListView;
private SuggestionSpan mMisspelledSpan;
private int mContainerMarginWidth;
private int mContainerMarginTop;
@@ -3252,12 +3256,12 @@
mClippingLimitLeft = lp.leftMargin;
mClippingLimitRight = lp.rightMargin;
- final ListView suggestionListView = (ListView) relativeLayout.findViewById(
+ mSuggestionListView = (ListView) relativeLayout.findViewById(
com.android.internal.R.id.suggestionContainer);
mSuggestionsAdapter = new SuggestionAdapter();
- suggestionListView.setAdapter(mSuggestionsAdapter);
- suggestionListView.setOnItemClickListener(this);
+ mSuggestionListView.setAdapter(mSuggestionsAdapter);
+ mSuggestionListView.setOnItemClickListener(this);
// Inflate the suggestion items once and for all.
mSuggestionInfos = new SuggestionInfo[MAX_NUMBER_SUGGESTIONS];
@@ -3416,6 +3420,7 @@
popupBackground.getPadding(mTempRect);
width += mTempRect.left + mTempRect.right;
}
+ mSuggestionListView.getLayoutParams().width = width;
mPopupWindow.setWidth(width);
}
@@ -4161,13 +4166,15 @@
}
if (isVisible()) {
- final int positionX = parentPositionX + mPositionX;
- final int positionY = parentPositionY + mPositionY;
+ // Transform to the window coordinates to follow the view tranformation.
+ final int[] pts = { mPositionX + mHotspotX + getHorizontalOffset(), mPositionY};
+ mTextView.transformFromViewToWindowSpace(pts);
+ pts[0] -= mHotspotX + getHorizontalOffset();
+
if (isShowing()) {
- mContainer.update(positionX, positionY, -1, -1);
+ mContainer.update(pts[0], pts[1], -1, -1);
} else {
- mContainer.showAtLocation(mTextView, Gravity.NO_GRAVITY,
- positionX, positionY);
+ mContainer.showAtLocation(mTextView, Gravity.NO_GRAVITY, pts[0], pts[1]);
}
} else {
if (isShowing()) {
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 8fa71a2..df2f575 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -23,7 +23,6 @@
import android.annotation.NonNull;
import android.content.Context;
-import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.PixelFormat;
import android.graphics.Rect;
@@ -1587,18 +1586,16 @@
public int getMaxAvailableHeight(
@NonNull View anchor, int yOffset, boolean ignoreBottomDecorations) {
final Rect displayFrame = new Rect();
- anchor.getWindowVisibleDisplayFrame(displayFrame);
+ if (ignoreBottomDecorations) {
+ anchor.getWindowDisplayFrame(displayFrame);
+ } else {
+ anchor.getWindowVisibleDisplayFrame(displayFrame);
+ }
final int[] anchorPos = mDrawingLocation;
anchor.getLocationOnScreen(anchorPos);
- final int bottomEdge;
- if (ignoreBottomDecorations) {
- final Resources res = anchor.getContext().getResources();
- bottomEdge = res.getDisplayMetrics().heightPixels;
- } else {
- bottomEdge = displayFrame.bottom;
- }
+ final int bottomEdge = displayFrame.bottom;
final int distanceToBottom;
if (mOverlapAnchor) {
@@ -1653,7 +1650,7 @@
// can expect the OnAttachStateChangeListener to have been called prior
// to executing this method, so we can rely on that instead.
final Transition exitTransition = mExitTransition;
- if (!mIsAnchorRootAttached && exitTransition != null && decorView.isLaidOut()) {
+ if (mIsAnchorRootAttached && exitTransition != null && decorView.isLaidOut()) {
// The decor view is non-interactive during exit transitions.
final LayoutParams p = (LayoutParams) decorView.getLayoutParams();
p.flags |= LayoutParams.FLAG_NOT_TOUCHABLE;
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 2099b04..72a50ec1 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -17,21 +17,15 @@
package android.widget;
import android.animation.ObjectAnimator;
+import android.annotation.InterpolatorRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.graphics.PorterDuff;
-
-import android.util.FloatProperty;
-import android.util.IntProperty;
-import android.view.accessibility.AccessibilityNodeInfo;
-import com.android.internal.R;
-
-import android.annotation.InterpolatorRes;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.Shader;
import android.graphics.drawable.Animatable;
@@ -46,6 +40,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
+import android.util.FloatProperty;
import android.util.MathUtils;
import android.util.Pools.SynchronizedPool;
import android.view.Gravity;
@@ -55,6 +50,7 @@
import android.view.ViewHierarchyEncoder;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
@@ -63,6 +59,7 @@
import android.view.animation.LinearInterpolator;
import android.view.animation.Transformation;
import android.widget.RemoteViews.RemoteView;
+import com.android.internal.R;
import java.util.ArrayList;
@@ -606,15 +603,30 @@
if (indeterminate) {
// swap between indeterminate and regular backgrounds
- mCurrentDrawable = mIndeterminateDrawable;
+ swapCurrentDrawable(mIndeterminateDrawable);
startAnimation();
} else {
- mCurrentDrawable = mProgressDrawable;
+ swapCurrentDrawable(mProgressDrawable);
stopAnimation();
}
}
}
+ private void swapCurrentDrawable(Drawable newDrawable) {
+ final Drawable oldDrawable = mCurrentDrawable;
+ mCurrentDrawable = newDrawable;
+ if (oldDrawable != mCurrentDrawable) {
+ if (oldDrawable != null) {
+ oldDrawable.setVisible(false, false);
+ }
+ if (mCurrentDrawable != null) {
+ mCurrentDrawable.setVisible(
+ getVisibility() == VISIBLE && getWindowVisibility() == VISIBLE,
+ false);
+ }
+ }
+ }
+
/**
* <p>Get the drawable used to draw the progress bar in
* indeterminate mode.</p>
@@ -654,7 +666,7 @@
}
if (mIndeterminate) {
- mCurrentDrawable = d;
+ swapCurrentDrawable(d);
postInvalidate();
}
}
@@ -820,7 +832,7 @@
}
if (!mIndeterminate) {
- mCurrentDrawable = d;
+ swapCurrentDrawable(d);
postInvalidate();
}
@@ -1555,7 +1567,7 @@
* <p>Start the indeterminate progress animation.</p>
*/
void startAnimation() {
- if (getVisibility() != VISIBLE) {
+ if (getVisibility() != VISIBLE || getWindowVisibility() != VISIBLE) {
return;
}
@@ -1653,14 +1665,30 @@
protected void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
+ updateVisibility();
+ }
+
+ @Override
+ protected void onWindowVisibilityChanged(@Visibility int visibility) {
+ super.onWindowVisibilityChanged(visibility);
+
+ updateVisibility();
+ }
+
+ private void updateVisibility() {
+ final boolean isVisible = getVisibility() == VISIBLE && getWindowVisibility() == VISIBLE;
if (mIndeterminate) {
// let's be nice with the UI thread
- if (visibility == GONE || visibility == INVISIBLE) {
- stopAnimation();
- } else {
+ if (isVisible) {
startAnimation();
+ } else {
+ stopAnimation();
}
}
+
+ if (mCurrentDrawable != null) {
+ mCurrentDrawable.setVisible(isVisible, false);
+ }
}
@Override
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 4ed175d..063288e 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -454,12 +454,19 @@
public void onClick(View v) {
// Insure that this view is a child of an AdapterView
View parent = (View) v.getParent();
+ // Break the for loop on the first encounter of:
+ // 1) an AdapterView,
+ // 2) an AppWidgetHostView that is not a RemoteViewsFrameLayout, or
+ // 3) a null parent.
+ // 2) and 3) are unexpected and catch the case where a child is not
+ // correctly parented in an AdapterView.
while (parent != null && !(parent instanceof AdapterView<?>)
- && !(parent instanceof AppWidgetHostView)) {
+ && !((parent instanceof AppWidgetHostView) &&
+ !(parent instanceof RemoteViewsAdapter.RemoteViewsFrameLayout))) {
parent = (View) parent.getParent();
}
- if (parent instanceof AppWidgetHostView || parent == null) {
+ if (!(parent instanceof AdapterView<?>)) {
// Somehow they've managed to get this far without having
// and AdapterView as a parent.
Log.e(LOG_TAG, "Collection item doesn't have AdapterView parent");
@@ -1973,13 +1980,13 @@
public SetRemoteInputsAction(Parcel parcel) {
viewId = parcel.readInt();
- remoteInputs = parcel.readParcelableArray(RemoteInput.class.getClassLoader());
+ remoteInputs = parcel.createTypedArray(RemoteInput.CREATOR);
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(TAG);
dest.writeInt(viewId);
- dest.writeParcelableArray(remoteInputs, flags);
+ dest.writeTypedArray(remoteInputs, flags);
}
@Override
@@ -2556,6 +2563,8 @@
* @param format The Chronometer format string, or null to
* simply display the timer value.
* @param started True if you want the clock to be started, false if not.
+ *
+ * @see #setChronometerCountsDown(int, boolean)
*/
public void setChronometer(int viewId, long base, String format, boolean started) {
setLong(viewId, "setBase", base);
@@ -2564,6 +2573,18 @@
}
/**
+ * Equivalent to calling {@link Chronometer#setCountDown(boolean) Chronometer.setCountDown} on
+ * the chronometer with the given viewId.
+ *
+ * @param viewId The id of the {@link Chronometer} to change
+ * @param isCountDown True if you want the chronometer to count down to base instead of
+ * counting up.
+ */
+ public void setChronometerCountsDown(int viewId, boolean isCountDown) {
+ setBoolean(viewId, "setCountDown", isCountDown);
+ }
+
+ /**
* Equivalent to calling {@link ProgressBar#setMax ProgressBar.setMax},
* {@link ProgressBar#setProgress ProgressBar.setProgress}, and
* {@link ProgressBar#setIndeterminate ProgressBar.setIndeterminate}
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index 8278c5a..10abbab 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -288,7 +288,7 @@
* A FrameLayout which contains a loading view, and manages the re/applying of RemoteViews when
* they are loaded.
*/
- private static class RemoteViewsFrameLayout extends AppWidgetHostView {
+ static class RemoteViewsFrameLayout extends AppWidgetHostView {
private final FixedSizeRemoteViewsCache mCache;
public RemoteViewsFrameLayout(Context context, FixedSizeRemoteViewsCache cache) {
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 3796df7..9a4d69f 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -1358,6 +1358,17 @@
+ Integer.toHexString(System.identityHashCode(this))
+ " isIconified=" + isIconified + "}";
}
+
+ public static final Parcelable.Creator<SavedState> CREATOR =
+ new Parcelable.Creator<SavedState>() {
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
}
@Override
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 6feefb4..73f8fdc 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -20,6 +20,7 @@
import android.R;
import android.annotation.ColorInt;
import android.annotation.DrawableRes;
+import android.annotation.FloatRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
@@ -662,11 +663,12 @@
*/
private int mDeviceProvisionedState = DEVICE_PROVISIONED_UNKNOWN;
- /*
+ /**
* Kick-start the font cache for the zygote process (to pay the cost of
* initializing freetype for our default font only once).
+ * @hide
*/
- static {
+ public static void preloadFontCache() {
Paint p = new Paint();
p.setAntiAlias(true);
// We don't care about the result, just the side-effect of measuring.
@@ -5828,8 +5830,7 @@
final int layoutDirection = getLayoutDirection();
final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
- if (mEllipsize == TextUtils.TruncateAt.MARQUEE &&
- mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
+ if (isMarqueeFadeEnabled()) {
if (!mSingleLine && getLineCount() == 1 && canMarquee() &&
(absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) != Gravity.LEFT) {
final int width = mRight - mLeft;
@@ -7884,7 +7885,7 @@
}
/**
- * Causes words in the text that are longer than the view is wide
+ * Causes words in the text that are longer than the view's width
* to be ellipsized instead of broken in the middle. You may also
* want to {@link #setSingleLine} or {@link #setHorizontallyScrolling}
* to constrain the text to a single line. Use <code>null</code>
@@ -8615,78 +8616,59 @@
@Override
protected float getLeftFadingEdgeStrength() {
- if (mEllipsize == TextUtils.TruncateAt.MARQUEE &&
- mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
- if (mMarquee != null && !mMarquee.isStopped()) {
- final Marquee marquee = mMarquee;
- if (marquee.shouldDrawLeftFade()) {
- final float scroll = marquee.getScroll();
- return scroll / getHorizontalFadingEdgeLength();
- } else {
- return 0.0f;
- }
- } else if (getLineCount() == 1) {
- final int layoutDirection = getLayoutDirection();
- final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
- switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
- case Gravity.LEFT:
- return 0.0f;
- case Gravity.RIGHT:
- return (mLayout.getLineRight(0) - (mRight - mLeft) -
- getCompoundPaddingLeft() - getCompoundPaddingRight() -
- mLayout.getLineLeft(0)) / getHorizontalFadingEdgeLength();
- case Gravity.CENTER_HORIZONTAL:
- case Gravity.FILL_HORIZONTAL:
- final int textDirection = mLayout.getParagraphDirection(0);
- if (textDirection == Layout.DIR_LEFT_TO_RIGHT) {
- return 0.0f;
- } else {
- return (mLayout.getLineRight(0) - (mRight - mLeft) -
- getCompoundPaddingLeft() - getCompoundPaddingRight() -
- mLayout.getLineLeft(0)) / getHorizontalFadingEdgeLength();
- }
- }
+ if (isMarqueeFadeEnabled() && mMarquee != null && !mMarquee.isStopped()) {
+ final Marquee marquee = mMarquee;
+ if (marquee.shouldDrawLeftFade()) {
+ return getHorizontalFadingEdgeStrength(marquee.getScroll(), 0.0f);
+ } else {
+ return 0.0f;
}
+ } else if (getLineCount() == 1) {
+ final float lineLeft = getLayout().getLineLeft(0);
+ if(lineLeft > mScrollX) return 0.0f;
+ return getHorizontalFadingEdgeStrength(mScrollX, lineLeft);
}
return super.getLeftFadingEdgeStrength();
}
@Override
protected float getRightFadingEdgeStrength() {
- if (mEllipsize == TextUtils.TruncateAt.MARQUEE &&
- mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
- if (mMarquee != null && !mMarquee.isStopped()) {
- final Marquee marquee = mMarquee;
- final float maxFadeScroll = marquee.getMaxFadeScroll();
- final float scroll = marquee.getScroll();
- return (maxFadeScroll - scroll) / getHorizontalFadingEdgeLength();
- } else if (getLineCount() == 1) {
- final int layoutDirection = getLayoutDirection();
- final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
- switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
- case Gravity.LEFT:
- final int textWidth = (mRight - mLeft) - getCompoundPaddingLeft() -
- getCompoundPaddingRight();
- final float lineWidth = mLayout.getLineWidth(0);
- return (lineWidth - textWidth) / getHorizontalFadingEdgeLength();
- case Gravity.RIGHT:
- return 0.0f;
- case Gravity.CENTER_HORIZONTAL:
- case Gravity.FILL_HORIZONTAL:
- final int textDirection = mLayout.getParagraphDirection(0);
- if (textDirection == Layout.DIR_RIGHT_TO_LEFT) {
- return 0.0f;
- } else {
- return (mLayout.getLineWidth(0) - ((mRight - mLeft) -
- getCompoundPaddingLeft() - getCompoundPaddingRight())) /
- getHorizontalFadingEdgeLength();
- }
- }
- }
+ if (isMarqueeFadeEnabled() && mMarquee != null && !mMarquee.isStopped()) {
+ final Marquee marquee = mMarquee;
+ return getHorizontalFadingEdgeStrength(marquee.getMaxFadeScroll(), marquee.getScroll());
+ } else if (getLineCount() == 1) {
+ final float rightEdge = mScrollX + (getWidth() - getCompoundPaddingLeft() -
+ getCompoundPaddingRight());
+ final float lineRight = getLayout().getLineRight(0);
+ if(lineRight < rightEdge) return 0.0f;
+ return getHorizontalFadingEdgeStrength(rightEdge, lineRight);
}
return super.getRightFadingEdgeStrength();
}
+ /**
+ * Calculates the fading edge strength as the ratio of the distance between two
+ * horizontal positions to {@link View#getHorizontalFadingEdgeLength()}. Uses the absolute
+ * value for the distance calculation.
+ *
+ * @param position1 A horizontal position.
+ * @param position2 A horizontal position.
+ * @return Fading edge strength between [0.0f, 1.0f].
+ */
+ @FloatRange(from=0.0, to=1.0)
+ private final float getHorizontalFadingEdgeStrength(float position1, float position2) {
+ final int horizontalFadingEdgeLength = getHorizontalFadingEdgeLength();
+ if(horizontalFadingEdgeLength == 0) return 0.0f;
+ final float diff = Math.abs(position1 - position2);
+ if(diff > horizontalFadingEdgeLength) return 1.0f;
+ return diff / horizontalFadingEdgeLength;
+ }
+
+ private final boolean isMarqueeFadeEnabled() {
+ return mEllipsize == TextUtils.TruncateAt.MARQUEE &&
+ mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS;
+ }
+
@Override
protected int computeHorizontalScrollRange() {
if (mLayout != null) {
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index a24d37f..f2fc617 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -22,8 +22,11 @@
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
+import android.os.Parcel;
import android.os.Parcelable;
+import android.os.Parcelable.Creator;
import android.util.AttributeSet;
+import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import com.android.internal.R;
@@ -301,5 +304,69 @@
mContext = context;
mLocale = context.getResources().getConfiguration().locale;
}
+
+ protected static class SavedState extends View.BaseSavedState {
+ private final int mHour;
+ private final int mMinute;
+ private final boolean mIs24HourMode;
+ private final int mCurrentItemShowing;
+
+ public SavedState(Parcelable superState, int hour, int minute, boolean is24HourMode) {
+ this(superState, hour, minute, is24HourMode, 0);
+ }
+
+ public SavedState(Parcelable superState, int hour, int minute, boolean is24HourMode,
+ int currentItemShowing) {
+ super(superState);
+ mHour = hour;
+ mMinute = minute;
+ mIs24HourMode = is24HourMode;
+ mCurrentItemShowing = currentItemShowing;
+ }
+
+ private SavedState(Parcel in) {
+ super(in);
+ mHour = in.readInt();
+ mMinute = in.readInt();
+ mIs24HourMode = (in.readInt() == 1);
+ mCurrentItemShowing = in.readInt();
+ }
+
+ public int getHour() {
+ return mHour;
+ }
+
+ public int getMinute() {
+ return mMinute;
+ }
+
+ public boolean is24HourMode() {
+ return mIs24HourMode;
+ }
+
+ public int getCurrentItemShowing() {
+ return mCurrentItemShowing;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(mHour);
+ dest.writeInt(mMinute);
+ dest.writeInt(mIs24HourMode ? 1 : 0);
+ dest.writeInt(mCurrentItemShowing);
+ }
+
+ @SuppressWarnings({"unused", "hiding"})
+ public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
}
}
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index 05fd4c8..4a24e26 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -21,7 +21,6 @@
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.TypedArray;
-import android.os.Parcel;
import android.os.Parcelable;
import android.text.SpannableStringBuilder;
import android.text.format.DateFormat;
@@ -45,7 +44,6 @@
import com.android.internal.widget.NumericTextView.OnValueChangedListener;
import java.util.Calendar;
-import java.util.Locale;
/**
* A delegate implementing the radial clock-based TimePicker.
@@ -501,9 +499,11 @@
@Override
public void onRestoreInstanceState(Parcelable state) {
- final SavedState ss = (SavedState) state;
- initialize(ss.getHour(), ss.getMinute(), ss.is24HourMode(), ss.getCurrentItemShowing());
- mRadialTimePickerView.invalidate();
+ if (state instanceof SavedState) {
+ final SavedState ss = (SavedState) state;
+ initialize(ss.getHour(), ss.getMinute(), ss.is24HourMode(), ss.getCurrentItemShowing());
+ mRadialTimePickerView.invalidate();
+ }
}
@Override
@@ -544,70 +544,6 @@
}
}
- /**
- * Used to save / restore state of time picker
- */
- private static class SavedState extends View.BaseSavedState {
-
- private final int mHour;
- private final int mMinute;
- private final boolean mIs24HourMode;
- private final int mCurrentItemShowing;
-
- private SavedState(Parcelable superState, int hour, int minute, boolean is24HourMode,
- int currentItemShowing) {
- super(superState);
- mHour = hour;
- mMinute = minute;
- mIs24HourMode = is24HourMode;
- mCurrentItemShowing = currentItemShowing;
- }
-
- private SavedState(Parcel in) {
- super(in);
- mHour = in.readInt();
- mMinute = in.readInt();
- mIs24HourMode = (in.readInt() == 1);
- mCurrentItemShowing = in.readInt();
- }
-
- public int getHour() {
- return mHour;
- }
-
- public int getMinute() {
- return mMinute;
- }
-
- public boolean is24HourMode() {
- return mIs24HourMode;
- }
-
- public int getCurrentItemShowing() {
- return mCurrentItemShowing;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeInt(mHour);
- dest.writeInt(mMinute);
- dest.writeInt(mIs24HourMode ? 1 : 0);
- dest.writeInt(mCurrentItemShowing);
- }
-
- @SuppressWarnings({"unused", "hiding"})
- public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
-
private void tryVibrate() {
mDelegator.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK);
}
diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java
index 863d409..b113fd9 100644
--- a/core/java/android/widget/TimePickerSpinnerDelegate.java
+++ b/core/java/android/widget/TimePickerSpinnerDelegate.java
@@ -18,7 +18,6 @@
import android.content.Context;
import android.content.res.TypedArray;
-import android.os.Parcel;
import android.os.Parcelable;
import android.text.format.DateFormat;
import android.text.format.DateUtils;
@@ -32,7 +31,6 @@
import com.android.internal.R;
import java.util.Calendar;
-import java.util.Locale;
import libcore.icu.LocaleData;
@@ -387,14 +385,16 @@
@Override
public Parcelable onSaveInstanceState(Parcelable superState) {
- return new SavedState(superState, getHour(), getMinute());
+ return new SavedState(superState, getHour(), getMinute(), is24Hour());
}
@Override
public void onRestoreInstanceState(Parcelable state) {
- SavedState ss = (SavedState) state;
- setHour(ss.getHour());
- setMinute(ss.getMinute());
+ if (state instanceof SavedState) {
+ final SavedState ss = (SavedState) state;
+ setHour(ss.getHour());
+ setMinute(ss.getMinute());
+ }
}
@Override
@@ -525,52 +525,6 @@
}
}
- /**
- * Used to save / restore state of time picker
- */
- private static class SavedState extends View.BaseSavedState {
- private final int mHour;
- private final int mMinute;
-
- private SavedState(Parcelable superState, int hour, int minute) {
- super(superState);
- mHour = hour;
- mMinute = minute;
- }
-
- private SavedState(Parcel in) {
- super(in);
- mHour = in.readInt();
- mMinute = in.readInt();
- }
-
- public int getHour() {
- return mHour;
- }
-
- public int getMinute() {
- return mMinute;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeInt(mHour);
- dest.writeInt(mMinute);
- }
-
- @SuppressWarnings({"unused", "hiding"})
- public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
-
public static String[] getAmPmStrings(Context context) {
String[] result = new String[2];
LocaleData d = LocaleData.get(context.getResources().getConfiguration().locale);
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 8c3c2b5..6085164 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -311,24 +311,6 @@
}
@Override
- public boolean shouldAutoLaunchSingleChoice(TargetInfo target) {
- final Intent intent = target.getResolvedIntent();
- final ResolveInfo resolve = target.getResolveInfo();
-
- // When GET_CONTENT is handled by the DocumentsUI system component,
- // we're okay automatically launching it, since it offers it's own
- // intent disambiguation UI.
- if (intent != null && Intent.ACTION_GET_CONTENT.equals(intent.getAction())
- && resolve != null && resolve.priority > 0
- && resolve.activityInfo != null && DocumentsContract.PACKAGE_DOCUMENTS_UI
- .equals(resolve.activityInfo.packageName)) {
- return true;
- }
-
- return false;
- }
-
- @Override
public void showTargetDetails(ResolveInfo ri) {
ComponentName name = ri.activityInfo.getComponentName();
boolean pinned = mPinnedSharedPrefs.getBoolean(name.flattenToString(), false);
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 9fa2c23..b13be97 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -44,6 +44,7 @@
int checkAudioOperation(int code, int usage, int uid, String packageName);
void setAudioRestriction(int code, int usage, int uid, int mode, in String[] exceptionPackages);
- void setUserRestrictions(in Bundle restrictions, int userHandle);
+ void setUserRestrictions(in Bundle restrictions, IBinder token, int userHandle);
+ void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle);
void removeUser(int userHandle);
}
diff --git a/core/java/com/android/internal/app/LocaleHelper.java b/core/java/com/android/internal/app/LocaleHelper.java
index c7459d7..d8d6e56 100644
--- a/core/java/com/android/internal/app/LocaleHelper.java
+++ b/core/java/com/android/internal/app/LocaleHelper.java
@@ -16,8 +16,8 @@
package com.android.internal.app;
-import android.icu.util.ULocale;
import android.icu.text.ListFormatter;
+import android.icu.util.ULocale;
import android.util.LocaleList;
import java.text.Collator;
@@ -99,7 +99,7 @@
* @return the localized name of the locale.
*/
public static String getDisplayName(Locale locale, Locale displayLocale, boolean sentenceCase) {
- String result = ULocale.getDisplayName(locale.toLanguageTag(),
+ String result = ULocale.getDisplayNameWithDialect(locale.toLanguageTag(),
ULocale.forLocale(displayLocale));
return sentenceCase ? toSentenceCase(result, displayLocale) : result;
}
@@ -112,7 +112,8 @@
* @return the localized name of the locale.
*/
public static String getDisplayName(Locale locale, boolean sentenceCase) {
- String result = ULocale.getDisplayName(locale.toLanguageTag(), ULocale.getDefault());
+ String result = ULocale.getDisplayNameWithDialect(locale.toLanguageTag(),
+ ULocale.getDefault());
return sentenceCase ? toSentenceCase(result, Locale.getDefault()) : result;
}
@@ -155,7 +156,7 @@
}
ListFormatter lfn = ListFormatter.getInstance(dispLocale);
- return lfn.format(localeNames);
+ return lfn.format((Object[]) localeNames);
}
/**
@@ -179,14 +180,16 @@
*/
public static final class LocaleInfoComparator implements Comparator<LocaleStore.LocaleInfo> {
private final Collator mCollator;
+ private final boolean mCountryMode;
/**
* Constructor.
*
* @param sortLocale the locale to be used for sorting.
*/
- public LocaleInfoComparator(Locale sortLocale) {
+ public LocaleInfoComparator(Locale sortLocale, boolean countryMode) {
mCollator = Collator.getInstance(sortLocale);
+ mCountryMode = countryMode;
}
/**
@@ -201,9 +204,9 @@
public int compare(LocaleStore.LocaleInfo lhs, LocaleStore.LocaleInfo rhs) {
// We don't care about the various suggestion types, just "suggested" (!= 0)
// and "all others" (== 0)
- if (lhs.isSuggested() == rhs.isSuggested()) {
+ if (mCountryMode || (lhs.isSuggested() == rhs.isSuggested())) {
// They are in the same "bucket" (suggested / others), so we compare the text
- return mCollator.compare(lhs.getLabel(), rhs.getLabel());
+ return mCollator.compare(lhs.getLabel(mCountryMode), rhs.getLabel(mCountryMode));
} else {
// One locale is suggested and one is not, so we put them in different "buckets"
return lhs.isSuggested() ? -1 : 1;
diff --git a/core/java/com/android/internal/app/LocalePicker.java b/core/java/com/android/internal/app/LocalePicker.java
index 6a365e0..b1b019c 100644
--- a/core/java/com/android/internal/app/LocalePicker.java
+++ b/core/java/com/android/internal/app/LocalePicker.java
@@ -275,7 +275,7 @@
config.setLocales(locales);
config.userSetLocale = true;
- am.updateConfiguration(config);
+ am.updatePersistentConfiguration(config);
// Trigger the dirty bit for the Settings Provider.
BackupManager.dataChanged("com.android.providers.settings");
} catch (RemoteException e) {
diff --git a/core/java/com/android/internal/app/LocalePickerWithRegion.java b/core/java/com/android/internal/app/LocalePickerWithRegion.java
index 956ee8c..2ea225f 100644
--- a/core/java/com/android/internal/app/LocalePickerWithRegion.java
+++ b/core/java/com/android/internal/app/LocalePickerWithRegion.java
@@ -50,7 +50,6 @@
private Set<LocaleStore.LocaleInfo> mLocaleList;
private LocaleStore.LocaleInfo mParentLocale;
private boolean mTranslatedOnly = false;
- private boolean mCountryMode = false;
/**
* Other classes can register to be notified when a locale was selected.
@@ -70,15 +69,14 @@
boolean translatedOnly) {
LocalePickerWithRegion localePicker = new LocalePickerWithRegion();
boolean shouldShowTheList = localePicker.setListener(context, listener, parent,
- true /* country mode */, translatedOnly);
+ translatedOnly);
return shouldShowTheList ? localePicker : null;
}
public static LocalePickerWithRegion createLanguagePicker(Context context,
LocaleSelectedListener listener, boolean translatedOnly) {
LocalePickerWithRegion localePicker = new LocalePickerWithRegion();
- localePicker.setListener(context, listener, null,
- false /* language mode */, translatedOnly);
+ localePicker.setListener(context, listener, /* parent */ null, translatedOnly);
return localePicker;
}
@@ -96,14 +94,7 @@
* "pretending" it was selected, and return false.</p>
*/
private boolean setListener(Context context, LocaleSelectedListener listener,
- LocaleStore.LocaleInfo parent, boolean countryMode, boolean translatedOnly) {
- if (countryMode && (parent == null || parent.getLocale() == null)) {
- // The list of countries is determined as all the countries where the parent language
- // is used.
- throw new IllegalArgumentException("The country selection list needs a parent.");
- }
-
- this.mCountryMode = countryMode;
+ LocaleStore.LocaleInfo parent, boolean translatedOnly) {
this.mParentLocale = parent;
this.mListener = listener;
this.mTranslatedOnly = translatedOnly;
@@ -116,7 +107,7 @@
Collections.addAll(langTagsToIgnore, langTags);
}
- if (countryMode) {
+ if (parent != null) {
mLocaleList = LocaleStore.getLevelLocales(context,
langTagsToIgnore, parent, translatedOnly);
if (mLocaleList.size() <= 1) {
@@ -138,13 +129,11 @@
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
- final Locale sortingLocale = (mCountryMode && mParentLocale != null)
- ? mParentLocale.getLocale()
- : Locale.getDefault();
-
- mAdapter = new SuggestedLocaleAdapter(mLocaleList, mCountryMode);
+ final boolean countryMode = mParentLocale != null;
+ final Locale sortingLocale = countryMode ? mParentLocale.getLocale() : Locale.getDefault();
+ mAdapter = new SuggestedLocaleAdapter(mLocaleList, countryMode);
final LocaleHelper.LocaleInfoComparator comp =
- new LocaleHelper.LocaleInfoComparator(sortingLocale);
+ new LocaleHelper.LocaleInfoComparator(sortingLocale, countryMode);
mAdapter.sort(comp);
setListAdapter(mAdapter);
}
@@ -164,12 +153,8 @@
public void onResume() {
super.onResume();
- if (mCountryMode) {
- if (mParentLocale == null) {
- this.getActivity().setTitle(R.string.country_selection_title);
- } else {
- this.getActivity().setTitle(mParentLocale.getFullNameNative());
- }
+ if (mParentLocale != null) {
+ this.getActivity().setTitle(mParentLocale.getFullNameNative());
} else {
this.getActivity().setTitle(R.string.language_selection_title);
}
@@ -182,7 +167,7 @@
final LocaleStore.LocaleInfo locale =
(LocaleStore.LocaleInfo) getListAdapter().getItem(position);
- if (mCountryMode || locale.getParent() != null) {
+ if (locale.getParent() != null) {
if (mListener != null) {
mListener.onLocaleSelected(locale);
}
@@ -205,7 +190,7 @@
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- if (!mCountryMode) {
+ if (mParentLocale == null) {
inflater.inflate(R.menu.language_selection_list, menu);
MenuItem mSearchMenuItem = menu.findItem(R.id.locale_search_menu);
diff --git a/core/java/com/android/internal/app/LocaleStore.java b/core/java/com/android/internal/app/LocaleStore.java
index 465c4d8..c4e6675 100644
--- a/core/java/com/android/internal/app/LocaleStore.java
+++ b/core/java/com/android/internal/app/LocaleStore.java
@@ -145,11 +145,11 @@
return mLangScriptKey;
}
- String getLabel() {
- if (getParent() == null || this.isSuggestionOfType(SUGGESTION_TYPE_SIM)) {
- return getFullNameNative();
- } else {
+ String getLabel(boolean countryMode) {
+ if (countryMode) {
return getFullCountryNameNative();
+ } else {
+ return getFullNameNative();
}
}
@@ -311,9 +311,7 @@
if (level == 2) {
if (parent != null) { // region selection
if (parentId.equals(li.getParent().toLanguageTag())) {
- if (!li.isSuggestionOfType(LocaleInfo.SUGGESTION_TYPE_SIM)) {
- result.add(li);
- }
+ result.add(li);
}
} else { // language selection
if (li.isSuggestionOfType(LocaleInfo.SUGGESTION_TYPE_SIM)) {
diff --git a/core/java/com/android/internal/app/PlatLogoActivity.java b/core/java/com/android/internal/app/PlatLogoActivity.java
index 0964dcf..5944568 100644
--- a/core/java/com/android/internal/app/PlatLogoActivity.java
+++ b/core/java/com/android/internal/app/PlatLogoActivity.java
@@ -73,62 +73,28 @@
final int size = (int)
(Math.min(Math.min(dm.widthPixels, dm.heightPixels), 600*dp) - 100*dp);
- final View im = new View(this);
+ final ImageView im = new ImageView(this);
+ final int pad = (int)(40*dp);
+ im.setPadding(pad, pad, pad, pad);
im.setTranslationZ(20);
im.setScaleX(0.5f);
im.setScaleY(0.5f);
im.setAlpha(0f);
- im.setOutlineProvider(new ViewOutlineProvider() {
- @Override
- public void getOutline(View view, Outline outline) {
- final int pad = (int) (8 * dp);
- outline.setOval(pad, pad, view.getWidth() - pad, view.getHeight() - pad);
- }
- });
- final float hue = (float) Math.random();
- final Paint bgPaint = new Paint();
- bgPaint.setColor(HSBtoColor(hue, 0.4f, 1f));
- final Paint fgPaint = new Paint();
- fgPaint.setColor(HSBtoColor(hue, 0.5f, 1f));
- final Drawable M = getDrawable(com.android.internal.R.drawable.platlogo_m);
- final Drawable platlogo = new Drawable() {
- @Override
- public void setAlpha(int alpha) { }
- @Override
- public void setColorFilter(@Nullable ColorFilter colorFilter) { }
-
- @Override
- public int getOpacity() {
- return PixelFormat.TRANSLUCENT;
- }
-
- @Override
- public void draw(Canvas c) {
- final float r = c.getWidth() / 2f;
- c.drawCircle(r, r, r, bgPaint);
- c.drawArc(0, 0, 2 * r, 2 * r, 135, 180, false, fgPaint);
- M.setBounds(0, 0, c.getWidth(), c.getHeight());
- M.draw(c);
- }
- };
im.setBackground(new RippleDrawable(
ColorStateList.valueOf(0xFFFFFFFF),
- platlogo,
+ getDrawable(com.android.internal.R.drawable.platlogo),
null));
- im.setOutlineProvider(new ViewOutlineProvider() {
- @Override
- public void getOutline(View view, Outline outline) {
- outline.setOval(0, 0, view.getWidth(), view.getHeight());
- }
- });
+// im.setOutlineProvider(new ViewOutlineProvider() {
+// @Override
+// public void getOutline(View view, Outline outline) {
+// outline.setOval(0, 0, view.getWidth(), view.getHeight());
+// }
+// });
im.setClickable(true);
im.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- if (mTapCount == 0) {
- showMarshmallow(im);
- }
im.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
@@ -175,9 +141,6 @@
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode != KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
- if (mKeyCount == 0) {
- showMarshmallow(im);
- }
++mKeyCount;
if (mKeyCount > 2) {
if (mTapCount > 5) {
@@ -201,81 +164,4 @@
.setStartDelay(800)
.start();
}
-
- public void showMarshmallow(View im) {
- final Drawable fg = getDrawable(com.android.internal.R.drawable.platlogo);
- fg.setBounds(0, 0, im.getWidth(), im.getHeight());
- fg.setAlpha(0);
- im.getOverlay().add(fg);
-
- final Animator fadeIn = ObjectAnimator.ofInt(fg, "alpha", 255);
- fadeIn.setInterpolator(mInterpolator);
- fadeIn.setDuration(300);
- fadeIn.start();
- }
-
- /**
- * Convert HSB components to an ARGB color. Alpha set to 0xFF.
- * hsv[0] is Hue [0 .. 1)
- * hsv[1] is Saturation [0...1]
- * hsv[2] is Value [0...1]
- * If hsv values are out of range, they are pinned.
- * @param h Hue component
- * @param s Saturation component
- * @param b Brightness component
- * @return the resulting argb color
- */
- private static int HSBtoColor(float h, float s, float b) {
- h = MathUtils.constrain(h, 0.0f, 1.0f);
- s = MathUtils.constrain(s, 0.0f, 1.0f);
- b = MathUtils.constrain(b, 0.0f, 1.0f);
-
- float red = 0.0f;
- float green = 0.0f;
- float blue = 0.0f;
-
- final float hf = (h - (int) h) * 6.0f;
- final int ihf = (int) hf;
- final float f = hf - ihf;
- final float pv = b * (1.0f - s);
- final float qv = b * (1.0f - s * f);
- final float tv = b * (1.0f - s * (1.0f - f));
-
- switch (ihf) {
- case 0: // Red is the dominant color
- red = b;
- green = tv;
- blue = pv;
- break;
- case 1: // Green is the dominant color
- red = qv;
- green = b;
- blue = pv;
- break;
- case 2:
- red = pv;
- green = b;
- blue = tv;
- break;
- case 3: // Blue is the dominant color
- red = pv;
- green = qv;
- blue = b;
- break;
- case 4:
- red = tv;
- green = pv;
- blue = b;
- break;
- case 5: // Red is the dominant color
- red = b;
- green = pv;
- blue = qv;
- break;
- }
-
- return 0xFF000000 | (((int) (red * 255.0f)) << 16) |
- (((int) (green * 255.0f)) << 8) | ((int) (blue * 255.0f));
- }
-
}
diff --git a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
index 478a56d..98102ea 100644
--- a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
+++ b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
@@ -23,7 +23,6 @@
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
-import android.widget.ImageView;
import android.widget.TextView;
import com.android.internal.R;
@@ -156,16 +155,9 @@
}
TextView text = (TextView) convertView.findViewById(R.id.locale);
- ImageView localized = (ImageView) convertView.findViewById(R.id.l10nWarn);
LocaleStore.LocaleInfo item = (LocaleStore.LocaleInfo) getItem(position);
- text.setText(item.getLabel());
- if (item.isTranslated() || mCountryMode) {
- localized.setVisibility(View.GONE);
- text.setTextLocale(item.getLocale());
- } else {
- localized.setVisibility(View.VISIBLE);
- text.setTextLocale(Locale.getDefault());
- }
+ text.setText(item.getLabel(mCountryMode));
+ text.setTextLocale(item.getLocale());
if (mCountryMode) {
int layoutDir = TextUtils.getLayoutDirectionFromLocale(item.getParent());
//noinspection ResourceType
@@ -179,6 +171,9 @@
}
private boolean showHeaders() {
+ if (mCountryMode) { // never show suggestions in country mode
+ return false;
+ }
return mSuggestionCount != 0 && mSuggestionCount != mLocaleOptions.size();
}
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 62e149a..f04bcf2 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -32,6 +32,7 @@
import android.text.TextUtils.SimpleStringSplitter;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.LocaleList;
import android.util.Pair;
import android.util.Printer;
import android.util.Slog;
@@ -486,18 +487,29 @@
return NOT_A_SUBTYPE_ID;
}
+ private static final LocaleUtils.LocaleExtractor<InputMethodSubtype> sSubtypeToLocale =
+ new LocaleUtils.LocaleExtractor<InputMethodSubtype>() {
+ @Override
+ public Locale get(InputMethodSubtype source) {
+ return source != null ? source.getLocaleObject() : null;
+ }
+ };
+
@VisibleForTesting
public static ArrayList<InputMethodSubtype> getImplicitlyApplicableSubtypesLocked(
Resources res, InputMethodInfo imi) {
final List<InputMethodSubtype> subtypes = InputMethodUtils.getSubtypes(imi);
- final String systemLocale = res.getConfiguration().locale.toString();
+ final LocaleList systemLocales = res.getConfiguration().getLocales();
+ final String systemLocale = systemLocales.get(0).toString();
if (TextUtils.isEmpty(systemLocale)) return new ArrayList<>();
- final String systemLanguage = res.getConfiguration().locale.getLanguage();
+ final int numSubtypes = subtypes.size();
+
+ // Handle overridesImplicitlyEnabledSubtype mechanism.
+ final String systemLanguage = systemLocales.get(0).getLanguage();
final HashMap<String, InputMethodSubtype> applicableModeAndSubtypesMap = new HashMap<>();
- final int N = subtypes.size();
- for (int i = 0; i < N; ++i) {
+ for (int i = 0; i < numSubtypes; ++i) {
// scan overriding implicitly enabled subtypes.
- InputMethodSubtype subtype = subtypes.get(i);
+ final InputMethodSubtype subtype = subtypes.get(i);
if (subtype.overridesImplicitlyEnabledSubtype()) {
final String mode = subtype.getMode();
if (!applicableModeAndSubtypesMap.containsKey(mode)) {
@@ -508,56 +520,65 @@
if (applicableModeAndSubtypesMap.size() > 0) {
return new ArrayList<>(applicableModeAndSubtypesMap.values());
}
- for (int i = 0; i < N; ++i) {
+
+ final ArrayList<InputMethodSubtype> keyboardSubtypes = new ArrayList<>();
+ for (int i = 0; i < numSubtypes; ++i) {
final InputMethodSubtype subtype = subtypes.get(i);
- final String locale = subtype.getLocale();
- final String mode = subtype.getMode();
- final String language = getLanguageFromLocaleString(locale);
- // When system locale starts with subtype's locale, that subtype will be applicable
- // for system locale. We need to make sure the languages are the same, to prevent
- // locales like "fil" (Filipino) being matched by "fi" (Finnish).
- //
- // For instance, it's clearly applicable for cases like system locale = en_US and
- // subtype = en, but it is not necessarily considered applicable for cases like system
- // locale = en and subtype = en_US.
- //
- // We just call systemLocale.startsWith(locale) in this function because there is no
- // need to find applicable subtypes aggressively unlike
- // findLastResortApplicableSubtypeLocked.
- //
- // TODO: This check is broken. It won't take scripts into account and doesn't
- // account for the mandatory conversions performed by Locale#toString.
- if (language.equals(systemLanguage) && systemLocale.startsWith(locale)) {
- final InputMethodSubtype applicableSubtype = applicableModeAndSubtypesMap.get(mode);
- // If more applicable subtypes are contained, skip.
- if (applicableSubtype != null) {
- if (systemLocale.equals(applicableSubtype.getLocale())) continue;
- if (!systemLocale.equals(locale)) continue;
- }
- applicableModeAndSubtypesMap.put(mode, subtype);
- }
- }
- final InputMethodSubtype keyboardSubtype
- = applicableModeAndSubtypesMap.get(SUBTYPE_MODE_KEYBOARD);
- final ArrayList<InputMethodSubtype> applicableSubtypes = new ArrayList<>(
- applicableModeAndSubtypesMap.values());
- if (keyboardSubtype != null && !keyboardSubtype.containsExtraValueKey(TAG_ASCII_CAPABLE)) {
- for (int i = 0; i < N; ++i) {
- final InputMethodSubtype subtype = subtypes.get(i);
+ if (TextUtils.equals(SUBTYPE_MODE_KEYBOARD, subtype.getMode())) {
+ keyboardSubtypes.add(subtype);
+ } else {
+ final Locale locale = subtype.getLocaleObject();
final String mode = subtype.getMode();
- if (SUBTYPE_MODE_KEYBOARD.equals(mode) && subtype.containsExtraValueKey(
- TAG_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)) {
- applicableSubtypes.add(subtype);
+ // TODO: Take secondary system locales into consideration.
+ if (locale != null && locale.equals(systemLanguage)) {
+ final InputMethodSubtype applicableSubtype =
+ applicableModeAndSubtypesMap.get(mode);
+ // If more applicable subtypes are contained, skip.
+ if (applicableSubtype != null) {
+ if (systemLocale.equals(applicableSubtype.getLocaleObject())) continue;
+ if (!systemLocale.equals(locale)) continue;
+ }
+ applicableModeAndSubtypesMap.put(mode, subtype);
}
}
}
- if (keyboardSubtype == null) {
+
+ final ArrayList<InputMethodSubtype> applicableSubtypes = new ArrayList<>();
+ LocaleUtils.filterByLanguage(keyboardSubtypes, sSubtypeToLocale, systemLocales,
+ applicableSubtypes);
+
+ if (!applicableSubtypes.isEmpty()) {
+ boolean hasAsciiCapableKeyboard = false;
+ final int numApplicationSubtypes = applicableSubtypes.size();
+ for (int i = 0; i < numApplicationSubtypes; ++i) {
+ final InputMethodSubtype subtype = applicableSubtypes.get(i);
+ if (subtype.containsExtraValueKey(TAG_ASCII_CAPABLE)) {
+ hasAsciiCapableKeyboard = true;
+ break;
+ }
+ }
+ if (!hasAsciiCapableKeyboard) {
+ final int numKeyboardSubtypes = keyboardSubtypes.size();
+ for (int i = 0; i < numKeyboardSubtypes; ++i) {
+ final InputMethodSubtype subtype = keyboardSubtypes.get(i);
+ final String mode = subtype.getMode();
+ if (SUBTYPE_MODE_KEYBOARD.equals(mode) && subtype.containsExtraValueKey(
+ TAG_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)) {
+ applicableSubtypes.add(subtype);
+ }
+ }
+ }
+ }
+
+ if (applicableSubtypes.isEmpty()) {
InputMethodSubtype lastResortKeyboardSubtype = findLastResortApplicableSubtypeLocked(
res, subtypes, SUBTYPE_MODE_KEYBOARD, systemLocale, true);
if (lastResortKeyboardSubtype != null) {
applicableSubtypes.add(lastResortKeyboardSubtype);
}
}
+
+ applicableSubtypes.addAll(applicableModeAndSubtypesMap.values());
return applicableSubtypes;
}
diff --git a/core/java/com/android/internal/inputmethod/LocaleUtils.java b/core/java/com/android/internal/inputmethod/LocaleUtils.java
new file mode 100644
index 0000000..99bb4cb
--- /dev/null
+++ b/core/java/com/android/internal/inputmethod/LocaleUtils.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.inputmethod;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.text.TextUtils;
+import android.util.LocaleList;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Objects;
+
+public final class LocaleUtils {
+
+ @VisibleForTesting
+ public interface LocaleExtractor<T> {
+ @Nullable
+ Locale get(@Nullable T source);
+ }
+
+ @Nullable
+ private static String getLanguage(@Nullable Locale locale) {
+ if (locale == null) {
+ return null;
+ }
+ return locale.getLanguage();
+ }
+
+ /**
+ * Filters the given items based on language preferences.
+ *
+ * <p>For each language found in {@code preferredLanguages}, this method tries to copy at most
+ * one best-match item from {@code source} to {@code dest}. For example, if
+ * {@code "en-GB", "ja", "en-AU", "fr-CA", "en-IN"} is specified to {@code preferredLanguages},
+ * this method tries to copy at most one English locale, at most one Japanese, and at most one
+ * French locale from {@code source} to {@code dest}. Here the best matching English locale
+ * will be searched from {@code source} as follows.
+ * <ol>
+ * <li>The first instance in {@code sources} that exactly matches {@code "en-GB"}</li>
+ * <li>The first instance in {@code sources} that exactly matches {@code "en-AU"}</li>
+ * <li>The first instance in {@code sources} that exactly matches {@code "en-IN"}</li>
+ * <li>The first instance in {@code sources} that partially matches {@code "en"}</li>
+ * </ol>
+ * <p>Then this method iterates the same algorithm for Japanese then French.</p>
+ *
+ * @param sources Source items to be filtered.
+ * @param extractor Type converter from the source items to {@link Locale} object.
+ * @param preferredLanguages Ordered list of locales with which the input items will be
+ * filtered.
+ * @param dest Destination into which the filtered items will be added.
+ * @param <T> Type of the data items.
+ */
+ @VisibleForTesting
+ public static <T> void filterByLanguage(
+ @NonNull List<T> sources,
+ @NonNull LocaleExtractor<T> extractor,
+ @NonNull LocaleList preferredLanguages,
+ @NonNull ArrayList<T> dest) {
+ final Locale[] availableLocales = new Locale[sources.size()];
+ for (int i = 0; i < availableLocales.length; ++i) {
+ availableLocales[i] = extractor.get(sources.get(i));
+ }
+ final Locale[] sortedPreferredLanguages = new Locale[preferredLanguages.size()];
+ if (sortedPreferredLanguages.length > 0) {
+ int nextIndex = 0;
+ final int N = preferredLanguages.size();
+ languageLoop:
+ for (int i = 0; i < N; ++i) {
+ final String language = getLanguage(preferredLanguages.get(i));
+ for (int j = 0; j < nextIndex; ++j) {
+ if (TextUtils.equals(getLanguage(sortedPreferredLanguages[j]), language)) {
+ continue languageLoop;
+ }
+ }
+ for (int j = i; j < N; ++j) {
+ final Locale locale = preferredLanguages.get(j);
+ if (TextUtils.equals(language, getLanguage(locale))) {
+ sortedPreferredLanguages[nextIndex] = locale;
+ ++nextIndex;
+ }
+ }
+ }
+ }
+
+
+ for (int languageIndex = 0; languageIndex < sortedPreferredLanguages.length;) {
+ // Finding the range.
+ final String language = getLanguage(sortedPreferredLanguages[languageIndex]);
+ int nextLanguageIndex = languageIndex;
+ for (; nextLanguageIndex < sortedPreferredLanguages.length; ++nextLanguageIndex) {
+ final Locale locale = sortedPreferredLanguages[nextLanguageIndex];
+ if (!TextUtils.equals(getLanguage(locale), language)) {
+ break;
+ }
+ }
+
+ // Check exact match
+ boolean found = false;
+ for (int i = languageIndex; !found && i < nextLanguageIndex; ++i) {
+ final Locale locale = sortedPreferredLanguages[i];
+ for (int j = 0; j < availableLocales.length; ++j) {
+ if (!Objects.equals(locale, availableLocales[j])) {
+ continue;
+ }
+ dest.add(sources.get(j));
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ // No exact match. Use language match.
+ for (int j = 0; j < availableLocales.length; ++j) {
+ if (!TextUtils.equals(language, getLanguage(availableLocales[j]))) {
+ continue;
+ }
+ dest.add(sources.get(j));
+ break;
+ }
+ }
+ languageIndex = nextLanguageIndex;
+ }
+ }
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index f178c8c..1b52146 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -754,8 +754,7 @@
try {
ParcelFileDescriptor pfd = service.getStatisticsStream();
if (pfd != null) {
- FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
- try {
+ try (FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) {
byte[] data = readFully(fis, MemoryFile.getSize(pfd.getFileDescriptor()));
Parcel parcel = Parcel.obtain();
parcel.unmarshall(data, 0, data.length);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 648b1a5..60c9e14 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -93,7 +93,7 @@
* battery life. All times are represented in microseconds except where indicated
* otherwise.
*/
-public final class BatteryStatsImpl extends BatteryStats {
+public class BatteryStatsImpl extends BatteryStats {
private static final String TAG = "BatteryStatsImpl";
private static final boolean DEBUG = false;
public static final boolean DEBUG_ENERGY = false;
@@ -126,6 +126,8 @@
// Number of transmit power states the Bluetooth controller can be in.
private static final int NUM_BT_TX_LEVELS = 1;
+ protected Clocks mClocks;
+
private final JournaledFile mFile;
public final AtomicFile mCheckinFile;
public final AtomicFile mDailyFile;
@@ -185,6 +187,21 @@
}
}
+ public interface Clocks {
+ public long elapsedRealtime();
+ public long uptimeMillis();
+ }
+
+ public static class SystemClocks implements Clocks {
+ public long elapsedRealtime() {
+ return SystemClock.elapsedRealtime();
+ }
+
+ public long uptimeMillis() {
+ return SystemClock.uptimeMillis();
+ }
+ }
+
public interface ExternalStatsSync {
public static final int UPDATE_CPU = 0x01;
public static final int UPDATE_WIFI = 0x02;
@@ -236,7 +253,7 @@
// These are the objects that will want to do something when the device
// is unplugged from power.
- final TimeBase mOnBatteryTimeBase = new TimeBase();
+ protected final TimeBase mOnBatteryTimeBase = new TimeBase();
// These are the objects that will want to do something when the device
// is unplugged from power *and* the screen is off.
@@ -541,6 +558,11 @@
}
public BatteryStatsImpl() {
+ this(new SystemClocks());
+ }
+
+ public BatteryStatsImpl(Clocks clocks) {
+ init(clocks);
mFile = null;
mCheckinFile = null;
mDailyFile = null;
@@ -549,25 +571,40 @@
clearHistoryLocked();
}
+ private void init(Clocks clocks) {
+ mClocks = clocks;
+ mMobileNetworkStats = new NetworkStats[] {
+ new NetworkStats(mClocks.elapsedRealtime(), 50),
+ new NetworkStats(mClocks.elapsedRealtime(), 50),
+ new NetworkStats(mClocks.elapsedRealtime(), 50)
+ };
+ mWifiNetworkStats = new NetworkStats[] {
+ new NetworkStats(mClocks.elapsedRealtime(), 50),
+ new NetworkStats(mClocks.elapsedRealtime(), 50),
+ new NetworkStats(mClocks.elapsedRealtime(), 50)
+ };
+ }
+
public static interface TimeBaseObs {
void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime);
void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime);
}
- static class TimeBase {
- private final ArrayList<TimeBaseObs> mObservers = new ArrayList<>();
+ // methods are protected not private to be VisibleForTesting
+ public static class TimeBase {
+ protected final ArrayList<TimeBaseObs> mObservers = new ArrayList<>();
- private long mUptime;
- private long mRealtime;
+ protected long mUptime;
+ protected long mRealtime;
- private boolean mRunning;
+ protected boolean mRunning;
- private long mPastUptime;
- private long mUptimeStart;
- private long mPastRealtime;
- private long mRealtimeStart;
- private long mUnpluggedUptime;
- private long mUnpluggedRealtime;
+ protected long mPastUptime;
+ protected long mUptimeStart;
+ protected long mPastRealtime;
+ protected long mRealtimeStart;
+ protected long mUnpluggedUptime;
+ protected long mUnpluggedRealtime;
public void dump(PrintWriter pw, String prefix) {
StringBuilder sb = new StringBuilder(128);
@@ -608,6 +645,10 @@
}
}
+ public boolean hasObserver(TimeBaseObs observer) {
+ return mObservers.contains(observer);
+ }
+
public void init(long uptime, long realtime) {
mRealtime = 0;
mUptime = 0;
@@ -626,7 +667,10 @@
} else {
mUptimeStart = uptime;
mRealtimeStart = realtime;
+ // TODO: Since mUptimeStart was just reset and we are running, getUptime will
+ // just return mPastUptime. Also, are we sure we don't want to reset that?
mUnpluggedUptime = getUptime(uptime);
+ // TODO: likewise.
mUnpluggedRealtime = getRealtime(realtime);
}
}
@@ -949,13 +993,14 @@
* State for keeping track of timing information.
*/
public static abstract class Timer extends BatteryStats.Timer implements TimeBaseObs {
- final int mType;
- final TimeBase mTimeBase;
+ protected final Clocks mClocks;
+ protected final int mType;
+ protected final TimeBase mTimeBase;
- int mCount;
- int mLoadedCount;
- int mLastCount;
- int mUnpluggedCount;
+ protected int mCount;
+ protected int mLoadedCount;
+ protected int mLastCount;
+ protected int mUnpluggedCount;
// Times are in microseconds for better accuracy when dividing by the
// lock count, and are in "battery realtime" units.
@@ -965,32 +1010,32 @@
* boot, to the last time something interesting happened in the
* current run.
*/
- long mTotalTime;
+ protected long mTotalTime;
/**
* The total time we loaded for the previous runs. Subtract this from
* mTotalTime to find the time for the current run of the system.
*/
- long mLoadedTime;
+ protected long mLoadedTime;
/**
* The run time of the last run of the system, as loaded from the
* saved data.
*/
- long mLastTime;
+ protected long mLastTime;
/**
* The value of mTotalTime when unplug() was last called. Subtract
* this from mTotalTime to find the time since the last unplug from
* power.
*/
- long mUnpluggedTime;
+ protected long mUnpluggedTime;
/**
* The total time this timer has been running until the latest mark has been set.
* Subtract this from mTotalTime to get the time spent running since the mark was set.
*/
- long mTimeBeforeMark;
+ protected long mTimeBeforeMark;
/**
* Constructs from a parcel.
@@ -998,7 +1043,8 @@
* @param timeBase
* @param in
*/
- Timer(int type, TimeBase timeBase, Parcel in) {
+ public Timer(Clocks clocks, int type, TimeBase timeBase, Parcel in) {
+ mClocks = clocks;
mType = type;
mTimeBase = timeBase;
@@ -1015,7 +1061,8 @@
if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTime);
}
- Timer(int type, TimeBase timeBase) {
+ public Timer(Clocks clocks, int type, TimeBase timeBase) {
+ mClocks = clocks;
mType = type;
mTimeBase = timeBase;
timeBase.add(this);
@@ -1029,7 +1076,7 @@
* Clear state of this timer. Returns true if the timer is inactive
* so can be completely dropped.
*/
- boolean reset(boolean detachIfReset) {
+ public boolean reset(boolean detachIfReset) {
mTotalTime = mLoadedTime = mLastTime = mTimeBeforeMark = 0;
mCount = mLoadedCount = mLastCount = 0;
if (detachIfReset) {
@@ -1038,7 +1085,7 @@
return true;
}
- void detach() {
+ public void detach() {
mTimeBase.remove(this);
}
@@ -1142,13 +1189,13 @@
}
- void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
+ public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
long runTime = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
out.writeLong(runTime);
out.writeInt(mCount);
}
- void readSummaryFromParcelLocked(Parcel in) {
+ public void readSummaryFromParcelLocked(Parcel in) {
// Multiply by 1000 for backwards compatibility
mTotalTime = mLoadedTime = in.readLong();
mLastTime = 0;
@@ -1162,7 +1209,7 @@
}
}
- public static final class SamplingTimer extends Timer {
+ public static class SamplingTimer extends Timer {
/**
* The most recent reported count from /proc/wakelocks.
@@ -1202,8 +1249,8 @@
*/
int mUpdateVersion;
- SamplingTimer(TimeBase timeBase, Parcel in) {
- super(0, timeBase, in);
+ SamplingTimer(Clocks clocks, TimeBase timeBase, Parcel in) {
+ super(clocks, 0, timeBase, in);
mCurrentReportedCount = in.readInt();
mUnpluggedReportedCount = in.readInt();
mCurrentReportedTotalTime = in.readLong();
@@ -1212,8 +1259,8 @@
mTimeBaseRunning = timeBase.isRunning();
}
- SamplingTimer(TimeBase timeBase, boolean trackReportedValues) {
- super(0, timeBase);
+ SamplingTimer(Clocks clocks, TimeBase timeBase, boolean trackReportedValues) {
+ super(clocks, 0, timeBase);
mTrackingReportedValues = trackReportedValues;
mTimeBaseRunning = timeBase.isRunning();
}
@@ -1301,20 +1348,20 @@
out.writeInt(mTrackingReportedValues ? 1 : 0);
}
- boolean reset(boolean detachIfReset) {
+ public boolean reset(boolean detachIfReset) {
super.reset(detachIfReset);
setStale();
return true;
}
- void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) {
+ public void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) {
super.writeSummaryFromParcelLocked(out, batteryRealtime);
out.writeLong(mCurrentReportedTotalTime);
out.writeInt(mCurrentReportedCount);
out.writeInt(mTrackingReportedValues ? 1 : 0);
}
- void readSummaryFromParcelLocked(Parcel in) {
+ public void readSummaryFromParcelLocked(Parcel in) {
super.readSummaryFromParcelLocked(in);
mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = in.readLong();
mUnpluggedReportedCount = mCurrentReportedCount = in.readInt();
@@ -1326,7 +1373,7 @@
* A timer that increments in batches. It does not run for durations, but just jumps
* for a pre-determined amount.
*/
- public static final class BatchTimer extends Timer {
+ public static class BatchTimer extends Timer {
final Uid mUid;
/**
@@ -1344,16 +1391,16 @@
*/
boolean mInDischarge;
- BatchTimer(Uid uid, int type, TimeBase timeBase, Parcel in) {
- super(type, timeBase, in);
+ BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase, Parcel in) {
+ super(clocks, type, timeBase, in);
mUid = uid;
mLastAddedTime = in.readLong();
mLastAddedDuration = in.readLong();
mInDischarge = timeBase.isRunning();
}
- BatchTimer(Uid uid, int type, TimeBase timeBase) {
- super(type, timeBase);
+ BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase) {
+ super(clocks, type, timeBase);
mUid = uid;
mInDischarge = timeBase.isRunning();
}
@@ -1367,7 +1414,7 @@
@Override
public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
- recomputeLastDuration(SystemClock.elapsedRealtime() * 1000, false);
+ recomputeLastDuration(mClocks.elapsedRealtime() * 1000, false);
mInDischarge = false;
super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
}
@@ -1416,7 +1463,7 @@
}
public void addDuration(BatteryStatsImpl stats, long durationMillis) {
- final long now = SystemClock.elapsedRealtime() * 1000;
+ final long now = mClocks.elapsedRealtime() * 1000;
recomputeLastDuration(now, true);
mLastAddedTime = now;
mLastAddedDuration = durationMillis * 1000;
@@ -1427,7 +1474,7 @@
}
public void abortLastDuration(BatteryStatsImpl stats) {
- final long now = SystemClock.elapsedRealtime() * 1000;
+ final long now = mClocks.elapsedRealtime() * 1000;
recomputeLastDuration(now, true);
}
@@ -1438,7 +1485,7 @@
@Override
protected long computeRunTimeLocked(long curBatteryRealtime) {
- final long overage = computeOverage(SystemClock.elapsedRealtime() * 1000);
+ final long overage = computeOverage(mClocks.elapsedRealtime() * 1000);
if (overage > 0) {
return mTotalTime = overage;
}
@@ -1446,8 +1493,8 @@
}
@Override
- boolean reset(boolean detachIfReset) {
- final long now = SystemClock.elapsedRealtime() * 1000;
+ public boolean reset(boolean detachIfReset) {
+ final long now = mClocks.elapsedRealtime() * 1000;
recomputeLastDuration(now, true);
boolean stillActive = mLastAddedTime == now;
super.reset(!stillActive && detachIfReset);
@@ -1458,7 +1505,7 @@
/**
* State for keeping track of timing information.
*/
- public static final class StopwatchTimer extends Timer {
+ public static class StopwatchTimer extends Timer {
final Uid mUid;
final ArrayList<StopwatchTimer> mTimerPool;
@@ -1485,22 +1532,22 @@
*/
boolean mInList;
- StopwatchTimer(Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
+ public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
TimeBase timeBase, Parcel in) {
- super(type, timeBase, in);
+ super(clocks, type, timeBase, in);
mUid = uid;
mTimerPool = timerPool;
mUpdateTime = in.readLong();
}
- StopwatchTimer(Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
+ public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
TimeBase timeBase) {
- super(type, timeBase);
+ super(clocks, type, timeBase);
mUid = uid;
mTimerPool = timerPool;
}
- void setTimeout(long timeout) {
+ public void setTimeout(long timeout) {
mTimeout = timeout;
}
@@ -1528,7 +1575,7 @@
+ " mAcquireTime=" + mAcquireTime);
}
- void startRunningLocked(long elapsedRealtimeMs) {
+ public void startRunningLocked(long elapsedRealtimeMs) {
if (mNesting++ == 0) {
final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
mUpdateTime = batteryRealtime;
@@ -1550,11 +1597,11 @@
}
}
- boolean isRunningLocked() {
+ public boolean isRunningLocked() {
return mNesting > 0;
}
- void stopRunningLocked(long elapsedRealtimeMs) {
+ public void stopRunningLocked(long elapsedRealtimeMs) {
// Ignore attempt to stop a timer that isn't running
if (mNesting == 0) {
return;
@@ -1587,7 +1634,7 @@
}
}
- void stopAllRunningLocked(long elapsedRealtimeMs) {
+ public void stopAllRunningLocked(long elapsedRealtimeMs) {
if (mNesting > 0) {
mNesting = 1;
stopRunningLocked(elapsedRealtimeMs);
@@ -1632,18 +1679,18 @@
}
@Override
- boolean reset(boolean detachIfReset) {
+ public boolean reset(boolean detachIfReset) {
boolean canDetach = mNesting <= 0;
super.reset(canDetach && detachIfReset);
if (mNesting > 0) {
- mUpdateTime = mTimeBase.getRealtime(SystemClock.elapsedRealtime() * 1000);
+ mUpdateTime = mTimeBase.getRealtime(mClocks.elapsedRealtime() * 1000);
}
mAcquireTime = mTotalTime;
return canDetach;
}
@Override
- void detach() {
+ public void detach() {
super.detach();
if (mTimerPool != null) {
mTimerPool.remove(this);
@@ -1651,7 +1698,7 @@
}
@Override
- void readSummaryFromParcelLocked(Parcel in) {
+ public void readSummaryFromParcelLocked(Parcel in) {
super.readSummaryFromParcelLocked(in);
mNesting = 0;
}
@@ -1943,7 +1990,7 @@
public SamplingTimer getWakeupReasonTimerLocked(String name) {
SamplingTimer timer = mWakeupReasonStats.get(name);
if (timer == null) {
- timer = new SamplingTimer(mOnBatteryTimeBase, true);
+ timer = new SamplingTimer(mClocks, mOnBatteryTimeBase, true);
mWakeupReasonStats.put(name, timer);
}
return timer;
@@ -1956,7 +2003,8 @@
public SamplingTimer getKernelWakelockTimerLocked(String name) {
SamplingTimer kwlt = mKernelWakelockStats.get(name);
if (kwlt == null) {
- kwlt = new SamplingTimer(mOnBatteryScreenOffTimeBase, true /* track reported values */);
+ kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase,
+ true /* track reported values */);
mKernelWakelockStats.put(name, kwlt);
}
return kwlt;
@@ -2729,8 +2777,8 @@
if (!mActiveEvents.updateState(code, name, uid, 0)) {
return;
}
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
addHistoryEventLocked(elapsedRealtime, uptime, code, name, uid);
}
@@ -2740,7 +2788,7 @@
// If the start clock time has changed by more than a year, then presumably
// the previous time was completely bogus. So we are going to figure out a
// new time based on how much time has elapsed since we started counting.
- mStartClockTime = currentTime - (SystemClock.elapsedRealtime()-(mRealtimeStart/1000));
+ mStartClockTime = currentTime - (mClocks.elapsedRealtime()-(mRealtimeStart/1000));
return true;
}
return false;
@@ -2748,8 +2796,8 @@
public void noteCurrentTimeChangedLocked() {
final long currentTime = System.currentTimeMillis();
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
recordCurrentTimeChangeLocked(currentTime, elapsedRealtime, uptime);
ensureStartClockTime(currentTime);
}
@@ -2766,8 +2814,8 @@
if (!mRecordAllHistory) {
return;
}
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_START, name, uid);
}
@@ -2800,15 +2848,15 @@
if (!mRecordAllHistory) {
return;
}
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_FINISH, name, uid);
}
public void noteSyncStartLocked(String name, int uid) {
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
getUidStatsLocked(uid).noteStartSyncLocked(name, elapsedRealtime);
if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
return;
@@ -2818,8 +2866,8 @@
public void noteSyncFinishLocked(String name, int uid) {
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
getUidStatsLocked(uid).noteStopSyncLocked(name, elapsedRealtime);
if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
return;
@@ -2829,8 +2877,8 @@
public void noteJobStartLocked(String name, int uid) {
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
getUidStatsLocked(uid).noteStartJobLocked(name, elapsedRealtime);
if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
return;
@@ -2840,8 +2888,8 @@
public void noteJobFinishLocked(String name, int uid) {
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
getUidStatsLocked(uid).noteStopJobLocked(name, elapsedRealtime);
if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
return;
@@ -2854,8 +2902,8 @@
return;
}
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
if (!mActiveEvents.updateState(HistoryItem.EVENT_ALARM_START, name, uid, 0)) {
return;
}
@@ -2867,8 +2915,8 @@
return;
}
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
if (!mActiveEvents.updateState(HistoryItem.EVENT_ALARM_FINISH, name, uid, 0)) {
return;
}
@@ -2898,8 +2946,8 @@
HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
HistoryItem.EVENT_PROC);
if (active != null) {
- long mSecRealtime = SystemClock.elapsedRealtime();
- final long mSecUptime = SystemClock.uptimeMillis();
+ long mSecRealtime = mClocks.elapsedRealtime();
+ final long mSecUptime = mClocks.uptimeMillis();
for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
SparseIntArray uids = ent.getValue();
for (int j=0; j<uids.size(); j++) {
@@ -2913,8 +2961,8 @@
HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(
HistoryItem.EVENT_PROC);
if (active != null) {
- long mSecRealtime = SystemClock.elapsedRealtime();
- final long mSecUptime = SystemClock.uptimeMillis();
+ long mSecRealtime = mClocks.elapsedRealtime();
+ final long mSecUptime = mClocks.uptimeMillis();
for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
SparseIntArray uids = ent.getValue();
for (int j=0; j<uids.size(); j++) {
@@ -3023,8 +3071,8 @@
public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
String historyName, int type, boolean unimportantForLogging) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
final int N = ws.size();
for (int i=0; i<N; i++) {
noteStartWakeLocked(ws.get(i), pid, name, historyName, type, unimportantForLogging,
@@ -3035,8 +3083,8 @@
public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name,
String historyName, int type, WorkSource newWs, int newPid, String newName,
String newHistoryName, int newType, boolean newUnimportantForLogging) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
// For correct semantics, we start the need worksources first, so that we won't
// make inappropriate history items as if all wake locks went away and new ones
// appeared. This is okay because tracking of wake locks allows nesting.
@@ -3053,8 +3101,8 @@
public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name,
String historyName, int type) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
final int N = ws.size();
for (int i=0; i<N; i++) {
noteStopWakeLocked(ws.get(i), pid, name, historyName, type, elapsedRealtime, uptime);
@@ -3072,8 +3120,8 @@
}
public void noteWakeupReasonLocked(String reason) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": "
+ Integer.toHexString(mHistoryCur.states));
aggregateLastWakeupUptimeLocked(uptime);
@@ -3147,8 +3195,8 @@
public void noteStartSensorLocked(int uid, int sensor) {
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
if (mSensorNesting == 0) {
mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: "
@@ -3161,8 +3209,8 @@
public void noteStopSensorLocked(int uid, int sensor) {
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
mSensorNesting--;
if (mSensorNesting == 0) {
mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG;
@@ -3177,8 +3225,8 @@
public void noteStartGpsLocked(int uid) {
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
if (mGpsNesting == 0) {
mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: "
@@ -3191,8 +3239,8 @@
public void noteStopGpsLocked(int uid) {
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
mGpsNesting--;
if (mGpsNesting == 0) {
mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG;
@@ -3223,8 +3271,8 @@
if (state == Display.STATE_ON) {
// Screen turning on.
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
+ Integer.toHexString(mHistoryCur.states));
@@ -3235,7 +3283,7 @@
}
updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), false,
- SystemClock.uptimeMillis() * 1000, elapsedRealtime * 1000);
+ mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
// Fake a wake lock, so we consider the device waked as long
// as the screen is on.
@@ -3248,8 +3296,8 @@
}
} else if (oldState == Display.STATE_ON) {
// Screen turning off or dozing.
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
+ Integer.toHexString(mHistoryCur.states));
@@ -3263,7 +3311,7 @@
elapsedRealtime, uptime);
updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), true,
- SystemClock.uptimeMillis() * 1000, elapsedRealtime * 1000);
+ mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000);
// Update discharge amounts.
if (mOnBatteryInternal) {
@@ -3279,8 +3327,8 @@
if (bin < 0) bin = 0;
else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
if (mScreenBrightnessBin != bin) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_BRIGHTNESS_MASK)
| (bin << HistoryItem.STATE_BRIGHTNESS_SHIFT);
if (DEBUG_HISTORY) Slog.v(TAG, "Screen brightness " + bin + " to: "
@@ -3304,15 +3352,15 @@
}
public void noteWakeUpLocked(String reason, int reasonUid) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SCREEN_WAKE_UP,
reason, reasonUid);
}
public void noteInteractiveLocked(boolean interactive) {
if (mInteractive != interactive) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
mInteractive = interactive;
if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
if (interactive) {
@@ -3324,16 +3372,16 @@
}
public void noteConnectivityChangedLocked(int type, String extra) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_CONNECTIVITY_CHANGED,
extra, type);
mNumConnectivityChange++;
}
public void noteMobileRadioPowerState(int powerState, long timestampNs) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
if (mMobileRadioPowerState != powerState) {
long realElapsedRealtimeMs;
final boolean active =
@@ -3375,8 +3423,8 @@
int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState;
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
mPowerSaveModeEnabled = enabled;
if (enabled) {
mHistoryCur.states2 |= HistoryItem.STATE2_POWER_SAVE_FLAG;
@@ -3394,8 +3442,8 @@
}
public void noteDeviceIdleModeLocked(int mode, String activeReason, int activeUid) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
boolean nowIdling = mode == DEVICE_IDLE_MODE_FULL;
if (mDeviceIdling && !nowIdling && activeReason == null) {
// We don't go out of general idling mode until explicitly taken out of
@@ -3460,8 +3508,8 @@
}
public void notePackageInstalledLocked(String pkgName, int versionCode) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_INSTALLED,
pkgName, versionCode);
PackageChange pc = new PackageChange();
@@ -3472,8 +3520,8 @@
}
public void notePackageUninstalledLocked(String pkgName) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_UNINSTALLED,
pkgName, 0);
PackageChange pc = new PackageChange();
@@ -3491,8 +3539,8 @@
public void notePhoneOnLocked() {
if (!mPhoneOn) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
mHistoryCur.states2 |= HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: "
+ Integer.toHexString(mHistoryCur.states));
@@ -3504,8 +3552,8 @@
public void notePhoneOffLocked() {
if (mPhoneOn) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
mHistoryCur.states2 &= ~HistoryItem.STATE2_PHONE_IN_CALL_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: "
+ Integer.toHexString(mHistoryCur.states));
@@ -3516,7 +3564,7 @@
}
void stopAllPhoneSignalStrengthTimersLocked(int except) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
for (int i = 0; i < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
if (i == except) {
continue;
@@ -3548,8 +3596,8 @@
mPhoneSimStateRaw = simState;
mPhoneSignalStrengthBinRaw = strengthBin;
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
if (simState == TelephonyManager.SIM_STATE_ABSENT) {
// In this case we will always be STATE_OUT_OF_SERVICE, so need
@@ -3697,8 +3745,8 @@
}
if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
if (mPhoneDataConnectionType != bin) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK)
| (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT);
if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: "
@@ -3715,8 +3763,8 @@
public void noteWifiOnLocked() {
if (!mWifiOn) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
+ Integer.toHexString(mHistoryCur.states));
@@ -3728,8 +3776,8 @@
}
public void noteWifiOffLocked() {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
if (mWifiOn) {
mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: "
@@ -3743,8 +3791,8 @@
public void noteAudioOnLocked(int uid) {
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
if (mAudioOnNesting == 0) {
mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: "
@@ -3761,8 +3809,8 @@
return;
}
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
if (--mAudioOnNesting == 0) {
mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
@@ -3775,8 +3823,8 @@
public void noteVideoOnLocked(int uid) {
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
if (mVideoOnNesting == 0) {
mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: "
@@ -3793,8 +3841,8 @@
return;
}
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
if (--mVideoOnNesting == 0) {
mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
@@ -3807,8 +3855,8 @@
public void noteResetAudioLocked() {
if (mAudioOnNesting > 0) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
mAudioOnNesting = 0;
mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: "
@@ -3824,8 +3872,8 @@
public void noteResetVideoLocked() {
if (mVideoOnNesting > 0) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
mAudioOnNesting = 0;
mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: "
@@ -3841,12 +3889,12 @@
public void noteActivityResumedLocked(int uid) {
uid = mapUid(uid);
- getUidStatsLocked(uid).noteActivityResumedLocked(SystemClock.elapsedRealtime());
+ getUidStatsLocked(uid).noteActivityResumedLocked(mClocks.elapsedRealtime());
}
public void noteActivityPausedLocked(int uid) {
uid = mapUid(uid);
- getUidStatsLocked(uid).noteActivityPausedLocked(SystemClock.elapsedRealtime());
+ getUidStatsLocked(uid).noteActivityPausedLocked(mClocks.elapsedRealtime());
}
public void noteVibratorOnLocked(int uid, long durationMillis) {
@@ -3861,8 +3909,8 @@
public void noteFlashlightOnLocked(int uid) {
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
if (mFlashlightOnNesting++ == 0) {
mHistoryCur.states2 |= HistoryItem.STATE2_FLASHLIGHT_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight on to: "
@@ -3878,8 +3926,8 @@
return;
}
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
if (--mFlashlightOnNesting == 0) {
mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
@@ -3892,8 +3940,8 @@
public void noteCameraOnLocked(int uid) {
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
if (mCameraOnNesting++ == 0) {
mHistoryCur.states2 |= HistoryItem.STATE2_CAMERA_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Camera on to: "
@@ -3909,8 +3957,8 @@
return;
}
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
if (--mCameraOnNesting == 0) {
mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
@@ -3923,8 +3971,8 @@
public void noteResetCameraLocked() {
if (mCameraOnNesting > 0) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
mCameraOnNesting = 0;
mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: "
@@ -3940,8 +3988,8 @@
public void noteResetFlashlightLocked() {
if (mFlashlightOnNesting > 0) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
mFlashlightOnNesting = 0;
mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: "
@@ -4015,8 +4063,8 @@
}
public void noteWifiRadioPowerState(int powerState, long timestampNs) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
if (mWifiRadioPowerState != powerState) {
final boolean active =
powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
@@ -4035,8 +4083,8 @@
public void noteWifiRunningLocked(WorkSource ws) {
if (!mGlobalWifiRunning) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: "
+ Integer.toHexString(mHistoryCur.states));
@@ -4056,7 +4104,7 @@
public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs) {
if (mGlobalWifiRunning) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
int N = oldWs.size();
for (int i=0; i<N; i++) {
int uid = mapUid(oldWs.get(i));
@@ -4074,8 +4122,8 @@
public void noteWifiStoppedLocked(WorkSource ws) {
if (mGlobalWifiRunning) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: "
+ Integer.toHexString(mHistoryCur.states));
@@ -4096,7 +4144,7 @@
public void noteWifiStateLocked(int wifiState, String accessPoint) {
if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState);
if (mWifiState != wifiState) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
if (mWifiState >= 0) {
mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtime);
}
@@ -4109,8 +4157,8 @@
public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth) {
if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState);
if (mWifiSupplState != supplState) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
if (mWifiSupplState >= 0) {
mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtime);
}
@@ -4126,7 +4174,7 @@
}
void stopAllWifiSignalStrengthTimersLocked(int except) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
if (i == except) {
continue;
@@ -4141,8 +4189,8 @@
int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS);
if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin);
if (mWifiSignalStrengthBin != strengthBin) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
if (mWifiSignalStrengthBin >= 0) {
mWifiSignalStrengthsTimer[mWifiSignalStrengthBin].stopRunningLocked(
elapsedRealtime);
@@ -4168,8 +4216,8 @@
public void noteFullWifiLockAcquiredLocked(int uid) {
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
if (mWifiFullLockNesting == 0) {
mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: "
@@ -4182,8 +4230,8 @@
public void noteFullWifiLockReleasedLocked(int uid) {
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
mWifiFullLockNesting--;
if (mWifiFullLockNesting == 0) {
mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
@@ -4198,8 +4246,8 @@
public void noteWifiScanStartedLocked(int uid) {
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
if (mWifiScanNesting == 0) {
mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: "
@@ -4212,8 +4260,8 @@
public void noteWifiScanStoppedLocked(int uid) {
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
mWifiScanNesting--;
if (mWifiScanNesting == 0) {
mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG;
@@ -4226,13 +4274,13 @@
public void noteWifiBatchedScanStartedLocked(int uid, int csph) {
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
getUidStatsLocked(uid).noteWifiBatchedScanStartedLocked(csph, elapsedRealtime);
}
public void noteWifiBatchedScanStoppedLocked(int uid) {
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
getUidStatsLocked(uid).noteWifiBatchedScanStoppedLocked(elapsedRealtime);
}
@@ -4240,8 +4288,8 @@
public void noteWifiMulticastEnabledLocked(int uid) {
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
if (mWifiMulticastNesting == 0) {
mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: "
@@ -4254,8 +4302,8 @@
public void noteWifiMulticastDisabledLocked(int uid) {
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
mWifiMulticastNesting--;
if (mWifiMulticastNesting == 0) {
mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
@@ -4369,7 +4417,7 @@
// During device boot, qtaguid isn't enabled until after the inital
// loading of battery stats. Now that they're enabled, take our initial
// snapshot for future delta calculation.
- updateMobileRadioStateLocked(SystemClock.elapsedRealtime(), null);
+ updateMobileRadioStateLocked(mClocks.elapsedRealtime(), null);
updateWifiStateLocked(null);
}
@@ -4623,8 +4671,8 @@
@Override public long getStartClockTime() {
final long currentTime = System.currentTimeMillis();
if (ensureStartClockTime(currentTime)) {
- recordCurrentTimeChangeLocked(currentTime, SystemClock.elapsedRealtime(),
- SystemClock.uptimeMillis());
+ recordCurrentTimeChangeLocked(currentTime, mClocks.elapsedRealtime(),
+ mClocks.uptimeMillis());
}
return mStartClockTime;
}
@@ -4652,7 +4700,11 @@
/**
* The statistics associated with a particular uid.
*/
- public final class Uid extends BatteryStats.Uid {
+ public static class Uid extends BatteryStats.Uid {
+ /**
+ * BatteryStatsImpl that we are associated with.
+ */
+ protected BatteryStatsImpl mBsi;
final int mUid;
@@ -4717,35 +4769,25 @@
long mCurStepUserTime;
long mCurStepSystemTime;
- LongSamplingCounter mUserCpuTime = new LongSamplingCounter(mOnBatteryTimeBase);
- LongSamplingCounter mSystemCpuTime = new LongSamplingCounter(mOnBatteryTimeBase);
- LongSamplingCounter mCpuPower = new LongSamplingCounter(mOnBatteryTimeBase);
+ LongSamplingCounter mUserCpuTime;
+ LongSamplingCounter mSystemCpuTime;
+ LongSamplingCounter mCpuPower;
LongSamplingCounter[][] mCpuClusterSpeed;
/**
* The statistics we have collected for this uid's wake locks.
*/
- final OverflowArrayMap<Wakelock> mWakelockStats = new OverflowArrayMap<Wakelock>() {
- @Override public Wakelock instantiateObject() { return new Wakelock(); }
- };
+ final OverflowArrayMap<Wakelock> mWakelockStats;
/**
* The statistics we have collected for this uid's syncs.
*/
- final OverflowArrayMap<StopwatchTimer> mSyncStats = new OverflowArrayMap<StopwatchTimer>() {
- @Override public StopwatchTimer instantiateObject() {
- return new StopwatchTimer(Uid.this, SYNC, null, mOnBatteryTimeBase);
- }
- };
+ final OverflowArrayMap<StopwatchTimer> mSyncStats;
/**
* The statistics we have collected for this uid's jobs.
*/
- final OverflowArrayMap<StopwatchTimer> mJobStats = new OverflowArrayMap<StopwatchTimer>() {
- @Override public StopwatchTimer instantiateObject() {
- return new StopwatchTimer(Uid.this, JOB, null, mOnBatteryTimeBase);
- }
- };
+ final OverflowArrayMap<StopwatchTimer> mJobStats;
/**
* The statistics we have collected for this uid's sensor activations.
@@ -4767,17 +4809,41 @@
*/
final SparseArray<Pid> mPids = new SparseArray<>();
- public Uid(int uid) {
+ public Uid(BatteryStatsImpl bsi, int uid) {
+ mBsi = bsi;
mUid = uid;
- mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
- mWifiRunningTimers, mOnBatteryTimeBase);
- mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
- mFullWifiLockTimers, mOnBatteryTimeBase);
- mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
- mWifiScanTimers, mOnBatteryTimeBase);
+
+ mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
+ mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
+ mCpuPower = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
+
+ mWakelockStats = mBsi.new OverflowArrayMap<Wakelock>() {
+ @Override public Wakelock instantiateObject() {
+ return new Wakelock(mBsi, Uid.this);
+ }
+ };
+ mSyncStats = mBsi.new OverflowArrayMap<StopwatchTimer>() {
+ @Override public StopwatchTimer instantiateObject() {
+ return new StopwatchTimer(mBsi.mClocks, Uid.this, SYNC, null,
+ mBsi.mOnBatteryTimeBase);
+ }
+ };
+ mJobStats = mBsi.new OverflowArrayMap<StopwatchTimer>() {
+ @Override public StopwatchTimer instantiateObject() {
+ return new StopwatchTimer(mBsi.mClocks, Uid.this, JOB, null,
+ mBsi.mOnBatteryTimeBase);
+ }
+ };
+
+ mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_RUNNING,
+ mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
+ mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, this, FULL_WIFI_LOCK,
+ mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
+ mWifiScanTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_SCAN,
+ mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase);
mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
- mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
- mWifiMulticastTimers, mOnBatteryTimeBase);
+ mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, this, WIFI_MULTICAST_ENABLED,
+ mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
}
@@ -4821,8 +4887,8 @@
if (!mWifiRunning) {
mWifiRunning = true;
if (mWifiRunningTimer == null) {
- mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
- mWifiRunningTimers, mOnBatteryTimeBase);
+ mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
+ mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase);
}
mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
}
@@ -4841,8 +4907,8 @@
if (!mFullWifiLockOut) {
mFullWifiLockOut = true;
if (mFullWifiLockTimer == null) {
- mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
- mFullWifiLockTimers, mOnBatteryTimeBase);
+ mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
+ mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase);
}
mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs);
}
@@ -4861,8 +4927,8 @@
if (!mWifiScanStarted) {
mWifiScanStarted = true;
if (mWifiScanTimer == null) {
- mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
- mWifiScanTimers, mOnBatteryTimeBase);
+ mWifiScanTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
+ mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase);
}
mWifiScanTimer.startRunningLocked(elapsedRealtimeMs);
}
@@ -4911,8 +4977,8 @@
if (!mWifiMulticastEnabled) {
mWifiMulticastEnabled = true;
if (mWifiMulticastTimer == null) {
- mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
- mWifiMulticastTimers, mOnBatteryTimeBase);
+ mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
+ WIFI_MULTICAST_ENABLED, mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
}
mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
}
@@ -4943,7 +5009,7 @@
public ControllerActivityCounterImpl getOrCreateWifiControllerActivityLocked() {
if (mWifiControllerActivity == null) {
- mWifiControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+ mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
NUM_BT_TX_LEVELS);
}
return mWifiControllerActivity;
@@ -4951,7 +5017,7 @@
public ControllerActivityCounterImpl getOrCreateBluetoothControllerActivityLocked() {
if (mBluetoothControllerActivity == null) {
- mBluetoothControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+ mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
NUM_BT_TX_LEVELS);
}
return mBluetoothControllerActivity;
@@ -4959,7 +5025,7 @@
public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() {
if (mModemControllerActivity == null) {
- mModemControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+ mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
ModemActivityInfo.TX_POWER_LEVELS);
}
return mModemControllerActivity;
@@ -4967,8 +5033,8 @@
public StopwatchTimer createAudioTurnedOnTimerLocked() {
if (mAudioTurnedOnTimer == null) {
- mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
- mAudioTurnedOnTimers, mOnBatteryTimeBase);
+ mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
+ mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase);
}
return mAudioTurnedOnTimer;
}
@@ -4991,8 +5057,8 @@
public StopwatchTimer createVideoTurnedOnTimerLocked() {
if (mVideoTurnedOnTimer == null) {
- mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
- mVideoTurnedOnTimers, mOnBatteryTimeBase);
+ mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
+ mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase);
}
return mVideoTurnedOnTimer;
}
@@ -5015,8 +5081,8 @@
public StopwatchTimer createFlashlightTurnedOnTimerLocked() {
if (mFlashlightTurnedOnTimer == null) {
- mFlashlightTurnedOnTimer = new StopwatchTimer(Uid.this, FLASHLIGHT_TURNED_ON,
- mFlashlightTurnedOnTimers, mOnBatteryTimeBase);
+ mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
+ FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase);
}
return mFlashlightTurnedOnTimer;
}
@@ -5039,8 +5105,8 @@
public StopwatchTimer createCameraTurnedOnTimerLocked() {
if (mCameraTurnedOnTimer == null) {
- mCameraTurnedOnTimer = new StopwatchTimer(Uid.this, CAMERA_TURNED_ON,
- mCameraTurnedOnTimers, mOnBatteryTimeBase);
+ mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
+ mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase);
}
return mCameraTurnedOnTimer;
}
@@ -5063,16 +5129,16 @@
public StopwatchTimer createForegroundActivityTimerLocked() {
if (mForegroundActivityTimer == null) {
- mForegroundActivityTimer = new StopwatchTimer(
- Uid.this, FOREGROUND_ACTIVITY, null, mOnBatteryTimeBase);
+ mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
+ FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase);
}
return mForegroundActivityTimer;
}
public StopwatchTimer createBluetoothScanTimerLocked() {
if (mBluetoothScanTimer == null) {
- mBluetoothScanTimer = new StopwatchTimer(Uid.this, BLUETOOTH_SCAN_ON,
- mBluetoothScanOnTimers, mOnBatteryTimeBase);
+ mBluetoothScanTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
+ mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase);
}
return mBluetoothScanTimer;
}
@@ -5108,18 +5174,19 @@
public BatchTimer createVibratorOnTimerLocked() {
if (mVibratorOnTimer == null) {
- mVibratorOnTimer = new BatchTimer(Uid.this, VIBRATOR_ON, mOnBatteryTimeBase);
+ mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
+ mBsi.mOnBatteryTimeBase);
}
return mVibratorOnTimer;
}
public void noteVibratorOnLocked(long durationMillis) {
- createVibratorOnTimerLocked().addDuration(BatteryStatsImpl.this, durationMillis);
+ createVibratorOnTimerLocked().addDuration(mBsi, durationMillis);
}
public void noteVibratorOffLocked() {
if (mVibratorOnTimer != null) {
- mVibratorOnTimer.abortLastDuration(BatteryStatsImpl.this);
+ mVibratorOnTimer.abortLastDuration(mBsi);
}
}
@@ -5215,11 +5282,11 @@
if (i < 0 || i >= NUM_PROCESS_STATE) return;
if (in == null) {
- mProcessStateTimer[i] = new StopwatchTimer(this, PROCESS_STATE, null,
- mOnBatteryTimeBase);
+ mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
+ mBsi.mOnBatteryTimeBase);
} else {
- mProcessStateTimer[i] = new StopwatchTimer(this, PROCESS_STATE, null,
- mOnBatteryTimeBase, in);
+ mProcessStateTimer[i] = new StopwatchTimer(mBsi.mClocks, this, PROCESS_STATE, null,
+ mBsi.mOnBatteryTimeBase, in);
}
}
@@ -5266,17 +5333,17 @@
void makeWifiBatchedScanBin(int i, Parcel in) {
if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return;
- ArrayList<StopwatchTimer> collected = mWifiBatchedScanTimers.get(i);
+ ArrayList<StopwatchTimer> collected = mBsi.mWifiBatchedScanTimers.get(i);
if (collected == null) {
collected = new ArrayList<StopwatchTimer>();
- mWifiBatchedScanTimers.put(i, collected);
+ mBsi.mWifiBatchedScanTimers.put(i, collected);
}
if (in == null) {
- mWifiBatchedScanTimer[i] = new StopwatchTimer(this, WIFI_BATCHED_SCAN, collected,
- mOnBatteryTimeBase);
+ mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
+ collected, mBsi.mOnBatteryTimeBase);
} else {
- mWifiBatchedScanTimer[i] = new StopwatchTimer(this, WIFI_BATCHED_SCAN, collected,
- mOnBatteryTimeBase, in);
+ mWifiBatchedScanTimer[i] = new StopwatchTimer(mBsi.mClocks, this, WIFI_BATCHED_SCAN,
+ collected, mBsi.mOnBatteryTimeBase, in);
}
}
@@ -5284,7 +5351,7 @@
void initUserActivityLocked() {
mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
- mUserActivityCounters[i] = new Counter(mOnBatteryTimeBase);
+ mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase);
}
}
@@ -5383,11 +5450,11 @@
mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
- mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
- mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
+ mNetworkByteActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
+ mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
}
- mMobileRadioActiveTime = new LongSamplingCounter(mOnBatteryTimeBase);
- mMobileRadioActiveCount = new LongSamplingCounter(mOnBatteryTimeBase);
+ mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
+ mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
}
/**
@@ -5475,12 +5542,12 @@
mWifiControllerActivity.reset(false);
}
- if (mBluetoothActivity != null) {
- mBluetoothActivity.reset(false);
+ if (mBsi.mBluetoothActivity != null) {
+ mBsi.mBluetoothActivity.reset(false);
}
- if (mModemActivity != null) {
- mModemActivity.reset(false);
+ if (mBsi.mModemActivity != null) {
+ mBsi.mModemActivity.reset(false);
}
mUserCpuTime.reset(false);
@@ -5871,7 +5938,7 @@
mWakelockStats.clear();
for (int j = 0; j < numWakelocks; j++) {
String wakelockName = in.readString();
- Uid.Wakelock wakelock = new Wakelock();
+ Uid.Wakelock wakelock = new Wakelock(mBsi, this);
wakelock.readFromParcelLocked(timeBase, screenOffTimeBase, in);
mWakelockStats.add(wakelockName, wakelock);
}
@@ -5882,7 +5949,7 @@
String syncName = in.readString();
if (in.readInt() != 0) {
mSyncStats.add(syncName,
- new StopwatchTimer(Uid.this, SYNC, null, timeBase, in));
+ new StopwatchTimer(mBsi.mClocks, Uid.this, SYNC, null, timeBase, in));
}
}
@@ -5891,7 +5958,8 @@
for (int j = 0; j < numJobs; j++) {
String jobName = in.readString();
if (in.readInt() != 0) {
- mJobStats.add(jobName, new StopwatchTimer(Uid.this, JOB, null, timeBase, in));
+ mJobStats.add(jobName, new StopwatchTimer(mBsi.mClocks, Uid.this, JOB, null,
+ timeBase, in));
}
}
@@ -5899,8 +5967,8 @@
mSensorStats.clear();
for (int k = 0; k < numSensors; k++) {
int sensorNumber = in.readInt();
- Uid.Sensor sensor = new Sensor(sensorNumber);
- sensor.readFromParcelLocked(mOnBatteryTimeBase, in);
+ Uid.Sensor sensor = new Sensor(mBsi, this, sensorNumber);
+ sensor.readFromParcelLocked(mBsi.mOnBatteryTimeBase, in);
mSensorStats.put(sensorNumber, sensor);
}
@@ -5908,7 +5976,7 @@
mProcessStats.clear();
for (int k = 0; k < numProcs; k++) {
String processName = in.readString();
- Uid.Proc proc = new Proc(processName);
+ Uid.Proc proc = new Proc(mBsi, processName);
proc.readFromParcelLocked(in);
mProcessStats.put(processName, proc);
}
@@ -5917,29 +5985,29 @@
mPackageStats.clear();
for (int l = 0; l < numPkgs; l++) {
String packageName = in.readString();
- Uid.Pkg pkg = new Pkg();
+ Uid.Pkg pkg = new Pkg(mBsi);
pkg.readFromParcelLocked(in);
mPackageStats.put(packageName, pkg);
}
mWifiRunning = false;
if (in.readInt() != 0) {
- mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
- mWifiRunningTimers, mOnBatteryTimeBase, in);
+ mWifiRunningTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_RUNNING,
+ mBsi.mWifiRunningTimers, mBsi.mOnBatteryTimeBase, in);
} else {
mWifiRunningTimer = null;
}
mFullWifiLockOut = false;
if (in.readInt() != 0) {
- mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
- mFullWifiLockTimers, mOnBatteryTimeBase, in);
+ mFullWifiLockTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, FULL_WIFI_LOCK,
+ mBsi.mFullWifiLockTimers, mBsi.mOnBatteryTimeBase, in);
} else {
mFullWifiLockTimer = null;
}
mWifiScanStarted = false;
if (in.readInt() != 0) {
- mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
- mWifiScanTimers, mOnBatteryTimeBase, in);
+ mWifiScanTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_SCAN,
+ mBsi.mWifiScanTimers, mBsi.mOnBatteryTimeBase, in);
} else {
mWifiScanTimer = null;
}
@@ -5953,44 +6021,44 @@
}
mWifiMulticastEnabled = false;
if (in.readInt() != 0) {
- mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
- mWifiMulticastTimers, mOnBatteryTimeBase, in);
+ mWifiMulticastTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, WIFI_MULTICAST_ENABLED,
+ mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase, in);
} else {
mWifiMulticastTimer = null;
}
if (in.readInt() != 0) {
- mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
- mAudioTurnedOnTimers, mOnBatteryTimeBase, in);
+ mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
+ mBsi.mAudioTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
} else {
mAudioTurnedOnTimer = null;
}
if (in.readInt() != 0) {
- mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
- mVideoTurnedOnTimers, mOnBatteryTimeBase, in);
+ mVideoTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, VIDEO_TURNED_ON,
+ mBsi.mVideoTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
} else {
mVideoTurnedOnTimer = null;
}
if (in.readInt() != 0) {
- mFlashlightTurnedOnTimer = new StopwatchTimer(Uid.this, FLASHLIGHT_TURNED_ON,
- mFlashlightTurnedOnTimers, mOnBatteryTimeBase, in);
+ mFlashlightTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
+ FLASHLIGHT_TURNED_ON, mBsi.mFlashlightTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
} else {
mFlashlightTurnedOnTimer = null;
}
if (in.readInt() != 0) {
- mCameraTurnedOnTimer = new StopwatchTimer(Uid.this, CAMERA_TURNED_ON,
- mCameraTurnedOnTimers, mOnBatteryTimeBase, in);
+ mCameraTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, CAMERA_TURNED_ON,
+ mBsi.mCameraTurnedOnTimers, mBsi.mOnBatteryTimeBase, in);
} else {
mCameraTurnedOnTimer = null;
}
if (in.readInt() != 0) {
- mForegroundActivityTimer = new StopwatchTimer(
- Uid.this, FOREGROUND_ACTIVITY, null, mOnBatteryTimeBase, in);
+ mForegroundActivityTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
+ FOREGROUND_ACTIVITY, null, mBsi.mOnBatteryTimeBase, in);
} else {
mForegroundActivityTimer = null;
}
if (in.readInt() != 0) {
- mBluetoothScanTimer = new StopwatchTimer(Uid.this, BLUETOOTH_SCAN_ON,
- mBluetoothScanOnTimers, mOnBatteryTimeBase, in);
+ mBluetoothScanTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
+ mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase, in);
} else {
mBluetoothScanTimer = null;
}
@@ -6003,14 +6071,15 @@
}
}
if (in.readInt() != 0) {
- mVibratorOnTimer = new BatchTimer(Uid.this, VIBRATOR_ON, mOnBatteryTimeBase, in);
+ mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
+ mBsi.mOnBatteryTimeBase, in);
} else {
mVibratorOnTimer = null;
}
if (in.readInt() != 0) {
mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
- mUserActivityCounters[i] = new Counter(mOnBatteryTimeBase, in);
+ mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase, in);
}
} else {
mUserActivityCounters = null;
@@ -6021,45 +6090,45 @@
= new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
mNetworkByteActivityCounters[i]
- = new LongSamplingCounter(mOnBatteryTimeBase, in);
+ = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
mNetworkPacketActivityCounters[i]
- = new LongSamplingCounter(mOnBatteryTimeBase, in);
+ = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
}
- mMobileRadioActiveTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
- mMobileRadioActiveCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
+ mMobileRadioActiveTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
+ mMobileRadioActiveCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
} else {
mNetworkByteActivityCounters = null;
mNetworkPacketActivityCounters = null;
}
if (in.readInt() != 0) {
- mWifiControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+ mWifiControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
NUM_WIFI_TX_LEVELS, in);
} else {
mWifiControllerActivity = null;
}
if (in.readInt() != 0) {
- mBluetoothControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+ mBluetoothControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
NUM_BT_TX_LEVELS, in);
} else {
mBluetoothControllerActivity = null;
}
if (in.readInt() != 0) {
- mModemControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+ mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase,
ModemActivityInfo.TX_POWER_LEVELS, in);
} else {
mModemControllerActivity = null;
}
- mUserCpuTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
- mSystemCpuTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
- mCpuPower = new LongSamplingCounter(mOnBatteryTimeBase, in);
+ mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
+ mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
+ mCpuPower = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
if (in.readInt() != 0) {
int numCpuClusters = in.readInt();
- if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numCpuClusters) {
+ if (mBsi.mPowerProfile != null && mBsi.mPowerProfile.getNumCpuClusters() != numCpuClusters) {
throw new ParcelFormatException("Incompatible number of cpu clusters");
}
@@ -6067,8 +6136,8 @@
for (int cluster = 0; cluster < numCpuClusters; cluster++) {
if (in.readInt() != 0) {
int numSpeeds = in.readInt();
- if (mPowerProfile != null &&
- mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != numSpeeds) {
+ if (mBsi.mPowerProfile != null &&
+ mBsi.mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != numSpeeds) {
throw new ParcelFormatException("Incompatible number of cpu speeds");
}
@@ -6076,7 +6145,7 @@
mCpuClusterSpeed[cluster] = cpuSpeeds;
for (int speed = 0; speed < numSpeeds; speed++) {
if (in.readInt() != 0) {
- cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase, in);
+ cpuSpeeds[speed] = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
}
}
} else {
@@ -6091,7 +6160,17 @@
/**
* The statistics associated with a particular wake lock.
*/
- public final class Wakelock extends BatteryStats.Uid.Wakelock {
+ public static class Wakelock extends BatteryStats.Uid.Wakelock {
+ /**
+ * BatteryStatsImpl that we are associated with.
+ */
+ protected BatteryStatsImpl mBsi;
+
+ /**
+ * BatteryStatsImpl that we are associated with.
+ */
+ protected Uid mUid;
+
/**
* How long (in ms) this uid has been keeping the device partially awake.
*/
@@ -6112,6 +6191,11 @@
*/
StopwatchTimer mTimerDraw;
+ public Wakelock(BatteryStatsImpl bsi, Uid uid) {
+ mBsi = bsi;
+ mUid = uid;
+ }
+
/**
* Reads a possibly null Timer from a Parcel. The timer is associated with the
* proper timer pool from the given BatteryStatsImpl object.
@@ -6125,7 +6209,7 @@
return null;
}
- return new StopwatchTimer(Uid.this, type, pool, timeBase, in);
+ return new StopwatchTimer(mBsi.mClocks, mUid, type, pool, timeBase, in);
}
boolean reset() {
@@ -6165,10 +6249,10 @@
void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
mTimerPartial = readTimerFromParcel(WAKE_TYPE_PARTIAL,
- mPartialTimers, screenOffTimeBase, in);
- mTimerFull = readTimerFromParcel(WAKE_TYPE_FULL, mFullTimers, timeBase, in);
- mTimerWindow = readTimerFromParcel(WAKE_TYPE_WINDOW, mWindowTimers, timeBase, in);
- mTimerDraw = readTimerFromParcel(WAKE_TYPE_DRAW, mDrawTimers, timeBase, in);
+ mBsi.mPartialTimers, screenOffTimeBase, in);
+ mTimerFull = readTimerFromParcel(WAKE_TYPE_FULL, mBsi.mFullTimers, timeBase, in);
+ mTimerWindow = readTimerFromParcel(WAKE_TYPE_WINDOW, mBsi.mWindowTimers, timeBase, in);
+ mTimerDraw = readTimerFromParcel(WAKE_TYPE_DRAW, mBsi.mDrawTimers, timeBase, in);
}
void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
@@ -6195,32 +6279,32 @@
case WAKE_TYPE_PARTIAL:
t = mTimerPartial;
if (t == null) {
- t = new StopwatchTimer(Uid.this, WAKE_TYPE_PARTIAL,
- mPartialTimers, mOnBatteryScreenOffTimeBase);
+ t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_PARTIAL,
+ mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase);
mTimerPartial = t;
}
return t;
case WAKE_TYPE_FULL:
t = mTimerFull;
if (t == null) {
- t = new StopwatchTimer(Uid.this, WAKE_TYPE_FULL,
- mFullTimers, mOnBatteryTimeBase);
+ t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_FULL,
+ mBsi.mFullTimers, mBsi.mOnBatteryTimeBase);
mTimerFull = t;
}
return t;
case WAKE_TYPE_WINDOW:
t = mTimerWindow;
if (t == null) {
- t = new StopwatchTimer(Uid.this, WAKE_TYPE_WINDOW,
- mWindowTimers, mOnBatteryTimeBase);
+ t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_WINDOW,
+ mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase);
mTimerWindow = t;
}
return t;
case WAKE_TYPE_DRAW:
t = mTimerDraw;
if (t == null) {
- t = new StopwatchTimer(Uid.this, WAKE_TYPE_DRAW,
- mDrawTimers, mOnBatteryTimeBase);
+ t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_DRAW,
+ mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase);
mTimerDraw = t;
}
return t;
@@ -6230,11 +6314,23 @@
}
}
- public final class Sensor extends BatteryStats.Uid.Sensor {
+ public static class Sensor extends BatteryStats.Uid.Sensor {
+ /**
+ * BatteryStatsImpl that we are associated with.
+ */
+ protected BatteryStatsImpl mBsi;
+
+ /**
+ * BatteryStatsImpl that we are associated with.
+ */
+ protected Uid mUid;
+
final int mHandle;
StopwatchTimer mTimer;
- public Sensor(int handle) {
+ public Sensor(BatteryStatsImpl bsi, Uid uid, int handle) {
+ mBsi = bsi;
+ mUid = uid;
mHandle = handle;
}
@@ -6243,12 +6339,12 @@
return null;
}
- ArrayList<StopwatchTimer> pool = mSensorTimers.get(mHandle);
+ ArrayList<StopwatchTimer> pool = mBsi.mSensorTimers.get(mHandle);
if (pool == null) {
pool = new ArrayList<StopwatchTimer>();
- mSensorTimers.put(mHandle, pool);
+ mBsi.mSensorTimers.put(mHandle, pool);
}
- return new StopwatchTimer(Uid.this, 0, pool, timeBase, in);
+ return new StopwatchTimer(mBsi.mClocks, mUid, 0, pool, timeBase, in);
}
boolean reset() {
@@ -6281,7 +6377,12 @@
/**
* The statistics associated with a particular process.
*/
- public final class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
+ public static class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
+ /**
+ * BatteryStatsImpl that we are associated with.
+ */
+ protected BatteryStatsImpl mBsi;
+
/**
* The name of this process.
*/
@@ -6384,9 +6485,10 @@
ArrayList<ExcessivePower> mExcessivePower;
- Proc(String name) {
+ public Proc(BatteryStatsImpl bsi, String name) {
+ mBsi = bsi;
mName = name;
- mOnBatteryTimeBase.add(this);
+ mBsi.mOnBatteryTimeBase.add(this);
}
public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
@@ -6403,7 +6505,7 @@
void detach() {
mActive = false;
- mOnBatteryTimeBase.remove(this);
+ mBsi.mOnBatteryTimeBase.remove(this);
}
public int countExcessivePowers() {
@@ -6617,7 +6719,12 @@
/**
* The statistics associated with a particular package.
*/
- public final class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
+ public static class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
+ /**
+ * BatteryStatsImpl that we are associated with.
+ */
+ protected BatteryStatsImpl mBsi;
+
/**
* Number of times wakeup alarms have occurred for this app.
*/
@@ -6628,8 +6735,9 @@
*/
final ArrayMap<String, Serv> mServiceStats = new ArrayMap<>();
- Pkg() {
- mOnBatteryScreenOffTimeBase.add(this);
+ public Pkg(BatteryStatsImpl bsi) {
+ mBsi = bsi;
+ mBsi.mOnBatteryScreenOffTimeBase.add(this);
}
public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
@@ -6639,7 +6747,7 @@
}
void detach() {
- mOnBatteryScreenOffTimeBase.remove(this);
+ mBsi.mOnBatteryScreenOffTimeBase.remove(this);
}
void readFromParcelLocked(Parcel in) {
@@ -6647,14 +6755,14 @@
mWakeupAlarms.clear();
for (int i=0; i<numWA; i++) {
String tag = in.readString();
- mWakeupAlarms.put(tag, new Counter(mOnBatteryTimeBase, in));
+ mWakeupAlarms.put(tag, new Counter(mBsi.mOnBatteryTimeBase, in));
}
int numServs = in.readInt();
mServiceStats.clear();
for (int m = 0; m < numServs; m++) {
String serviceName = in.readString();
- Uid.Pkg.Serv serv = new Serv();
+ Uid.Pkg.Serv serv = new Serv(mBsi);
mServiceStats.put(serviceName, serv);
serv.readFromParcelLocked(in);
@@ -6686,7 +6794,7 @@
public void noteWakeupAlarmLocked(String tag) {
Counter c = mWakeupAlarms.get(tag);
if (c == null) {
- c = new Counter(mOnBatteryTimeBase);
+ c = new Counter(mBsi.mOnBatteryTimeBase);
mWakeupAlarms.put(tag, c);
}
c.stepAtomic();
@@ -6700,99 +6808,113 @@
/**
* The statistics associated with a particular service.
*/
- public final class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
+ public static class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
+ /**
+ * BatteryStatsImpl that we are associated with.
+ */
+ protected BatteryStatsImpl mBsi;
+
+ /**
+ * The android package in which this service resides.
+ */
+ protected Pkg mPkg;
+
/**
* Total time (ms in battery uptime) the service has been left started.
*/
- long mStartTime;
+ protected long mStartTime;
/**
* If service has been started and not yet stopped, this is
* when it was started.
*/
- long mRunningSince;
+ protected long mRunningSince;
/**
* True if we are currently running.
*/
- boolean mRunning;
+ protected boolean mRunning;
/**
* Total number of times startService() has been called.
*/
- int mStarts;
+ protected int mStarts;
/**
* Total time (ms in battery uptime) the service has been left launched.
*/
- long mLaunchedTime;
+ protected long mLaunchedTime;
/**
* If service has been launched and not yet exited, this is
* when it was launched (ms in battery uptime).
*/
- long mLaunchedSince;
+ protected long mLaunchedSince;
/**
* True if we are currently launched.
*/
- boolean mLaunched;
+ protected boolean mLaunched;
/**
* Total number times the service has been launched.
*/
- int mLaunches;
+ protected int mLaunches;
/**
* The amount of time spent started loaded from a previous save
* (ms in battery uptime).
*/
- long mLoadedStartTime;
+ protected long mLoadedStartTime;
/**
* The number of starts loaded from a previous save.
*/
- int mLoadedStarts;
+ protected int mLoadedStarts;
/**
* The number of launches loaded from a previous save.
*/
- int mLoadedLaunches;
+ protected int mLoadedLaunches;
/**
* The amount of time spent started as of the last run (ms
* in battery uptime).
*/
- long mLastStartTime;
+ protected long mLastStartTime;
/**
* The number of starts as of the last run.
*/
- int mLastStarts;
+ protected int mLastStarts;
/**
* The number of launches as of the last run.
*/
- int mLastLaunches;
+ protected int mLastLaunches;
/**
* The amount of time spent started when last unplugged (ms
* in battery uptime).
*/
- long mUnpluggedStartTime;
+ protected long mUnpluggedStartTime;
/**
* The number of starts when last unplugged.
*/
- int mUnpluggedStarts;
+ protected int mUnpluggedStarts;
/**
* The number of launches when last unplugged.
*/
- int mUnpluggedLaunches;
+ protected int mUnpluggedLaunches;
- Serv() {
- mOnBatteryTimeBase.add(this);
+ /**
+ * Construct a Serv. Also adds it to the on-battery time base as a listener.
+ */
+ public Serv(BatteryStatsImpl bsi) {
+ mBsi = bsi;
+ mBsi.mOnBatteryTimeBase.add(this);
}
public void onTimeStarted(long elapsedRealtime, long baseUptime,
@@ -6806,11 +6928,14 @@
long baseRealtime) {
}
- void detach() {
- mOnBatteryTimeBase.remove(this);
+ /**
+ * Remove this Serv as a listener from the time base.
+ */
+ public void detach() {
+ mBsi.mOnBatteryTimeBase.remove(this);
}
- void readFromParcelLocked(Parcel in) {
+ public void readFromParcelLocked(Parcel in) {
mStartTime = in.readLong();
mRunningSince = in.readLong();
mRunning = in.readInt() != 0;
@@ -6830,7 +6955,7 @@
mUnpluggedLaunches = in.readInt();
}
- void writeToParcelLocked(Parcel out) {
+ public void writeToParcelLocked(Parcel out) {
out.writeLong(mStartTime);
out.writeLong(mRunningSince);
out.writeInt(mRunning ? 1 : 0);
@@ -6847,12 +6972,12 @@
out.writeInt(mUnpluggedLaunches);
}
- long getLaunchTimeToNowLocked(long batteryUptime) {
+ public long getLaunchTimeToNowLocked(long batteryUptime) {
if (!mLaunched) return mLaunchedTime;
return mLaunchedTime + batteryUptime - mLaunchedSince;
}
- long getStartTimeToNowLocked(long batteryUptime) {
+ public long getStartTimeToNowLocked(long batteryUptime) {
if (!mRunning) return mStartTime;
return mStartTime + batteryUptime - mRunningSince;
}
@@ -6860,14 +6985,14 @@
public void startLaunchedLocked() {
if (!mLaunched) {
mLaunches++;
- mLaunchedSince = getBatteryUptimeLocked();
+ mLaunchedSince = mBsi.getBatteryUptimeLocked();
mLaunched = true;
}
}
public void stopLaunchedLocked() {
if (mLaunched) {
- long time = getBatteryUptimeLocked() - mLaunchedSince;
+ long time = mBsi.getBatteryUptimeLocked() - mLaunchedSince;
if (time > 0) {
mLaunchedTime += time;
} else {
@@ -6880,14 +7005,14 @@
public void startRunningLocked() {
if (!mRunning) {
mStarts++;
- mRunningSince = getBatteryUptimeLocked();
+ mRunningSince = mBsi.getBatteryUptimeLocked();
mRunning = true;
}
}
public void stopRunningLocked() {
if (mRunning) {
- long time = getBatteryUptimeLocked() - mRunningSince;
+ long time = mBsi.getBatteryUptimeLocked() - mRunningSince;
if (time > 0) {
mStartTime += time;
} else {
@@ -6898,7 +7023,7 @@
}
public BatteryStatsImpl getBatteryStats() {
- return BatteryStatsImpl.this;
+ return mBsi;
}
@Override
@@ -6937,7 +7062,7 @@
}
final Serv newServiceStatsLocked() {
- return new Serv();
+ return new Serv(mBsi);
}
}
@@ -6948,7 +7073,7 @@
public Proc getProcessStatsLocked(String name) {
Proc ps = mProcessStats.get(name);
if (ps == null) {
- ps = new Proc(name);
+ ps = new Proc(mBsi, name);
mProcessStats.put(name, ps);
}
@@ -6977,7 +7102,7 @@
if (mProcessState == uidRunningState) return;
- final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long elapsedRealtime = mBsi.mClocks.elapsedRealtime();
if (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtime);
@@ -7011,7 +7136,7 @@
public Pkg getPackageStatsLocked(String name) {
Pkg ps = mPackageStats.get(name);
if (ps == null) {
- ps = new Pkg();
+ ps = new Pkg(mBsi);
mPackageStats.put(name, ps);
}
@@ -7046,7 +7171,7 @@
}
public void readWakeSummaryFromParcelLocked(String wlName, Parcel in) {
- Wakelock wl = new Wakelock();
+ Wakelock wl = new Wakelock(mBsi, this);
mWakelockStats.add(wlName, wl);
if (in.readInt() != 0) {
wl.getStopwatchTimer(WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
@@ -7068,19 +7193,20 @@
if (!create) {
return null;
}
- se = new Sensor(sensor);
+ se = new Sensor(mBsi, this, sensor);
mSensorStats.put(sensor, se);
}
StopwatchTimer t = se.mTimer;
if (t != null) {
return t;
}
- ArrayList<StopwatchTimer> timers = mSensorTimers.get(sensor);
+ ArrayList<StopwatchTimer> timers = mBsi.mSensorTimers.get(sensor);
if (timers == null) {
timers = new ArrayList<StopwatchTimer>();
- mSensorTimers.put(sensor, timers);
+ mBsi.mSensorTimers.put(sensor, timers);
}
- t = new StopwatchTimer(Uid.this, BatteryStats.SENSOR, timers, mOnBatteryTimeBase);
+ t = new StopwatchTimer(mBsi.mClocks, this, BatteryStats.SENSOR, timers,
+ mBsi.mOnBatteryTimeBase);
se.mTimer = t;
return t;
}
@@ -7186,11 +7312,18 @@
}
public BatteryStatsImpl getBatteryStats() {
- return BatteryStatsImpl.this;
+ return mBsi;
}
}
public BatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync) {
+ this(new SystemClocks(), systemDir, handler, externalSync);
+ }
+
+ public BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler,
+ ExternalStatsSync externalSync) {
+ init(clocks);
+
if (systemDir != null) {
mFile = new JournaledFile(new File(systemDir, "batterystats.bin"),
new File(systemDir, "batterystats.bin.tmp"));
@@ -7202,24 +7335,28 @@
mExternalSync = externalSync;
mHandler = new MyHandler(handler.getLooper());
mStartCount++;
- mScreenOnTimer = new StopwatchTimer(null, -1, null, mOnBatteryTimeBase);
+ mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase);
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
- mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mOnBatteryTimeBase);
- }
- mInteractiveTimer = new StopwatchTimer(null, -10, null, mOnBatteryTimeBase);
- mPowerSaveModeEnabledTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase);
- mDeviceIdleModeLightTimer = new StopwatchTimer(null, -11, null, mOnBatteryTimeBase);
- mDeviceIdleModeFullTimer = new StopwatchTimer(null, -14, null, mOnBatteryTimeBase);
- mDeviceLightIdlingTimer = new StopwatchTimer(null, -15, null, mOnBatteryTimeBase);
- mDeviceIdlingTimer = new StopwatchTimer(null, -12, null, mOnBatteryTimeBase);
- mPhoneOnTimer = new StopwatchTimer(null, -3, null, mOnBatteryTimeBase);
- for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
- mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i, null,
+ mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
mOnBatteryTimeBase);
}
- mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mOnBatteryTimeBase);
+ mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase);
+ mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
+ mOnBatteryTimeBase);
+ mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -11, null,
+ mOnBatteryTimeBase);
+ mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
+ mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null, mOnBatteryTimeBase);
+ mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase);
+ mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase);
+ for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
+ mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i, null,
+ mOnBatteryTimeBase);
+ }
+ mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
+ mOnBatteryTimeBase);
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
- mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i, null,
+ mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i, null,
mOnBatteryTimeBase);
}
for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
@@ -7232,31 +7369,34 @@
mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
ModemActivityInfo.TX_POWER_LEVELS);
- mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mOnBatteryTimeBase);
- mMobileRadioActivePerAppTimer = new StopwatchTimer(null, -401, null, mOnBatteryTimeBase);
+ mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null, mOnBatteryTimeBase);
+ mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
+ mOnBatteryTimeBase);
mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase);
mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase);
- mWifiOnTimer = new StopwatchTimer(null, -4, null, mOnBatteryTimeBase);
- mGlobalWifiRunningTimer = new StopwatchTimer(null, -5, null, mOnBatteryTimeBase);
+ mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase);
+ mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null, mOnBatteryTimeBase);
for (int i=0; i<NUM_WIFI_STATES; i++) {
- mWifiStateTimer[i] = new StopwatchTimer(null, -600-i, null, mOnBatteryTimeBase);
- }
- for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
- mWifiSupplStateTimer[i] = new StopwatchTimer(null, -700-i, null, mOnBatteryTimeBase);
- }
- for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
- mWifiSignalStrengthsTimer[i] = new StopwatchTimer(null, -800-i, null,
+ mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i, null,
mOnBatteryTimeBase);
}
- mAudioOnTimer = new StopwatchTimer(null, -7, null, mOnBatteryTimeBase);
- mVideoOnTimer = new StopwatchTimer(null, -8, null, mOnBatteryTimeBase);
- mFlashlightOnTimer = new StopwatchTimer(null, -9, null, mOnBatteryTimeBase);
- mCameraOnTimer = new StopwatchTimer(null, -13, null, mOnBatteryTimeBase);
- mBluetoothScanTimer = new StopwatchTimer(null, -14, null, mOnBatteryTimeBase);
+ for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
+ mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i, null,
+ mOnBatteryTimeBase);
+ }
+ for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
+ mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i, null,
+ mOnBatteryTimeBase);
+ }
+ mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
+ mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
+ mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase);
+ mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase);
+ mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
mOnBattery = mOnBatteryInternal = false;
- long uptime = SystemClock.uptimeMillis() * 1000;
- long realtime = SystemClock.elapsedRealtime() * 1000;
+ long uptime = mClocks.uptimeMillis() * 1000;
+ long realtime = mClocks.elapsedRealtime() * 1000;
initTimes(uptime, realtime);
mStartPlatformVersion = mEndPlatformVersion = Build.ID;
mDischargeStartLevel = 0;
@@ -7270,6 +7410,11 @@
}
public BatteryStatsImpl(Parcel p) {
+ this(new SystemClocks(), p);
+ }
+
+ public BatteryStatsImpl(Clocks clocks, Parcel p) {
+ init(clocks);
mFile = null;
mCheckinFile = null;
mDailyFile = null;
@@ -7808,9 +7953,9 @@
public void resetAllStatsCmdLocked() {
resetAllStatsLocked();
- final long mSecUptime = SystemClock.uptimeMillis();
+ final long mSecUptime = mClocks.uptimeMillis();
long uptime = mSecUptime * 1000;
- long mSecRealtime = SystemClock.elapsedRealtime();
+ long mSecRealtime = mClocks.elapsedRealtime();
long realtime = mSecRealtime * 1000;
mDischargeStartLevel = mHistoryCur.batteryLevel;
pullPendingStateUpdatesLocked();
@@ -7835,7 +7980,7 @@
private void resetAllStatsLocked() {
mStartCount = 0;
- initTimes(SystemClock.uptimeMillis() * 1000, SystemClock.elapsedRealtime() * 1000);
+ initTimes(mClocks.uptimeMillis() * 1000, mClocks.elapsedRealtime() * 1000);
mScreenOnTimer.reset(false);
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
mScreenBrightnessTimer[i].reset(false);
@@ -7983,17 +8128,8 @@
private static final int NETWORK_STATS_NEXT = 1;
private static final int NETWORK_STATS_DELTA = 2;
- private final NetworkStats[] mMobileNetworkStats = new NetworkStats[] {
- new NetworkStats(SystemClock.elapsedRealtime(), 50),
- new NetworkStats(SystemClock.elapsedRealtime(), 50),
- new NetworkStats(SystemClock.elapsedRealtime(), 50)
- };
-
- private final NetworkStats[] mWifiNetworkStats = new NetworkStats[] {
- new NetworkStats(SystemClock.elapsedRealtime(), 50),
- new NetworkStats(SystemClock.elapsedRealtime(), 50),
- new NetworkStats(SystemClock.elapsedRealtime(), 50)
- };
+ private NetworkStats[] mMobileNetworkStats;
+ private NetworkStats[] mWifiNetworkStats;
/**
* Retrieves the delta of network stats for the given network ifaces. Uses networkStatsBuffer
@@ -8026,7 +8162,7 @@
Slog.d(TAG, "Updating wifi stats");
}
- final long elapsedRealtimeMs = SystemClock.elapsedRealtime();
+ final long elapsedRealtimeMs = mClocks.elapsedRealtime();
NetworkStats delta = null;
try {
if (!ArrayUtils.isEmpty(mWifiIfaces)) {
@@ -8056,7 +8192,8 @@
+ " txPackets=" + entry.txPackets);
}
- if (entry.rxBytes == 0 || entry.txBytes == 0) {
+ if (entry.rxBytes == 0 && entry.txBytes == 0) {
+ // Skip the lookup below since there is no work to do.
continue;
}
@@ -8570,7 +8707,7 @@
SamplingTimer kwlt = mKernelWakelockStats.get(name);
if (kwlt == null) {
- kwlt = new SamplingTimer(mOnBatteryScreenOffTimeBase,
+ kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase,
true /* track reported val */);
mKernelWakelockStats.put(name, kwlt);
}
@@ -8663,7 +8800,7 @@
// Read the CPU data for each UID. This will internally generate a snapshot so next time
// we read, we get a delta. If we are to distribute the cpu time, then do so. Otherwise
// we just ignore the data.
- final long startTimeMs = SystemClock.elapsedRealtime();
+ final long startTimeMs = mClocks.elapsedRealtime();
mKernelUidCpuTimeReader.readDelta(!mOnBatteryInternal ? null :
new KernelUidCpuTimeReader.Callback() {
@Override
@@ -8735,7 +8872,7 @@
});
if (DEBUG_ENERGY_CPU) {
- Slog.d(TAG, "Reading cpu stats took " + (SystemClock.elapsedRealtime() - startTimeMs) +
+ Slog.d(TAG, "Reading cpu stats took " + (mClocks.elapsedRealtime() - startTimeMs) +
" ms");
}
@@ -9000,8 +9137,8 @@
public void setBatteryStateLocked(int status, int health, int plugType, int level,
int temp, int volt) {
final boolean onBattery = plugType == BATTERY_PLUGGED_NONE;
- final long uptime = SystemClock.uptimeMillis();
- final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
if (!mHaveBatteryLevel) {
mHaveBatteryLevel = true;
// We start out assuming that the device is plugged in (not
@@ -9147,7 +9284,7 @@
}
public long getAwakeTimePlugged() {
- return (SystemClock.uptimeMillis() * 1000) - getAwakeTimeBattery();
+ return (mClocks.uptimeMillis() * 1000) - getAwakeTimeBattery();
}
@Override
@@ -9310,8 +9447,8 @@
return mDailyPackageChanges;
}
- long getBatteryUptimeLocked() {
- return mOnBatteryTimeBase.getUptime(SystemClock.uptimeMillis() * 1000);
+ protected long getBatteryUptimeLocked() {
+ return mOnBatteryTimeBase.getUptime(mClocks.uptimeMillis() * 1000);
}
@Override
@@ -9429,7 +9566,7 @@
public Uid getUidStatsLocked(int uid) {
Uid u = mUidStats.get(uid);
if (u == null) {
- u = new Uid(uid);
+ u = new Uid(this, uid);
mUidStats.put(uid, u);
}
return u;
@@ -9474,7 +9611,7 @@
}
public void shutdownLocked() {
- recordShutdownLocked(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
+ recordShutdownLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis());
writeSyncLocked();
mShuttingDown = true;
}
@@ -9502,7 +9639,7 @@
Parcel out = Parcel.obtain();
writeSummaryToParcel(out, true);
- mLastWriteTime = SystemClock.elapsedRealtime();
+ mLastWriteTime = mClocks.elapsedRealtime();
if (mPendingWrite != null) {
mPendingWrite.recycle();
@@ -9583,8 +9720,8 @@
if (mHistoryBuffer.dataPosition() > 0) {
mRecordingHistory = true;
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
+ final long elapsedRealtime = mClocks.elapsedRealtime();
+ final long uptime = mClocks.uptimeMillis();
if (USE_OLD_HISTORY) {
addHistoryRecordLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
}
@@ -9663,7 +9800,7 @@
// We are just arbitrarily going to insert 1 minute from the sample of
// the last run until samples in this run.
if (mHistoryBaseTime > 0) {
- long oldnow = SystemClock.elapsedRealtime();
+ long oldnow = mClocks.elapsedRealtime();
mHistoryBaseTime = mHistoryBaseTime - oldnow + 1;
if (DEBUG_HISTORY) {
StringBuilder sb = new StringBuilder(128);
@@ -9870,7 +10007,7 @@
}
for (int iu = 0; iu < NU; iu++) {
int uid = in.readInt();
- Uid u = new Uid(uid);
+ Uid u = new Uid(this, uid);
mUidStats.put(uid, u);
u.mWifiRunning = false;
@@ -10083,8 +10220,8 @@
// if we had originally pulled a time before the RTC was set.
long startClockTime = getStartClockTime();
- final long NOW_SYS = SystemClock.uptimeMillis() * 1000;
- final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000;
+ final long NOW_SYS = mClocks.uptimeMillis() * 1000;
+ final long NOWREAL_SYS = mClocks.elapsedRealtime() * 1000;
out.writeInt(VERSION);
@@ -10469,29 +10606,34 @@
mOnBatteryScreenOffTimeBase.readFromParcel(in);
mScreenState = Display.STATE_UNKNOWN;
- mScreenOnTimer = new StopwatchTimer(null, -1, null, mOnBatteryTimeBase, in);
+ mScreenOnTimer = new StopwatchTimer(mClocks, null, -1, null, mOnBatteryTimeBase, in);
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
- mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mOnBatteryTimeBase,
- in);
+ mScreenBrightnessTimer[i] = new StopwatchTimer(mClocks, null, -100-i, null,
+ mOnBatteryTimeBase, in);
}
mInteractive = false;
- mInteractiveTimer = new StopwatchTimer(null, -10, null, mOnBatteryTimeBase, in);
+ mInteractiveTimer = new StopwatchTimer(mClocks, null, -10, null, mOnBatteryTimeBase, in);
mPhoneOn = false;
- mPowerSaveModeEnabledTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in);
+ mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null,
+ mOnBatteryTimeBase, in);
mLongestLightIdleTime = in.readLong();
mLongestFullIdleTime = in.readLong();
- mDeviceIdleModeLightTimer = new StopwatchTimer(null, -14, null, mOnBatteryTimeBase, in);
- mDeviceIdleModeFullTimer = new StopwatchTimer(null, -11, null, mOnBatteryTimeBase, in);
- mDeviceLightIdlingTimer = new StopwatchTimer(null, -15, null, mOnBatteryTimeBase, in);
- mDeviceIdlingTimer = new StopwatchTimer(null, -12, null, mOnBatteryTimeBase, in);
- mPhoneOnTimer = new StopwatchTimer(null, -3, null, mOnBatteryTimeBase, in);
+ mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -14, null,
+ mOnBatteryTimeBase, in);
+ mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -11, null,
+ mOnBatteryTimeBase, in);
+ mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null,
+ mOnBatteryTimeBase, in);
+ mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase, in);
+ mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase, in);
for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
- mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i,
+ mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i,
null, mOnBatteryTimeBase, in);
}
- mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mOnBatteryTimeBase, in);
+ mPhoneSignalScanningTimer = new StopwatchTimer(mClocks, null, -200+1, null,
+ mOnBatteryTimeBase, in);
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
- mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i,
+ mPhoneDataConnectionsTimer[i] = new StopwatchTimer(mClocks, null, -300-i,
null, mOnBatteryTimeBase, in);
}
for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
@@ -10499,27 +10641,29 @@
mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
}
mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
- mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mOnBatteryTimeBase, in);
- mMobileRadioActivePerAppTimer = new StopwatchTimer(null, -401, null, mOnBatteryTimeBase,
- in);
+ mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null,
+ mOnBatteryTimeBase, in);
+ mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
+ mOnBatteryTimeBase, in);
mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
mWifiOn = false;
- mWifiOnTimer = new StopwatchTimer(null, -4, null, mOnBatteryTimeBase, in);
+ mWifiOnTimer = new StopwatchTimer(mClocks, null, -4, null, mOnBatteryTimeBase, in);
mGlobalWifiRunning = false;
- mGlobalWifiRunningTimer = new StopwatchTimer(null, -5, null, mOnBatteryTimeBase, in);
+ mGlobalWifiRunningTimer = new StopwatchTimer(mClocks, null, -5, null,
+ mOnBatteryTimeBase, in);
for (int i=0; i<NUM_WIFI_STATES; i++) {
- mWifiStateTimer[i] = new StopwatchTimer(null, -600-i,
+ mWifiStateTimer[i] = new StopwatchTimer(mClocks, null, -600-i,
null, mOnBatteryTimeBase, in);
}
for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) {
- mWifiSupplStateTimer[i] = new StopwatchTimer(null, -700-i,
+ mWifiSupplStateTimer[i] = new StopwatchTimer(mClocks, null, -700-i,
null, mOnBatteryTimeBase, in);
}
for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
- mWifiSignalStrengthsTimer[i] = new StopwatchTimer(null, -800-i,
+ mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i,
null, mOnBatteryTimeBase, in);
}
@@ -10537,15 +10681,15 @@
mLoadedNumConnectivityChange = in.readInt();
mUnpluggedNumConnectivityChange = in.readInt();
mAudioOnNesting = 0;
- mAudioOnTimer = new StopwatchTimer(null, -7, null, mOnBatteryTimeBase);
+ mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
mVideoOnNesting = 0;
- mVideoOnTimer = new StopwatchTimer(null, -8, null, mOnBatteryTimeBase);
+ mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
mFlashlightOnNesting = 0;
- mFlashlightOnTimer = new StopwatchTimer(null, -9, null, mOnBatteryTimeBase, in);
+ mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase, in);
mCameraOnNesting = 0;
- mCameraOnTimer = new StopwatchTimer(null, -13, null, mOnBatteryTimeBase, in);
+ mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase, in);
mBluetoothScanNesting = 0;
- mBluetoothScanTimer = new StopwatchTimer(null, -14, null, mOnBatteryTimeBase, in);
+ mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase, in);
mDischargeUnplugLevel = in.readInt();
mDischargePlugLevel = in.readInt();
mDischargeCurrentLevel = in.readInt();
@@ -10565,7 +10709,7 @@
for (int ikw = 0; ikw < NKW; ikw++) {
if (in.readInt() != 0) {
String wakelockName = in.readString();
- SamplingTimer kwlt = new SamplingTimer(mOnBatteryScreenOffTimeBase, in);
+ SamplingTimer kwlt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
mKernelWakelockStats.put(wakelockName, kwlt);
}
}
@@ -10575,7 +10719,7 @@
for (int iwr = 0; iwr < NWR; iwr++) {
if (in.readInt() != 0) {
String reasonName = in.readString();
- SamplingTimer timer = new SamplingTimer(mOnBatteryTimeBase, in);
+ SamplingTimer timer = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
mWakeupReasonStats.put(reasonName, timer);
}
}
@@ -10597,7 +10741,7 @@
mUidStats.clear();
for (int i = 0; i < numUids; i++) {
int uid = in.readInt();
- Uid u = new Uid(uid);
+ Uid u = new Uid(this, uid);
u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in);
mUidStats.append(uid, u);
}
@@ -10620,8 +10764,8 @@
// if we had originally pulled a time before the RTC was set.
long startClockTime = getStartClockTime();
- final long uSecUptime = SystemClock.uptimeMillis() * 1000;
- final long uSecRealtime = SystemClock.elapsedRealtime() * 1000;
+ final long uSecUptime = mClocks.uptimeMillis() * 1000;
+ final long uSecRealtime = mClocks.elapsedRealtime() * 1000;
final long batteryRealtime = mOnBatteryTimeBase.getRealtime(uSecRealtime);
final long batteryScreenOffRealtime = mOnBatteryScreenOffTimeBase.getRealtime(uSecRealtime);
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 3b8b7cb..fff9d7c 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -20,6 +20,7 @@
import android.app.ActivityThread;
import android.app.ApplicationErrorReport;
import android.os.Build;
+import android.os.DeadObjectException;
import android.os.Debug;
import android.os.IBinder;
import android.os.Process;
@@ -57,8 +58,7 @@
private static final native void nativeSetExitWithoutCleanup(boolean exitWithoutCleanup);
private static int Clog_e(String tag, String msg, Throwable tr) {
- return Log.println_native(Log.LOG_ID_CRASH, Log.ERROR, tag,
- msg + '\n' + Log.getStackTraceString(tr));
+ return Log.printlns(Log.LOG_ID_CRASH, Log.ERROR, tag, msg, tr);
}
/**
@@ -97,10 +97,14 @@
ActivityManagerNative.getDefault().handleApplicationCrash(
mApplicationObject, new ApplicationErrorReport.CrashInfo(e));
} catch (Throwable t2) {
- try {
- Clog_e(TAG, "Error reporting crash", t2);
- } catch (Throwable t3) {
- // Even Clog_e() fails! Oh well.
+ if (t2 instanceof DeadObjectException) {
+ // System process is dead; ignore
+ } else {
+ try {
+ Clog_e(TAG, "Error reporting crash", t2);
+ } catch (Throwable t3) {
+ // Even Clog_e() fails! Oh well.
+ }
}
} finally {
// Try everything to make sure this process goes away.
@@ -359,8 +363,12 @@
System.exit(10);
}
} catch (Throwable t2) {
- Slog.e(TAG, "Error reporting WTF", t2);
- Slog.e(TAG, "Original WTF:", t);
+ if (t2 instanceof DeadObjectException) {
+ // System process is dead; ignore
+ } else {
+ Slog.e(TAG, "Error reporting WTF", t2);
+ Slog.e(TAG, "Original WTF:", t);
+ }
}
}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 6ad9e20..3abea26 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -36,6 +36,7 @@
import android.util.EventLog;
import android.util.Log;
import android.webkit.WebViewFactory;
+import android.widget.TextView;
import com.android.internal.os.InstallerConnection.InstallerException;
@@ -214,6 +215,7 @@
private static void preloadTextResources() {
Hyphenator.init();
+ TextView.preloadFontCache();
}
/**
@@ -497,11 +499,11 @@
try {
for (String classPathElement : classPathElements) {
+ // System server is fully AOTed and never profiled
+ // for profile guided compilation.
final int dexoptNeeded = DexFile.getDexOptNeeded(
- classPathElement, "*", instructionSet, false /* defer */);
+ classPathElement, instructionSet, DexFile.COMPILATION_TYPE_FULL);
if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
- // System server is fully AOTed and never profiled
- // for profile guided compilation.
installer.dexopt(classPathElement, Process.SYSTEM_UID, instructionSet,
dexoptNeeded, 0 /*dexFlags*/, null /*volumeUuid*/,
false /*useProfiles*/);
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index af3f7ec..df48d6d 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -198,7 +198,7 @@
int mStackId;
private boolean mWindowResizeCallbacksAdded = false;
-
+ private Drawable.Callback mLastBackgroundDrawableCb = null;
private BackdropFrameRenderer mBackdropFrameRenderer = null;
private Drawable mResizingBackgroundDrawable;
private Drawable mCaptionBackgroundDrawable;
@@ -585,14 +585,14 @@
w = 0;
}
if (DEBUG_MEASURE) Log.d(mLogTag, "Fixed width: " + w);
+ final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
if (w > 0) {
- final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
widthMeasureSpec = MeasureSpec.makeMeasureSpec(
Math.min(w, widthSize), EXACTLY);
fixedWidth = true;
} else {
widthMeasureSpec = MeasureSpec.makeMeasureSpec(
- widthMeasureSpec - mFloatingInsets.left - mFloatingInsets.right,
+ widthSize - mFloatingInsets.left - mFloatingInsets.right,
AT_MOST);
mApplyFloatingHorizontalInsets = true;
}
@@ -863,6 +863,7 @@
if (getBackground() != drawable) {
setBackgroundDrawable(drawable);
if (drawable != null) {
+ mResizingBackgroundDrawable = drawable;
drawable.getPadding(mBackgroundPadding);
} else {
mBackgroundPadding.setEmpty();
@@ -1001,7 +1002,8 @@
boolean consumingNavBar =
(attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
&& (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0
- && (sysUiVisibility & SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
+ && (sysUiVisibility & SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
+ || (insets != null && insets.shouldAlwaysConsumeNavBar());
// If we didn't request fullscreen layout, but we still got it because of the
// mForceWindowDrawsStatusBarBackground flag, also consume top inset.
@@ -1743,6 +1745,10 @@
mCaptionBackgroundDrawable = getContext().getDrawable(
R.drawable.decor_caption_title_focused);
}
+ if (mResizingBackgroundDrawable != null) {
+ mLastBackgroundDrawableCb = mResizingBackgroundDrawable.getCallback();
+ mResizingBackgroundDrawable.setCallback(null);
+ }
}
// Free floating overlapping windows require a caption.
@@ -1956,6 +1962,11 @@
/** Release the renderer thread which is usually done when the user stops resizing. */
private void releaseThreadedRenderer() {
+ if (mResizingBackgroundDrawable != null && mLastBackgroundDrawableCb != null) {
+ mResizingBackgroundDrawable.setCallback(mLastBackgroundDrawableCb);
+ mLastBackgroundDrawableCb = null;
+ }
+
if (mBackdropFrameRenderer != null) {
mBackdropFrameRenderer.releaseRenderer();
mBackdropFrameRenderer = null;
diff --git a/core/java/com/android/internal/policy/DockedDividerUtils.java b/core/java/com/android/internal/policy/DockedDividerUtils.java
index 00c65bd..c68e506 100644
--- a/core/java/com/android/internal/policy/DockedDividerUtils.java
+++ b/core/java/com/android/internal/policy/DockedDividerUtils.java
@@ -17,9 +17,9 @@
package com.android.internal.policy;
import android.graphics.Rect;
-import android.view.WindowManager;
import static android.view.WindowManager.DOCKED_BOTTOM;
+import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.DOCKED_LEFT;
import static android.view.WindowManager.DOCKED_RIGHT;
import static android.view.WindowManager.DOCKED_TOP;
@@ -35,46 +35,61 @@
int displayWidth, int displayHeight, int dividerSize) {
outRect.set(0, 0, displayWidth, displayHeight);
switch (dockSide) {
- case WindowManager.DOCKED_LEFT:
+ case DOCKED_LEFT:
outRect.right = position;
break;
- case WindowManager.DOCKED_TOP:
+ case DOCKED_TOP:
outRect.bottom = position;
break;
- case WindowManager.DOCKED_RIGHT:
+ case DOCKED_RIGHT:
outRect.left = position + dividerSize;
break;
- case WindowManager.DOCKED_BOTTOM:
+ case DOCKED_BOTTOM:
outRect.top = position + dividerSize;
break;
}
- sanitizeStackBounds(outRect);
+ sanitizeStackBounds(outRect, dockSide == DOCKED_LEFT || dockSide == DOCKED_TOP);
}
- public static void sanitizeStackBounds(Rect bounds) {
- if (bounds.left >= bounds.right) {
- bounds.left = bounds.right - 1;
- }
- if (bounds.top >= bounds.bottom) {
- bounds.top = bounds.bottom - 1;
- }
- if (bounds.right <= bounds.left) {
- bounds.right = bounds.left + 1;
- }
- if (bounds.bottom <= bounds.top) {
- bounds.bottom = bounds.top + 1;
+ /**
+ * Makes sure that the bounds are always valid, i. e. they are at least one pixel high and wide.
+ *
+ * @param bounds The bounds to sanitize.
+ * @param topLeft Pass true if the bounds are at the top/left of the screen, false if they are
+ * at the bottom/right. This is used to determine in which direction to extend
+ * the bounds.
+ */
+ public static void sanitizeStackBounds(Rect bounds, boolean topLeft) {
+
+ // If the bounds are either on the top or left of the screen, rather move it further to the
+ // left/top to make it more offscreen. If they are on the bottom or right, push them off the
+ // screen by moving it even more to the bottom/right.
+ if (topLeft) {
+ if (bounds.left >= bounds.right) {
+ bounds.left = bounds.right - 1;
+ }
+ if (bounds.top >= bounds.bottom) {
+ bounds.top = bounds.bottom - 1;
+ }
+ } else {
+ if (bounds.right <= bounds.left) {
+ bounds.right = bounds.left + 1;
+ }
+ if (bounds.bottom <= bounds.top) {
+ bounds.bottom = bounds.top + 1;
+ }
}
}
public static int calculatePositionForBounds(Rect bounds, int dockSide, int dividerSize) {
switch (dockSide) {
- case WindowManager.DOCKED_LEFT:
+ case DOCKED_LEFT:
return bounds.right;
- case WindowManager.DOCKED_TOP:
+ case DOCKED_TOP:
return bounds.bottom;
- case WindowManager.DOCKED_RIGHT:
+ case DOCKED_RIGHT:
return bounds.left - dividerSize;
- case WindowManager.DOCKED_BOTTOM:
+ case DOCKED_BOTTOM:
return bounds.top - dividerSize;
default:
return 0;
@@ -109,16 +124,16 @@
public static int invertDockSide(int dockSide) {
switch (dockSide) {
- case WindowManager.DOCKED_LEFT:
- return WindowManager.DOCKED_RIGHT;
- case WindowManager.DOCKED_TOP:
- return WindowManager.DOCKED_BOTTOM;
- case WindowManager.DOCKED_RIGHT:
- return WindowManager.DOCKED_LEFT;
- case WindowManager.DOCKED_BOTTOM:
- return WindowManager.DOCKED_TOP;
+ case DOCKED_LEFT:
+ return DOCKED_RIGHT;
+ case DOCKED_TOP:
+ return DOCKED_BOTTOM;
+ case DOCKED_RIGHT:
+ return DOCKED_LEFT;
+ case DOCKED_BOTTOM:
+ return DOCKED_TOP;
default:
- return WindowManager.DOCKED_INVALID;
+ return DOCKED_INVALID;
}
}
}
diff --git a/core/java/android/hardware/ICameraServiceListener.aidl b/core/java/com/android/internal/policy/IShortcutService.aidl
similarity index 62%
rename from core/java/android/hardware/ICameraServiceListener.aidl
rename to core/java/com/android/internal/policy/IShortcutService.aidl
index 49278b6..8550728 100644
--- a/core/java/android/hardware/ICameraServiceListener.aidl
+++ b/core/java/com/android/internal/policy/IShortcutService.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,15 +14,16 @@
* limitations under the License.
*/
-package android.hardware;
+package com.android.internal.policy;
-/** @hide */
-interface ICameraServiceListener
-{
+/**
+ * An interface to notify the shortcut service that a shortcut key is pressed
+ * @hide
+ */
+oneway interface IShortcutService {
/**
- * Keep up-to-date with frameworks/av/include/camera/ICameraServiceListener.h
+ * @param shortcutCode the keycode packed with meta information
*/
- void onStatusChanged(int status, int cameraId);
-
- void onTorchStatusChanged(int status, String cameraId);
+ void notifyShortcutKeyPressed(long shortcutCode);
}
+
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 08d4fba..64c5b8d 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -60,6 +60,7 @@
void showRecentApps(boolean triggeredFromAltTab);
void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
void toggleRecentApps();
+ void toggleSplitScreen();
void preloadRecentApps();
void cancelPreloadRecentApps();
void showScreenPinningRequest();
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index 8026949..a84a061 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -27,6 +27,7 @@
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import java.util.Objects;
/**
@@ -126,6 +127,13 @@
/**
* Checks if given array is null or has zero elements.
*/
+ public static boolean isEmpty(@Nullable List<?> array) {
+ return array == null || array.isEmpty();
+ }
+
+ /**
+ * Checks if given array is null or has zero elements.
+ */
public static <T> boolean isEmpty(@Nullable T[] array) {
return array == null || array.length == 0;
}
diff --git a/core/java/com/android/internal/util/MessageUtils.java b/core/java/com/android/internal/util/MessageUtils.java
new file mode 100644
index 0000000..184245e
--- /dev/null
+++ b/core/java/com/android/internal/util/MessageUtils.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import android.os.Message;
+import android.util.Log;
+import android.util.SparseArray;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+/**
+ * Static utility class for dealing with {@link Message} objects.
+ */
+public class MessageUtils {
+
+ private static final String TAG = MessageUtils.class.getSimpleName();
+ private static final boolean DBG = false;
+
+ /** Thrown when two different constants have the same value. */
+ public static class DuplicateConstantError extends Error {
+ private DuplicateConstantError() {}
+ public DuplicateConstantError(String name1, String name2, int value) {
+ super(String.format("Duplicate constant value: both %s and %s = %d",
+ name1, name2, value));
+ }
+ }
+
+ /**
+ * Finds the names of integer constants. Searches the specified {@code classes}, looking for
+ * accessible static integer fields whose names begin with one of the specified {@prefixes}.
+ *
+ * @param classes the classes to examine.
+ * @prefixes only consider fields names starting with one of these prefixes.
+ * @return a {@link SparseArray} mapping integer constants to their names.
+ */
+ public static SparseArray<String> findMessageNames(Class[] classes, String[] prefixes) {
+ SparseArray<String> messageNames = new SparseArray<>();
+ for (Class c : classes) {
+ String className = c.getName();
+ if (DBG) Log.d(TAG, "Examining class " + className);
+
+ Field[] fields;
+ try {
+ fields = c.getDeclaredFields();
+ } catch (SecurityException e) {
+ Log.e(TAG, "Can't list fields of class " + className);
+ continue;
+ }
+
+ for (Field field : fields) {
+ int modifiers = field.getModifiers();
+ if (!Modifier.isStatic(modifiers) | !Modifier.isFinal(modifiers)) {
+ continue;
+ }
+
+ String name = field.getName();
+ for (String prefix : prefixes) {
+ // Does this look like a constant?
+ if (!name.startsWith(prefix)) {
+ continue;
+ }
+
+ try {
+ // TODO: can we have the caller try to access the field instead, so we don't
+ // expose constants it does not have access to?
+ field.setAccessible(true);
+
+ // Fetch the constant's value.
+ int value;
+ try {
+ value = field.getInt(null);
+ } catch (IllegalArgumentException | ExceptionInInitializerError e) {
+ // The field is not an integer (or short or byte), or c's static
+ // initializer failed and we have no idea what its value is.
+ // Either way, give up on this field.
+ break;
+ }
+
+ // Check for duplicate values.
+ String previousName = messageNames.get(value);
+ if (previousName != null && !previousName.equals(name)) {
+ throw new DuplicateConstantError(name, previousName, value);
+ }
+
+ messageNames.put(value, name);
+ if (DBG) {
+ Log.d(TAG, String.format("Found constant: %s.%s = %d",
+ className, name, value));
+ }
+ } catch (SecurityException | IllegalAccessException e) {
+ // Not allowed to make the field accessible, or no access. Ignore.
+ continue;
+ }
+ }
+ }
+ }
+ return messageNames;
+ }
+
+ /**
+ * Default prefixes for constants.
+ */
+ public static final String[] DEFAULT_PREFIXES = {"CMD_", "EVENT_"};
+
+ /**
+ * Finds the names of integer constants. Searches the specified {@code classes}, looking for
+ * accessible static integer values whose names begin with {@link #DEFAULT_PREFIXES}.
+ *
+ * @param classNames the classes to examine.
+ * @prefixes only consider fields names starting with one of these prefixes.
+ * @return a {@link SparseArray} mapping integer constants to their names.
+ */
+ public static SparseArray<String> findMessageNames(Class[] classNames) {
+ return findMessageNames(classNames, DEFAULT_PREFIXES);
+ }
+}
+
diff --git a/core/java/com/android/internal/util/WakeupMessage.java b/core/java/com/android/internal/util/WakeupMessage.java
index 77859b8..2653745 100644
--- a/core/java/com/android/internal/util/WakeupMessage.java
+++ b/core/java/com/android/internal/util/WakeupMessage.java
@@ -21,6 +21,8 @@
import android.os.Handler;
import android.os.Message;
+import com.android.internal.annotations.VisibleForTesting;
+
/**
* An AlarmListener that sends the specified message to a Handler and keeps the system awake until
* the message is processed.
@@ -33,19 +35,21 @@
* the message, but does not guarantee that the system will be awake until the target object has
* processed it. This is because as soon as the onAlarmListener sends the message and returns, the
* AlarmManager releases its wakelock and the system is free to go to sleep again.
- *
*/
public class WakeupMessage implements AlarmManager.OnAlarmListener {
- private static AlarmManager sAlarmManager;
- private final Handler mHandler;
- private final String mCmdName;
- private final int mCmd, mArg1, mArg2;
+ private final AlarmManager mAlarmManager;
+
+ @VisibleForTesting
+ protected final Handler mHandler;
+ @VisibleForTesting
+ protected final String mCmdName;
+ @VisibleForTesting
+ protected final int mCmd, mArg1, mArg2;
+ private boolean mScheduled;
public WakeupMessage(Context context, Handler handler,
String cmdName, int cmd, int arg1, int arg2) {
- if (sAlarmManager == null) {
- sAlarmManager = context.getSystemService(AlarmManager.class);
- }
+ mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
mHandler = handler;
mCmdName = cmdName;
mCmd = cmd;
@@ -61,19 +65,43 @@
this(context, handler, cmdName, cmd, 0, 0);
}
- public void schedule(long when) {
- sAlarmManager.setExact(
+ /**
+ * Schedule the message to be delivered at the time in milliseconds of the
+ * {@link android.os.SystemClock#elapsedRealtime SystemClock.elapsedRealtime()} clock and wakeup
+ * the device when it goes off. If schedule is called multiple times without the message being
+ * dispatched then the alarm is rescheduled to the new time.
+ */
+ public synchronized void schedule(long when) {
+ mAlarmManager.setExact(
AlarmManager.ELAPSED_REALTIME_WAKEUP, when, mCmdName, this, mHandler);
+ mScheduled = true;
}
- public void cancel() {
- sAlarmManager.cancel(this);
+ /**
+ * Cancel all pending messages. This includes alarms that may have been fired, but have not been
+ * run on the handler yet.
+ */
+ public synchronized void cancel() {
+ if (mScheduled) {
+ mAlarmManager.cancel(this);
+ mScheduled = false;
+ }
}
@Override
public void onAlarm() {
- Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2);
- mHandler.handleMessage(msg);
- msg.recycle();
+ // Once this method is called the alarm has already been fired and removed from
+ // AlarmManager (it is still partially tracked, but only for statistics). The alarm can now
+ // be marked as unscheduled so that it can be rescheduled in the message handler.
+ final boolean stillScheduled;
+ synchronized (this) {
+ stillScheduled = mScheduled;
+ mScheduled = false;
+ }
+ if (stillScheduled) {
+ Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2);
+ mHandler.handleMessage(msg);
+ msg.recycle();
+ }
}
}
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index bcc310f..ab918c8 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -38,7 +38,7 @@
@Override
public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets,
Rect stableInsets, Rect outsets, boolean reportDraw, Configuration newConfig,
- Rect backDropFrame, boolean forceLayout) {
+ Rect backDropFrame, boolean forceLayout, boolean alwaysConsumeNavBar) {
if (reportDraw) {
try {
mSession.finishDrawing(this);
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index db3ecc6..5576f13 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -46,17 +46,14 @@
in IInputContext inputContext, int uid, int pid);
void removeClient(in IInputMethodClient client);
- InputBindResult startInput(/* @InputMethodClient.StartInputReason */ int startInputReason,
- in IInputMethodClient client, IInputContext inputContext, in EditorInfo attribute,
- int controlFlags);
void finishInput(in IInputMethodClient client);
boolean showSoftInput(in IInputMethodClient client, int flags,
in ResultReceiver resultReceiver);
boolean hideSoftInput(in IInputMethodClient client, int flags,
in ResultReceiver resultReceiver);
- // Report that a window has gained focus. If 'attribute' is non-null,
- // this will also do a startInput.
- InputBindResult windowGainedFocus(
+ // If windowToken is null, this just does startInput(). Otherwise this reports that a window
+ // has gained focus, and if 'attribute' is non-null then also does startInput.
+ InputBindResult startInputOrWindowGainedFocus(
/* @InputMethodClient.StartInputReason */ int startInputReason,
in IInputMethodClient client, in IBinder windowToken, int controlFlags,
int softInputMode, int windowFlags, in EditorInfo attribute,
diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java
index 94790c1..fc67245 100644
--- a/core/java/com/android/internal/view/InputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/InputConnectionWrapper.java
@@ -17,6 +17,7 @@
package com.android.internal.view;
import android.os.Bundle;
+import android.os.Handler;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;
@@ -454,4 +455,9 @@
}
return result;
}
+
+ public Handler getHandler() {
+ // Nothing should happen when called from input method.
+ return null;
+ }
}
diff --git a/core/java/com/android/internal/widget/ImageFloatingTextView.java b/core/java/com/android/internal/widget/ImageFloatingTextView.java
index c4ed2e1..78c5e34 100644
--- a/core/java/com/android/internal/widget/ImageFloatingTextView.java
+++ b/core/java/com/android/internal/widget/ImageFloatingTextView.java
@@ -65,6 +65,8 @@
.setTextDirection(getTextDirectionHeuristic())
.setLineSpacing(getLineSpacingExtra(), getLineSpacingMultiplier())
.setIncludePad(getIncludeFontPadding())
+ .setEllipsize(shouldEllipsize ? effectiveEllipsize : null)
+ .setEllipsizedWidth(ellipsisWidth)
.setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY)
.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
// we set the endmargin on the first 2 lines. this works just in our case but that's
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index cbc735f..795012d 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -896,8 +896,7 @@
* @return true if device is file encrypted
*/
public static boolean isFileEncryptionEnabled() {
- final String status = SystemProperties.get("ro.crypto.type", "");
- return "file".equalsIgnoreCase(status);
+ return StorageManager.isFileBasedEncryptionEnabled();
}
/**
diff --git a/core/java/com/android/internal/widget/MediaNotificationView.java b/core/java/com/android/internal/widget/MediaNotificationView.java
index b45fd06..6bba1b3 100644
--- a/core/java/com/android/internal/widget/MediaNotificationView.java
+++ b/core/java/com/android/internal/widget/MediaNotificationView.java
@@ -21,6 +21,7 @@
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.RemoteViews;
@@ -31,16 +32,16 @@
* @hide
*/
@RemoteViews.RemoteView
-public class MediaNotificationView extends RelativeLayout {
+public class MediaNotificationView extends FrameLayout {
private final int mMaxImageSize;
- private final int mImageMarginBottom;
private final int mImageMinTopMargin;
private final int mNotificationContentMarginEnd;
private final int mNotificationContentImageMarginEnd;
private ImageView mRightIcon;
private View mActions;
private View mHeader;
+ private View mMainColumn;
public MediaNotificationView(Context context) {
this(context, null);
@@ -61,39 +62,49 @@
if (hasIcon && mode != MeasureSpec.UNSPECIFIED) {
measureChild(mActions, widthMeasureSpec, heightMeasureSpec);
int size = MeasureSpec.getSize(widthMeasureSpec);
- int height = MeasureSpec.getSize(heightMeasureSpec);
size = size - mActions.getMeasuredWidth();
ViewGroup.MarginLayoutParams layoutParams =
(MarginLayoutParams) mRightIcon.getLayoutParams();
- size -= layoutParams.getMarginEnd();
+ int imageEndMargin = layoutParams.getMarginEnd();
+ size -= imageEndMargin;
size = Math.min(size, mMaxImageSize);
size = Math.max(size, mRightIcon.getMinimumWidth());
layoutParams.width = size;
layoutParams.height = size;
- // because we can't allign it to the bottom with a margin, we add a topmargin to it
- layoutParams.topMargin = height - size - mImageMarginBottom;
- // If the topMargin is high enough we can also remove the header constraint!
- if (layoutParams.topMargin >= mImageMinTopMargin) {
- resetHeaderIndention();
- } else {
- int paddingEnd = mNotificationContentImageMarginEnd;
- ViewGroup.MarginLayoutParams headerParams =
- (MarginLayoutParams) mHeader.getLayoutParams();
- headerParams.setMarginEnd(size + layoutParams.getMarginEnd());
- if (mHeader.getPaddingEnd() != paddingEnd) {
- mHeader.setPadding(
- isLayoutRtl() ? paddingEnd : mHeader.getPaddingLeft(),
- mHeader.getPaddingTop(),
- isLayoutRtl() ? mHeader.getPaddingLeft() : paddingEnd,
- mHeader.getPaddingBottom());
- mHeader.setLayoutParams(headerParams);
- }
- }
mRightIcon.setLayoutParams(layoutParams);
- } else if (!hasIcon && mHeader.getPaddingEnd() != mNotificationContentMarginEnd) {
- resetHeaderIndention();
+
+ // lets ensure that the main column doesn't run into the image
+ ViewGroup.MarginLayoutParams mainParams
+ = (MarginLayoutParams) mMainColumn.getLayoutParams();
+ int marginEnd = size + imageEndMargin + mNotificationContentMarginEnd;
+ if (marginEnd != mainParams.getMarginEnd()) {
+ mainParams.setMarginEnd(marginEnd);
+ mMainColumn.setLayoutParams(mainParams);
+ }
+
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ ViewGroup.MarginLayoutParams iconParams =
+ (MarginLayoutParams) mRightIcon.getLayoutParams();
+ int topMargin = getMeasuredHeight() - mRightIcon.getMeasuredHeight()
+ - iconParams.bottomMargin;
+ // If the topMargin is high enough we can also remove the header constraint!
+ if (!hasIcon || topMargin >= mImageMinTopMargin) {
+ resetHeaderIndention();
+ } else {
+ int paddingEnd = mNotificationContentImageMarginEnd;
+ ViewGroup.MarginLayoutParams headerParams =
+ (MarginLayoutParams) mHeader.getLayoutParams();
+ headerParams.setMarginEnd(mRightIcon.getMeasuredWidth() + iconParams.getMarginEnd());
+ if (mHeader.getPaddingEnd() != paddingEnd) {
+ mHeader.setPadding(
+ isLayoutRtl() ? paddingEnd : mHeader.getPaddingLeft(),
+ mHeader.getPaddingTop(),
+ isLayoutRtl() ? mHeader.getPaddingLeft() : paddingEnd,
+ mHeader.getPaddingBottom());
+ mHeader.setLayoutParams(headerParams);
+ }
+ }
}
private void resetHeaderIndention() {
@@ -115,8 +126,6 @@
super(context, attrs, defStyleAttr, defStyleRes);
mMaxImageSize = context.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.media_notification_expanded_image_max_size);
- mImageMarginBottom = context.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.media_notification_expanded_image_margin_bottom);
mImageMinTopMargin = (int) (context.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.notification_content_margin_top)
+ getResources().getDisplayMetrics().density * 2);
@@ -132,5 +141,6 @@
mRightIcon = (ImageView) findViewById(com.android.internal.R.id.right_icon);
mActions = findViewById(com.android.internal.R.id.media_actions);
mHeader = findViewById(com.android.internal.R.id.notification_header);
+ mMainColumn = findViewById(com.android.internal.R.id.notification_main_column);
}
}
diff --git a/core/java/com/android/server/net/NetworkPinner.java b/core/java/com/android/server/net/NetworkPinner.java
new file mode 100644
index 0000000..d922a48
--- /dev/null
+++ b/core/java/com/android/server/net/NetworkPinner.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.net;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.Network;
+import android.net.NetworkRequest;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * A class that pins a process to the first network that satisfies a particular NetworkRequest.
+ *
+ * We use this to maintain compatibility with pre-M apps that call WifiManager.enableNetwork()
+ * to connect to a Wi-Fi network that has no Internet access, and then assume that they will be
+ * able to use that network because it's the system default.
+ *
+ * In order to maintain compatibility with apps that call setProcessDefaultNetwork themselves,
+ * we try not to set the default network unless they have already done so, and we try not to
+ * clear the default network unless we set it ourselves.
+ *
+ * This should maintain behaviour that's compatible with L, which would pin the whole system to
+ * any wifi network that was created via enableNetwork(..., true) until that network
+ * disconnected.
+ *
+ * Note that while this hack allows network traffic to flow, it is quite limited. For example:
+ *
+ * 1. setProcessDefaultNetwork only affects this process, so:
+ * - Any subprocesses spawned by this process will not be pinned to Wi-Fi.
+ * - If this app relies on any other apps on the device also being on Wi-Fi, that won't work
+ * either, because other apps on the device will not be pinned.
+ * 2. The behaviour of other APIs is not modified. For example:
+ * - getActiveNetworkInfo will return the system default network, not Wi-Fi.
+ * - There will be no CONNECTIVITY_ACTION broadcasts about TYPE_WIFI.
+ * - getProcessDefaultNetwork will not return null, so if any apps are relying on that, they
+ * will be surprised as well.
+ *
+ * This class is a per-process singleton because the process default network is a per-process
+ * singleton.
+ *
+ */
+public class NetworkPinner extends NetworkCallback {
+
+ private static final String TAG = NetworkPinner.class.getSimpleName();
+
+ @VisibleForTesting
+ protected static final Object sLock = new Object();
+
+ @GuardedBy("sLock")
+ private static ConnectivityManager sCM;
+ @GuardedBy("sLock")
+ private static Callback sCallback;
+ @VisibleForTesting
+ @GuardedBy("sLock")
+ protected static Network sNetwork;
+
+ private static void maybeInitConnectivityManager(Context context) {
+ // TODO: what happens if an app calls a WifiManager API before ConnectivityManager is
+ // registered? Can we fix this by starting ConnectivityService before WifiService?
+ if (sCM == null) {
+ // Getting a ConnectivityManager does not leak the calling context, because it stores
+ // the application context and not the calling context.
+ sCM = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ if (sCM == null) {
+ throw new IllegalStateException("Bad luck, ConnectivityService not started.");
+ }
+ }
+ }
+
+ private static class Callback extends NetworkCallback {
+ @Override
+ public void onAvailable(Network network) {
+ synchronized(sLock) {
+ if (this != sCallback) return;
+
+ if (sCM.getBoundNetworkForProcess() == null && sNetwork == null) {
+ sCM.bindProcessToNetwork(network);
+ sNetwork = network;
+ Log.d(TAG, "Wifi alternate reality enabled on network " + network);
+ }
+ sLock.notify();
+ }
+ }
+
+ @Override
+ public void onLost(Network network) {
+ synchronized (sLock) {
+ if (this != sCallback) return;
+
+ if (network.equals(sNetwork) && network.equals(sCM.getBoundNetworkForProcess())) {
+ unpin();
+ Log.d(TAG, "Wifi alternate reality disabled on network " + network);
+ }
+ sLock.notify();
+ }
+ }
+ }
+
+ public static void pin(Context context, NetworkRequest request) {
+ synchronized (sLock) {
+ if (sCallback == null) {
+ maybeInitConnectivityManager(context);
+ sCallback = new Callback();
+ try {
+ sCM.registerNetworkCallback(request, sCallback);
+ } catch (SecurityException e) {
+ Log.d(TAG, "Failed to register network callback", e);
+ sCallback = null;
+ }
+ }
+ }
+ }
+
+ public static void unpin() {
+ synchronized (sLock) {
+ if (sCallback != null) {
+ try {
+ sCM.bindProcessToNetwork(null);
+ sCM.unregisterNetworkCallback(sCallback);
+ } catch (SecurityException e) {
+ Log.d(TAG, "Failed to unregister network callback", e);
+ }
+ sCallback = null;
+ sNetwork = null;
+ }
+ }
+ }
+}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 1b6b53a..623b603 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -33,6 +33,8 @@
com_android_internal_content_NativeLibraryHelper.cpp \
com_google_android_gles_jni_EGLImpl.cpp \
com_google_android_gles_jni_GLImpl.cpp.arm \
+ android_app_Activity.cpp \
+ android_app_ApplicationLoaders.cpp \
android_app_NativeActivity.cpp \
android_auditing_SecurityLog.cpp \
android_opengl_EGL14.cpp \
@@ -177,8 +179,7 @@
com_android_internal_net_NetworkStatsFactory.cpp \
com_android_internal_os_Zygote.cpp \
com_android_internal_util_VirtualRefBasePtr.cpp \
- com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp \
- android_os_HardwarePropertiesManager.cpp
+ com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE) \
@@ -189,7 +190,6 @@
$(call include-path-for, bluedroid) \
$(call include-path-for, libhardware)/hardware \
$(call include-path-for, libhardware_legacy)/hardware_legacy \
- $(TOP)/frameworks/av/include \
$(TOP)/frameworks/base/media/jni \
$(TOP)/system/core/base/include \
$(TOP)/system/core/include \
@@ -260,7 +260,8 @@
libprocessgroup \
libnativebridge \
libradio_metadata \
- libnativeloader
+ libnativeloader \
+ libmemunreachable \
LOCAL_SHARED_LIBRARIES += \
libhwui \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 223fc1a..2a04526 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -177,6 +177,8 @@
extern int register_android_backup_FileBackupHelperBase(JNIEnv *env);
extern int register_android_backup_BackupHelperDispatcher(JNIEnv *env);
extern int register_android_app_backup_FullBackup(JNIEnv *env);
+extern int register_android_app_ApplicationLoaders(JNIEnv* env);
+extern int register_android_app_Activity(JNIEnv *env);
extern int register_android_app_ActivityThread(JNIEnv *env);
extern int register_android_app_NativeActivity(JNIEnv *env);
extern int register_android_media_RemoteDisplay(JNIEnv *env);
@@ -198,7 +200,6 @@
extern int register_com_android_internal_net_NetworkStatsFactory(JNIEnv *env);
extern int register_com_android_internal_os_Zygote(JNIEnv *env);
extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env);
-extern int register_android_os_HardwarePropertiesManager(JNIEnv *env);
static AndroidRuntime* gCurRuntime = NULL;
@@ -1372,6 +1373,8 @@
REG_JNI(register_android_backup_FileBackupHelperBase),
REG_JNI(register_android_backup_BackupHelperDispatcher),
REG_JNI(register_android_app_backup_FullBackup),
+ REG_JNI(register_android_app_ApplicationLoaders),
+ REG_JNI(register_android_app_Activity),
REG_JNI(register_android_app_ActivityThread),
REG_JNI(register_android_app_NativeActivity),
REG_JNI(register_android_util_jar_StrictJarFile),
@@ -1390,7 +1393,6 @@
REG_JNI(register_android_animation_PropertyValuesHolder),
REG_JNI(register_com_android_internal_content_NativeLibraryHelper),
REG_JNI(register_com_android_internal_net_NetworkStatsFactory),
- REG_JNI(register_android_os_HardwarePropertiesManager),
};
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 8b248b0..29c1075 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -555,6 +555,12 @@
std::unique_ptr<SkFILEStream> fileStream(new SkFILEStream(file,
SkFILEStream::kCallerPasses_Ownership));
+ // If there is no offset for the file descriptor, we use SkFILEStream directly.
+ if (::lseek(descriptor, 0, SEEK_CUR) == 0) {
+ assert(isSeekable(dupDescriptor));
+ return doDecode(env, fileStream.release(), padding, bitmapFactoryOptions);
+ }
+
// Use a buffered stream. Although an SkFILEStream can be rewound, this
// ensures that SkImageDecoder::Factory never rewinds beyond the
// current position of the file descriptor.
@@ -584,7 +590,7 @@
static jboolean nativeIsSeekable(JNIEnv* env, jobject, jobject fileDescriptor) {
jint descriptor = jniGetFDFromFileDescriptor(env, fileDescriptor);
- return ::lseek64(descriptor, 0, SEEK_CUR) != -1 ? JNI_TRUE : JNI_FALSE;
+ return isSeekable(descriptor) ? JNI_TRUE : JNI_FALSE;
}
jobject decodeBitmap(JNIEnv* env, void* data, size_t size) {
diff --git a/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp b/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp
index ae99f0b..731d22a 100644
--- a/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp
+++ b/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp
@@ -39,7 +39,6 @@
#include <SkPoint.h>
#include <SkRect.h>
#include <SkTypeface.h>
-#include <SkUtils.h>
#include <hb.h>
@@ -82,17 +81,16 @@
static hb_bool_t harfbuzzGetGlyph(hb_font_t* hbFont, void* fontData, hb_codepoint_t unicode, hb_codepoint_t variationSelector, hb_codepoint_t* glyph, void* userData)
{
HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData);
+ SkPaint* paint = hbFontData->m_paint;
+ paint->setTextEncoding(SkPaint::kUTF32_TextEncoding);
if (unicode > 0x10ffff) {
unicode = 0xfffd;
}
- SkPaint* paint = hbFontData->m_paint;
- // It would be better to use kUTF32_TextEncoding directly
- paint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
+ SkUnichar unichar = unicode;
+
uint16_t glyph16;
- uint16_t unichar[2];
- size_t size = SkUTF16_FromUnichar(unicode, unichar);
- paint->textToGlyphs(unichar, size * sizeof(*unichar), &glyph16);
+ paint->textToGlyphs(&unichar, sizeof(unichar), &glyph16);
*glyph = glyph16;
return !!*glyph;
}
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index a3214eb..d00e94c 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -654,15 +654,14 @@
size_t measuredCount = 0;
float measured = 0;
- Layout layout;
- MinikinUtils::doLayout(&layout, &paint, bidiFlags, typeface, text, 0, count, count);
- float* advances = new float[count];
- layout.getAdvances(advances);
+ std::unique_ptr<float[]> advancesArray(new float[count]);
+ MinikinUtils::measureText(&paint, bidiFlags, typeface, text, 0, count, count,
+ advancesArray.get());
for (int i = 0; i < count; i++) {
// traverse in the given direction
int index = forwardScan ? i : (count - i - 1);
- float width = advances[index];
+ float width = advancesArray[index];
if (measured + width > maxWidth) {
break;
}
@@ -672,7 +671,6 @@
}
measured += width;
}
- delete[] advances;
if (jmeasured && env->GetArrayLength(jmeasured) > 0) {
AutoJavaFloatArray autoMeasured(env, jmeasured, 1);
@@ -824,10 +822,15 @@
static jfloat doRunAdvance(const Paint* paint, TypefaceImpl* typeface, const jchar buf[],
jint start, jint count, jint bufSize, jboolean isRtl, jint offset) {
- Layout layout;
int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
- MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, buf, start, count, bufSize);
- return getRunAdvance(layout, buf, start, count, offset);
+ if (offset == count) {
+ return MinikinUtils::measureText(paint, bidiFlags, typeface, buf, start, count,
+ bufSize, nullptr);
+ }
+ std::unique_ptr<float[]> advancesArray(new float[count]);
+ MinikinUtils::measureText(paint, bidiFlags, typeface, buf, start, count, bufSize,
+ advancesArray.get());
+ return getRunAdvance(advancesArray.get(), buf, start, count, offset);
}
static jfloat getRunAdvance___CIIIIZI_F(JNIEnv *env, jclass, jlong paintHandle,
@@ -845,11 +848,13 @@
static jint doOffsetForAdvance(const Paint* paint, TypefaceImpl* typeface, const jchar buf[],
jint start, jint count, jint bufSize, jboolean isRtl, jfloat advance) {
- Layout layout;
int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
- MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, buf, start, count, bufSize);
- return getOffsetForAdvance(layout, buf, start, count, advance);
+ std::unique_ptr<float[]> advancesArray(new float[count]);
+ MinikinUtils::measureText(paint, bidiFlags, typeface, buf, start, count, bufSize,
+ advancesArray.get());
+ return getOffsetForAdvance(advancesArray.get(), buf, start, count, advance);
}
+
static jint getOffsetForAdvance___CIIIIZF_I(JNIEnv *env, jclass, jlong paintHandle,
jlong typefaceHandle, jcharArray text, jint start, jint end, jint contextStart,
jint contextEnd, jboolean isRtl, jfloat advance) {
diff --git a/core/jni/android/graphics/Utils.cpp b/core/jni/android/graphics/Utils.cpp
index 4f9ce8b..5fa445e 100644
--- a/core/jni/android/graphics/Utils.cpp
+++ b/core/jni/android/graphics/Utils.cpp
@@ -116,3 +116,7 @@
}
return NULL;
}
+
+bool android::isSeekable(int descriptor) {
+ return ::lseek64(descriptor, 0, SEEK_CUR) != -1;
+}
diff --git a/core/jni/android/graphics/Utils.h b/core/jni/android/graphics/Utils.h
index c0b9410..d1a74a0 100644
--- a/core/jni/android/graphics/Utils.h
+++ b/core/jni/android/graphics/Utils.h
@@ -68,6 +68,10 @@
jobject nullObjectReturn(const char msg[]);
+/** Check if the file descriptor is seekable.
+ */
+bool isSeekable(int descriptor);
+
}; // namespace android
#endif // _ANDROID_GRAPHICS_UTILS_H_
diff --git a/core/jni/android_app_Activity.cpp b/core/jni/android_app_Activity.cpp
new file mode 100644
index 0000000..56f4f01
--- /dev/null
+++ b/core/jni/android_app_Activity.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <poll.h>
+
+#include <string>
+
+#include "core_jni_helpers.h"
+
+extern "C" void android_dlwarning(void*, void (*)(void*, const char*));
+
+namespace android
+{
+
+static jstring getDlWarning_native(JNIEnv* env, jobject) {
+ std::string msg;
+ android_dlwarning(&msg, [](void* obj, const char* msg) {
+ if (msg != nullptr) {
+ *reinterpret_cast<std::string*>(obj) = msg;
+ }
+ });
+
+ return msg.empty() ? nullptr : env->NewStringUTF(msg.c_str());
+}
+
+static const JNINativeMethod g_methods[] = {
+ { "getDlWarning",
+ "()Ljava/lang/String;",
+ reinterpret_cast<void*>(getDlWarning_native) },
+};
+
+static const char* const kActivityPathName = "android/app/Activity";
+
+int register_android_app_Activity(JNIEnv* env) {
+ return RegisterMethodsOrDie(env, kActivityPathName, g_methods, NELEM(g_methods));
+}
+
+} // namespace android
diff --git a/core/jni/android_app_ApplicationLoaders.cpp b/core/jni/android_app_ApplicationLoaders.cpp
new file mode 100644
index 0000000..89f22eb
--- /dev/null
+++ b/core/jni/android_app_ApplicationLoaders.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string>
+
+#include "nativeloader/native_loader.h"
+
+#include "core_jni_helpers.h"
+
+
+static jstring createClassloaderNamespace_native(JNIEnv* env,
+ jobject clazz,
+ jobject classLoader,
+ jint targetSdkVersion,
+ jstring librarySearchPath,
+ jstring libraryPermittedPath,
+ jboolean isShared) {
+ return android::CreateClassLoaderNamespace(env, targetSdkVersion,
+ classLoader, isShared == JNI_TRUE,
+ librarySearchPath, libraryPermittedPath);
+}
+
+static const JNINativeMethod g_methods[] = {
+ { "createClassloaderNamespace",
+ "(Ljava/lang/ClassLoader;ILjava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;",
+ reinterpret_cast<void*>(createClassloaderNamespace_native) },
+};
+
+static const char* const kApplicationLoadersPathName = "android/app/ApplicationLoaders";
+
+namespace android
+{
+
+int register_android_app_ApplicationLoaders(JNIEnv* env) {
+ return RegisterMethodsOrDie(env, kApplicationLoadersPathName, g_methods, NELEM(g_methods));
+}
+
+} // namespace android
diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp
index 88a56d2..6431b94 100644
--- a/core/jni/android_app_NativeActivity.cpp
+++ b/core/jni/android_app_NativeActivity.cpp
@@ -259,8 +259,7 @@
loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName,
jobject messageQueue, jstring internalDataDir, jstring obbDir,
jstring externalDataDir, jint sdkVersion, jobject jAssetMgr,
- jbyteArray savedState, jobject classLoader, jstring libraryPath,
- jstring isolationPath) {
+ jbyteArray savedState, jobject classLoader, jstring libraryPath) {
if (kLogTrace) {
ALOGD("loadNativeCode_native");
}
@@ -269,8 +268,7 @@
std::unique_ptr<NativeCode> code;
bool needNativeBridge = false;
- void* handle = OpenNativeLibrary(env, sdkVersion, pathStr, classLoader,
- false, libraryPath, isolationPath);
+ void* handle = OpenNativeLibrary(env, sdkVersion, pathStr, classLoader, libraryPath);
if (handle == NULL) {
if (NativeBridgeIsSupported(pathStr)) {
handle = NativeBridgeLoadLibrary(pathStr, RTLD_LAZY);
@@ -656,7 +654,7 @@
static const JNINativeMethod g_methods[] = {
{ "loadNativeCode",
- "(Ljava/lang/String;Ljava/lang/String;Landroid/os/MessageQueue;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILandroid/content/res/AssetManager;[BLjava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/String;)J",
+ "(Ljava/lang/String;Ljava/lang/String;Landroid/os/MessageQueue;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILandroid/content/res/AssetManager;[BLjava/lang/ClassLoader;Ljava/lang/String;)J",
(void*)loadNativeCode_native },
{ "getDlError", "()Ljava/lang/String;", (void*) getDlError_native },
{ "unloadNativeCode", "(J)V", (void*)unloadNativeCode_native },
diff --git a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
index 7a3c598..4b2a72d 100644
--- a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
+++ b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
@@ -43,12 +43,13 @@
return env;
}
-static AnimationListener* createAnimationListener(JNIEnv* env, jobject finishListener) {
+static AnimationListener* createAnimationListener(JNIEnv* env, jobject finishListener, jint id) {
class AnimationListenerBridge : public AnimationListener {
public:
- AnimationListenerBridge(JNIEnv* env, jobject finishListener) {
+ AnimationListenerBridge(JNIEnv* env, jobject finishListener, jint id) {
mFinishListener = env->NewGlobalRef(finishListener);
env->GetJavaVM(&mJvm);
+ mId = id;
}
virtual ~AnimationListenerBridge() {
@@ -63,7 +64,7 @@
env->CallStaticVoidMethod(
gVectorDrawableAnimatorClassInfo.clazz,
gVectorDrawableAnimatorClassInfo.callOnFinished,
- mFinishListener);
+ mFinishListener, mId);
releaseJavaObject();
}
@@ -76,8 +77,9 @@
JavaVM* mJvm;
jobject mFinishListener;
+ jint mId;
};
- return new AnimationListenerBridge(env, finishListener);
+ return new AnimationListenerBridge(env, finishListener, id);
}
static void addAnimator(JNIEnv*, jobject, jlong animatorSetPtr, jlong propertyHolderPtr,
@@ -142,15 +144,16 @@
holder->setPropertyDataSource(propertyData, length);
env->ReleaseFloatArrayElements(srcData, propertyData, JNI_ABORT);
}
-static void start(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener) {
+static void start(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener, jint id) {
PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr);
- // TODO: keep a ref count in finish listener
- AnimationListener* listener = createAnimationListener(env, finishListener);
+ AnimationListener* listener = createAnimationListener(env, finishListener, id);
set->start(listener);
}
-static void reverse(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener) {
- // TODO: implement reverse
+static void reverse(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener, jint id) {
+ PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr);
+ AnimationListener* listener = createAnimationListener(env, finishListener, id);
+ set->reverse(listener);
}
static void end(JNIEnv*, jobject, jlong animatorSetPtr) {
@@ -172,13 +175,13 @@
{"nCreatePathPropertyHolder", "!(JIFF)J", (void*)createPathPropertyHolder},
{"nCreateRootAlphaPropertyHolder", "!(JFF)J", (void*)createRootAlphaPropertyHolder},
{"nSetPropertyHolderData", "(J[FI)V", (void*)setPropertyHolderData},
- {"nStart", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;)V", (void*)start},
- {"nReverse", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;)V", (void*)reverse},
+ {"nStart", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;I)V", (void*)start},
+ {"nReverse", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;I)V", (void*)reverse},
{"nEnd", "!(J)V", (void*)end},
{"nReset", "!(J)V", (void*)reset},
};
-const char* const kClassPathName = "android/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator";
+const char* const kClassPathName = "android/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT";
int register_android_graphics_drawable_AnimatedVectorDrawable(JNIEnv* env) {
gVectorDrawableAnimatorClassInfo.clazz = FindClassOrDie(env, kClassPathName);
gVectorDrawableAnimatorClassInfo.clazz = MakeGlobalRefOrDie(env,
@@ -186,7 +189,7 @@
gVectorDrawableAnimatorClassInfo.callOnFinished = GetStaticMethodIDOrDie(
env, gVectorDrawableAnimatorClassInfo.clazz, "callOnFinished",
- "(Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;)V");
+ "(Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;I)V");
return RegisterMethodsOrDie(env, "android/graphics/drawable/AnimatedVectorDrawable",
gMethods, NELEM(gMethods));
}
diff --git a/core/jni/android_hardware_camera2_CameraMetadata.cpp b/core/jni/android_hardware_camera2_CameraMetadata.cpp
index 7930027..f37fd78 100644
--- a/core/jni/android_hardware_camera2_CameraMetadata.cpp
+++ b/core/jni/android_hardware_camera2_CameraMetadata.cpp
@@ -33,9 +33,9 @@
#include "core_jni_helpers.h"
#include "android_runtime/android_hardware_camera2_CameraMetadata.h"
+#include <android/hardware/ICameraService.h>
#include <binder/IServiceManager.h>
#include <camera/CameraMetadata.h>
-#include <camera/ICameraService.h>
#include <camera/VendorTagDescriptor.h>
#include <nativehelper/ScopedUtfChars.h>
#include <nativehelper/ScopedPrimitiveArray.h>
@@ -906,32 +906,35 @@
static jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jobject thiz) {
const String16 NAME("media.camera");
- sp<ICameraService> cameraService;
+ sp<hardware::ICameraService> cameraService;
status_t err = getService(NAME, /*out*/&cameraService);
if (err != OK) {
ALOGE("%s: Failed to get camera service, received error %s (%d)", __FUNCTION__,
strerror(-err), err);
- return err;
+ return hardware::ICameraService::ERROR_DISCONNECTED;
}
- sp<VendorTagDescriptor> desc;
- err = cameraService->getCameraVendorTagDescriptor(/*out*/desc);
+ sp<VendorTagDescriptor> desc = new VendorTagDescriptor();
+ binder::Status res = cameraService->getCameraVendorTagDescriptor(/*out*/desc.get());
- if (err == -EOPNOTSUPP) {
- ALOGW("%s: Camera HAL too old; does not support vendor tags", __FUNCTION__);
+ if (res.serviceSpecificErrorCode() == hardware::ICameraService::ERROR_DISCONNECTED) {
+ // No camera module available, not an error on devices with no cameras
VendorTagDescriptor::clearGlobalVendorTagDescriptor();
-
return OK;
- } else if (err != OK) {
- ALOGE("%s: Failed to setup vendor tag descriptors, received error %s (%d)",
- __FUNCTION__, strerror(-err), err);
- return err;
+ } else if (!res.isOk()) {
+ VendorTagDescriptor::clearGlobalVendorTagDescriptor();
+ ALOGE("%s: Failed to setup vendor tag descriptors: %s",
+ __FUNCTION__, res.toString8().string());
+ return res.serviceSpecificErrorCode();
}
err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
- return err;
+ if (err != OK) {
+ return hardware::ICameraService::ERROR_INVALID_OPERATION;
+ }
+ return OK;
}
} // extern "C"
diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
index cb0abb6..c6baf1c 100644
--- a/core/jni/android_hardware_camera2_DngCreator.cpp
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -80,6 +80,13 @@
return nullptr; \
}
+#define BAIL_IF_EXPR_RET_NULL_SP(expr, jnienv, tagId, writer) \
+ if (expr) { \
+ jniThrowExceptionFmt(jnienv, "java/lang/IllegalArgumentException", \
+ "Invalid metadata for tag %s (%x)", (writer)->getTagName(tagId), (tagId)); \
+ return nullptr; \
+ }
+
#define ANDROID_DNGCREATOR_CTX_JNI_ID "mNativeContext"
@@ -195,8 +202,8 @@
NativeContext::NativeContext(const CameraMetadata& characteristics, const CameraMetadata& result) :
mCharacteristics(std::make_shared<CameraMetadata>(characteristics)),
mResult(std::make_shared<CameraMetadata>(result)), mThumbnailWidth(0),
- mThumbnailHeight(0), mOrientation(0), mThumbnailSet(false), mGpsSet(false),
- mDescriptionSet(false), mCaptureTimeSet(false) {}
+ mThumbnailHeight(0), mOrientation(TAG_ORIENTATION_UNKNOWN), mThumbnailSet(false),
+ mGpsSet(false), mDescriptionSet(false), mCaptureTimeSet(false) {}
NativeContext::~NativeContext() {}
@@ -1096,7 +1103,7 @@
{
// Set orientation
- uint16_t orientation = 1; // Normal
+ uint16_t orientation = TAG_ORIENTATION_NORMAL;
BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_ORIENTATION, 1, &orientation, TIFF_IFD_0),
env, TAG_ORIENTATION, writer);
}
@@ -1138,12 +1145,27 @@
}
{
- // Set blacklevel tags
+ // Set blacklevel tags, using dynamic black level if available
camera_metadata_entry entry =
- characteristics.find(ANDROID_SENSOR_BLACK_LEVEL_PATTERN);
- BAIL_IF_EMPTY_RET_NULL_SP(entry, env, TAG_BLACKLEVEL, writer);
- const uint32_t* blackLevel = reinterpret_cast<const uint32_t*>(entry.data.i32);
- BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_BLACKLEVEL, entry.count, blackLevel,
+ results.find(ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL);
+ uint32_t blackLevelRational[8] = {0};
+ if (entry.count != 0) {
+ BAIL_IF_EXPR_RET_NULL_SP(entry.count != 4, env, TAG_BLACKLEVEL, writer);
+ for (size_t i = 0; i < entry.count; i++) {
+ blackLevelRational[i * 2] = static_cast<uint32_t>(entry.data.f[i] * 100);
+ blackLevelRational[i * 2 + 1] = 100;
+ }
+ } else {
+ // Fall back to static black level which is guaranteed
+ entry = characteristics.find(ANDROID_SENSOR_BLACK_LEVEL_PATTERN);
+ BAIL_IF_EXPR_RET_NULL_SP(entry.count != 4, env, TAG_BLACKLEVEL, writer);
+ for (size_t i = 0; i < entry.count; i++) {
+ blackLevelRational[i * 2] = static_cast<uint32_t>(entry.data.i32[i]);
+ blackLevelRational[i * 2 + 1] = 1;
+ }
+
+ }
+ BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_BLACKLEVEL, 4, blackLevelRational,
TIFF_IFD_0), env, TAG_BLACKLEVEL, writer);
uint16_t repeatDim[2] = {2, 2};
@@ -1913,8 +1935,10 @@
{
// Set bits per sample
- uint16_t bits = BITS_PER_RGB_SAMPLE;
- BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_BITSPERSAMPLE, 1, &bits, TIFF_IFD_0),
+ uint16_t bits[SAMPLES_PER_RGB_PIXEL];
+ for (int i = 0; i < SAMPLES_PER_RGB_PIXEL; i++) bits[i] = BITS_PER_RGB_SAMPLE;
+ BAIL_IF_INVALID_RET_NULL_SP(
+ writer->addEntry(TAG_BITSPERSAMPLE, SAMPLES_PER_RGB_PIXEL, bits, TIFF_IFD_0),
env, TAG_BITSPERSAMPLE, writer);
}
diff --git a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
index f1ea7ec..80f9d57 100644
--- a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
+++ b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
@@ -29,6 +29,7 @@
#include <gui/Surface.h>
#include <gui/IGraphicBufferProducer.h>
+#include <gui/IProducerListener.h>
#include <ui/GraphicBuffer.h>
#include <system/window.h>
#include <hardware/camera3.h>
@@ -93,27 +94,17 @@
cStep, yStride, cStride);
}
-static status_t configureSurface(const sp<ANativeWindow>& anw,
- int32_t width,
- int32_t height,
- int32_t pixelFmt,
- int32_t maxBufferSlack) {
+static status_t connectSurface(const sp<Surface>& surface, int32_t maxBufferSlack) {
status_t err = NO_ERROR;
- err = native_window_set_buffers_dimensions(anw.get(), width, height);
- if (err != NO_ERROR) {
- ALOGE("%s: Failed to set native window buffer dimensions, error %s (%d).", __FUNCTION__,
+
+ err = surface->connect(NATIVE_WINDOW_API_CAMERA, /*listener*/NULL);
+ if (err != OK) {
+ ALOGE("%s: Unable to connect to surface, error %s (%d).", __FUNCTION__,
strerror(-err), err);
return err;
}
- err = native_window_set_buffers_format(anw.get(), pixelFmt);
- if (err != NO_ERROR) {
- ALOGE("%s: Failed to set native window buffer format, error %s (%d).", __FUNCTION__,
- strerror(-err), err);
- return err;
- }
-
- err = native_window_set_usage(anw.get(), GRALLOC_USAGE_SW_WRITE_OFTEN);
+ err = native_window_set_usage(surface.get(), GRALLOC_USAGE_SW_WRITE_OFTEN);
if (err != NO_ERROR) {
ALOGE("%s: Failed to set native window usage flag, error %s (%d).", __FUNCTION__,
strerror(-err), err);
@@ -121,19 +112,17 @@
}
int minUndequeuedBuffers;
- err = anw.get()->query(anw.get(),
- NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
- &minUndequeuedBuffers);
+ err = static_cast<ANativeWindow*>(surface.get())->query(surface.get(),
+ NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers);
if (err != NO_ERROR) {
ALOGE("%s: Failed to get native window min undequeued buffers, error %s (%d).",
__FUNCTION__, strerror(-err), err);
return err;
}
- ALOGV("%s: Setting buffer count to %d, size to (%dx%d), fmt (0x%x)", __FUNCTION__,
- maxBufferSlack + 1 + minUndequeuedBuffers,
- width, height, pixelFmt);
- err = native_window_set_buffer_count(anw.get(), maxBufferSlack + 1 + minUndequeuedBuffers);
+ ALOGV("%s: Setting buffer count to %d", __FUNCTION__,
+ maxBufferSlack + 1 + minUndequeuedBuffers);
+ err = native_window_set_buffer_count(surface.get(), maxBufferSlack + 1 + minUndequeuedBuffers);
if (err != NO_ERROR) {
ALOGE("%s: Failed to set native window buffer count, error %s (%d).", __FUNCTION__,
strerror(-err), err);
@@ -509,6 +498,26 @@
return usage;
}
+static jint LegacyCameraDevice_nativeDisconnectSurface(JNIEnv* env, jobject thiz,
+ jobject surface) {
+ ALOGV("nativeDisconnectSurface");
+ if (surface == nullptr) return NO_ERROR;
+
+ sp<ANativeWindow> anw;
+ if ((anw = getNativeWindow(env, surface)) == NULL) {
+ ALOGV("Buffer queue has already been abandoned.");
+ return NO_ERROR;
+ }
+
+ status_t err = native_window_api_disconnect(anw.get(), NATIVE_WINDOW_API_CAMERA);
+ if(err != NO_ERROR) {
+ jniThrowException(env, "Ljava/lang/UnsupportedOperationException;",
+ "Error while disconnecting surface");
+ return err;
+ }
+ return NO_ERROR;
+}
+
static jint LegacyCameraDevice_nativeDetectTextureDimens(JNIEnv* env, jobject thiz,
jobject surfaceTexture, jintArray dimens) {
ALOGV("nativeDetectTextureDimens");
@@ -540,15 +549,14 @@
return NO_ERROR;
}
-static jint LegacyCameraDevice_nativeConfigureSurface(JNIEnv* env, jobject thiz, jobject surface,
- jint width, jint height, jint pixelFormat) {
- ALOGV("nativeConfigureSurface");
- sp<ANativeWindow> anw;
- if ((anw = getNativeWindow(env, surface)) == NULL) {
- ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
+static jint LegacyCameraDevice_nativeConnectSurface(JNIEnv* env, jobject thiz, jobject surface) {
+ ALOGV("nativeConnectSurface");
+ sp<Surface> s;
+ if ((s = getSurface(env, surface)) == NULL) {
+ ALOGE("%s: Could not retrieve surface.", __FUNCTION__);
return BAD_VALUE;
}
- status_t err = configureSurface(anw, width, height, pixelFormat, CAMERA_DEVICE_BUFFER_SLACK);
+ status_t err = connectSurface(s, CAMERA_DEVICE_BUFFER_SLACK);
if (err != NO_ERROR) {
ALOGE("%s: Error while configuring surface %s (%d).", __FUNCTION__, strerror(-err), err);
return err;
@@ -740,9 +748,9 @@
{ "nativeDetectSurfaceDimens",
"(Landroid/view/Surface;[I)I",
(void *)LegacyCameraDevice_nativeDetectSurfaceDimens },
- { "nativeConfigureSurface",
- "(Landroid/view/Surface;III)I",
- (void *)LegacyCameraDevice_nativeConfigureSurface },
+ { "nativeConnectSurface",
+ "(Landroid/view/Surface;)I",
+ (void *)LegacyCameraDevice_nativeConnectSurface },
{ "nativeProduceFrame",
"(Landroid/view/Surface;[BIII)I",
(void *)LegacyCameraDevice_nativeProduceFrame },
@@ -773,6 +781,9 @@
{ "nativeSetScalingMode",
"(Landroid/view/Surface;I)I",
(void *)LegacyCameraDevice_nativeSetScalingMode },
+ { "nativeDisconnectSurface",
+ "(Landroid/view/Surface;)I",
+ (void *)LegacyCameraDevice_nativeDisconnectSurface },
};
// Get all the required offsets in java class and register native functions
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index d0326f1..3e4e352 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -180,54 +180,15 @@
// ----------------------------------------------------------------------------
static jint
android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this,
- jobject jaa, jint sampleRateInHertz, jint channelMask, jint channelIndexMask,
- jint audioFormat, jint buffSizeInBytes, jintArray jSession, jstring opPackageName)
+ jobject jaa, jintArray jSampleRate, jint channelMask, jint channelIndexMask,
+ jint audioFormat, jint buffSizeInBytes, jintArray jSession, jstring opPackageName,
+ jlong nativeRecordInJavaObj)
{
//ALOGV(">> Entering android_media_AudioRecord_setup");
- //ALOGV("sampleRate=%d, audioFormat=%d, channel mask=%x, buffSizeInBytes=%d",
- // sampleRateInHertz, audioFormat, channelMask, buffSizeInBytes);
-
- if (jaa == 0) {
- ALOGE("Error creating AudioRecord: invalid audio attributes");
- return (jint) AUDIO_JAVA_ERROR;
- }
-
- // channel index mask takes priority over channel position masks.
- if (channelIndexMask) {
- // Java channel index masks need the representation bits set.
- channelMask = audio_channel_mask_from_representation_and_bits(
- AUDIO_CHANNEL_REPRESENTATION_INDEX,
- channelIndexMask);
- }
- // Java channel position masks map directly to the native definition
-
- if (!audio_is_input_channel(channelMask)) {
- ALOGE("Error creating AudioRecord: channel mask %#x is not valid.", channelMask);
- return (jint) AUDIORECORD_ERROR_SETUP_INVALIDCHANNELMASK;
- }
- uint32_t channelCount = audio_channel_count_from_in_mask(channelMask);
-
- // compare the format against the Java constants
- audio_format_t format = audioFormatToNative(audioFormat);
- if (format == AUDIO_FORMAT_INVALID) {
- ALOGE("Error creating AudioRecord: unsupported audio format %d.", audioFormat);
- return (jint) AUDIORECORD_ERROR_SETUP_INVALIDFORMAT;
- }
-
- size_t bytesPerSample = audio_bytes_per_sample(format);
-
- if (buffSizeInBytes == 0) {
- ALOGE("Error creating AudioRecord: frameCount is 0.");
- return (jint) AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT;
- }
- size_t frameSize = channelCount * bytesPerSample;
- size_t frameCount = buffSizeInBytes / frameSize;
-
- jclass clazz = env->GetObjectClass(thiz);
- if (clazz == NULL) {
- ALOGE("Can't find %s when setting up callback.", kClassPathName);
- return (jint) AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED;
- }
+ //ALOGV("sampleRate=%d, audioFormat=%d, channel mask=%x, buffSizeInBytes=%d "
+ // "nativeRecordInJavaObj=0x%llX",
+ // sampleRateInHertz, audioFormat, channelMask, buffSizeInBytes, nativeRecordInJavaObj);
+ audio_channel_mask_t localChanMask = inChannelMaskToNative(channelMask);
if (jSession == NULL) {
ALOGE("Error creating AudioRecord: invalid session ID pointer");
@@ -243,55 +204,132 @@
env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
nSession = NULL;
- ScopedUtfChars opPackageNameStr(env, opPackageName);
-
- // create an uninitialized AudioRecord object
- sp<AudioRecord> lpRecorder = new AudioRecord(String16(opPackageNameStr.c_str()));
-
audio_attributes_t *paa = NULL;
- // read the AudioAttributes values
- paa = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
- const jstring jtags =
- (jstring) env->GetObjectField(jaa, javaAudioAttrFields.fieldFormattedTags);
- const char* tags = env->GetStringUTFChars(jtags, NULL);
- // copying array size -1, char array for tags was calloc'd, no need to NULL-terminate it
- strncpy(paa->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
- env->ReleaseStringUTFChars(jtags, tags);
- paa->source = (audio_source_t) env->GetIntField(jaa, javaAudioAttrFields.fieldRecSource);
- paa->flags = (audio_flags_mask_t)env->GetIntField(jaa, javaAudioAttrFields.fieldFlags);
- ALOGV("AudioRecord_setup for source=%d tags=%s flags=%08x", paa->source, paa->tags, paa->flags);
+ sp<AudioRecord> lpRecorder = 0;
+ audiorecord_callback_cookie *lpCallbackData = NULL;
- audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE;
- if (paa->flags & AUDIO_FLAG_HW_HOTWORD) {
- flags = AUDIO_INPUT_FLAG_HW_HOTWORD;
+ jclass clazz = env->GetObjectClass(thiz);
+ if (clazz == NULL) {
+ ALOGE("Can't find %s when setting up callback.", kClassPathName);
+ return (jint) AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED;
}
- // create the callback information:
- // this data will be passed with every AudioRecord callback
- audiorecord_callback_cookie *lpCallbackData = new audiorecord_callback_cookie;
- lpCallbackData->audioRecord_class = (jclass)env->NewGlobalRef(clazz);
- // we use a weak reference so the AudioRecord object can be garbage collected.
- lpCallbackData->audioRecord_ref = env->NewGlobalRef(weak_this);
- lpCallbackData->busy = false;
- const status_t status = lpRecorder->set(paa->source,
- sampleRateInHertz,
- format, // word length, PCM
- channelMask,
- frameCount,
- recorderCallback,// callback_t
- lpCallbackData,// void* user
- 0, // notificationFrames,
- true, // threadCanCallJava
- sessionId,
- AudioRecord::TRANSFER_DEFAULT,
- flags,
- -1, -1, // default uid, pid
- paa);
+ // if we pass in an existing *Native* AudioRecord, we don't need to create/initialize one.
+ if (nativeRecordInJavaObj == 0) {
+ if (jaa == 0) {
+ ALOGE("Error creating AudioRecord: invalid audio attributes");
+ return (jint) AUDIO_JAVA_ERROR;
+ }
- if (status != NO_ERROR) {
- ALOGE("Error creating AudioRecord instance: initialization check failed with status %d.",
- status);
- goto native_init_failure;
+ if (jSampleRate == 0) {
+ ALOGE("Error creating AudioRecord: invalid sample rates");
+ return (jint) AUDIO_JAVA_ERROR;
+ }
+ jint elements[1];
+ env->GetIntArrayRegion(jSampleRate, 0, 1, elements);
+ int sampleRateInHertz = elements[0];
+
+ // channel index mask takes priority over channel position masks.
+ if (channelIndexMask) {
+ // Java channel index masks need the representation bits set.
+ localChanMask = audio_channel_mask_from_representation_and_bits(
+ AUDIO_CHANNEL_REPRESENTATION_INDEX,
+ channelIndexMask);
+ }
+ // Java channel position masks map directly to the native definition
+
+ if (!audio_is_input_channel(localChanMask)) {
+ ALOGE("Error creating AudioRecord: channel mask %#x is not valid.", localChanMask);
+ return (jint) AUDIORECORD_ERROR_SETUP_INVALIDCHANNELMASK;
+ }
+ uint32_t channelCount = audio_channel_count_from_in_mask(localChanMask);
+
+ // compare the format against the Java constants
+ audio_format_t format = audioFormatToNative(audioFormat);
+ if (format == AUDIO_FORMAT_INVALID) {
+ ALOGE("Error creating AudioRecord: unsupported audio format %d.", audioFormat);
+ return (jint) AUDIORECORD_ERROR_SETUP_INVALIDFORMAT;
+ }
+
+ size_t bytesPerSample = audio_bytes_per_sample(format);
+
+ if (buffSizeInBytes == 0) {
+ ALOGE("Error creating AudioRecord: frameCount is 0.");
+ return (jint) AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT;
+ }
+ size_t frameSize = channelCount * bytesPerSample;
+ size_t frameCount = buffSizeInBytes / frameSize;
+
+ ScopedUtfChars opPackageNameStr(env, opPackageName);
+
+ // create an uninitialized AudioRecord object
+ lpRecorder = new AudioRecord(String16(opPackageNameStr.c_str()));
+
+ // read the AudioAttributes values
+ paa = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
+ const jstring jtags =
+ (jstring) env->GetObjectField(jaa, javaAudioAttrFields.fieldFormattedTags);
+ const char* tags = env->GetStringUTFChars(jtags, NULL);
+ // copying array size -1, char array for tags was calloc'd, no need to NULL-terminate it
+ strncpy(paa->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
+ env->ReleaseStringUTFChars(jtags, tags);
+ paa->source = (audio_source_t) env->GetIntField(jaa, javaAudioAttrFields.fieldRecSource);
+ paa->flags = (audio_flags_mask_t)env->GetIntField(jaa, javaAudioAttrFields.fieldFlags);
+ ALOGV("AudioRecord_setup for source=%d tags=%s flags=%08x", paa->source, paa->tags, paa->flags);
+
+ audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE;
+ if (paa->flags & AUDIO_FLAG_HW_HOTWORD) {
+ flags = AUDIO_INPUT_FLAG_HW_HOTWORD;
+ }
+ // create the callback information:
+ // this data will be passed with every AudioRecord callback
+ lpCallbackData = new audiorecord_callback_cookie;
+ lpCallbackData->audioRecord_class = (jclass)env->NewGlobalRef(clazz);
+ // we use a weak reference so the AudioRecord object can be garbage collected.
+ lpCallbackData->audioRecord_ref = env->NewGlobalRef(weak_this);
+ lpCallbackData->busy = false;
+
+ const status_t status = lpRecorder->set(paa->source,
+ sampleRateInHertz,
+ format, // word length, PCM
+ localChanMask,
+ frameCount,
+ recorderCallback,// callback_t
+ lpCallbackData,// void* user
+ 0, // notificationFrames,
+ true, // threadCanCallJava
+ sessionId,
+ AudioRecord::TRANSFER_DEFAULT,
+ flags,
+ -1, -1, // default uid, pid
+ paa);
+
+ if (status != NO_ERROR) {
+ ALOGE("Error creating AudioRecord instance: initialization check failed with status %d.",
+ status);
+ goto native_init_failure;
+ }
+ } else { // end if nativeRecordInJavaObj == 0)
+ lpRecorder = (AudioRecord*)nativeRecordInJavaObj;
+ // TODO: We need to find out which members of the Java AudioRecord might need to be
+ // initialized from the Native AudioRecord
+ // these are directly returned from getters:
+ // mSampleRate
+ // mRecordSource
+ // mAudioFormat
+ // mChannelMask
+ // mChannelCount
+ // mState (?)
+ // mRecordingState (?)
+ // mPreferredDevice
+
+ // create the callback information:
+ // this data will be passed with every AudioRecord callback
+ lpCallbackData = new audiorecord_callback_cookie;
+ lpCallbackData->audioRecord_class = (jclass)env->NewGlobalRef(clazz);
+ // we use a weak reference so the AudioRecord object can be garbage collected.
+ lpCallbackData->audioRecord_ref = env->NewGlobalRef(weak_this);
+ lpCallbackData->busy = false;
}
nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL);
@@ -304,6 +342,11 @@
env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
nSession = NULL;
+ {
+ const jint elements[1] = { (jint) lpRecorder->getSampleRate() };
+ env->SetIntArrayRegion(jSampleRate, 0, 1, elements);
+ }
+
{ // scope for the lock
Mutex::Autolock l(sLock);
sAudioRecordCallBackCookies.add(lpCallbackData);
@@ -717,8 +760,8 @@
// name, signature, funcPtr
{"native_start", "(II)I", (void *)android_media_AudioRecord_start},
{"native_stop", "()V", (void *)android_media_AudioRecord_stop},
- {"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;IIIII[ILjava/lang/String;)I",
- (void *)android_media_AudioRecord_setup},
+ {"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;[IIIII[ILjava/lang/String;J)I",
+ (void *)android_media_AudioRecord_setup},
{"native_finalize", "()V", (void *)android_media_AudioRecord_finalize},
{"native_release", "()V", (void *)android_media_AudioRecord_release},
{"native_read_in_byte_array",
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 80f8a64..1eb0111 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -320,7 +320,7 @@
static jint
android_media_AudioSystem_newAudioSessionId(JNIEnv *env, jobject thiz)
{
- return AudioSystem::newAudioUniqueId();
+ return AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
}
static jint
@@ -388,18 +388,47 @@
}
static void
-android_media_AudioSystem_recording_callback(int event, int session, int source)
+android_media_AudioSystem_recording_callback(int event, int session, int source,
+ const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
+ audio_patch_handle_t patchHandle)
{
JNIEnv *env = AndroidRuntime::getJNIEnv();
if (env == NULL) {
return;
}
+ if (clientConfig == NULL || deviceConfig == NULL) {
+ ALOGE("Unexpected null client/device configurations in recording callback");
+ return;
+ }
+ // create an array for 2*3 integers to store the record configurations (client + device)
+ // plus 1 integer for the patch handle
+ const int REC_PARAM_SIZE = 7;
+ jintArray recParamArray = env->NewIntArray(REC_PARAM_SIZE);
+ if (recParamArray == NULL) {
+ ALOGE("recording callback: Couldn't allocate int array for configuration data");
+ return;
+ }
+ jint recParamData[REC_PARAM_SIZE];
+ recParamData[0] = (jint) audioFormatFromNative(clientConfig->format);
+ // FIXME this doesn't support index-based masks
+ recParamData[1] = (jint) inChannelMaskFromNative(clientConfig->channel_mask);
+ recParamData[2] = (jint) clientConfig->sample_rate;
+ recParamData[3] = (jint) audioFormatFromNative(deviceConfig->format);
+ // FIXME this doesn't support index-based masks
+ recParamData[4] = (jint) inChannelMaskFromNative(deviceConfig->channel_mask);
+ recParamData[5] = (jint) deviceConfig->sample_rate;
+ recParamData[6] = (jint) patchHandle;
+ env->SetIntArrayRegion(recParamArray, 0, REC_PARAM_SIZE, recParamData);
+
+ // callback into java
jclass clazz = env->FindClass(kClassPathName);
env->CallStaticVoidMethod(clazz,
gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative,
- event, session, source);
+ event, session, source, recParamArray);
env->DeleteLocalRef(clazz);
+
+ env->DeleteLocalRef(recParamArray);
}
static jint
@@ -1819,7 +1848,7 @@
"dynamicPolicyCallbackFromNative", "(ILjava/lang/String;I)V");
gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative =
GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName),
- "recordingCallbackFromNative", "(III)V");
+ "recordingCallbackFromNative", "(III[I)V");
jclass audioMixClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMix");
gAudioMixClass = MakeGlobalRefOrDie(env, audioMixClass);
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 1ab9504..660cbdc 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -213,51 +213,17 @@
// ----------------------------------------------------------------------------
static jint
-android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this,
- jobject jaa,
- jint sampleRateInHertz, jint channelPositionMask, jint channelIndexMask,
- jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession) {
+android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, jobject jaa,
+ jintArray jSampleRate, jint channelPositionMask, jint channelIndexMask,
+ jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession,
+ jlong nativeAudioTrack) {
- ALOGV("sampleRate=%d, channel mask=%x, index mask=%x, audioFormat(Java)=%d, buffSize=%d",
- sampleRateInHertz, channelPositionMask, channelIndexMask, audioFormat, buffSizeInBytes);
+ ALOGV("sampleRates=%p, channel mask=%x, index mask=%x, audioFormat(Java)=%d, buffSize=%d"
+ "nativeAudioTrack=0x%llX",
+ jSampleRate, channelPositionMask, channelIndexMask, audioFormat, buffSizeInBytes,
+ nativeAudioTrack);
- if (jaa == 0) {
- ALOGE("Error creating AudioTrack: invalid audio attributes");
- return (jint) AUDIO_JAVA_ERROR;
- }
-
- // Invalid channel representations are caught by !audio_is_output_channel() below.
- audio_channel_mask_t nativeChannelMask = nativeChannelMaskFromJavaChannelMasks(
- channelPositionMask, channelIndexMask);
- if (!audio_is_output_channel(nativeChannelMask)) {
- ALOGE("Error creating AudioTrack: invalid native channel mask %#x.", nativeChannelMask);
- return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDCHANNELMASK;
- }
-
- uint32_t channelCount = audio_channel_count_from_out_mask(nativeChannelMask);
-
- // check the format.
- // This function was called from Java, so we compare the format against the Java constants
- audio_format_t format = audioFormatToNative(audioFormat);
- if (format == AUDIO_FORMAT_INVALID) {
- ALOGE("Error creating AudioTrack: unsupported audio format %d.", audioFormat);
- return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDFORMAT;
- }
-
- // compute the frame count
- size_t frameCount;
- if (audio_has_proportional_frames(format)) {
- const size_t bytesPerSample = audio_bytes_per_sample(format);
- frameCount = buffSizeInBytes / (channelCount * bytesPerSample);
- } else {
- frameCount = buffSizeInBytes;
- }
-
- jclass clazz = env->GetObjectClass(thiz);
- if (clazz == NULL) {
- ALOGE("Can't find %s when setting up callback.", kClassPathName);
- return (jint) AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED;
- }
+ sp<AudioTrack> lpTrack = 0;
if (jSession == NULL) {
ALOGE("Error creating AudioTrack: invalid session ID pointer");
@@ -273,91 +239,168 @@
env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
nSession = NULL;
- // create the native AudioTrack object
- sp<AudioTrack> lpTrack = new AudioTrack();
+ AudioTrackJniStorage* lpJniStorage = NULL;
audio_attributes_t *paa = NULL;
- // read the AudioAttributes values
- paa = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
- const jstring jtags =
- (jstring) env->GetObjectField(jaa, javaAudioAttrFields.fieldFormattedTags);
- const char* tags = env->GetStringUTFChars(jtags, NULL);
- // copying array size -1, char array for tags was calloc'd, no need to NULL-terminate it
- strncpy(paa->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
- env->ReleaseStringUTFChars(jtags, tags);
- paa->usage = (audio_usage_t) env->GetIntField(jaa, javaAudioAttrFields.fieldUsage);
- paa->content_type =
- (audio_content_type_t) env->GetIntField(jaa, javaAudioAttrFields.fieldContentType);
- paa->flags = env->GetIntField(jaa, javaAudioAttrFields.fieldFlags);
- ALOGV("AudioTrack_setup for usage=%d content=%d flags=0x%#x tags=%s",
- paa->usage, paa->content_type, paa->flags, paa->tags);
+ jclass clazz = env->GetObjectClass(thiz);
+ if (clazz == NULL) {
+ ALOGE("Can't find %s when setting up callback.", kClassPathName);
+ return (jint) AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED;
+ }
- // initialize the callback information:
- // this data will be passed with every AudioTrack callback
- AudioTrackJniStorage* lpJniStorage = new AudioTrackJniStorage();
- lpJniStorage->mCallbackData.audioTrack_class = (jclass)env->NewGlobalRef(clazz);
- // we use a weak reference so the AudioTrack object can be garbage collected.
- lpJniStorage->mCallbackData.audioTrack_ref = env->NewGlobalRef(weak_this);
- lpJniStorage->mCallbackData.busy = false;
+ // if we pass in an existing *Native* AudioTrack, we don't need to create/initialize one.
+ if (nativeAudioTrack == 0) {
+ if (jaa == 0) {
+ ALOGE("Error creating AudioTrack: invalid audio attributes");
+ return (jint) AUDIO_JAVA_ERROR;
+ }
- // initialize the native AudioTrack object
- status_t status = NO_ERROR;
- switch (memoryMode) {
- case MODE_STREAM:
+ if (jSampleRate == 0) {
+ ALOGE("Error creating AudioTrack: invalid sample rates");
+ return (jint) AUDIO_JAVA_ERROR;
+ }
- status = lpTrack->set(
- AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument)
- sampleRateInHertz,
- format,// word length, PCM
- nativeChannelMask,
- frameCount,
- AUDIO_OUTPUT_FLAG_NONE,
- audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)
- 0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
- 0,// shared mem
- true,// thread can call Java
- sessionId,// audio session ID
- AudioTrack::TRANSFER_SYNC,
- NULL, // default offloadInfo
- -1, -1, // default uid, pid values
- paa);
- break;
+ int* sampleRates = env->GetIntArrayElements(jSampleRate, NULL);
+ int sampleRateInHertz = sampleRates[0];
+ env->ReleaseIntArrayElements(jSampleRate, sampleRates, JNI_ABORT);
- case MODE_STATIC:
- // AudioTrack is using shared memory
+ // Invalid channel representations are caught by !audio_is_output_channel() below.
+ audio_channel_mask_t nativeChannelMask = nativeChannelMaskFromJavaChannelMasks(
+ channelPositionMask, channelIndexMask);
+ if (!audio_is_output_channel(nativeChannelMask)) {
+ ALOGE("Error creating AudioTrack: invalid native channel mask %#x.", nativeChannelMask);
+ return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDCHANNELMASK;
+ }
- if (!lpJniStorage->allocSharedMem(buffSizeInBytes)) {
- ALOGE("Error creating AudioTrack in static mode: error creating mem heap base");
+ uint32_t channelCount = audio_channel_count_from_out_mask(nativeChannelMask);
+
+ // check the format.
+ // This function was called from Java, so we compare the format against the Java constants
+ audio_format_t format = audioFormatToNative(audioFormat);
+ if (format == AUDIO_FORMAT_INVALID) {
+ ALOGE("Error creating AudioTrack: unsupported audio format %d.", audioFormat);
+ return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDFORMAT;
+ }
+
+ // compute the frame count
+ size_t frameCount;
+ if (audio_is_linear_pcm(format)) {
+ const size_t bytesPerSample = audio_bytes_per_sample(format);
+ frameCount = buffSizeInBytes / (channelCount * bytesPerSample);
+ } else {
+ frameCount = buffSizeInBytes;
+ }
+
+ // create the native AudioTrack object
+ lpTrack = new AudioTrack();
+
+ // read the AudioAttributes values
+ paa = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
+ const jstring jtags =
+ (jstring) env->GetObjectField(jaa, javaAudioAttrFields.fieldFormattedTags);
+ const char* tags = env->GetStringUTFChars(jtags, NULL);
+ // copying array size -1, char array for tags was calloc'd, no need to NULL-terminate it
+ strncpy(paa->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
+ env->ReleaseStringUTFChars(jtags, tags);
+ paa->usage = (audio_usage_t) env->GetIntField(jaa, javaAudioAttrFields.fieldUsage);
+ paa->content_type =
+ (audio_content_type_t) env->GetIntField(jaa, javaAudioAttrFields.fieldContentType);
+ paa->flags = env->GetIntField(jaa, javaAudioAttrFields.fieldFlags);
+
+ ALOGV("AudioTrack_setup for usage=%d content=%d flags=0x%#x tags=%s",
+ paa->usage, paa->content_type, paa->flags, paa->tags);
+
+ // initialize the callback information:
+ // this data will be passed with every AudioTrack callback
+ lpJniStorage = new AudioTrackJniStorage();
+ lpJniStorage->mCallbackData.audioTrack_class = (jclass)env->NewGlobalRef(clazz);
+ // we use a weak reference so the AudioTrack object can be garbage collected.
+ lpJniStorage->mCallbackData.audioTrack_ref = env->NewGlobalRef(weak_this);
+ lpJniStorage->mCallbackData.busy = false;
+
+ // initialize the native AudioTrack object
+ status_t status = NO_ERROR;
+ switch (memoryMode) {
+ case MODE_STREAM:
+
+ status = lpTrack->set(
+ AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument)
+ sampleRateInHertz,
+ format,// word length, PCM
+ nativeChannelMask,
+ frameCount,
+ AUDIO_OUTPUT_FLAG_NONE,
+ audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)
+ 0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
+ 0,// shared mem
+ true,// thread can call Java
+ sessionId,// audio session ID
+ AudioTrack::TRANSFER_SYNC,
+ NULL, // default offloadInfo
+ -1, -1, // default uid, pid values
+ paa);
+ break;
+
+ case MODE_STATIC:
+ // AudioTrack is using shared memory
+
+ if (!lpJniStorage->allocSharedMem(buffSizeInBytes)) {
+ ALOGE("Error creating AudioTrack in static mode: error creating mem heap base");
+ goto native_init_failure;
+ }
+
+ status = lpTrack->set(
+ AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument)
+ sampleRateInHertz,
+ format,// word length, PCM
+ nativeChannelMask,
+ frameCount,
+ AUDIO_OUTPUT_FLAG_NONE,
+ audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user));
+ 0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
+ lpJniStorage->mMemBase,// shared mem
+ true,// thread can call Java
+ sessionId,// audio session ID
+ AudioTrack::TRANSFER_SHARED,
+ NULL, // default offloadInfo
+ -1, -1, // default uid, pid values
+ paa);
+ break;
+
+ default:
+ ALOGE("Unknown mode %d", memoryMode);
goto native_init_failure;
}
- status = lpTrack->set(
- AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument)
- sampleRateInHertz,
- format,// word length, PCM
- nativeChannelMask,
- frameCount,
- AUDIO_OUTPUT_FLAG_NONE,
- audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user));
- 0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
- lpJniStorage->mMemBase,// shared mem
- true,// thread can call Java
- sessionId,// audio session ID
- AudioTrack::TRANSFER_SHARED,
- NULL, // default offloadInfo
- -1, -1, // default uid, pid values
- paa);
- break;
+ if (status != NO_ERROR) {
+ ALOGE("Error %d initializing AudioTrack", status);
+ goto native_init_failure;
+ }
+ } else { // end if (nativeAudioTrack == 0)
+ lpTrack = (AudioTrack*)nativeAudioTrack;
+ // TODO: We need to find out which members of the Java AudioTrack might
+ // need to be initialized from the Native AudioTrack
+ // these are directly returned from getters:
+ // mSampleRate
+ // mAudioFormat
+ // mStreamType
+ // mChannelConfiguration
+ // mChannelCount
+ // mState (?)
+ // mPlayState (?)
+ // these may be used internally (Java AudioTrack.audioParamCheck():
+ // mChannelMask
+ // mChannelIndexMask
+ // mDataLoadMode
- default:
- ALOGE("Unknown mode %d", memoryMode);
- goto native_init_failure;
- }
-
- if (status != NO_ERROR) {
- ALOGE("Error %d initializing AudioTrack", status);
- goto native_init_failure;
+ // initialize the callback information:
+ // this data will be passed with every AudioTrack callback
+ lpJniStorage = new AudioTrackJniStorage();
+ lpJniStorage->mCallbackData.audioTrack_class = (jclass)env->NewGlobalRef(clazz);
+ // we use a weak reference so the AudioTrack object can be garbage collected.
+ lpJniStorage->mCallbackData.audioTrack_ref = env->NewGlobalRef(weak_this);
+ lpJniStorage->mCallbackData.busy = false;
}
nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL);
@@ -370,6 +413,11 @@
env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
nSession = NULL;
+ {
+ const jint elements[1] = { (jint) lpTrack->getSampleRate() };
+ env->SetIntArrayRegion(jSampleRate, 0, 1, elements);
+ }
+
{ // scope for the lock
Mutex::Autolock l(sLock);
sAudioTrackCallBackCookies.add(&lpJniStorage->mCallbackData);
@@ -385,9 +433,11 @@
// since we had audio attributes, the stream type was derived from them during the
// creation of the native AudioTrack: push the same value to the Java object
env->SetIntField(thiz, javaAudioTrackFields.fieldStreamType, (jint) lpTrack->streamType());
- // audio attributes were copied in AudioTrack creation
- free(paa);
- paa = NULL;
+ if (paa != NULL) {
+ // audio attributes were copied in AudioTrack creation
+ free(paa);
+ paa = NULL;
+ }
return (jint) AUDIO_JAVA_SUCCESS;
@@ -409,7 +459,6 @@
return (jint) AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED;
}
-
// ----------------------------------------------------------------------------
static void
android_media_AudioTrack_start(JNIEnv *env, jobject thiz)
@@ -1114,7 +1163,7 @@
{"native_stop", "()V", (void *)android_media_AudioTrack_stop},
{"native_pause", "()V", (void *)android_media_AudioTrack_pause},
{"native_flush", "()V", (void *)android_media_AudioTrack_flush},
- {"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;IIIIII[I)I",
+ {"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;[IIIIII[IJ)I",
(void *)android_media_AudioTrack_setup},
{"native_finalize", "()V", (void *)android_media_AudioTrack_finalize},
{"native_release", "()V", (void *)android_media_AudioTrack_release},
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index ba0876d..880a79c 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -26,10 +26,13 @@
#include <net/if.h>
#include <linux/filter.h>
#include <linux/if.h>
+#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <net/if_ether.h>
+#include <netinet/icmp6.h>
#include <netinet/ip.h>
+#include <netinet/ip6.h>
#include <netinet/udp.h>
#include <cutils/properties.h>
@@ -39,23 +42,6 @@
int ifc_enable(const char *ifname);
int ifc_disable(const char *ifname);
int ifc_reset_connections(const char *ifname, int reset_mask);
-
-int dhcp_start(const char * const ifname);
-int dhcp_start_renew(const char * const ifname);
-int dhcp_get_results(const char * const ifname,
- const char *ipaddr,
- const char *gateway,
- uint32_t *prefixLength,
- const char *dns[],
- const char *server,
- uint32_t *lease,
- const char *vendorInfo,
- const char *domains,
- const char *mtu);
-
-int dhcp_stop(const char *ifname);
-int dhcp_release_lease(const char *ifname);
-char *dhcp_get_errmsg();
}
#define NETUTILS_PKG_NAME "android/net/NetworkUtils"
@@ -64,22 +50,6 @@
static const uint16_t kDhcpClientPort = 68;
-/*
- * The following remembers the jfieldID's of the fields
- * of the DhcpInfo Java object, so that we don't have
- * to look them up every time.
- */
-static struct fieldIds {
- jmethodID clear;
- jmethodID setIpAddress;
- jmethodID setGateway;
- jmethodID addDns;
- jmethodID setDomains;
- jmethodID setServerAddress;
- jmethodID setLeaseDuration;
- jmethodID setVendorInfo;
-} dhcpResultsFieldIds;
-
static jint android_net_utils_resetConnections(JNIEnv* env, jobject clazz,
jstring ifname, jint mask)
{
@@ -95,143 +65,11 @@
return (jint)result;
}
-static jboolean android_net_utils_getDhcpResults(JNIEnv* env, jobject clazz, jstring ifname,
- jobject dhcpResults)
-{
- int result;
- char ipaddr[PROPERTY_VALUE_MAX];
- uint32_t prefixLength;
- char gateway[PROPERTY_VALUE_MAX];
- char dns1[PROPERTY_VALUE_MAX];
- char dns2[PROPERTY_VALUE_MAX];
- char dns3[PROPERTY_VALUE_MAX];
- char dns4[PROPERTY_VALUE_MAX];
- const char *dns[5] = {dns1, dns2, dns3, dns4, NULL};
- char server[PROPERTY_VALUE_MAX];
- uint32_t lease;
- char vendorInfo[PROPERTY_VALUE_MAX];
- char domains[PROPERTY_VALUE_MAX];
- char mtu[PROPERTY_VALUE_MAX];
-
- const char *nameStr = env->GetStringUTFChars(ifname, NULL);
- if (nameStr == NULL) return (jboolean)false;
-
- result = ::dhcp_get_results(nameStr, ipaddr, gateway, &prefixLength,
- dns, server, &lease, vendorInfo, domains, mtu);
- if (result != 0) {
- ALOGD("dhcp_get_results failed : %s (%s)", nameStr, ::dhcp_get_errmsg());
- }
-
- env->ReleaseStringUTFChars(ifname, nameStr);
- if (result == 0) {
- env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.clear);
-
- // set the linkAddress
- // dhcpResults->addLinkAddress(inetAddress, prefixLength)
- result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.setIpAddress,
- env->NewStringUTF(ipaddr), prefixLength);
- }
-
- if (result == 0) {
- // set the gateway
- result = env->CallBooleanMethod(dhcpResults,
- dhcpResultsFieldIds.setGateway, env->NewStringUTF(gateway));
- }
-
- if (result == 0) {
- // dhcpResults->addDns(new InetAddress(dns1))
- result = env->CallBooleanMethod(dhcpResults,
- dhcpResultsFieldIds.addDns, env->NewStringUTF(dns1));
- }
-
- if (result == 0) {
- env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setDomains,
- env->NewStringUTF(domains));
-
- result = env->CallBooleanMethod(dhcpResults,
- dhcpResultsFieldIds.addDns, env->NewStringUTF(dns2));
-
- if (result == 0) {
- result = env->CallBooleanMethod(dhcpResults,
- dhcpResultsFieldIds.addDns, env->NewStringUTF(dns3));
- if (result == 0) {
- result = env->CallBooleanMethod(dhcpResults,
- dhcpResultsFieldIds.addDns, env->NewStringUTF(dns4));
- }
- }
- }
-
- if (result == 0) {
- // dhcpResults->setServerAddress(new InetAddress(server))
- result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.setServerAddress,
- env->NewStringUTF(server));
- }
-
- if (result == 0) {
- // dhcpResults->setLeaseDuration(lease)
- env->CallVoidMethod(dhcpResults,
- dhcpResultsFieldIds.setLeaseDuration, lease);
-
- // dhcpResults->setVendorInfo(vendorInfo)
- env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setVendorInfo,
- env->NewStringUTF(vendorInfo));
- }
- return (jboolean)(result == 0);
-}
-
-static jboolean android_net_utils_startDhcp(JNIEnv* env, jobject clazz, jstring ifname)
-{
- const char *nameStr = env->GetStringUTFChars(ifname, NULL);
- if (nameStr == NULL) return (jboolean)false;
- if (::dhcp_start(nameStr) != 0) {
- ALOGD("dhcp_start failed : %s", nameStr);
- return (jboolean)false;
- }
- return (jboolean)true;
-}
-
-static jboolean android_net_utils_startDhcpRenew(JNIEnv* env, jobject clazz, jstring ifname)
-{
- const char *nameStr = env->GetStringUTFChars(ifname, NULL);
- if (nameStr == NULL) return (jboolean)false;
- if (::dhcp_start_renew(nameStr) != 0) {
- ALOGD("dhcp_start_renew failed : %s", nameStr);
- return (jboolean)false;
- }
- return (jboolean)true;
-}
-
-static jboolean android_net_utils_stopDhcp(JNIEnv* env, jobject clazz, jstring ifname)
-{
- int result;
-
- const char *nameStr = env->GetStringUTFChars(ifname, NULL);
- result = ::dhcp_stop(nameStr);
- env->ReleaseStringUTFChars(ifname, nameStr);
- return (jboolean)(result == 0);
-}
-
-static jboolean android_net_utils_releaseDhcpLease(JNIEnv* env, jobject clazz, jstring ifname)
-{
- int result;
-
- const char *nameStr = env->GetStringUTFChars(ifname, NULL);
- result = ::dhcp_release_lease(nameStr);
- env->ReleaseStringUTFChars(ifname, nameStr);
- return (jboolean)(result == 0);
-}
-
-static jstring android_net_utils_getDhcpError(JNIEnv* env, jobject clazz)
-{
- return env->NewStringUTF(::dhcp_get_errmsg());
-}
-
static void android_net_utils_attachDhcpFilter(JNIEnv *env, jobject clazz, jobject javaFd)
{
- int fd = jniGetFDFromFileDescriptor(env, javaFd);
uint32_t ip_offset = sizeof(ether_header);
uint32_t proto_offset = ip_offset + offsetof(iphdr, protocol);
- uint32_t flags_offset = ip_offset + offsetof(iphdr, frag_off);
+ uint32_t flags_offset = ip_offset + offsetof(iphdr, frag_off);
uint32_t dport_indirect_offset = ip_offset + offsetof(udphdr, dest);
struct sock_filter filter_code[] = {
// Check the protocol is UDP.
@@ -258,6 +96,45 @@
filter_code,
};
+ int fd = jniGetFDFromFileDescriptor(env, javaFd);
+ if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) != 0) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "setsockopt(SO_ATTACH_FILTER): %s", strerror(errno));
+ }
+}
+
+static void android_net_utils_attachRaFilter(JNIEnv *env, jobject clazz, jobject javaFd,
+ jint hardwareAddressType)
+{
+ if (hardwareAddressType != ARPHRD_ETHER) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "attachRaFilter only supports ARPHRD_ETHER");
+ return;
+ }
+
+ uint32_t ipv6_offset = sizeof(ether_header);
+ uint32_t ipv6_next_header_offset = ipv6_offset + offsetof(ip6_hdr, ip6_nxt);
+ uint32_t icmp6_offset = ipv6_offset + sizeof(ip6_hdr);
+ uint32_t icmp6_type_offset = icmp6_offset + offsetof(icmp6_hdr, icmp6_type);
+ struct sock_filter filter_code[] = {
+ // Check IPv6 Next Header is ICMPv6.
+ BPF_STMT(BPF_LD | BPF_B | BPF_ABS, ipv6_next_header_offset),
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, IPPROTO_ICMPV6, 0, 3),
+
+ // Check ICMPv6 type is Router Advertisement.
+ BPF_STMT(BPF_LD | BPF_B | BPF_ABS, icmp6_type_offset),
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ND_ROUTER_ADVERT, 0, 1),
+
+ // Accept or reject.
+ BPF_STMT(BPF_RET | BPF_K, 0xffff),
+ BPF_STMT(BPF_RET | BPF_K, 0)
+ };
+ struct sock_fprog filter = {
+ sizeof(filter_code) / sizeof(filter_code[0]),
+ filter_code,
+ };
+
+ int fd = jniGetFDFromFileDescriptor(env, javaFd);
if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) != 0) {
jniThrowExceptionFmt(env, "java/net/SocketException",
"setsockopt(SO_ATTACH_FILTER): %s", strerror(errno));
@@ -305,12 +182,6 @@
static const JNINativeMethod gNetworkUtilMethods[] = {
/* name, signature, funcPtr */
{ "resetConnections", "(Ljava/lang/String;I)I", (void *)android_net_utils_resetConnections },
- { "startDhcp", "(Ljava/lang/String;)Z", (void *)android_net_utils_startDhcp },
- { "startDhcpRenew", "(Ljava/lang/String;)Z", (void *)android_net_utils_startDhcpRenew },
- { "getDhcpResults", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z", (void *)android_net_utils_getDhcpResults },
- { "stopDhcp", "(Ljava/lang/String;)Z", (void *)android_net_utils_stopDhcp },
- { "releaseDhcpLease", "(Ljava/lang/String;)Z", (void *)android_net_utils_releaseDhcpLease },
- { "getDhcpError", "()Ljava/lang/String;", (void*) android_net_utils_getDhcpError },
{ "bindProcessToNetwork", "(I)Z", (void*) android_net_utils_bindProcessToNetwork },
{ "getBoundNetworkForProcess", "()I", (void*) android_net_utils_getBoundNetworkForProcess },
{ "bindProcessToNetworkForHostResolution", "(I)Z", (void*) android_net_utils_bindProcessToNetworkForHostResolution },
@@ -318,28 +189,11 @@
{ "protectFromVpn", "(I)Z", (void*)android_net_utils_protectFromVpn },
{ "queryUserAccess", "(II)Z", (void*)android_net_utils_queryUserAccess },
{ "attachDhcpFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_attachDhcpFilter },
+ { "attachRaFilter", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_attachRaFilter },
};
int register_android_net_NetworkUtils(JNIEnv* env)
{
- jclass dhcpResultsClass = FindClassOrDie(env, "android/net/DhcpResults");
-
- dhcpResultsFieldIds.clear = GetMethodIDOrDie(env, dhcpResultsClass, "clear", "()V");
- dhcpResultsFieldIds.setIpAddress =GetMethodIDOrDie(env, dhcpResultsClass, "setIpAddress",
- "(Ljava/lang/String;I)Z");
- dhcpResultsFieldIds.setGateway = GetMethodIDOrDie(env, dhcpResultsClass, "setGateway",
- "(Ljava/lang/String;)Z");
- dhcpResultsFieldIds.addDns = GetMethodIDOrDie(env, dhcpResultsClass, "addDns",
- "(Ljava/lang/String;)Z");
- dhcpResultsFieldIds.setDomains = GetMethodIDOrDie(env, dhcpResultsClass, "setDomains",
- "(Ljava/lang/String;)V");
- dhcpResultsFieldIds.setServerAddress = GetMethodIDOrDie(env, dhcpResultsClass,
- "setServerAddress", "(Ljava/lang/String;)Z");
- dhcpResultsFieldIds.setLeaseDuration = GetMethodIDOrDie(env, dhcpResultsClass,
- "setLeaseDuration", "(I)V");
- dhcpResultsFieldIds.setVendorInfo = GetMethodIDOrDie(env, dhcpResultsClass, "setVendorInfo",
- "(Ljava/lang/String;)V");
-
return RegisterMethodsOrDie(env, NETUTILS_PKG_NAME, gNetworkUtilMethods,
NELEM(gNetworkUtilMethods));
}
diff --git a/core/jni/android_opengl_GLES30.cpp b/core/jni/android_opengl_GLES30.cpp
index c9b5af7..59b8911 100644
--- a/core/jni/android_opengl_GLES30.cpp
+++ b/core/jni/android_opengl_GLES30.cpp
@@ -2012,22 +2012,35 @@
static void
android_glGetTransformFeedbackVarying__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2B
(JNIEnv *_env, jobject _this, jint program, jint index, jint bufsize, jobject length_buf, jobject size_buf, jobject type_buf, jbyte name) {
+ jniThrowException(_env, "java/lang/UnsupportedOperationException", "deprecated");
+}
+
+/* void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name ) */
+static void
+android_glGetTransformFeedbackVarying__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_ByteBuffer_2
+ (JNIEnv *_env, jobject _this, jint program, jint index, jint bufsize, jobject length_buf, jobject size_buf, jobject type_buf, jobject name_buf) {
jintArray _lengthArray = (jintArray) 0;
jint _lengthBufferOffset = (jint) 0;
jintArray _sizeArray = (jintArray) 0;
jint _sizeBufferOffset = (jint) 0;
jintArray _typeArray = (jintArray) 0;
jint _typeBufferOffset = (jint) 0;
+ jbyteArray _nameArray = (jbyteArray)0;
+ jint _nameBufferOffset = (jint)0;
jint _lengthRemaining;
GLsizei *length = (GLsizei *) 0;
jint _sizeRemaining;
GLint *size = (GLint *) 0;
jint _typeRemaining;
GLenum *type = (GLenum *) 0;
+ jint _nameRemaining;
+ GLchar* name = (GLchar*)0;
+
length = (GLsizei *)getPointer(_env, length_buf, (jarray*)&_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
size = (GLint *)getPointer(_env, size_buf, (jarray*)&_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
type = (GLenum *)getPointer(_env, type_buf, (jarray*)&_typeArray, &_typeRemaining, &_typeBufferOffset);
+ name = (GLchar*)getPointer(_env, name_buf, (jarray*)&_nameArray, &_nameRemaining, &_nameBufferOffset);
if (length == NULL) {
char * _lengthBase = (char *)_env->GetIntArrayElements(_lengthArray, (jboolean *) 0);
length = (GLsizei *) (_lengthBase + _lengthBufferOffset);
@@ -2040,6 +2053,10 @@
char * _typeBase = (char *)_env->GetIntArrayElements(_typeArray, (jboolean *) 0);
type = (GLenum *) (_typeBase + _typeBufferOffset);
}
+ if (name == NULL) {
+ char* _nameBase = (char *)_env->GetByteArrayElements(_nameArray, (jboolean*)0);
+ name = (GLchar *) (_nameBase + _nameBufferOffset);
+ }
glGetTransformFeedbackVarying(
(GLuint)program,
(GLuint)index,
@@ -2047,11 +2064,7 @@
(GLsizei *)length,
(GLint *)size,
(GLenum *)type,
- // The cast below is incorrect. The driver will end up writing to the
- // address specified by name, which will always crash the process since
- // it is guaranteed to be in low memory. The additional static_cast
- // suppresses the warning for now. http://b/19478262
- (char *)static_cast<uintptr_t>(name)
+ (GLchar*)name
);
if (_typeArray) {
releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _typeArray, (jint*)type, JNI_TRUE);
@@ -2062,6 +2075,9 @@
if (_lengthArray) {
releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _lengthArray, (jint*)length, JNI_TRUE);
}
+ if (_nameArray) {
+ releaseArrayPointer<jbyteArray, jbyte*, ByteArrayReleaser>(_env, _nameArray, (jbyte*)name, JNI_TRUE);
+ }
}
/* void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name ) */
@@ -5155,6 +5171,21 @@
}
}
+/* void glReadPixels ( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint offset ) */
+static void
+android_glReadPixels__IIIIIII
+ (JNIEnv *_env, jobject _this, jint x, jint y, jint width, jint height, jint format, jint type, jint offset) {
+ glReadPixels(
+ (GLint)x,
+ (GLint)y,
+ (GLsizei)width,
+ (GLsizei)height,
+ (GLenum)format,
+ (GLenum)type,
+ reinterpret_cast<GLvoid *>(offset)
+ );
+}
+
static const char *classPathName = "android/opengl/GLES30";
static const JNINativeMethod methods[] = {
@@ -5218,6 +5249,7 @@
{"glTransformFeedbackVaryings", "(I[Ljava/lang/String;I)V", (void *) android_glTransformFeedbackVaryings },
{"glGetTransformFeedbackVarying", "(III[II[II[II[BI)V", (void *) android_glGetTransformFeedbackVarying__III_3II_3II_3II_3BI },
{"glGetTransformFeedbackVarying", "(IIILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;B)V", (void *) android_glGetTransformFeedbackVarying__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2B },
+{"glGetTransformFeedbackVarying", "(IIILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/ByteBuffer;)V", (void *) android_glGetTransformFeedbackVarying__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_ByteBuffer_2 },
{"glGetTransformFeedbackVarying", "(II[II[II)Ljava/lang/String;", (void *) android_glGetTransformFeedbackVarying1 },
{"glGetTransformFeedbackVarying", "(IILjava/nio/IntBuffer;Ljava/nio/IntBuffer;)Ljava/lang/String;", (void *) android_glGetTransformFeedbackVarying2 },
{"glVertexAttribIPointerBounds", "(IIIILjava/nio/Buffer;I)V", (void *) android_glVertexAttribIPointerBounds__IIIILjava_nio_Buffer_2I },
@@ -5320,6 +5352,7 @@
{"glTexStorage3D", "(IIIIII)V", (void *) android_glTexStorage3D__IIIIII },
{"glGetInternalformativ", "(IIII[II)V", (void *) android_glGetInternalformativ__IIII_3II },
{"glGetInternalformativ", "(IIIILjava/nio/IntBuffer;)V", (void *) android_glGetInternalformativ__IIIILjava_nio_IntBuffer_2 },
+{"glReadPixels", "(IIIIIII)V", (void *) android_glReadPixels__IIIIIII },
};
int register_android_opengl_jni_GLES30(JNIEnv *_env)
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 03a1e71..f870a89 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -21,6 +21,7 @@
#include "utils/misc.h"
#include "cutils/debugger.h"
#include <memtrack/memtrack.h>
+#include <memunreachable/memunreachable.h>
#include <cutils/log.h>
#include <fcntl.h>
@@ -36,6 +37,9 @@
#include <ctype.h>
#include <malloc.h>
+#include <iomanip>
+#include <string>
+
namespace android
{
@@ -258,7 +262,13 @@
}
name = line + name_pos;
nameLen = strlen(name);
-
+ // Trim the end of the line if it is " (deleted)".
+ const char* deleted_str = " (deleted)";
+ if (nameLen > (int)strlen(deleted_str) &&
+ strcmp(name+nameLen-strlen(deleted_str), deleted_str) == 0) {
+ nameLen -= strlen(deleted_str);
+ name[nameLen] = '\0';
+ }
if ((strstr(name, "[heap]") == name)) {
whichHeap = HEAP_NATIVE;
} else if (strncmp(name, "[anon:libc_malloc]", 18) == 0) {
@@ -1023,6 +1033,13 @@
close(fd);
}
+static jstring android_os_Debug_getUnreachableMemory(JNIEnv* env, jobject clazz,
+ jint limit, jboolean contents)
+{
+ std::string s = GetUnreachableMemoryString(contents, limit);
+ return env->NewStringUTF(s.c_str());
+}
+
/*
* JNI registration.
*/
@@ -1058,6 +1075,8 @@
(void*)android_os_Debug_getDeathObjectCount },
{ "dumpNativeBacktraceToFile", "(ILjava/lang/String;)V",
(void*)android_os_Debug_dumpNativeBacktraceToFile },
+ { "getUnreachableMemory", "(IZ)Ljava/lang/String;",
+ (void*)android_os_Debug_getUnreachableMemory },
};
int register_android_os_Debug(JNIEnv *env)
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index ae109c6..abc6c4b 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -556,7 +556,7 @@
}
// For the rest of the function we will hold this lock, to serialize
- // looking/creation of Java proxies for native Binder proxies.
+ // looking/creation/destruction of Java proxies for native Binder proxies.
AutoMutex _l(mProxyLock);
// Someone else's... do we know about it?
@@ -1225,16 +1225,21 @@
static void android_os_BinderProxy_destroy(JNIEnv* env, jobject obj)
{
+ // Don't race with construction/initialization
+ AutoMutex _l(mProxyLock);
+
IBinder* b = (IBinder*)
env->GetLongField(obj, gBinderProxyOffsets.mObject);
DeathRecipientList* drl = (DeathRecipientList*)
env->GetLongField(obj, gBinderProxyOffsets.mOrgue);
LOGDEATH("Destroying BinderProxy %p: binder=%p drl=%p\n", obj, b, drl);
- env->SetLongField(obj, gBinderProxyOffsets.mObject, 0);
- env->SetLongField(obj, gBinderProxyOffsets.mOrgue, 0);
- drl->decStrong((void*)javaObjectForIBinder);
- b->decStrong((void*)javaObjectForIBinder);
+ if (b != nullptr) {
+ env->SetLongField(obj, gBinderProxyOffsets.mObject, 0);
+ env->SetLongField(obj, gBinderProxyOffsets.mOrgue, 0);
+ drl->decStrong((void*)javaObjectForIBinder);
+ b->decStrong((void*)javaObjectForIBinder);
+ }
IPCThreadState::self()->flushCommands();
}
diff --git a/core/jni/android_view_DisplayListCanvas.cpp b/core/jni/android_view_DisplayListCanvas.cpp
index 03c94a6..c87a770 100644
--- a/core/jni/android_view_DisplayListCanvas.cpp
+++ b/core/jni/android_view_DisplayListCanvas.cpp
@@ -160,7 +160,7 @@
}
// In the emulator this property will be set > 0 when OpenGL ES 2.0 is
// enabled, 0 otherwise. On old emulator versions it will be undefined.
- property_get("ro.kernel.qemu.gles", prop, "0");
+ property_get("qemu.gles", prop, "0");
return atoi(prop) > 0 ? JNI_TRUE : JNI_FALSE;
}
diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp
index 0926e9b..c9eac79 100644
--- a/core/jni/android_view_RenderNodeAnimator.cpp
+++ b/core/jni/android_view_RenderNodeAnimator.cpp
@@ -184,7 +184,7 @@
static void end(JNIEnv* env, jobject clazz, jlong animatorPtr) {
BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
- animator->end();
+ animator->cancel();
}
// ----------------------------------------------------------------------------
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index cf68449..b7701d6 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -411,22 +411,27 @@
return 0;
}
+ android::view::Surface surfaceShim;
+
+ // Calling code in Surface.java has already read the name of the Surface
+ // from the Parcel
+ surfaceShim.readFromParcel(parcel, /*nameAlreadyRead*/true);
+
sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
- sp<IBinder> binder(parcel->readStrongBinder());
// update the Surface only if the underlying IGraphicBufferProducer
// has changed.
- if (self != NULL
- && (IInterface::asBinder(self->getIGraphicBufferProducer()) == binder)) {
+ if (self != nullptr
+ && (IInterface::asBinder(self->getIGraphicBufferProducer()) ==
+ IInterface::asBinder(surfaceShim.graphicBufferProducer))) {
// same IGraphicBufferProducer, return ourselves
return jlong(self.get());
}
sp<Surface> sur;
- sp<IGraphicBufferProducer> gbp(interface_cast<IGraphicBufferProducer>(binder));
- if (gbp != NULL) {
+ if (surfaceShim.graphicBufferProducer != nullptr) {
// we have a new IGraphicBufferProducer, create a new Surface for it
- sur = new Surface(gbp, true);
+ sur = new Surface(surfaceShim.graphicBufferProducer, true);
// and keep a reference before passing to java
sur->incStrong(&sRefBaseOwner);
}
@@ -447,7 +452,13 @@
return;
}
sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
- parcel->writeStrongBinder( self != 0 ? IInterface::asBinder(self->getIGraphicBufferProducer()) : NULL);
+ android::view::Surface surfaceShim;
+ if (self != nullptr) {
+ surfaceShim.graphicBufferProducer = self->getIGraphicBufferProducer();
+ }
+ // Calling code in Surface.java has already written the name of the Surface
+ // to the Parcel
+ surfaceShim.writeToParcel(parcel, /*nameAlreadyWritten*/true);
}
static jint nativeGetWidth(JNIEnv* env, jclass clazz, jlong nativeObject) {
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 1dfe40a..c838d03 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -110,6 +110,13 @@
ctrl->decStrong((void *)nativeCreate);
}
+static void nativeDisconnect(JNIEnv* env, jclass clazz, jlong nativeObject) {
+ SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ if (ctrl != NULL) {
+ ctrl->disconnect();
+ }
+}
+
static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz,
jobject displayTokenObj, jobject sourceCropObj, jint width, jint height,
jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform,
@@ -595,6 +602,8 @@
(void*)nativeRelease },
{"nativeDestroy", "(J)V",
(void*)nativeDestroy },
+ {"nativeDisconnect", "(J)V",
+ (void*)nativeDisconnect },
{"nativeScreenshot", "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZI)Landroid/graphics/Bitmap;",
(void*)nativeScreenshotBitmap },
{"nativeScreenshot", "(Landroid/os/IBinder;Landroid/view/Surface;Landroid/graphics/Rect;IIIIZZ)V",
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index cd2c0d6..07868c5 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -164,6 +164,13 @@
mPendingAnimatingRenderNodes.clear();
}
+ void destroy() {
+ for (auto& renderNode : mPendingAnimatingRenderNodes) {
+ renderNode->animators().endAllStagingAnimators();
+ }
+ mPendingAnimatingRenderNodes.clear();
+ }
+
private:
sp<Looper> mLooper;
JavaVM* mVm;
@@ -476,7 +483,9 @@
}
static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
- jlong proxyPtr) {
+ jlong proxyPtr, jlong rootNodePtr) {
+ RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
+ rootRenderNode->destroy();
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
proxy->destroy();
}
@@ -698,7 +707,7 @@
{ "nSetLightCenter", "(JFFF)V", (void*) android_view_ThreadedRenderer_setLightCenter },
{ "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
{ "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
- { "nDestroy", "(J)V", (void*) android_view_ThreadedRenderer_destroy },
+ { "nDestroy", "(JJ)V", (void*) android_view_ThreadedRenderer_destroy },
{ "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
{ "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
{ "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 4194aa4..612f4df 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -608,8 +608,12 @@
jlong capabilities = 0;
// Grant CAP_WAKE_ALARM to the Bluetooth process.
+ // Additionally, allow bluetooth to open packet sockets so it can start the DHCP client.
+ // TODO: consider making such functionality an RPC to netd.
if (multiuser_get_app_id(uid) == AID_BLUETOOTH) {
capabilities |= (1LL << CAP_WAKE_ALARM);
+ capabilities |= (1LL << CAP_NET_RAW);
+ capabilities |= (1LL << CAP_NET_BIND_SERVICE);
}
// Grant CAP_BLOCK_SUSPEND to processes that belong to GID "wakelock"
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 9b989b9..8f85d4a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -87,6 +87,7 @@
<protected-broadcast android:name="android.os.action.DEVICE_IDLE_MODE_CHANGED" />
<protected-broadcast android:name="android.os.action.POWER_SAVE_WHITELIST_CHANGED" />
<protected-broadcast android:name="android.os.action.POWER_SAVE_TEMP_WHITELIST_CHANGED" />
+ <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED_INTERNAL" />
<protected-broadcast android:name="android.os.action.SCREEN_BRIGHTNESS_BOOST_CHANGED" />
@@ -265,6 +266,7 @@
<protected-broadcast android:name="com.android.server.WifiManager.action.START_SCAN" />
<protected-broadcast android:name="com.android.server.WifiManager.action.START_PNO" />
<protected-broadcast android:name="com.android.server.WifiManager.action.DELAYED_DRIVER_STOP" />
+ <protected-broadcast android:name="com.android.server.WifiManager.action.DEVICE_IDLE" />
<protected-broadcast android:name="com.android.server.action.REMOTE_BUGREPORT_SHARING_ACCEPTED" />
<protected-broadcast android:name="com.android.server.action.REMOTE_BUGREPORT_SHARING_DECLINED" />
<protected-broadcast android:name="android.net.wifi.WIFI_STATE_CHANGED" />
@@ -296,10 +298,6 @@
<protected-broadcast android:name="android.intent.action.AIRPLANE_MODE" />
<protected-broadcast android:name="android.intent.action.ADVANCED_SETTINGS" />
<protected-broadcast android:name="android.intent.action.APPLICATION_RESTRICTIONS_CHANGED" />
- <protected-broadcast android:name="android.intent.action.BUGREPORT_STARTED" />
- <protected-broadcast android:name="android.intent.action.BUGREPORT_FINISHED" />
- <protected-broadcast android:name="android.intent.action.REMOTE_BUGREPORT_FINISHED" />
- <protected-broadcast android:name="android.intent.action.REMOTE_BUGREPORT_DISPATCH" />
<!-- Legacy -->
<protected-broadcast android:name="android.intent.action.ACTION_IDLE_MAINTENANCE_START" />
@@ -378,7 +376,10 @@
<protected-broadcast android:name="android.app.action.ACTION_PASSWORD_FAILED" />
<protected-broadcast android:name="android.app.action.ACTION_PASSWORD_SUCCEEDED" />
<protected-broadcast android:name="com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION" />
+
<protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_ADDED" />
+ <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_UNLOCKED" />
+ <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_REMOVED" />
<protected-broadcast android:name="android.bluetooth.adapter.action.BLE_STATE_CHANGED" />
<protected-broadcast android:name="android.content.jobscheduler.JOB_DELAY_EXPIRED" />
@@ -436,7 +437,6 @@
<protected-broadcast android:name="android.intent.action.DYNAMIC_SENSOR_CHANGED" />
<protected-broadcast android:name="android.intent.action.ACTION_RADIO_OFF" />
- <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_UNLOCKED" />
<protected-broadcast android:name="android.accounts.LOGIN_ACCOUNTS_CHANGED" />
<protected-broadcast android:name="com.android.sync.SYNC_CONN_STATUS_CHANGED" />
@@ -452,6 +452,12 @@
<protected-broadcast android:name="android.bluetooth.input.profile.action.HANDSHAKE" />
<protected-broadcast android:name="android.bluetooth.input.profile.action.REPORT" />
+ <protected-broadcast android:name="android.intent.action.TWILIGHT_CHANGED" />
+
+ <protected-broadcast android:name="com.android.server.fingerprint.ACTION_LOCKOUT_RESET" />
+ <protected-broadcast android:name="android.net.wifi.PASSPOINT_ICON_RECEIVED" />
+ <protected-broadcast android:name="com.android.server.notification.CountdownConditionProvider" />
+
<!-- ====================================================================== -->
<!-- RUNTIME PERMISSIONS -->
<!-- ====================================================================== -->
@@ -891,92 +897,82 @@
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.READ_PROFILE"
android:protectionLevel="normal"
- android:permissionFlags="hidden"/>
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.WRITE_PROFILE"
android:protectionLevel="normal"
- android:permissionFlags="hidden"/>
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.READ_SOCIAL_STREAM"
android:protectionLevel="normal"
- android:permissionFlags="hidden"/>
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.WRITE_SOCIAL_STREAM"
android:protectionLevel="normal"
- android:permissionFlags="hidden"/>
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.READ_USER_DICTIONARY"
android:protectionLevel="normal"
- android:permissionFlags="hidden"/>
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.WRITE_USER_DICTIONARY"
android:protectionLevel="normal"
- android:permissionFlags="hidden"/>
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.WRITE_SMS"
android:protectionLevel="normal"
- android:permissionFlags="hidden"/>
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"
android:protectionLevel="normal"
- android:permissionFlags="hidden"/>
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="com.android.browser.permission.WRITE_HISTORY_BOOKMARKS"
android:protectionLevel="normal"
- android:permissionFlags="hidden"/>
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"
android:protectionLevel="normal"
- android:permissionFlags="hidden"/>
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.MANAGE_ACCOUNTS"
android:protectionLevel="normal"
- android:permissionFlags="hidden"/>
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.USE_CREDENTIALS"
android:protectionLevel="normal"
- android:permissionFlags="hidden"/>
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.SUBSCRIBED_FEEDS_READ"
android:protectionLevel="normal"
- android:permissionFlags="hidden"/>
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.SUBSCRIBED_FEEDS_WRITE"
android:protectionLevel="normal"
- android:permissionFlags="hidden"/>
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.FLASHLIGHT"
android:protectionLevel="normal"
- android:permissionFlags="hidden"/>
+ android:permissionFlags="removed"/>
<!-- ====================================================================== -->
<!-- INSTALL PERMISSIONS -->
<!-- ====================================================================== -->
-` <!-- =========================================== -->
- <!-- Permissions for accessing contact metadata -->
- <!-- =========================================== -->
- <eat-comment />
-
- <!-- @SystemApi Allows an application to read/write contact metadata.
- <p>Not for use by third-party applications. -->
- <permission android:name="android.permission.READ_WRITE_CONTACT_METADATA"
- android:protectionLevel="signature|system" />
-
<!-- ================================== -->
<!-- Permissions for accessing messages -->
<!-- ================================== -->
@@ -1610,6 +1606,11 @@
<permission android:name="android.permission.GET_PACKAGE_IMPORTANCE"
android:protectionLevel="signature|privileged" />
+ <!-- Allows use of PendingIntent.getIntent().
+ @hide -->
+ <permission android:name="android.permission.GET_INTENT_SENDER_INTENT"
+ android:protectionLevel="signature" />
+
<!-- ================================== -->
<!-- Permissions affecting the display of other applications -->
<!-- ================================== -->
@@ -2006,6 +2007,12 @@
<permission android:name="android.permission.UPDATE_APP_OPS_STATS"
android:protectionLevel="signature|privileged|installer" />
+ <!-- Allows an application to update the user app op restrictions.
+ Not for use by third party apps.
+ @hide -->
+ <permission android:name="android.permission.MANAGE_APP_OPS_RESTRICTIONS"
+ android:protectionLevel="signature|installer" />
+
<!-- @SystemApi Allows an application to open windows that are for use by parts
of the system user interface.
<p>Not for use by third-party applications.
diff --git a/core/res/res/drawable-nodpi/default_wallpaper.jpg b/core/res/res/drawable-nodpi/default_wallpaper.jpg
deleted file mode 100644
index d7475b4c..0000000
--- a/core/res/res/drawable-nodpi/default_wallpaper.jpg
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-nodpi/default_wallpaper.png b/core/res/res/drawable-nodpi/default_wallpaper.png
new file mode 100644
index 0000000..e9c4d5c
--- /dev/null
+++ b/core/res/res/drawable-nodpi/default_wallpaper.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/platlogo.xml b/core/res/res/drawable-nodpi/platlogo.xml
index bb423fef5..defa83a 100644
--- a/core/res/res/drawable-nodpi/platlogo.xml
+++ b/core/res/res/drawable-nodpi/platlogo.xml
@@ -1,5 +1,5 @@
<!--
-Copyright (C) 2015 The Android Open Source Project
+Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,20 +14,24 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
+ android:width="512dp"
+ android:height="512dp"
android:viewportWidth="48.0"
android:viewportHeight="48.0">
<path
- android:pathData="M34.9,13.2c-0.8,-0.8,-4.2,-2.4,-10.9,-2.4s-10.1,1.6,-10.9,2.4c-0.8,0.8,-2.4,4.2,-2.4,10.9s1.6,10.1,2.4,10.9 c0.8,0.8,4.2,2.4,10.9,2.4s10.1,-1.6,10.9,-2.4c0.8,-0.8,2.4,-4.2,2.4,-10.9S35.6,14,34.9,13.2z"
- android:fillColor="#FFFFFF"/>
+ android:fillColor="#FF7E5BBF"
+ android:pathData="M32.0,12.5l0.0,28.0l12.0,-5.0l0.0,-28.0z"/>
<path
- android:pathData="M34.7,13.7c0,0.8,-1.2,1.5,-3.1,2.1c-1.9,0.5,-4.6,0.8,-7.6,0.8s-5.6,-0.3,-7.6,-0.8 c-1.9,-0.5,-3.1,-1.2,-3.1,-2.1s1.2,-1.5,3.1,-2.1c1.9,-0.5,4.6,-0.8,7.6,-0.8s5.6,0.3,7.6,0.8C33.5,12.1,34.7,12.9,34.7,13.7z"
- android:fillColor="#EBEBEB"/>
+ android:fillColor="#FF7E5BBF"
+ android:pathData="M4.0,40.5l12.0,-5.0l0.0,-11.0l-12.0,-12.0z"/>
<path
- android:pathData="M30,13c-0.1,0,-0.1,0,-0.2,0c-0.4,-0.1,-0.7,-0.6,-0.6,-1l1.3,-5.5c0.1,-0.4,0.6,-0.7,1,-0.6c0.4,0.1,0.7,0.6,0.6,1 l-1.3,5.5C30.7,12.7,30.4,13,30,13z"
- android:fillColor="#FFFFFF"/>
+ android:fillColor="#40000000"
+ android:pathData="M44.0,35.5l-12.0,-12.0l0.0,-4.0z"/>
<path
- android:pathData="M18,13c-0.4,0,-0.7,-0.3,-0.8,-0.6l-1.3,-5.5c-0.1,-0.4,0.2,-0.9,0.6,-1c0.4,-0.1,0.9,0.2,1,0.6l1.3,5.5 c0.1,0.4,-0.2,0.9,-0.6,1C18.1,13,18.1,13,18,13z"
- android:fillColor="#FFFFFF"/>
+ android:fillColor="#40000000"
+ android:pathData="M4.0,12.5l12.0,12.0l0.0,4.0z"/>
+ <path
+ android:fillColor="#FF55C4F5"
+ android:pathData="M32.0,23.5l-16.0,-16.0l-12.0,5.0l0.0,0.0l12.0,12.0l16.0,16.0l12.0,-5.0l0.0,0.0z"/>
</vector>
+
diff --git a/core/res/res/drawable-nodpi/stat_sys_adb.xml b/core/res/res/drawable-nodpi/stat_sys_adb.xml
index 8cc9961..5043cba 100644
--- a/core/res/res/drawable-nodpi/stat_sys_adb.xml
+++ b/core/res/res/drawable-nodpi/stat_sys_adb.xml
@@ -1,5 +1,5 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,23 +14,23 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
<path
- android:pathData="M8.4,5.3c-0.2,0.0 -0.4,-0.2 -0.5,-0.4L7.1,1.6C7.0,1.4 7.2,1.1 7.4,1.0C7.7,0.9 8.0,1.1 8.0,1.4l0.8,3.3c0.1,0.3 -0.1,0.5 -0.4,0.6C8.5,5.3 8.4,5.3 8.4,5.3z"
- android:fillColor="#FFFFFF"/>
+ android:fillColor="#A0FFFFFF"
+ android:pathData="M32.0,12.5l0.0,28.0l12.0,-5.0l0.0,-28.0z"/>
<path
- android:pathData="M15.6,5.3c0.0,0.0 -0.1,0.0 -0.1,0.0c-0.3,-0.1 -0.4,-0.3 -0.4,-0.6L16.0,1.4C16.0,1.1 16.3,0.9 16.6,1.0c0.3,0.1 0.4,0.3 0.4,0.6l-0.8,3.3C16.1,5.1 15.9,5.3 15.6,5.3z"
- android:fillColor="#FFFFFF"/>
+ android:fillColor="#A0FFFFFF"
+ android:pathData="M4.0,40.5l12.0,-5.0l0.0,-11.0l-12.0,-12.0z"/>
<path
- android:pathData="M18.6,5.4c-0.1,-0.1 -0.2,-0.1 -0.3,-0.2c0.2,0.2 0.3,0.3 0.3,0.5c0.0,0.9 -2.9,1.7 -6.6,1.7S5.4,6.7 5.4,5.7c0.0,-0.2 0.1,-0.3 0.3,-0.5C5.6,5.3 5.5,5.4 5.4,5.4C5.0,5.9 4.0,8.0 4.0,12.0s1.0,6.1 1.4,6.6C5.9,19.0 8.0,20.0 12.0,20.0s6.1,-1.0 6.6,-1.4C19.0,18.1 20.0,16.0 20.0,12.0S19.0,5.9 18.6,5.4zM8.0,13.0c-0.6,0.0 -1.0,-0.4 -1.0,-1.0c0.0,-0.6 0.4,-1.0 1.0,-1.0s1.0,0.4 1.0,1.0C9.0,12.6 8.6,13.0 8.0,13.0zM16.0,13.0c-0.6,0.0 -1.0,-0.4 -1.0,-1.0c0.0,-0.6 0.4,-1.0 1.0,-1.0s1.0,0.4 1.0,1.0C17.0,12.6 16.6,13.0 16.0,13.0z"
- android:fillColor="#FFFFFF"/>
- <path
- android:pathData="M5.35,5.7
- a 6.6 1.75 0 1 1 13.25 0
- a 6.6 1.75 0 1 1 -13.25 0
- z"
- android:fillColor="#BBFFFFFF" />
+ android:fillColor="#40000000"
+ android:pathData="M44.0,35.5l-12.0,-12.0l0.0,-4.0z"/>
+ <path
+ android:fillColor="#40000000"
+ android:pathData="M4.0,12.5l12.0,12.0l0.0,4.0z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M32.0,23.5l-16.0,-16.0l-12.0,5.0l0.0,0.0l12.0,12.0l16.0,16.0l12.0,-5.0l0.0,0.0z"/>
</vector>
diff --git a/core/res/res/drawable-sw600dp-nodpi/default_wallpaper.jpg b/core/res/res/drawable-sw600dp-nodpi/default_wallpaper.jpg
deleted file mode 100644
index 03a14c0..0000000
--- a/core/res/res/drawable-sw600dp-nodpi/default_wallpaper.jpg
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-nodpi/default_wallpaper.png b/core/res/res/drawable-sw600dp-nodpi/default_wallpaper.png
new file mode 100644
index 0000000..9f3efa5
--- /dev/null
+++ b/core/res/res/drawable-sw600dp-nodpi/default_wallpaper.png
Binary files differ
diff --git a/core/res/res/drawable-sw720dp-nodpi/default_wallpaper.jpg b/core/res/res/drawable-sw720dp-nodpi/default_wallpaper.jpg
deleted file mode 100644
index 543d118..0000000
--- a/core/res/res/drawable-sw720dp-nodpi/default_wallpaper.jpg
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-sw720dp-nodpi/default_wallpaper.png b/core/res/res/drawable-sw720dp-nodpi/default_wallpaper.png
new file mode 100644
index 0000000..8199e70
--- /dev/null
+++ b/core/res/res/drawable-sw720dp-nodpi/default_wallpaper.png
Binary files differ
diff --git a/core/res/res/drawable/work_widget_mask_view_background.xml b/core/res/res/drawable/work_widget_mask_view_background.xml
deleted file mode 100644
index 17f0dbc..0000000
--- a/core/res/res/drawable/work_widget_mask_view_background.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
- <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
- <padding android:left="5dp" android:right="5dp" android:top="5dp" android:bottom="5dp"/>
- <stroke android:width="1dp" android:color="#CCCCCC" />
- </shape>
diff --git a/core/res/res/layout/language_picker_item.xml b/core/res/res/layout/language_picker_item.xml
index 22cb514..88012a9 100644
--- a/core/res/res/layout/language_picker_item.xml
+++ b/core/res/res/layout/language_picker_item.xml
@@ -14,37 +14,16 @@
limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_vertical"
- android:orientation="horizontal"
- android:layoutDirection="locale"
- android:textDirection="locale"
- android:paddingBottom="8dp"
- android:paddingTop="8dp">
-
- <TextView
- android:id="@+id/locale"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- tools:text="France"
- android:layout_weight="1"
- android:padding="12dp"
- android:paddingStart="18dp"
- android:paddingEnd="18dp"
- android:textAppearance="?android:attr/textAppearanceListItem"/>
-
- <ImageView
- android:id="@+id/l10nWarn"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@android:drawable/stat_sys_warning"
- android:focusableInTouchMode="false"
- android:focusable="false"
- android:paddingStart="12dp"
- android:paddingEnd="12dp"
- android:tint="?android:attr/colorAccent"/>
-
-</LinearLayout>
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/locale"
+ android:gravity="center_vertical"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:textAppearance="?android:attr/textAppearanceListItem"
+ android:layoutDirection="locale"
+ android:textDirection="locale"
+ android:paddingBottom="8dp"
+ android:paddingTop="8dp" />
diff --git a/core/res/res/layout/language_picker_section_header.xml b/core/res/res/layout/language_picker_section_header.xml
index b12ec8c..6cbd7c3 100644
--- a/core/res/res/layout/language_picker_section_header.xml
+++ b/core/res/res/layout/language_picker_section_header.xml
@@ -23,4 +23,5 @@
android:paddingStart="18dp"
android:paddingEnd="18dp"
android:textColor="?android:attr/colorAccent"
+ android:textStyle="bold"
tools:text="@string/language_picker_section_all"/>
diff --git a/core/res/res/layout/notification_template_material_big_media.xml b/core/res/res/layout/notification_template_material_big_media.xml
index aa78eff..a5ed187 100644
--- a/core/res/res/layout/notification_template_material_big_media.xml
+++ b/core/res/res/layout/notification_template_material_big_media.xml
@@ -19,41 +19,45 @@
<com.android.internal.widget.MediaNotificationView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/status_bar_latest_event_content"
android:layout_width="match_parent"
- android:layout_height="126dp"
+ android:layout_height="wrap_content"
android:background="#00000000"
android:tag="bigMediaNarrow"
>
<include layout="@layout/notification_template_header"
android:layout_width="match_parent"
android:layout_height="48dp"
- android:layout_alignParentStart="true"/>
+ android:layout_gravity="start"/>
<LinearLayout
- android:id="@+id/notification_main_column"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/notification_content_margin_top"
- android:layout_marginStart="@dimen/notification_content_margin_start"
- android:layout_marginBottom="@dimen/notification_content_margin_bottom"
- android:layout_marginEnd="@dimen/notification_content_margin_end"
- android:layout_toStartOf="@id/right_icon"
- android:minHeight="@dimen/notification_min_content_height"
android:orientation="vertical"
>
- <include layout="@layout/notification_template_part_line1" />
- <include layout="@layout/notification_template_text" />
- </LinearLayout>
- <LinearLayout
- android:id="@+id/media_actions"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_alignParentStart="true"
- android:paddingStart="8dp"
- android:paddingBottom="8dp"
- android:orientation="horizontal"
- android:layoutDirection="ltr"
- >
- <!-- media buttons will be added here -->
+ <LinearLayout
+ android:id="@+id/notification_main_column"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/notification_content_margin_top"
+ android:layout_marginStart="@dimen/notification_content_margin_start"
+ android:layout_marginBottom="@dimen/notification_content_margin_bottom"
+ android:layout_marginEnd="@dimen/notification_content_margin_end"
+ android:minHeight="@dimen/notification_min_content_height"
+ android:orientation="vertical"
+ >
+ <include layout="@layout/notification_template_part_line1" />
+ <include layout="@layout/notification_template_text" />
+ </LinearLayout>
+ <LinearLayout
+ android:id="@+id/media_actions"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="-15dp"
+ android:paddingStart="8dp"
+ android:paddingBottom="8dp"
+ android:orientation="horizontal"
+ android:layoutDirection="ltr"
+ >
+ <!-- media buttons will be added here -->
+ </LinearLayout>
</LinearLayout>
<ImageView android:id="@+id/right_icon"
@@ -61,9 +65,8 @@
android:layout_height="@dimen/media_notification_expanded_image_max_size"
android:minWidth="40dp"
android:layout_marginEnd="16dp"
- android:layout_marginTop="16dp"
- android:layout_alignParentEnd="true"
- android:layout_alignParentTop="true"
+ android:layout_marginBottom="16dp"
+ android:layout_gravity="bottom|end"
android:scaleType="centerCrop"
/>
</com.android.internal.widget.MediaNotificationView>
diff --git a/core/res/res/layout/notification_template_material_big_text.xml b/core/res/res/layout/notification_template_material_big_text.xml
index 9a4b28c..3c59b4e 100644
--- a/core/res/res/layout/notification_template_material_big_text.xml
+++ b/core/res/res/layout/notification_template_material_big_text.xml
@@ -39,7 +39,7 @@
<com.android.internal.widget.ImageFloatingTextView android:id="@+id/big_text"
android:layout_width="match_parent"
android:layout_height="0dp"
- android:layout_marginTop="1.5dp"
+ android:layout_marginTop="1dp"
android:paddingBottom="@dimen/notification_content_margin_bottom"
android:textAppearance="@style/TextAppearance.Material.Notification"
android:singleLine="false"
diff --git a/core/res/res/layout/notification_template_material_media.xml b/core/res/res/layout/notification_template_material_media.xml
index aea9b44..cda0636 100644
--- a/core/res/res/layout/notification_template_material_media.xml
+++ b/core/res/res/layout/notification_template_material_media.xml
@@ -36,6 +36,7 @@
android:tag="media"
>
<LinearLayout
+ android:id="@+id/notification_content_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="fill_vertical"
@@ -45,7 +46,6 @@
android:orientation="vertical"
>
<include layout="@layout/notification_template_part_line1"/>
- <include layout="@layout/notification_template_progress"/>
<include layout="@layout/notification_template_text"/>
</LinearLayout>
<LinearLayout
diff --git a/core/res/res/layout/notification_template_text.xml b/core/res/res/layout/notification_template_text.xml
index 38470cd..47b30ec 100644
--- a/core/res/res/layout/notification_template_text.xml
+++ b/core/res/res/layout/notification_template_text.xml
@@ -14,12 +14,12 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.internal.widget.ImageFloatingTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
- android:layout_marginTop="1.5dp"
+ android:layout_marginTop="1dp"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
android:gravity="top"
diff --git a/core/res/res/layout/text_edit_suggestion_container_material.xml b/core/res/res/layout/text_edit_suggestion_container_material.xml
index 20a80489..d1c65c0 100644
--- a/core/res/res/layout/text_edit_suggestion_container_material.xml
+++ b/core/res/res/layout/text_edit_suggestion_container_material.xml
@@ -31,9 +31,9 @@
android:showDividers="middle">
<ListView
android:id="@+id/suggestionContainer"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingTop="8dp"
+ android:paddingTop="4dp"
android:paddingBottom="0dp"
android:divider="@null" />
<LinearLayout
diff --git a/core/res/res/layout/work_widget_mask_view.xml b/core/res/res/layout/work_widget_mask_view.xml
index ce86ddc..3c47705 100644
--- a/core/res/res/layout/work_widget_mask_view.xml
+++ b/core/res/res/layout/work_widget_mask_view.xml
@@ -15,20 +15,24 @@
limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/work_widget_mask_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="#F3374248" >
+ android:background="#F3374248"
+ android:clickable="true" >
<ImageView android:id="@+id/work_widget_app_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center"/>
+ android:layout_gravity="center"
+ android:clickable="false" />
- <ImageView
+ <ImageView android:id="@+id/work_widget_badge_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_marginBottom="4dp"
android:layout_marginRight="4dp"
- android:src="@drawable/ic_corp_badge_off" />
+ android:src="@drawable/ic_corp_badge_off"
+ android:clickable="false" />
</FrameLayout>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 6b158dc..06fcda9 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Beller-ID se verstek is nie beperk nie. Volgende oproep: nie beperk nie"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Diens nie verskaf nie."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Jy kan nie die beller-ID-instelling verander nie."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Beperkte toegang het verander"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Datadiens word geblokkeer."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Nooddiens word geblokkeer."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Stemdiens word geblokkeer."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Stel terug en herbegin program"</string>
<string name="aerr_report" msgid="5371800241488400617">"Stuur terugvoer"</string>
<string name="aerr_close" msgid="2991640326563991340">"Maak toe"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Demp"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Demp totdat toestel herbegin"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Wag"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Maak program toe"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Raak vir meer opsies."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB-ontfouter gekoppel"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Raak om USB-ontfouting te deaktiveer."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Deel foutverslag?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Deel tans foutverslag …"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Jou IT-administrateur het \'n foutverslag versoek om met die foutsporing van hierdie toestel te help. Programme en data sal dalk gedeel word en jou toestel sal dalk tydelik stadiger wees."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Jou IT-administrateur het \'n foutverslag versoek om met die foutsporing van hierdie toestel te help. Programme en data sal dalk gedeel word."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Dit sal jou toestel dalk tydelik stadiger maak"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"AANVAAR"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"WEIER"</string>
<string name="select_input_method" msgid="8547250819326693584">"Verander sleutelbord"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Vra PIN voordat jy ontspeld"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Vra ontsluitpatroon voordat jy ontspeld"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Vra wagwoord voordat jy ontspeld"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Program se grootte kan nie verander word nie; rollees dit met twee vingers."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Program sal dalk nie met verdeelde skerm werk nie."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Program steun nie verdeelde skerm nie."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Deur jou administrateur geïnstalleer"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Opgedateer deur jou administrateur"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> gekies</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> gekies</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Diverse"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Jy stel die belangrikheid van hierdie kennisgewings."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Jy stel die belangrikheid van hierdie kennisgewings."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Dit is belangrik as gevolg van die mense wat betrokke is."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Laat <xliff:g id="APP">%1$s</xliff:g> toe om \'n nuwe gebruiker met <xliff:g id="ACCOUNT">%2$s</xliff:g> te skep?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Laat <xliff:g id="APP">%1$s</xliff:g> toe om \'n nuwe gebruiker met <xliff:g id="ACCOUNT">%2$s</xliff:g> te skep (\'n gebruiker met hierdie rekening bestaan reeds)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Taalvoorkeur"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Voeg \'n taal by"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Streekvoorkeur"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Voer taalnaam in"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Voorgestel"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Speld vas"</string>
<string name="unpin_target" msgid="3556545602439143442">"Ontspeld"</string>
<string name="app_info" msgid="6856026610594615344">"Programinligting"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 5332c62..f06d7de 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"የደዋይ ID ነባሪዎች ወደአልተከለከለም። ቀጥሎ ጥሪ፡አልተከለከለም"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"አገልግሎት አልቀረበም።"</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"የደዋይ መታወቂያ ቅንብሮች መለወጥ አትችልም፡፡"</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"ክልክል ድረስተለውጧል"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"የውሂብ አገልግሎት የታገደ ነው።"</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"የአደጋ ጊዜአገልግሎት የታገደ ነው።"</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"የድምፅ አገልግሎት ታግዷል።"</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"ዳግም ያቀናብሩ እና መተግበሪያ ዳግም ያስጀምሩት"</string>
<string name="aerr_report" msgid="5371800241488400617">"ግብረመልስ ይላኩ"</string>
<string name="aerr_close" msgid="2991640326563991340">"ዝጋ"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"ድምጽ-ከል አድርግ"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"መሣሪያ ዳግም እስኪጀመር ድረስ ድምጽ ያጥፉ"</string>
<string name="aerr_wait" msgid="3199956902437040261">"ጠብቅ"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"መተግበሪያን ዝጋ"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"ለተጨማሪ አማራጮች ነካ ያድርጉ።"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB አድስ ተያይዟል"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB ማረሚያ ላለማንቃት ዳስስ።"</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"የእርስዎ አይቲ አስተዳዳሪ ለዚህ መሣሪያ መላ ለመፈለግ እንዲያግዝ የሳንካ ሪፖርት ጠይቀዋል። መተግበሪያዎች እና ውሂብ ሊጋሩ ይችላሉ። ይሄ መሣሪያዎን ለጊዜው ሊያዘገየው ይችላል።"</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"የእርስዎ አይቲ አስተዳዳሪ ለዚህ መሣሪያ መላ ለመፈለግ የሳንካ ሪፖርት ጠይቀዋል። መተግበሪያዎች እና ውሂብ ሊጋሩ ይችላሉ።"</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"ይሄ መሣሪያዎን ለጊዜው ሊያዘገየው ይችላል"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ተቀበል"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ውድቅ አድርግ"</string>
<string name="select_input_method" msgid="8547250819326693584">"ቁልፍ ሰሌዳ ይቀይሩ"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ከመንቀል በፊት ፒን ጠይቅ"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ከመንቀል በፊት የማስከፈቻ ስርዓተ-ጥለት ጠይቅ"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ከመንቀል በፊት የይለፍ ቃል ጠይቅ"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"የመተግበሪያው መጠን ሊቀየር የሚችል አይደለም፣ በሁለት ጣቶች ያሸብልሉት።"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"መተግበሪያ ከተከፈለ ማያ ገጽ ጋር ላይሠራ ይችላል"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"መተግበሪያው የተከፈለ ማያ ገጽን አይደግፍም።"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"በእርስዎ አስተዳዳሪ ተጭኗል"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"በአስተዳዳሪዎ ተዘምኗል"</string>
@@ -1543,12 +1537,11 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ተመርጧል</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ተመርጠዋል</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"የተለያዩ"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"የእነዚህን ማሳወቂያዎች አስፈላጊነት አዘጋጅተዋል።"</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"የእነዚህን ማሳወቂያዎች አስፈላጊነት አዘጋጅተዋል።"</string>
<string name="importance_from_person" msgid="9160133597262938296">"ይሄ በሚሳተፉ ሰዎች ምክንያት አስፈላጊ ነው።"</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> በ<xliff:g id="ACCOUNT">%2$s</xliff:g> አዲስ ተጠቃሚ እንዲፈጥር ይፈቀድለት?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> በ<xliff:g id="ACCOUNT">%2$s</xliff:g> አዲስ ተጠቃሚ እንዲፈጥር ይፈቀድለት (ይህ መለያ ያለው ተጠቃሚ አስቀድሞ አለ)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"የቋንቋ ምርጫ"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"ቋንቋ ያክሉ"</string>
<string name="country_selection_title" msgid="2954859441620215513">"የክልል ምርጫ"</string>
<string name="search_language_hint" msgid="7042102592055108574">"የቋንቋ ስም ይተይቡ"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"የተጠቆሙ"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"ፒን"</string>
<string name="unpin_target" msgid="3556545602439143442">"ንቀል"</string>
<string name="app_info" msgid="6856026610594615344">"የመተግበሪያ መረጃ"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index e592fb9..d8a8377 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -92,7 +92,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"الإعداد الافتراضي لمعرف المتصل هو غير مقيّد. الاتصال التالي: غير مقيّد"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"الخدمة غير متوفرة."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"لا يمكنك تغيير إعداد معرف المتصل."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"تم تغيير الدخول المقيّد"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"خدمة البيانات محظورة."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"خدمة الطوارئ محظورة."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"الخدمة الصوتية محظورة."</string>
@@ -941,7 +940,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"إعادة ضبط التطبيق وإعادة تشغيله"</string>
<string name="aerr_report" msgid="5371800241488400617">"إرسال تعليقات"</string>
<string name="aerr_close" msgid="2991640326563991340">"إغلاق"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"تجاهل"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"التعطيل حتى إعادة تشغيل الجهاز"</string>
<string name="aerr_wait" msgid="3199956902437040261">"انتظار"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"إغلاق التطبيق"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1085,16 +1084,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"المس للحصول على مزيد من الخيارات."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"تم توصيل تصحيح أخطاء USB"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"المس لتعطيل تصحيح أخطاء USB."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"طلب مشرف تكنولوجيا المعلومات الحصول على تقرير خطأ للمساعدة في تحرِّي مشكلة هذا الجهاز وإصلاحها. قد تتم مشاركة التطبيقات والبيانات. وقد يؤدي هذا إلى حدوث بطء مؤقت في جهازك."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"طلب مشرف تكنولوجيا المعلومات الحصول على تقرير خطأ للمساعدة في تحرِّي مشكلة هذا الجهاز وإصلاحها. قد تتم مشاركة التطبيقات والبيانات."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"قد يؤدي هذا إلى حدوث بطء مؤقت في جهازك"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"قبول"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"رفض"</string>
<string name="select_input_method" msgid="8547250819326693584">"تغيير لوحة المفاتيح"</string>
@@ -1513,7 +1507,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"المطالبة برقم التعريف الشخصي قبل إزالة التثبيت"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"المطالبة بنقش إلغاء القفل قبل إزالة التثبيت"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"المطالبة بكلمة المرور قبل إزالة التثبيت"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"التطبيق غير قابل لتغيير الحجم، يمكنك تمريره بإصبعين."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"يمكن ألا يعمل التطبيق مع وضع تقسيم الشاشة."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"التطبيق لا يتيح تقسيم الشاشة."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"تم تثبيت الحزمة عن طريق المشرف"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"تم التحديث بواسطة المشرف"</string>
@@ -1619,12 +1613,11 @@
<item quantity="other">تم تحديد <xliff:g id="COUNT_1">%1$d</xliff:g> من العناصر</item>
<item quantity="one">تم تحديد <xliff:g id="COUNT_0">%1$d</xliff:g> عنصر</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"متنوعة"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"لقد عيَّنت أهمية هذه الإشعارات."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"لقد عيَّنت أهمية هذه الإشعارات."</string>
<string name="importance_from_person" msgid="9160133597262938296">"هذه الرسالة مهمة نظرًا لأهمية الأشخاص المعنيين."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"هل تسمح لـ <xliff:g id="APP">%1$s</xliff:g> بإنشاء مستخدم جديد باستخدام <xliff:g id="ACCOUNT">%2$s</xliff:g>؟"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"هل تسمح لـ <xliff:g id="APP">%1$s</xliff:g> بإنشاء مستخدم جديد باستخدام <xliff:g id="ACCOUNT">%2$s</xliff:g> (يوجد مستخدم بهذا الحساب مسبقًا)؟"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"تفضيل اللغة"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"إضافة لغة"</string>
<string name="country_selection_title" msgid="2954859441620215513">"تفضيل المنطقة"</string>
<string name="search_language_hint" msgid="7042102592055108574">"اكتب اسم اللغة"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"المقترحة"</string>
@@ -1647,4 +1640,5 @@
<string name="pin_target" msgid="3052256031352291362">"تثبيت"</string>
<string name="unpin_target" msgid="3556545602439143442">"إزالة تثبيت"</string>
<string name="app_info" msgid="6856026610594615344">"معلومات عن التطبيق"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index 7313063..33d1616 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Adətən zəng edənin ID\'si məhdudlaşdırılmır. Növbəti zəng: Məhdudlaşdırılmayıb"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Xidmət təmin edilməyib."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Siz zəng edənin ID nizamlarını dəyişə bilməzsiz."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Məhdudlaşdırılmış keçid dəyişdi"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Data xidmət bağlıdır."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Təcili xidmət bağlıdır."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Səs xidməti bağlıdır."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Tətbiqi sıfırlayın və yenidən başladın"</string>
<string name="aerr_report" msgid="5371800241488400617">"Geri əlaqə göndərin"</string>
<string name="aerr_close" msgid="2991640326563991340">"Bağla"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Susdur"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Cihaz yeniden başladılana kimi səssiz edin"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Gözləyin"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Tətbiqi qapadın"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Əlavə seçimlər üçün toxunun."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB sazlama qoşuludur"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB debaqı deaktivasiya etmək üçün toxunun."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Baq hesabatı paylaşılsın?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Baq hesabatı paylaşılır..."</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"IT admininiz bu cihazda nasazlıqların aşkarlanması üçün baq hesabatı sorğusu göndərdi. Tətbiqlər və data paylaşıla və cihazınız surəti müvəqqəti azala bilər."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"IT admininiz bu cihazda nasazlıqların aşkarlanması üçün baq hesabatı sorğusu göndərdi. Tətbiqlər və data paylaşıla bilər."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Bu cihazınızın sürətini müvəqqəti olaraq azalda bilər"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"QƏBUL EDİN"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"RƏDD ET"</string>
<string name="select_input_method" msgid="8547250819326693584">"Klaviaturanı dəyişin"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Ayırmadan öncə PIN istənilsin"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Ayırmadan öncə kilid modeli istənilsin"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Ayırmadan öncə parol istənilsin"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Tətbiq ölçüləndirilmədi, iki barmağınızla sürüşdürün."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Tətbiq bölünmüş ekran ilə işləməyə bilər."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Tətbiq ekran bölünməsini dəstəkləmir."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Administratorunuz tərəfindən quraşdırılıb"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Sizin administrator tərəfindən yeniləndi"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> seçilib</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> seçilib</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Müxtəlif"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Bildirişlərin əhəmiyyətini Siz ayarlaryırsınız."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Bildirişlərin əhəmiyyətini Siz ayarlaryırsınız."</string>
<string name="importance_from_person" msgid="9160133597262938296">"İnsanlar cəlb olunduğu üçün bu vacibdir."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> tətbiqinə <xliff:g id="ACCOUNT">%2$s</xliff:g> hesabı ilə yeni İstifadəçi yaratmağa icazə verilsin?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> tətbiqinə<xliff:g id="ACCOUNT">%2$s</xliff:g> (bu hesab ilə İstifadəçi artıq mövcuddur) hesabı ilə yeni İstifadəçi yaratmağa icazə verilsin?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Dil seçimi"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Dil əlavə edin"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Region seçimi"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Dil adını daxil edin"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Təklif edilmiş"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Pin kod"</string>
<string name="unpin_target" msgid="3556545602439143442">"Çıxarın"</string>
<string name="app_info" msgid="6856026610594615344">"Tətbiq məlumatı"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 3206faa..7ed9a20 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -89,7 +89,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"ID pozivaoca podrazumevano nije ograničen. Sledeći poziv: Nije ograničen."</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Usluga nije dobavljena."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Ne možete da promenite podešavanje ID-a korisnika."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Ograničeni pristup je promenjen"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Usluga za podatke je blokirana."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Usluga za hitne slučajeve je blokirana."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Glasovna usluga je blokirana."</string>
@@ -164,7 +163,7 @@
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Previše <xliff:g id="CONTENT_TYPE">%s</xliff:g> izbrisanih stavki."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Memorija tableta je puna! Izbrišite neke datoteke da biste oslobodili prostor."</string>
<string name="low_memory" product="watch" msgid="4415914910770005166">"Memorija sata je puna. Izbrišite neke datoteke da biste oslobodili prostor."</string>
- <string name="low_memory" product="tv" msgid="516619861191025923">"Skladišni prostor na TV-u je popunjen. Izbrišite neke datoteke da biste oslobodili prostor."</string>
+ <string name="low_memory" product="tv" msgid="516619861191025923">"Memorijski prostor na TV-u je popunjen. Izbrišite neke datoteke da biste oslobodili prostor."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Skladište telefona je puno! Izbrišite neke datoteke kako biste oslobodili prostor."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Mreža se možda nadgleda"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Od strane nepoznate treće strane"</string>
@@ -313,7 +312,7 @@
<string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Dozvoljava aplikaciji da učini sopstvene komponente trajnim u memoriji. Ovo može da ograniči memoriju dostupnu drugim aplikacijama i uspori tablet."</string>
<string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Dozvoljava aplikaciji da neke svoje delove trajno zadrži u memoriji. To može da ograniči memoriju dostupnu drugim aplikacijama i uspori TV."</string>
<string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Dozvoljava aplikaciji da učini sopstvene komponente trajnim u memoriji. Ovo može da ograniči memoriju dostupnu drugim aplikacijama i uspori telefon."</string>
- <string name="permlab_getPackageSize" msgid="7472921768357981986">"merenje prostora za skladištenje u aplikaciji"</string>
+ <string name="permlab_getPackageSize" msgid="7472921768357981986">"merenje memorijskog prostora u aplikaciji"</string>
<string name="permdesc_getPackageSize" msgid="3921068154420738296">"Dozvoljava aplikaciji da preuzme veličine kôda, podataka i keša."</string>
<string name="permlab_writeSettings" msgid="2226195290955224730">"izmena podešavanja sistema"</string>
<string name="permdesc_writeSettings" msgid="7775723441558907181">"Dozvoljava aplikaciji da menja podatke o podešavanju sistema. Zlonamerne aplikacije mogu da oštete konfiguraciju sistema."</string>
@@ -886,9 +885,9 @@
<string name="deleteText" msgid="6979668428458199034">"Izbriši"</string>
<string name="inputMethod" msgid="1653630062304567879">"Metod unosa"</string>
<string name="editTextMenuTitle" msgid="4909135564941815494">"Radnje u vezi sa tekstom"</string>
- <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Prostor za skladištenje je na izmaku"</string>
+ <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Memorijski prostor je na izmaku"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Neke sistemske funkcije možda ne funkcionišu"</string>
- <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Nema dovoljno skladišnog prostora za sistem. Uverite se da imate 250 MB slobodnog prostora i ponovo pokrenite."</string>
+ <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Nema dovoljno memorijskog prostora za sistem. Uverite se da imate 250 MB slobodnog prostora i ponovo pokrenite."</string>
<string name="app_running_notification_title" msgid="8718335121060787914">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> je pokrenuta"</string>
<string name="app_running_notification_text" msgid="4653586947747330058">"Dodirnite za više informacija ili zaustavljanje aplikacije."</string>
<string name="ok" msgid="5970060430562524910">"Potvrdi"</string>
@@ -923,7 +922,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Resetuj i ponovo pokreni aplikaciju"</string>
<string name="aerr_report" msgid="5371800241488400617">"Pošaljite povratne informacije"</string>
<string name="aerr_close" msgid="2991640326563991340">"Zatvori"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Ignoriši"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Ignoriši dok se uređaj ne pokrene ponovo"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Čekaj"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Zatvori aplikaciju"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1061,16 +1060,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Dodirnite za još opcija."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Otklanjanje grešaka sa USB-a je uspostavljeno"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Dodirnite da biste onemogućili otklanjanje grešaka sa USB-a."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Želite li da podelite izveštaj o grešci?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Deli se izveštaj o grešci…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"IT administrator je zatražio izveštaj o grešci radi lakšeg rešavanja problema u vezi sa ovim uređajem. Aplikacije i podaci mogu da se dele, a uređaj će se privremeno usporiti."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"IT administrator je zatražio izveštaj o grešci radi lakšeg rešavanja problema u vezi sa ovim uređajem. Aplikacije i podaci mogu da se dele."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Ovo će privremeno usporiti uređaj"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"PRIHVATI"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ODBIJ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Promenite tastaturu"</string>
@@ -1483,7 +1477,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Traži PIN pre otkačinjanja"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Traži šablon za otključavanje pre otkačinjanja"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Traži lozinku pre otkačinjanja"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Veličina aplikacije ne može da se menja. Pomerajte je pomoću dva prsta."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikacija možda neće funkcionisati sa podeljenim ekranom."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikacija ne podržava podeljeni ekran."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Instalirao je vaš administrator"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Ažurirao je administrator"</string>
@@ -1562,12 +1556,11 @@
<item quantity="few">Izabrane su <xliff:g id="COUNT_1">%1$d</xliff:g> stavke</item>
<item quantity="other">Izabrano je <xliff:g id="COUNT_1">%1$d</xliff:g> stavki</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Razno"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Vi podešavate važnost ovih obaveštenja."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Vi podešavate važnost ovih obaveštenja."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Ovo je važno zbog ljudi koji učestvuju."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Želite li da dozvolite aplikaciji <xliff:g id="APP">%1$s</xliff:g> da napravi novog korisnika za <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Želite li da dozvolite aplikaciji <xliff:g id="APP">%1$s</xliff:g> da napravi novog korisnika za <xliff:g id="ACCOUNT">%2$s</xliff:g> (korisnik sa ovim nalogom već postoji)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Podešavanje jezika"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Dodajte jezik"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Podešavanje regiona"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Unesite naziv jezika"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Predloženi"</string>
@@ -1590,4 +1583,5 @@
<string name="pin_target" msgid="3052256031352291362">"Zakači"</string>
<string name="unpin_target" msgid="3556545602439143442">"Otkači"</string>
<string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index a5255a6..ac2a0ec 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Стандартната идентификация на повикванията е „разрешено“. За следващото обаждане тя е разрешена."</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Услугата не е обезпечена."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Не можете да променяте настройката за идентификация на обажданията."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Ограниченият достъп е променен"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Услугата за данни е блокирана."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Услугата за спешни обаждания е блокирана."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Услугата за глас е блокирана."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Нулиране и рестартиране на приложението"</string>
<string name="aerr_report" msgid="5371800241488400617">"Изпращане на отзиви"</string>
<string name="aerr_close" msgid="2991640326563991340">"Затваряне"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Спиране"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Спиране, докато устройството се рестартира"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Изчакване"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Затваряне на приложението"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Докоснете за още опции."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Отстраняване на грешки през USB"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Докоснете за деактивиране"</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"Системният ви администратор поиска сигнал за програмна грешка с цел отстраняване на неизправностите на устройството. Възможно е да бъдат споделени приложения и данни и работата на устройството ви временно да се забави."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Системният ви администратор поиска сигнал за програмна грешка с цел отстраняване на неизправностите на това устройство. Възможно е да бъдат споделени приложения и данни."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Това може временно да забави работата на устройството ви"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ПРИЕМАМ"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ОТХВЪРЛЯМ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Промяна на клавиатурата"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Запитване за ПИН код преди освобождаване"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Запитване за фигура за отключване преди освобождаване"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Запитване за парола преди освобождаване"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Приложението не може да се преоразмерява. Превъртете го с два пръста."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Приложението може да не работи в режим на разделен екран."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Приложението не поддържа разделен екран."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Инсталирано от администратора ви"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Актуализирано от администратора ви"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other">Избрахте <xliff:g id="COUNT_1">%1$d</xliff:g></item>
<item quantity="one">Избрахте <xliff:g id="COUNT_0">%1$d</xliff:g></item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Други"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Зададохте важността на тези известия."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Зададохте важността на тези известия."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Това е важно заради участващите хора."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Да се разреши ли на <xliff:g id="APP">%1$s</xliff:g> да създаде нов потребител с профила <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Да се разреши ли на <xliff:g id="APP">%1$s</xliff:g> да създаде нов потребител с профила <xliff:g id="ACCOUNT">%2$s</xliff:g> (вече съществува потребител с този профил)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Езиково предпочитание"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Добавяне на език"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Предпочитание за региона"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Въведете име на език"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Предложени"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Фиксиране"</string>
<string name="unpin_target" msgid="3556545602439143442">"Освобождаване"</string>
<string name="app_info" msgid="6856026610594615344">"Информация за приложението"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index eacfd3b..4e6cd4b 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"ডিফল্টরুপে কলার ID সীমাবদ্ধ করা থাকে না৷ পরবর্তী কল: সীমাবদ্ধ নয়"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"পরিষেবা প্রস্তুত নয়৷"</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"আপনি কলার ID এর সেটিংস পরিবর্তন করতে পারবেন না৷"</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"সীমিত অ্যাক্সেসের পরিবর্তন করা হয়েছে"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"ডেটা পরিষেবা অবরুদ্ধ করা আছে৷"</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"জরুরী পরিষেবা অবরুদ্ধ করা আছে৷"</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"ভয়েস পরিষেবা অবরুদ্ধ করা আছে৷"</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"পুনরায় সেট করুন এবং অ্যাপ্লিকেশান পুনরায় আরম্ভ করুন"</string>
<string name="aerr_report" msgid="5371800241488400617">"প্রতিক্রিয়া পাঠান"</string>
<string name="aerr_close" msgid="2991640326563991340">"বন্ধ করুন"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"নিঃশব্দ করুন"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"ডিভাইসটি পুনরায় আরম্ভ না হওয়া পর্যন্ত নিঃশব্দ করুন"</string>
<string name="aerr_wait" msgid="3199956902437040261">"অপেক্ষা করুন"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"অ্যাপ্লিকেশান বন্ধ করুন"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"আরো বিকল্পের জন্য স্পর্শ করুন৷"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB ডিবাগিং সংযুক্ত হয়েছে"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB ডিবাগিং অক্ষম করতে স্পর্শ করুন৷"</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"আপনার আইটি প্রশাসক এই ডিভাইসটির সমস্যা নিবারণে সহায়তা করতে একটি ত্রুটির প্রতিবেদন চেয়েছেন৷ অ্যাপ্লিকেশানগুলি এবং ডেটা শেয়ার করা হতে পারে এবং আপনার ডিভাইসটিকে অস্থায়ীভাবে ধীর করে দিতে পারে৷"</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"আপনার আইটি প্রশাসক এই ডিভাইসটির সমস্যা নিবারণে সহায়তা করতে একটি ত্রুটির প্রতিবেদন চেয়েছেন৷ অ্যাপ্লিকেশান এবং ডেটা শেয়ার করা হতে পারে৷"</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"এটি অস্থায়ীভাবে আপনার ডিভাইসটিকে ধীর করে দিতে পারে"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"স্বীকার করুন"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"অস্বীকার করুন"</string>
<string name="select_input_method" msgid="8547250819326693584">"কীবোর্ড পরিবর্তন করুন"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"আনপিন করার আগে পিন চান"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"আনপিন করার আগে আনলক প্যাটার্ন চান"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"আনপিন করার আগে পাসওয়ার্ড চান"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"অ্যাপ্লিকেশানকে পুনরায় আকার দেওয়া যাবে না, দুটি আঙ্গুল ব্যবহার করে স্ক্রোল করুন৷"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"অ্যাপ্লিকেশানটি বিভক্ত স্ক্রীনে কাজ নাও করতে পারে৷"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"অ্যাপ্লিকেশান বিভক্ত-স্ক্রীন সমর্থন করে না৷"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"আপনার প্রশাসক দ্বারা ইনস্টল করা হয়েছে"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"আপনার প্রশাসক দ্বারা আপডেট করা হয়েছে"</string>
@@ -1543,12 +1537,11 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g>টি নির্বাচন করা হয়েছে</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>টি নির্বাচন করা হয়েছে</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"বিবিধ"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"আপনি এই বিজ্ঞপ্তিগুলির গুরুত্ব সেট করেছেন।"</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"আপনি এই বিজ্ঞপ্তিগুলির গুরুত্ব সেট করেছেন।"</string>
<string name="importance_from_person" msgid="9160133597262938296">"লোকজন জড়িত থাকার কারণে এটি গুরুত্বপূর্ণ।"</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> কে <xliff:g id="ACCOUNT">%2$s</xliff:g> এর সাথে একজন নতুন ব্যবহারকারী তৈরি করার অনুমতি দেবেন কি?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> কে <xliff:g id="ACCOUNT">%2$s</xliff:g> (একজন ব্যবহারকারী এই অ্যাকাউন্টে ইতিমধ্যেই বিদ্যমান আছেন) এর সাথে একজন নতুন ব্যবহারকারী তৈরি করার অনুমতি দেবেন কি?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"পছন্দের ভাষা"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"একটি ভাষা যোগ করুন"</string>
<string name="country_selection_title" msgid="2954859441620215513">"পছন্দের অঞ্চল"</string>
<string name="search_language_hint" msgid="7042102592055108574">"ভাষার নাম লিখুন"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"প্রস্তাবিত"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"পিন করুন"</string>
<string name="unpin_target" msgid="3556545602439143442">"আনপিন করুন"</string>
<string name="app_info" msgid="6856026610594615344">"অ্যাপ্লিকেশানের তথ্য"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-bs-rBA/strings.xml b/core/res/res/values-bs-rBA/strings.xml
index 84e2826..798f6f5 100644
--- a/core/res/res/values-bs-rBA/strings.xml
+++ b/core/res/res/values-bs-rBA/strings.xml
@@ -89,7 +89,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Prikaz ID-a pozivaoca u zadanim postavkama nije zabranjen. Sljedeći poziv: nije zabranjen"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Uslugu nije moguće koristiti."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Ne možete promijeniti postavke ID-a pozivaoca."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Promijenjen ograničen pristup"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Usluga prijenosa podataka je blokirana."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Hitni pozivi su blokirani."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Govorne usluge su blokirane."</string>
@@ -923,7 +922,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Vrati aplikaciju na zadano i pokreni ponovo"</string>
<string name="aerr_report" msgid="5371800241488400617">"Pošalji povratne informacije"</string>
<string name="aerr_close" msgid="2991640326563991340">"Zatvori"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Zanemari"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Isključiti zvuk dok se uređaj ponovo ne pokrene"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Sačekaj"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Zatvori aplikaciju"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1061,16 +1060,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Dodirnite za više opcija."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Uređaj za USB otklanjanje grešaka povezan"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Dodirnite da biste onemogućili USB otklanjanje grešaka."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Podijeliti izvještaj o grešci?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Dijeljenje izvještaja o grešci..."</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Vaš IT administrator je zatražio izvještaj o grešci kako bi pomogao riješiti problem na ovom uređaju. To može uzrokovati dijeljenje aplikacija i podataka te privremeno usporiti vaš uređaj."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Vaš IT administrator je zatražio izvještaj o grešci kako bi pomogao u rješavanju problema ovog uređaja. Aplikacije i podaci se mogu dijeliti."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"To može privremeno usporiti vaš uređaj"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"PRIHVATI"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ODBACI"</string>
<string name="select_input_method" msgid="8547250819326693584">"Promijeni tastaturu"</string>
@@ -1483,7 +1477,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Traži PIN prije nego se otkači"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Traži uzorak za otključavanje prije nego se otkači"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Traži lozinku prije nego se otkači"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Veličina aplikacije nije promjenjiva, pomičite je s dva prsta."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikacija možda neće raditi na podijeljenom ekranu"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikacija ne podržava dijeljenje ekrana."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Instalirao administrator"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Ažurirao administrator"</string>
@@ -1562,12 +1556,11 @@
<item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> stavke su odabrane</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> stavki je odabrano</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Razno"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Vi postavljate značaj ovih oabvještenja."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Vi određujete značaj ovih obavještenja."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Ovo je značajno zbog osoba koje su uključene."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Da li dozvoljate da <xliff:g id="APP">%1$s</xliff:g> kreira novog korisnika za nalog <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Da li dozvoljavate da <xliff:g id="APP">%1$s</xliff:g> kreira novog korisnika za <xliff:g id="ACCOUNT">%2$s</xliff:g> (Korisnik sa ovim nalogom već postoji)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Izbor jezika"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Dodaj jezik"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Izbor regije"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Ukucajte naziv jezika"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Predloženo"</string>
@@ -1590,4 +1583,5 @@
<string name="pin_target" msgid="3052256031352291362">"Zakači"</string>
<string name="unpin_target" msgid="3556545602439143442">"Otkači"</string>
<string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index f9ecd06..9bd8014 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"El valor predeterminat de l\'identificador de l\'emissor és no restringit. Següent trucada: no restringit"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"No s\'ha proveït el servei."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"No pots canviar la configuració de l\'identificador de l\'emissor."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Accés restringit canviat"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"El servei de dades està bloquejat."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"El servei d\'emergència està bloquejat."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"El servei de veu està bloquejat."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Restableix i reinicia l\'aplicació"</string>
<string name="aerr_report" msgid="5371800241488400617">"Envia suggeriments"</string>
<string name="aerr_close" msgid="2991640326563991340">"Tanca"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Silencia"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Silencia fins que es reiniciï el dispositiu"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Espera"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Tanca l\'aplicació"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Toca per veure més opcions."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Depuració USB activada"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Toca per desactivar la depuració USB"</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vols compartir l\'informe d\'errors?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"S\'està compartint l\'informe d\'errors…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"L\'administrador de TI ha sol·licitat un informe d\'errors per resoldre els problemes d\'aquest dispositiu. És possible que es comparteixin aplicacions i dades, i que el dispositiu funcioni més a poc a poc durant una estona."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"El teu administrador de TI ha sol·licitat un informe d\'errors per resoldre els problemes d\'aquest dispositiu. És possible que es comparteixin aplicacions i dades."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"És possible que el dispositiu funcioni més a poc a poc durant una estona"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACCEPTA"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"REBUTJA"</string>
<string name="select_input_method" msgid="8547250819326693584">"Canvia el teclat"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Sol·licita el codi PIN per anul·lar"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Sol·licita el patró de desbloqueig per anul·lar"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Demana la contrasenya per anul·lar"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"No es pot canviar la mida de l\'aplicació. Desplaça-la amb dos dits."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"És possible que l\'aplicació no funcioni amb la pantalla dividida."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"L\'aplicació no admet la pantalla dividida."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"L\'administrador ho ha instal·lat"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"L\'administrador l\'ha actualitzat"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other">Seleccionats: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
<item quantity="one">Seleccionats: <xliff:g id="COUNT_0">%1$d</xliff:g></item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Altres"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Tu has definit la importància d\'aquestes notificacions."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Has definit la importància d\'aquestes notificacions."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Aquest missatge és important per les persones implicades."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Concedeixes permís a <xliff:g id="APP">%1$s</xliff:g> per crear un usuari amb el compte <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Concedeixes permís a <xliff:g id="APP">%1$s</xliff:g> per crear un usuari amb el compte <xliff:g id="ACCOUNT">%2$s</xliff:g>? (Ja hi ha un usuari amb aquest compte.)"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Preferència d\'idioma"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Afegeix un idioma"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Preferència de regió"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Nom de l\'idioma"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Suggerits"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Fixa"</string>
<string name="unpin_target" msgid="3556545602439143442">"No fixis"</string>
<string name="app_info" msgid="6856026610594615344">"Informació de l\'aplicació"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 19f8864..facf368 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -90,7 +90,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Ve výchozím nastavení není identifikace volajícího omezena. Příští hovor: Neomezeno"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Služba není zřízena."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Nastavení identifikace volajícího nesmíte měnit."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Omezený přístup byl změněn."</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Datová služba je zablokována."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Tísňová linka je zablokována."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Hlasová služba je zablokována."</string>
@@ -929,7 +928,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Obnovit a restartovat aplikaci"</string>
<string name="aerr_report" msgid="5371800241488400617">"Odeslat zpětnou vazbu"</string>
<string name="aerr_close" msgid="2991640326563991340">"Zavřít"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Ignorovat"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Ignorovat do restartu zařízení"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Počkat"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Zavřít aplikaci"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1069,16 +1068,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Klepnutím zobrazíte další možnosti."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Ladění přes USB připojeno"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Dotykem zakážete ladění USB."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Sdílet zprávu o chybě?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Sdílení zprávy o chybě…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Administrátor IT si vyžádal zprávu o chybě, aby mohl problém odstranit. Mohou být sdíleny aplikace a data a zařízení se může dočasně zpomalit."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Administrátor IT si vyžádal zprávu o chybě, aby mohl problém odstranit. Aplikace a data mohou být sdílena."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Zařízení se může dočasně zpomalit"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"PŘIJMOUT"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ODMÍTNOUT"</string>
<string name="select_input_method" msgid="8547250819326693584">"Změna klávesnice"</string>
@@ -1493,7 +1487,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Před uvolněním požádat o PIN"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Před uvolněním požádat o bezpečnostní gesto"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Před uvolněním požádat o heslo"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Velikost aplikace nelze změnit. Zobrazení můžete posouvat dvěma prsty."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikace v režimu rozdělené obrazovky nemusí fungovat."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikace nepodporuje režim rozdělené obrazovky."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Nainstalováno administrátorem"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Aktualizováno administrátorem"</string>
@@ -1581,12 +1575,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> položek</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> položka</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Různé"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Důležitost oznámení určujete vy."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Důležitost oznámení určujete vy."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Tato zpráva je důležitá kvůli lidem zapojeným do konverzace."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Povolit aplikaci <xliff:g id="APP">%1$s</xliff:g> vytvořit nového uživatele s účtem <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Povolit aplikaci <xliff:g id="APP">%1$s</xliff:g> vytvořit nového uživatele s účtem <xliff:g id="ACCOUNT">%2$s</xliff:g>? (Uživatel s tímto účtem již existuje.)"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Preferovaný jazyk"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Přidat jazyk"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Preferovaná oblast"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Zadejte název jazyka"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Navrhované"</string>
@@ -1609,4 +1602,5 @@
<string name="pin_target" msgid="3052256031352291362">"Připnout"</string>
<string name="unpin_target" msgid="3556545602439143442">"Odepnout"</string>
<string name="app_info" msgid="6856026610594615344">"Informace o aplikaci"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 6c36d86..a0a3f8f 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Standarder for opkalds-id til ikke begrænset. Næste opkald: Ikke begrænset"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Tjenesten leveres ikke!"</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Du kan ikke ændre indstillingen for opkalds-id\'et."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Begrænset adgang ændret"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Datatjenesten er blokeret."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Nødtjenesten er blokeret."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Stemmetjenesten er blokeret."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Nulstil og genstart appen"</string>
<string name="aerr_report" msgid="5371800241488400617">"Send feedback"</string>
<string name="aerr_close" msgid="2991640326563991340">"Luk"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Ignorer"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Ignorer, indtil enheden genstarter"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Vent"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Luk app"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Tryk for at se flere muligheder."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB-fejlretning er tilsluttet"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Tryk for at deaktivere USB-fejlretning."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vil du dele fejlrapporten?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Deler fejlrapport…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Din it-administrator har anmodet om en fejlrapport for bedre at kunne finde og rette fejlen på enheden. Apps og data deles muligvis, og din enhed kan midlertidigt blive langsommere."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Din it-administrator har anmodet om en fejlrapport for bedre at kunne finde og rette fejlen på enheden. Apps og data deles muligvis."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Dette kan midlertidigt gøre enheden langsommere"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACCEPTÉR"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"AFVIS"</string>
<string name="select_input_method" msgid="8547250819326693584">"Skift tastatur"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Bed om pinkode inden frigørelse"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Bed om oplåsningsmønster ved deaktivering"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Bed om adgangskode inden frigørelse"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Appens størrelse kan ikke ændres. Gennemgå den ved at rulle med to fingre."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Appen fungerer muligvis ikke i delt skærm."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Appen understøtter ikke delt skærm."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Installeret af din administrator"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Opdateret af administrator"</string>
@@ -1543,12 +1537,11 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g>valgt</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> valgt</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Diverse"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Du angiver, hvor vigtige disse underretninger er."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Du angiver, hvor vigtige disse underretninger er."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Dette er vigtigt på grund af de personer, det handler om."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Vil du give <xliff:g id="APP">%1$s</xliff:g> tilladelse til at oprette en ny bruger med <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Vil du give <xliff:g id="APP">%1$s</xliff:g> tilladelse til at oprette en ny bruger med <xliff:g id="ACCOUNT">%2$s</xliff:g> (der findes allerede en bruger med denne konto)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Sprogindstilling"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Tilføj et sprog"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Områdeindstilling"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Angiv sprogets navn"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Foreslået"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Fastgør"</string>
<string name="unpin_target" msgid="3556545602439143442">"Frigør"</string>
<string name="app_info" msgid="6856026610594615344">"Oplysninger om appen"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index b68c7a1..8406a70 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Anrufer-ID ist standardmäßig nicht beschränkt. Nächster Anruf: Nicht beschränkt"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Dienst nicht eingerichtet."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Du kannst die Einstellung für die Anrufer-ID nicht ändern."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Eingeschränkter Zugriff geändert"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Daten-Dienst ist gesperrt."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Notruf ist gesperrt."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Sprachdienst ist gesperrt."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"App zurücksetzen und neu starten"</string>
<string name="aerr_report" msgid="5371800241488400617">"Feedback geben"</string>
<string name="aerr_close" msgid="2991640326563991340">"Schließen"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Ignorieren"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Bis zum Neustart des Geräts ausblenden"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Warten"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"App schließen"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Für weitere Optionen tippen"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB-Debugging"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Zum Deaktivieren berühren"</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Fehlerbericht teilen?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Fehlerbericht wird geteilt…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Dein IT-Administrator hat einen Fehlerbericht zur Fehlerbehebung dieses Geräts angefordert. Apps und Daten werden unter Umständen geteilt und dein Gerät wird möglicherweise vorübergehend langsamer."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Dein IT-Administrator hat einen Fehlerbericht zur Fehlerbehebung dieses Geräts angefordert. Apps und Daten werden unter Umständen geteilt."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Dadurch wird dein Gerät möglicherweise vorübergehend langsamer"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"AKZEPTIEREN"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ABLEHNEN"</string>
<string name="select_input_method" msgid="8547250819326693584">"Tastatur ändern"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Vor dem Beenden nach PIN fragen"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Vor dem Beenden nach Entsperrungsmuster fragen"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Vor dem Beenden nach Passwort fragen"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Die Größe der App kann nicht angepasst werden. Scrolle sie mit zwei Fingern."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Die App funktioniert unter Umständen bei geteiltem Bildschirm nicht."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Das Teilen des Bildschirms wird in dieser App nicht unterstützt."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Von deinem Administrator installiert"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Von deinem Administrator aktualisiert"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ausgewählt</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ausgewählt</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Sonstige"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Du legst die Wichtigkeit dieser Benachrichtigungen fest."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Du hast die Wichtigkeit dieser Benachrichtigungen festgelegt."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Diese Benachrichtigung ist aufgrund der beteiligten Personen wichtig."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Möchtest du zulassen, dass <xliff:g id="APP">%1$s</xliff:g> einen neuen Nutzer mit <xliff:g id="ACCOUNT">%2$s</xliff:g> erstellt?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Möchtest du zulassen, dass <xliff:g id="APP">%1$s</xliff:g> einen neuen Nutzer mit <xliff:g id="ACCOUNT">%2$s</xliff:g> erstellt? Dieses Konto wird jedoch bereits von einem anderen Nutzer verwendet."</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Spracheinstellung"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Sprache hinzufügen"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Region auswählen"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Sprache eingeben"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Vorschläge"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Markieren"</string>
<string name="unpin_target" msgid="3556545602439143442">"Markierung entfernen"</string>
<string name="app_info" msgid="6856026610594615344">"App-Informationen"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 63d49b1..f5192b7 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Η αναγνώριση κλήσης βρίσκεται από προεπιλογή στην \"μη περιορισμένη\". Επόμενη κλήση: Μη περιορισμένη"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Η υπηρεσία δεν προβλέπεται."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Δεν μπορείτε να αλλάξετε τη ρύθμιση του αναγνωριστικού καλούντος."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Η περιορισμένη πρόσβαση άλλαξε"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Η υπηρεσία δεδομένων είναι αποκλεισμένη."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Η υπηρεσία έκτακτης ανάγκης είναι αποκλεισμένη."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Η υπηρεσία φωνής έχει αποκλειστεί."</string>
@@ -163,7 +162,7 @@
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Πάρα πολλές <xliff:g id="CONTENT_TYPE">%s</xliff:g> διαγραφές."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Ο αποθηκευτικός χώρος του tablet είναι πλήρης. Διαγράψτε μερικά αρχεία για να δημιουργήσετε ελεύθερο χώρο."</string>
<string name="low_memory" product="watch" msgid="4415914910770005166">"Ο αποθηκευτικός χώρος παρακολούθησης είναι πλήρης! Διαγράψτε μερικά αρχεία για να απελευθερώσετε χώρο."</string>
- <string name="low_memory" product="tv" msgid="516619861191025923">"Ο χώρος αποθήκευσης της τηλεόρασης είναι πλήρης. Διαγράψτε ορισμένα αρχεία, για να ελευθερώσετε χώρο."</string>
+ <string name="low_memory" product="tv" msgid="516619861191025923">"Ο αποθηκευτικός χώρος της τηλεόρασης είναι πλήρης. Διαγράψτε ορισμένα αρχεία, για να ελευθερώσετε χώρο."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Ο αποθηκευτικός χώρος του τηλεφώνου είναι πλήρης. Διαγράψτε μερικά αρχεία για να δημιουργήσετε ελεύθερο χώρο."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Το δίκτυο ενδέχεται να παρακολουθείται"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Από ένα άγνωστο τρίτο μέρος"</string>
@@ -311,7 +310,7 @@
<string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Επιτρέπει στην εφαρμογή να δημιουργεί μόνιμα τμήματα του εαυτού της στη μνήμη. Αυτό μπορεί να περιορίζει τη μνήμη που διατίθεται σε άλλες εφαρμογές, καθυστερώντας τη λειτουργία του tablet."</string>
<string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Επιτρέπει στην εφαρμογή να καθιστά τμήματά της μόνιμα στη μνήμη. Αυτό μπορεί να περιορίσει τη μνήμη που διατίθεται σε άλλες εφαρμογές, επιβραδύνοντας τη λειτουργία της τηλεόρασης."</string>
<string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Επιτρέπει στην εφαρμογή να δημιουργεί μόνιμα τμήματα του εαυτού της στη μνήμη. Αυτό μπορεί να περιορίζει τη μνήμη που διατίθεται σε άλλες εφαρμογές, καθυστερώντας τη λειτουργία του τηλεφώνου."</string>
- <string name="permlab_getPackageSize" msgid="7472921768357981986">"μέτρηση χώρου αποθήκευσης εφαρμογής"</string>
+ <string name="permlab_getPackageSize" msgid="7472921768357981986">"μέτρηση αποθηκευτικού χώρου εφαρμογής"</string>
<string name="permdesc_getPackageSize" msgid="3921068154420738296">"Επιτρέπει στην εφαρμογή να ανακτήσει τα μεγέθη κώδικα, δεδομένων και προσωρινής μνήμης"</string>
<string name="permlab_writeSettings" msgid="2226195290955224730">"τροποποίηση ρυθμίσεων συστήματος"</string>
<string name="permdesc_writeSettings" msgid="7775723441558907181">"Επιτρέπει στην εφαρμογή την τροποποίηση των δεδομένων των ρυθμίσεων του συστήματος. Τυχόν κακόβουλες εφαρμογές ενδέχεται να καταστρέψουν τη διαμόρφωση του συστήματός σας."</string>
@@ -880,9 +879,9 @@
<string name="deleteText" msgid="6979668428458199034">"Διαγραφή"</string>
<string name="inputMethod" msgid="1653630062304567879">"Μέθοδος εισόδου"</string>
<string name="editTextMenuTitle" msgid="4909135564941815494">"Ενέργειες κειμένου"</string>
- <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Ο χώρος αποθήκευσης εξαντλείται"</string>
+ <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Ο αποθηκευτικός χώρος εξαντλείται"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Ορισμένες λειτουργίες συστήματος ενδέχεται να μην λειτουργούν"</string>
- <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Δεν υπάρχει αρκετός χώρος αποθήκευσης για το σύστημα. Βεβαιωθείτε ότι διαθέτετε 250 MB ελεύθερου χώρου και κάντε επανεκκίνηση."</string>
+ <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Δεν υπάρχει αρκετός αποθηκευτικός χώρος για το σύστημα. Βεβαιωθείτε ότι διαθέτετε 250 MB ελεύθερου χώρου και κάντε επανεκκίνηση."</string>
<string name="app_running_notification_title" msgid="8718335121060787914">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> εκτελείται"</string>
<string name="app_running_notification_text" msgid="4653586947747330058">"Αγγίξτε για περισσότερες πληροφορίες ή για να διακόψετε την εκτέλεση της εφαρμογής."</string>
<string name="ok" msgid="5970060430562524910">"OK"</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Επαναφορά και επανεκκίνηση εφαρμογής"</string>
<string name="aerr_report" msgid="5371800241488400617">"Αποστολή σχολίων"</string>
<string name="aerr_close" msgid="2991640326563991340">"Κλείσιμο"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Σίγαση"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Σίγαση μέχρι την επανεκκίνηση της συσκευής"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Αναμονή"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Κλείσιμο εφαρμογής"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Αγγίξτε για περισσότερες επιλογές."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Συνδέθηκε ο εντοπισμός σφαλμάτων USB"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Απεν. του εντοπ. σφαλμάτων USB."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"Ο διαχειριστής σας IT ζήτησε μια αναφορά σφάλματος για να συμβάλει στην αντιμετώπιση του προβλήματος αυτής της συσκευής. Ενδέχεται να γίνει κοινή χρήση των εφαρμογών και να επιβραδυνθεί προσωρινά τη λειτουργία της συσκευής σας."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Ο διαχειριστής σας IT ζήτησε μια αναφορά σφάλματος για να συμβάλει στην αντιμετώπιση του προβλήματος αυτής της συσκευής. Ενδέχεται να γίνει κοινή χρήση των εφαρμογών και των δεδομένων."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Αυτή η διαδικασία ενδέχεται να επιβραδύνει προσωρινά τη λειτουργία της συσκευής σας"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ΑΠΟΔΟΧΗ"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ΑΠΟΡΡΙΨΗ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Αλλαγή πληκτρολογίου"</string>
@@ -1171,7 +1165,7 @@
<item quantity="one">1 αντιστοιχία</item>
</plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Τέλος"</string>
- <string name="progress_erasing" product="nosdcard" msgid="4521573321524340058">"Διαγραφή χώρου αποθήκευσης USB..."</string>
+ <string name="progress_erasing" product="nosdcard" msgid="4521573321524340058">"Διαγραφή αποθηκευτικού χώρου USB..."</string>
<string name="progress_erasing" product="default" msgid="6596988875507043042">"Διαγραφή κάρτας SD..."</string>
<string name="share" msgid="1778686618230011964">"Κοινή χρ."</string>
<string name="find" msgid="4808270900322985960">"Εύρεση"</string>
@@ -1229,12 +1223,12 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Περισσότερες επιλογές"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Εσωτερικός χώρος αποθήκευσης"</string>
+ <string name="storage_internal" msgid="4891916833657929263">"Εσωτερικός αποθηκευτικός χώρος"</string>
<string name="storage_sd_card" msgid="3282948861378286745">"Κάρτα SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Κάρτα SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Μονάδα USB"</string>
<string name="storage_usb_drive_label" msgid="4501418548927759953">"Μονάδα USB <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
- <string name="storage_usb" msgid="3017954059538517278">"Χώρος αποθήκευσης USB"</string>
+ <string name="storage_usb" msgid="3017954059538517278">"Αποθηκευτικός χώρος USB"</string>
<string name="extract_edit_menu_button" msgid="8940478730496610137">"Επεξεργασία"</string>
<string name="data_usage_warning_title" msgid="1955638862122232342">"Προειδοποίηση χρήσης δεδομένων"</string>
<string name="data_usage_warning_body" msgid="2814673551471969954">"Αγγίξτε για προβολή χρήσης/ρυθμ."</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Να γίνεται ερώτηση για το PIN, πριν από το ξεκαρφίτσωμα"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Να γίνεται ερώτηση για το μοτίβο ξεκλειδώματος, πριν από το ξεκαρφίτσωμα"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Να γίνεται ερώτηση για τον κωδικό πρόσβασης, πριν από το ξεκαρφίτσωμα"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Το μέγεθος της εφαρμογής δεν είναι προσαρμόσιμο. Σύρετε προς τα κάτω με δύο δάχτυλα."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Δεν είναι δυνατή η λειτουργία της εφαρμογής με διαχωρισμό οθόνης."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Η εφαρμογή δεν υποστηρίζει διαχωρισμό οθόνης."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Εγκαταστάθηκε από το διαχειριστή σας"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Ενημερώθηκε από το διαχειριστή σας"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other">Επιλέχτηκαν <xliff:g id="COUNT_1">%1$d</xliff:g></item>
<item quantity="one">Επιλέχτηκε <xliff:g id="COUNT_0">%1$d</xliff:g></item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Διάφορα"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Μπορείτε να ρυθμίσετε τη βαρύτητα αυτών των ειδοποιήσεων."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Μπορείτε να ρυθμίσετε τη βαρύτητα αυτών των ειδοποιήσεων."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Αυτό είναι σημαντικό λόγω των ατόμων που συμμετέχουν."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Να επιτραπεί στην εφαρμογή <xliff:g id="APP">%1$s</xliff:g> να δημιουργήσει έναν νέο χρήστη με το λογαριασμό <xliff:g id="ACCOUNT">%2$s</xliff:g>;"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Να επιτραπεί στην εφαρμογή <xliff:g id="APP">%1$s</xliff:g> να δημιουργήσει έναν νέο χρήστη με το λογαριασμό <xliff:g id="ACCOUNT">%2$s</xliff:g> (υπάρχει ήδη χρήστης με αυτόν το λογαριασμό);"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Προτίμηση γλώσσας"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Προσθήκη γλώσσας"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Προτίμηση περιοχής"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Εισαγ. όνομα γλώσσας"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Προτεινόμενες"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Καρφίτσωμα"</string>
<string name="unpin_target" msgid="3556545602439143442">"Ξεκαρφίτσωμα"</string>
<string name="app_info" msgid="6856026610594615344">"Πληροφορίες εφαρμογής"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 7a709b6..7fdf1c1 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Caller ID defaults to not restricted. Next call: Not restricted"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Service not provisioned."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"You can\'t change the caller ID setting."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Restricted access changed"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Data service is blocked."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Emergency service is blocked."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Voice service is blocked."</string>
@@ -915,9 +914,9 @@
<string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> keeps stopping"</string>
<string name="aerr_restart" msgid="9001379185665886595">"Restart app"</string>
<string name="aerr_reset" msgid="7645427603514220451">"Reset and restart app"</string>
- <string name="aerr_report" msgid="5371800241488400617">"Sending feedback"</string>
+ <string name="aerr_report" msgid="5371800241488400617">"Send feedback"</string>
<string name="aerr_close" msgid="2991640326563991340">"Close"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Mute"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Mute until device restarts"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Wait"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Close app"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Touch for more options."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB debugging connected"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Touch to disable USB debugging."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Share bug report?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Sharing bug report…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared and your device may temporarily slow down."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"This may temporarily slow down your device"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACCEPT"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"DECLINE"</string>
<string name="select_input_method" msgid="8547250819326693584">"Change keyboard"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Ask for PIN before unpinning"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Ask for unlock pattern before unpinning"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Ask for password before unpinning"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"App is not resizeable, scroll it with two fingers."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"App may not work with split-screen."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"App does not support split-screen."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Installed by your administrator"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Updated by your administrator"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selected</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selected</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Miscellaneous"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"You set the importance of these notifications."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"You set the importance of these notifications."</string>
<string name="importance_from_person" msgid="9160133597262938296">"This is important because of the people involved."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Allow <xliff:g id="APP">%1$s</xliff:g> to create a new User with <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Allow <xliff:g id="APP">%1$s</xliff:g> to create a new User with <xliff:g id="ACCOUNT">%2$s</xliff:g> (a User with this account already exists) ?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Language preference"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Add a language"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Region preference"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Type language name"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Suggested"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Pin"</string>
<string name="unpin_target" msgid="3556545602439143442">"Unpin"</string>
<string name="app_info" msgid="6856026610594615344">"App info"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 7a709b6..7fdf1c1 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Caller ID defaults to not restricted. Next call: Not restricted"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Service not provisioned."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"You can\'t change the caller ID setting."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Restricted access changed"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Data service is blocked."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Emergency service is blocked."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Voice service is blocked."</string>
@@ -915,9 +914,9 @@
<string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> keeps stopping"</string>
<string name="aerr_restart" msgid="9001379185665886595">"Restart app"</string>
<string name="aerr_reset" msgid="7645427603514220451">"Reset and restart app"</string>
- <string name="aerr_report" msgid="5371800241488400617">"Sending feedback"</string>
+ <string name="aerr_report" msgid="5371800241488400617">"Send feedback"</string>
<string name="aerr_close" msgid="2991640326563991340">"Close"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Mute"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Mute until device restarts"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Wait"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Close app"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Touch for more options."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB debugging connected"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Touch to disable USB debugging."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Share bug report?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Sharing bug report…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared and your device may temporarily slow down."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"This may temporarily slow down your device"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACCEPT"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"DECLINE"</string>
<string name="select_input_method" msgid="8547250819326693584">"Change keyboard"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Ask for PIN before unpinning"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Ask for unlock pattern before unpinning"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Ask for password before unpinning"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"App is not resizeable, scroll it with two fingers."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"App may not work with split-screen."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"App does not support split-screen."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Installed by your administrator"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Updated by your administrator"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selected</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selected</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Miscellaneous"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"You set the importance of these notifications."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"You set the importance of these notifications."</string>
<string name="importance_from_person" msgid="9160133597262938296">"This is important because of the people involved."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Allow <xliff:g id="APP">%1$s</xliff:g> to create a new User with <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Allow <xliff:g id="APP">%1$s</xliff:g> to create a new User with <xliff:g id="ACCOUNT">%2$s</xliff:g> (a User with this account already exists) ?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Language preference"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Add a language"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Region preference"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Type language name"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Suggested"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Pin"</string>
<string name="unpin_target" msgid="3556545602439143442">"Unpin"</string>
<string name="app_info" msgid="6856026610594615344">"App info"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 7a709b6..7fdf1c1 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Caller ID defaults to not restricted. Next call: Not restricted"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Service not provisioned."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"You can\'t change the caller ID setting."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Restricted access changed"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Data service is blocked."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Emergency service is blocked."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Voice service is blocked."</string>
@@ -915,9 +914,9 @@
<string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> keeps stopping"</string>
<string name="aerr_restart" msgid="9001379185665886595">"Restart app"</string>
<string name="aerr_reset" msgid="7645427603514220451">"Reset and restart app"</string>
- <string name="aerr_report" msgid="5371800241488400617">"Sending feedback"</string>
+ <string name="aerr_report" msgid="5371800241488400617">"Send feedback"</string>
<string name="aerr_close" msgid="2991640326563991340">"Close"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Mute"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Mute until device restarts"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Wait"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Close app"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Touch for more options."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB debugging connected"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Touch to disable USB debugging."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Share bug report?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Sharing bug report…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared and your device may temporarily slow down."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"This may temporarily slow down your device"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACCEPT"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"DECLINE"</string>
<string name="select_input_method" msgid="8547250819326693584">"Change keyboard"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Ask for PIN before unpinning"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Ask for unlock pattern before unpinning"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Ask for password before unpinning"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"App is not resizeable, scroll it with two fingers."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"App may not work with split-screen."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"App does not support split-screen."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Installed by your administrator"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Updated by your administrator"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selected</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selected</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Miscellaneous"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"You set the importance of these notifications."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"You set the importance of these notifications."</string>
<string name="importance_from_person" msgid="9160133597262938296">"This is important because of the people involved."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Allow <xliff:g id="APP">%1$s</xliff:g> to create a new User with <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Allow <xliff:g id="APP">%1$s</xliff:g> to create a new User with <xliff:g id="ACCOUNT">%2$s</xliff:g> (a User with this account already exists) ?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Language preference"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Add a language"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Region preference"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Type language name"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Suggested"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Pin"</string>
<string name="unpin_target" msgid="3556545602439143442">"Unpin"</string>
<string name="app_info" msgid="6856026610594615344">"App info"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 465eceb..b101ded 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"El Identificador de llamadas está predeterminado en no restringido. Llamada siguiente: no restringido"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Servicio no suministrado."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"No puedes cambiar la configuración del identificador de llamadas."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Se ha cambiado el acceso restringido"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"El servicio de datos está bloqueado."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"El servicio de emergencias está bloqueado."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"El servicio de voz está bloqueado."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Restablecer y reiniciar la app"</string>
<string name="aerr_report" msgid="5371800241488400617">"Enviar comentarios"</string>
<string name="aerr_close" msgid="2991640326563991340">"Cerrar"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Silenciar"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Silenciar hasta que se reinicie el dispositivo"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Esperar"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Cerrar app"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -971,8 +970,8 @@
<string name="volume_icon_description_incall" msgid="8890073218154543397">"Volumen de la llamada"</string>
<string name="volume_icon_description_media" msgid="4217311719665194215">"Volumen de los medios"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"Volumen de notificación"</string>
- <string name="ringtone_default" msgid="3789758980357696936">"Tono de llamada predeterminado"</string>
- <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Tono de llamada predeterminado (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+ <string name="ringtone_default" msgid="3789758980357696936">"Tono predeterminado"</string>
+ <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Tono predeterminado (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Ninguno"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Tonos de llamada"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Tono de llamada desconocido"</string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Toca para ver más opciones."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Depuración por USB conectada"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Toca para desactivar la depuración por USB."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"¿Compartir informe de errores?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartiendo informe de errores…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"El administrador de TI solicitó un informe de errores para ayudar a solucionar los problemas de este dispositivo. Es posible que se compartan apps y datos, y que el dispositivo se ralentice temporalmente."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"El administrador de TI solicitó un informe de errores para ayudar a solucionar los problemas de este dispositivo. Es posible que se compartan apps y datos."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Es posible que tu dispositivo se ralentice temporalmente"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACEPTAR"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"RECHAZAR"</string>
<string name="select_input_method" msgid="8547250819326693584">"Cambiar el teclado"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Solicitar PIN para quitar fijación"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Solicitar patrón de desbloqueo para quitar fijación"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicitar contraseña para quitar fijación"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"No se puede modificar el tamaño de la app. Desplázala con dos dedos."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Es posible que la app no funcione en el modo de pantalla dividida."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"La app no es compatible con la función de pantalla dividida."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Lo instaló el administrador."</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Actualizado por el administrador"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> elementos seleccionados</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> elemento seleccionado</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Varios"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Estableciste la importancia de estas notificaciones."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Estableciste la importancia de estas notificaciones."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Es importante debido a las personas involucradas."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"¿Quieres permitir que <xliff:g id="APP">%1$s</xliff:g> cree un usuario nuevo con <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"¿Quieres permitir que <xliff:g id="APP">%1$s</xliff:g> cree un usuario nuevo con <xliff:g id="ACCOUNT">%2$s</xliff:g>? (Ya existe un usuario con esta cuenta)"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Preferencia de idioma"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Agregar un idioma"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Preferencia de región"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Nombre del idioma"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugeridos"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Fijar"</string>
<string name="unpin_target" msgid="3556545602439143442">"No fijar"</string>
<string name="app_info" msgid="6856026610594615344">"Información de la app"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 2a0e000..6b2c0f8 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"El ID de emisor presenta el valor predeterminado de no restringido. Siguiente llamada: No restringido"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"El servicio no se suministra."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"No puedes modificar el ID de emisor."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"El acceso restringido se ha modificado."</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"El servicio de datos está bloqueado."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"El servicio de emergencia está bloqueado."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"El servicio de voz está bloqueado."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Restablecer y reiniciar aplicación"</string>
<string name="aerr_report" msgid="5371800241488400617">"Enviar sugerencias"</string>
<string name="aerr_close" msgid="2991640326563991340">"Cerrar"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Silenciar"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Silenciar hasta que se reinicie el dispositivo"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Esperar"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Cerrar aplicación"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Toca para obtener más opciones"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Depuración USB habilitada"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Toca aquí para inhabilitarla"</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"¿Compartir informe de errores?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartiendo informe de errores…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Tu administrador de TI ha solicitado un informe de errores para solucionar problemas de este dispositivo. Es posible que se compartan las aplicaciones y los datos. Puede que el dispositivo funcione más lento de forma temporal."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Tu administrador de TI ha solicitado un informe de errores para solucionar problemas de este dispositivo. Es posible que se compartan las aplicaciones y los datos."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Puede que el dispositivo funcione más lento de forma temporal"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACEPTAR"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"RECHAZAR"</string>
<string name="select_input_method" msgid="8547250819326693584">"Cambiar teclado"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Solicitar PIN para desactivar"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Solicitar patrón de desbloqueo para desactivar"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicitar contraseña para desactivar"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"No se puede cambiar el tamaño de la aplicación, desplázala con dos dedos."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Es posible que la aplicación no funcione con la pantalla dividida."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"La aplicación no admite la pantalla dividida."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Instalado por tu administrador"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Actualizado por tu administrador"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> seleccionados</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> seleccionado</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Varios"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Tú determinas la importancia de estas notificaciones."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Tú determinas la importancia de estas notificaciones."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Esto es importante por los usuarios implicados."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"¿Permitir que <xliff:g id="APP">%1$s</xliff:g> cree un usuario con la cuenta <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"¿Permitir que <xliff:g id="APP">%1$s</xliff:g> cree un usuario con la cuenta <xliff:g id="ACCOUNT">%2$s</xliff:g> (ya existe un usuario con esta cuenta)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Preferencia de idioma"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Añade un idioma"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Preferencia de región"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Nombre de idioma"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugeridos"</string>
@@ -1575,4 +1568,5 @@
<string name="pin_target" msgid="3052256031352291362">"Fijar"</string>
<string name="unpin_target" msgid="3556545602439143442">"No fijar"</string>
<string name="app_info" msgid="6856026610594615344">"Información de la aplicación"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 15ba404..0236d2c 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Helistaja ID pole vaikimisi piiratud. Järgmine kõne: pole piiratud"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Teenus pole ette valmistatud."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Helistaja ID seadet ei saa muuta."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Piiratud juurdepääs muutunud"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Andmesideteenus on blokeeritud."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Hädaabiteenus on blokeeritud."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Häälteenus on blokeeritud."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Lähtesta ja taaskäivita rakendus"</string>
<string name="aerr_report" msgid="5371800241488400617">"Saada tagasiside"</string>
<string name="aerr_close" msgid="2991640326563991340">"Sule"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Vaigista"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Vaigista, kuni seade taaskäivitatakse"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Oota"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Sule rakendus"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Puudutage rohkemate valikute kuvamiseks."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB-silumine ühendatud"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Puudutage USB-silumise keelamiseks."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Kas jagada veaaruannet?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Veaaruande jagamine …"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"IT-administraator taotles veaaruannet, mis aitaks seadmes vigu otsida. Rakendusi ja andmeid võidakse jagada ja see võib ajutiselt teie seadet aeglustada."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"IT-administraator taotles veaaruannet, mis aitaks seadmes vigu otsida. Rakendusi ja andmeid võidakse jagada."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"See võib ajutiselt teie seadet aeglustada"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"NÕUSTU"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"KEELDU"</string>
<string name="select_input_method" msgid="8547250819326693584">"Klaviatuuri muutmine"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Enne vabastamist küsi PIN-koodi"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Enne vabastamist küsi avamismustrit"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Enne vabastamist küsi parooli"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Rakenduse suurust ei saa muuta. Kerige kahe sõrmega."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Rakendus ei pruugi poolitatud ekraaniga töötada."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Rakendus ei toeta jagatud ekraani."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Installis teie administraator"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Värskendas administraator"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> on valitud</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> on valitud</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Mitmesugust"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Teie määrasite nende märguannete tähtsuse."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Teie määrasite nende märguannete tähtsuse."</string>
<string name="importance_from_person" msgid="9160133597262938296">"See on tähtis osalevate inimeste tõttu."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Kas lubada rakendusel <xliff:g id="APP">%1$s</xliff:g> luua uus kasutaja kontoga <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Kas lubada rakendusel <xliff:g id="APP">%1$s</xliff:g> luua uus kasutaja kontoga <xliff:g id="ACCOUNT">%2$s</xliff:g> (selle kontoga kasutaja on juba olemas)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Keele-eelistus"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Keele lisamine"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Piirkonnaeelistus"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Sisestage keele nimi"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Soovitatud"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Kinnita"</string>
<string name="unpin_target" msgid="3556545602439143442">"Vabasta"</string>
<string name="app_info" msgid="6856026610594615344">"Rakenduse teave"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index b8fa962..2ed5463 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Deien identifikazio-zerbitzuaren balio lehenetsiak ez du murriztapenik ezartzen. Hurrengo deia: murriztapenik gabe"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Zerbitzua ez da hornitu."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Ezin duzu deien identifikazio-zerbitzuaren ezarpena aldatu."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Sarbide murriztua aldatu da"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Datu-zerbitzua blokeatuta dago."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Larrialdi-zerbitzua blokeatuta dago."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Ahots-zerbitzua blokeatuta dago."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Berrezarri eta berrabiarazi aplikazioa"</string>
<string name="aerr_report" msgid="5371800241488400617">"Bidali iritzia"</string>
<string name="aerr_close" msgid="2991640326563991340">"Itxi"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Ezkutatu"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Ezkutatu gailua berrabiarazi arte"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Itxaron"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Itxi aplikazioa"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Ukitu aukera gehiago ikusteko."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB arazketa konektatuta"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB arazketa desgaitzeko, ukitu hau."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Akatsen txostena partekatu nahi duzu?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Akatsen txostena partekatzen…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"IKT administratzaileak akatsen txostena eskatu du gailuko arazoa konpontzeko. Baliteke aplikazioak eta datuak partekatzea, eta agian motelago ibiliko da gailua aldi batez."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"IKT administratzaileak akatsen txostena eskatu du gailuko arazoa konpontzeko. Baliteke aplikazioak eta datuak partekatzea."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Agian motelago ibiliko da gailua aldi batez"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ONARTU"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"BAZTERTU"</string>
<string name="select_input_method" msgid="8547250819326693584">"Aldatu teklatua"</string>
@@ -1473,8 +1467,8 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Eskatu PIN kodea aingura kendu aurretik"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Eskatu desblokeatzeko eredua aingura kendu aurretik"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Eskatu pasahitza aingura kendu aurretik"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Ezin da aldatu aplikazioaren tamaina. Erabili bi hatz aplikazioan gora eta behera egiteko."</string>
- <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikazioak ez du onartzen pantaila banatua"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Baliteke aplikazioak ez funtzionatzea pantaila zatituan."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikazioak ez du onartzen pantaila zatitua"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Administratzaileak instalatu du"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Administratzaileak eguneratu du"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Administratzaileak ezabatu du"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> hautatuta</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> hautatuta</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Askotarikoak"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Zuk ezarri zenuen jakinarazpen hauen garrantzia."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Zuk ezarri duzu jakinarazpen hauen garrantzia."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Garrantzitsua da eragiten dien pertsonengatik."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> aplikazioari <xliff:g id="ACCOUNT">%2$s</xliff:g> kontua duen erabiltzailea sortzea baimendu nahi diozu?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> aplikazioari <xliff:g id="ACCOUNT">%2$s</xliff:g> kontua duen erabiltzailea sortzea baimendu nahi diozu? (Badago kontu hori duen erabiltzaile bat)"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Hizkuntza-hobespena"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Gehitu hizkuntza"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Lurralde-hobespena"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Adierazi hizkuntza"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Iradokitakoak"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Ainguratu"</string>
<string name="unpin_target" msgid="3556545602439143442">"Kendu aingura"</string>
<string name="app_info" msgid="6856026610594615344">"Aplikazioari buruzko informazioa"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 02eafe9..feae1ca 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"پیشفرض شناسه تماس گیرنده روی غیر محدود است. تماس بعدی: بدون محدودیت"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"سرویس دارای مجوز نیست."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"شما میتوانید تنظیم شناسه تماس گیرنده را تغییر دهید."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"دسترسی محدود تغییر یافت"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"سرویس داده مسدود است."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"سرویس اضطراری مسدود است."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"سرویس صوتی مسدود شده است."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"بازنشانی و راهاندازی مجدد برنامه"</string>
<string name="aerr_report" msgid="5371800241488400617">"ارسال بازخورد"</string>
<string name="aerr_close" msgid="2991640326563991340">"بستن"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"بیصدا کردن"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"صامت کردن تا وقتی دستگاه راهاندازی مجدد شود"</string>
<string name="aerr_wait" msgid="3199956902437040261">"انتظار"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"بستن برنامه"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"برای گزینههای بیشتر لمس کنید."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"اشکالزدایی USB متصل شد"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"غیرفعالکردن اشکالزداییUSB: با لمس آن."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"سرپرست فناوری اطلاعات شما برای کمک به عیبیابی این دستگاه، درخواست گزارش اشکال کرده است. ممکن است برنامهها و دادهها به اشتراک گذاشته شوند و سرعت دستگاهتان بهطور موقت کاهش یابد."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"سرپرست فناوری اطلاعات شما برای کمک به عیبیابی این دستگاه، گزارش اشکال درخواست کرده است. ممکن است برنامهها و دادهها به اشتراک گذاشته شوند."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"ممکن است سرعت دستگاهتان بهطور موقت کاهش یابد"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"پذیرفتن"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"نپذیرفتن"</string>
<string name="select_input_method" msgid="8547250819326693584">"تغییر صفحهکلید"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"درخواست کد پین قبل از برداشتن پین"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"درخواست الگوی باز کردن قفل قبل از برداشتن پین"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"درخواست گذرواژه قبل از برداشتن پین"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"اندازه برنامه قابل تغییر نیست، با دو انگشت آن را پیمایش کنید."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"ممکن است برنامه با تقسیم صفحه کار نکند."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"برنامه از تقسیم صفحه پشتیبانی نمیکند."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"توسط سرپرستتان نصب شد"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"توسط سرپرست شما بهروزرسانی شد"</string>
@@ -1543,12 +1537,11 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> انتخاب شد</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> انتخاب شد</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"متفرقه"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"شما اهمیت این اعلانها را تنظیم میکنید."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"شما اهمیت این اعلانها را تنظیم میکنید."</string>
<string name="importance_from_person" msgid="9160133597262938296">"به دلیل افراد درگیر مهم است."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"به <xliff:g id="APP">%1$s</xliff:g> امکان داده شود کاربر جدیدی با <xliff:g id="ACCOUNT">%2$s</xliff:g> اضافه کند؟"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"به <xliff:g id="APP">%1$s</xliff:g> امکان داده شود کاربر جدیدی با <xliff:g id="ACCOUNT">%2$s</xliff:g> ایجاد کند (کاربری با این حساب از قبل وجود دارد)؟"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"اولویتهای زبان"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"افزودن زبان"</string>
<string name="country_selection_title" msgid="2954859441620215513">"اولویتهای منطقه"</string>
<string name="search_language_hint" msgid="7042102592055108574">"نام زبان را تایپ کنید"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"پیشنهادشده"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"پین کردن"</string>
<string name="unpin_target" msgid="3556545602439143442">"برداشتن پین"</string>
<string name="app_info" msgid="6856026610594615344">"اطلاعات برنامه"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 812565a..2f0a361 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Soittajan tunnukseksi muutetaan rajoittamaton. Seuraava puhelu: ei rajoitettu"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Palvelua ei tarjota."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Et voi muuttaa soittajan tunnuksen asetusta."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Rajoitettua oikeutta muutettu"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Tiedonsiirtopalvelu on estetty."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Hätäpalvelu on estetty."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Äänipalvelu on estetty."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Nollaa sovellus ja käynnistä uudelleen"</string>
<string name="aerr_report" msgid="5371800241488400617">"Lähetä palautetta"</string>
<string name="aerr_close" msgid="2991640326563991340">"Sulje"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Ohita"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Mykistä laitteen uudelleenkäynnistykseen asti"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Odota"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Sulje sovellus"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Lisää vaihtoehtoja koskettamalla"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB-vianetsintä yhdistetty"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Sulje USB-vianetsintä koskettamalla."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Jaetaanko virheraportti?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Jaetaan virheraporttia…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Järjestelmänvalvoja pyysi virheraporttia voidakseen auttaa laitteen vianetsinnässä. Sovelluksia ja tietoja voidaan jakaa, ja laitteen toiminta voi hidastua väliaikaisesti."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Järjestelmänvalvoja pyysi virheraporttia voidakseen auttaa laitteen vianetsinnässä. Sovelluksia ja tietoja voidaan jakaa."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Tämä voi hidastaa laitteen toimintaa väliaikaisesti."</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"HYVÄKSY"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"HYLKÄÄ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Vaihda näppäimistö"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Pyydä PIN ennen irrotusta"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pyydä lukituksenpoistokuvio ennen irrotusta"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pyydä salasana ennen irrotusta"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Sovelluksen kokoa ei voi muuttaa. Vieritä näkymää kahdella sormella."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Sovellus ei ehkä toimi jaetulla näytöllä."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Sovellus ei tue jaetun näytön tilaa."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Järjestelmänvalvoja on asentanut paketin."</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Järjestelmänvalvojasi on päivittänyt paketin."</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> valittu</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> valittu</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Muut"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Voit valita näiden ilmoitusten tärkeyden."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Voit valita näiden ilmoitusten tärkeyden."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Tämä on tärkeää siihen liittyvien ihmisten perusteella."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Myönnetäänkö sovellukselle <xliff:g id="APP">%1$s</xliff:g> oikeus luoda käyttäjä tilille <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Myönnetäänkö sovellukselle <xliff:g id="APP">%1$s</xliff:g> oikeus luoda käyttäjä tilille <xliff:g id="ACCOUNT">%2$s</xliff:g> (tilillä on jo käyttäjä)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Kieliasetus"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Lisää kieli"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Alueasetus"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Anna kielen nimi"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Ehdotukset"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Kiinnitä"</string>
<string name="unpin_target" msgid="3556545602439143442">"Irrota"</string>
<string name="app_info" msgid="6856026610594615344">"Sovelluksen tiedot"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index d6c933f..4dce7e6 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Par défaut, les numéros des appelants ne sont pas restreints. Appel suivant : non restreint"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Ce service n\'est pas pris en charge."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Impossible de modifier le paramètre relatif au numéro de l\'appelant."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"L\'accès limité a été modifié."</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Le service de données est bloqué."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Le service d\'appel d\'urgence est bloqué."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Le service vocal est bloqué."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Réinitialiser et redémarrer l\'application"</string>
<string name="aerr_report" msgid="5371800241488400617">"Envoyer des commentaires"</string>
<string name="aerr_close" msgid="2991640326563991340">"Fermer"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Désactiver les notifications"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Désactiver jusqu\'au redémarrage de l\'appareil"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Attendre"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Fermer l\'application"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Touchez pour afficher plus d\'options."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Débogage USB connecté"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Appuyez pour désactiver le débogage USB."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Partager le rapport de bogue?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Partage du rapport de bogue en cours..."</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Votre administrateur informatique a demandé un rapport de bogue pour l\'aider à dépanner cet appareil. Les applications et les données peuvent être partagées. Cela pourrait temporairement ralentir votre appareil."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Votre administrateur informatique a demandé un rapport de bogue pour l\'aider à dépanner cet appareil. Les applications et les données peuvent être partagées."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Cela pourrait temporairement ralentir votre appareil."</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACCEPTER"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"REFUSER"</string>
<string name="select_input_method" msgid="8547250819326693584">"Changer de clavier"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Demander le NIP avant d\'annuler l\'épinglage"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Demander le schéma de déverrouillage avant d\'annuler l\'épinglage"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Demander le mot de passe avant d\'annuler l\'épinglage"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Impossible de redimensionner l\'application. Faites-la défiler avec deux doigts."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Il est possible que l\'application ne fonctionne pas en mode Écran partagé."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"L\'application n\'est pas compatible avec l\'écran partagé."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Installé par votre administrateur"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Mis à jour par votre administrateur"</string>
@@ -1543,12 +1537,11 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> élément sélectionné</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> éléments sélectionnés</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Divers"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Vous définissez l\'importance de ces notifications."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Vous définissez l\'importance de ces notifications."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Ces notifications sont importantes en raison des participants."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Autoriser <xliff:g id="APP">%1$s</xliff:g> à créer un profil d\'utilisateur avec le compte <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Autoriser <xliff:g id="APP">%1$s</xliff:g> à créer un profil d\'utilisateur avec le compte <xliff:g id="ACCOUNT">%2$s</xliff:g>? (Un utilisateur associé à ce compte existe déjà.)"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Préférences linguistiques"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Ajouter une langue"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Préférences régionales"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Entrez la langue"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Suggestions"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Épingler"</string>
<string name="unpin_target" msgid="3556545602439143442">"Annuler l\'épinglage"</string>
<string name="app_info" msgid="6856026610594615344">"Détails de l\'application"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 897a289..c8ef7d0 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Par défaut, les numéros des appelants ne sont pas restreints. Appel suivant : non restreint"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Ce service n\'est pas pris en charge."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Impossible de modifier le paramètre relatif au numéro de l\'appelant."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"L\'accès limité a été modifié."</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Le service de données est bloqué."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Le service d\'appel d\'urgence est bloqué."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Le service vocal est bloqué."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Réinitialiser et redémarrer l\'application"</string>
<string name="aerr_report" msgid="5371800241488400617">"Envoyer des commentaires"</string>
<string name="aerr_close" msgid="2991640326563991340">"Fermer"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Ignorer"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Ignorer jusqu\'au redémarrage de l\'appareil"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Attendre"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Fermer l\'application"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Appuyez pour afficher plus d\'options"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Débogage USB activé"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Appuyez pour désact. débogage USB"</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Partager le rapport de bug ?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Partage du rapport de bug…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Votre administrateur informatique a demandé un rapport de bug pour l\'aider à résoudre le problème lié à cet appareil. Il est possible que des applications et des données soient partagées et que votre appareil ralentisse temporairement."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Votre administrateur informatique a demandé un rapport de bug pour l\'aider à résoudre le problème lié à cet appareil. Il est possible que des applications et des données soient partagées."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Ceci risque de ralentir temporairement votre appareil."</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACCEPTER"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"REFUSER"</string>
<string name="select_input_method" msgid="8547250819326693584">"Changer de clavier"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Demander le code PIN avant d\'annuler l\'épinglage"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Demander le schéma de déverrouillage avant d\'annuler l\'épinglage"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Demander le mot de passe avant d\'annuler l\'épinglage"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Il est impossible de redimensionner l\'application. Faites-la défiler avec deux doigts."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Il est possible que l\'application ne fonctionne pas en mode Écran partagé."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Application incompatible avec l\'écran partagé."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Installé par votre administrateur"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Mis à jour par votre administrateur"</string>
@@ -1543,12 +1537,11 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> élément sélectionné</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> éléments sélectionnés</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Divers"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Vous définissez l\'importance de ces notifications."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Vous définissez l\'importance de ces notifications."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Ces notifications sont importantes en raison des participants."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Autoriser <xliff:g id="APP">%1$s</xliff:g> à créer un profil utilisateur avec le compte <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Autoriser <xliff:g id="APP">%1$s</xliff:g> à créer un profil utilisateur avec le compte <xliff:g id="ACCOUNT">%2$s</xliff:g> (un utilisateur associé à ce compte existe déjà) ?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Préférences linguistiques"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Ajouter une langue"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Préférences régionales"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Saisissez la langue"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Recommandations"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Épingler"</string>
<string name="unpin_target" msgid="3556545602439143442">"Retirer"</string>
<string name="app_info" msgid="6856026610594615344">"Infos sur l\'appli"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"− <xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index 0e54aad..41c600d 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"De forma predeterminada, non se restrinxe o ID de chamada. Próxima chamada: non restrinxido."</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Servizo non ofrecido."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Non podes cambiar a configuración do ID de chamada."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Modificouse o acceso restrinxido"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"O servizo de datos está bloqueado."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"O servizo de urxencia está bloqueado."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"O servizo de voz está bloqueado."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Restablecer e reiniciar aplicación"</string>
<string name="aerr_report" msgid="5371800241488400617">"Dános a túa opinión"</string>
<string name="aerr_close" msgid="2991640326563991340">"Pechar"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Ignorar"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Ignorar fallos ata que o dispositivo se reinicie"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Esperar"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Pechar aplicación"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Toca para ver máis opcións."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Depuración USB conectada"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Toca aquí para desactivala"</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Queres compartir o informe de erros?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartindo informe de erros..."</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"O teu administrador de TI solicitou un informe de erros para axudar a solucionar os problemas deste dispositivo. É posible que se compartan aplicacións e datos e que se reduza a velocidade do teu dispositivo temporalmente."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"O teu administrador de TI solicitou un informe de erros para axudar a solucionar os problemas deste dispositivo. É posible que se compartan aplicacións e datos."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Esta acción pode reducir a velocidade do teu dispositivo temporalmente"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACEPTAR"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ANULAR"</string>
<string name="select_input_method" msgid="8547250819326693584">"Cambiar teclado"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Solicitar un PIN antes de soltar a pantalla"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Solicitar un padrón de desbloqueo antes de soltar a pantalla"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicitar un contrasinal antes de soltar a pantalla"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Non se pode cambiar o tamaño da aplicación. Desprázate por ela con dous dedos."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Pode que a aplicación non funcione coa pantalla dividida."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"A aplicación non é compatible coa función de pantalla dividida."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Instalado polo administrador"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Actualizado polo administrador"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other">Seleccionáronse <xliff:g id="COUNT_1">%1$d</xliff:g></item>
<item quantity="one">Seleccionouse <xliff:g id="COUNT_0">%1$d</xliff:g></item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Varios"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Ti defines a importancia destas notificacións."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Ti defines a importancia destas notificacións."</string>
<string name="importance_from_person" msgid="9160133597262938296">"É importante polas persoas involucradas."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Queres permitir que <xliff:g id="APP">%1$s</xliff:g> cree un usuario novo con <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Queres permitir que <xliff:g id="APP">%1$s</xliff:g> cree un usuario novo con <xliff:g id="ACCOUNT">%2$s</xliff:g>? (Xa existe un usuario con esta conta)"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Preferencia de idioma"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Engadir un idioma"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Preferencia de rexión"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Nome do idioma"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Suxeridos"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Fixar"</string>
<string name="unpin_target" msgid="3556545602439143442">"Soltar"</string>
<string name="app_info" msgid="6856026610594615344">"Información da aplicación"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index 246f2b4..0bda139 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"કૉલર ID પ્રતિબંધિત નહીં પર ડિફોલ્ટ છે. આગલો કૉલ: પ્રતિબંધિત નહીં"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"સેવાની જોગવાઈ કરી નથી."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"તમે કૉલર ID સેટિંગ બદલી શકતાં નથી."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"પ્રતિબંધિત ઍક્સેસ બદલાઈ"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"ડેટા સેવા અવરોધિત છે."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"કટોકટીની સેવા અવરોધિત છે."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"વૉઇસ સેવા અવરોધિત છે."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"ફરીથી સેટ કરો અને ઍપ્લિકેશનને ફરીથી પ્રારંભ કરો"</string>
<string name="aerr_report" msgid="5371800241488400617">"પ્રતિસાદ મોકલો"</string>
<string name="aerr_close" msgid="2991640326563991340">"બંધ કરો"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"મ્યૂટ કરો"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"ઉપકરણ પુનઃપ્રારંભ ન થાય ત્યાં સુધી મ્યૂટ કરો"</string>
<string name="aerr_wait" msgid="3199956902437040261">"રાહ જુઓ"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"ઍપ્લિકેશન બંધ કરો"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"વધુ વિકલ્પો માટે ટચ કરો."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB ડીબગિંગ કનેક્ટ થયું."</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB ડીબગિંગ અક્ષમ કરવા માટે ટચ કરો."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"તમારા IT વ્યવસ્થાપક એ આ ઉપકરણની સમસ્યા નિવારણમાં સહાય માટે બગ રિપોર્ટની વિનંતી કરી છે. ઍપ્લિકેશનો અને ડેટા શેર કરવામાં આવી શકે છે અને તમારા ઉપકરણને અસ્થાયી રૂપે ધીમું કરી શકે છે."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"તમારા IT વ્યવસ્થાપક એ આ ઉપકરણની સમસ્યા નિવારણમાં સહાય માટે બગ રિપોર્ટની વિનંતી કરી છે. ઍપ્લિકેશનો અને ડેટા શેર કરવામાં આવી શકે છે."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"આ અસ્થાયી રૂપે તમારા ઉપકરણને ધીમું કરી શકે છે"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"સ્વીકારો"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"નકારો"</string>
<string name="select_input_method" msgid="8547250819326693584">"કીબોર્ડ બદલો"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"અનપિન કરતાં પહેલાં PIN માટે પૂછો"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"અનપિન કરતા પહેલાં અનલૉક પેટર્ન માટે પૂછો"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"અનપિન કરતાં પહેલાં પાસવર્ડ માટે પૂછો"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"ઍપ્લિકેશનનું કદ બદલવા યોગ્ય નથી, બે આંગળીઓ વડે તેને સ્ક્રોલ કરો."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"વિભાજિત-સ્ક્રીન સાથે ઍપ્લિકેશન કદાચ કામ ન કરે."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ઍપ્લિકેશન સ્ક્રીન-વિભાજનનું સમર્થન કરતી નથી."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"તમારા વ્યવસ્થાપક દ્વારા ઇન્સ્ટોલ કરેલ"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"તમારા વ્યવસ્થાપક દ્વારા અપડેટ થયેલ"</string>
@@ -1543,12 +1537,11 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> પસંદ કરી</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> પસંદ કરી</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"વિવિધ"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"તમે આ સૂચનાઓનું મહત્વ સેટ કર્યું છે."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"તમે આ સૂચનાઓનું મહત્વ સેટ કર્યું છે."</string>
<string name="importance_from_person" msgid="9160133597262938296">"શામેલ થયેલ લોકોને કારણે આ મહત્વપૂર્ણ છે."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> ને <xliff:g id="ACCOUNT">%2$s</xliff:g> સાથે એક નવા વપરાશકર્તાને બનાવવાની મંજૂરી આપીએ?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="ACCOUNT">%2$s</xliff:g> સાથે <xliff:g id="APP">%1$s</xliff:g> ને એક નવા વપરાશકર્તાને બનાવવાની મંજૂરી આપીએ (આ એકાઉન્ટ સાથેના એક વપરાશકર્તા પહેલાંથી અસ્તિત્વમાં છે)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"ભાષા પસંદગી"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"એક ભાષા ઉમેરો"</string>
<string name="country_selection_title" msgid="2954859441620215513">"પ્રદેશ પસંદગી"</string>
<string name="search_language_hint" msgid="7042102592055108574">"ભાષાનું નામ ટાઇપ કરો"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"સૂચવેલા"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"પિન કરો"</string>
<string name="unpin_target" msgid="3556545602439143442">"અનપિન કરો"</string>
<string name="app_info" msgid="6856026610594615344">"ઍપ્લિકેશન માહિતી"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-h426dp-port/integers.xml b/core/res/res/values-h426dp-port/integers.xml
new file mode 100644
index 0000000..94abbec
--- /dev/null
+++ b/core/res/res/values-h426dp-port/integers.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+ <integer name="date_picker_mode">2</integer>
+ <integer name="time_picker_mode">2</integer>
+</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 5e76c16..995c9c7 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"कॉलर ID प्रतिबंधित नहीं पर डिफ़ॉल्ट है. अगली कॉल: प्रतिबंधित नहीं"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"सेवा प्रावधान की हुई नहीं है."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"आप कॉलर आईडी सेटिंग नहीं बदल सकते."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"प्रतिबंधित पहुंच बदली गई"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"डेटा सेवा अवरोधित है."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"आपातकालीन सेवा अवरोधित है."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"ध्वनि सेवा अवरोधित है."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"ऐप रीसेट करें और पुन: प्रारंभ करें"</string>
<string name="aerr_report" msgid="5371800241488400617">"फ़ीडबैक भेजें"</string>
<string name="aerr_close" msgid="2991640326563991340">"बंद करें"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"म्यूट करें"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"डिवाइस पुन: प्रारंभ होने तक म्यूट करें"</string>
<string name="aerr_wait" msgid="3199956902437040261">"प्रतीक्षा करें"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"ऐप बंद करें"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"और विकल्पों के लिए स्पर्श करें."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB डीबग कनेक्ट किया गया"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB डीबग करना अक्षम करने के लिए स्पर्श करें."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"इस डिवाइस के समस्या निवारण में सहायता हेतु आपके आईटी व्यवस्थापक ने बग रिपोर्ट के लिए अनुरोध किया है. ऐप्स और डेटा को साझा किया जा सकता है और आपके डिवाइस की गति अस्थायी रूप से धीमी हो सकती है."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"आपके आईटी व्यवस्थापक ने इस डिवाइस के समस्या निवारण में सहायता के लिए एक बग रिपोर्ट का अनुरोध किया है. ऐप्स और डेटा साझा किए जा सकते हैं."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"इससे आपका डिवाइस अस्थायी रूप से धीमा हो सकता है"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"स्वीकार करें"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"अस्वीकार करें"</string>
<string name="select_input_method" msgid="8547250819326693584">"कीबोर्ड बदलें"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"अनपिन करने से पहले पिन के लिए पूछें"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"अनपिन करने से पहले अनलॉक पैटर्न के लिए पूछें"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"अनपिन करने से पहले पासवर्ड के लिए पूछें"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"ऐप का आकार बदला नहीं जा सकता है, इसे दो अंगुलियों से स्क्रॉल करें."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"हो सकता है कि ऐप्लिकेशन विभाजित स्क्रीन के साथ काम ना करे."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ऐप विभाजित स्क्रीन का समर्थन नहीं करता है."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"आपके नियंत्रक द्वारा इंस्टॉल किया गया"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"आपके नियंत्रक द्वारा अपडेट किया गया"</string>
@@ -1543,12 +1537,11 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> चयनित</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> चयनित</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"विविध"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"आपने इन नोटिफिकेशन का महत्व सेट किया है."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"आपने इन नोटिफिकेशन का महत्व सेट किया है."</string>
<string name="importance_from_person" msgid="9160133597262938296">"यह मौजूद व्यक्तियों के कारण महत्वपूर्ण है."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> को <xliff:g id="ACCOUNT">%2$s</xliff:g> के द्वारा एक नया उपयोगकर्ता बनाने दें?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> को <xliff:g id="ACCOUNT">%2$s</xliff:g> के द्वारा एक नया उपयोगकर्ता बनाने दें (इस खाते वाला एक उपयोगकर्ता पहले से मौजूद है) ?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"भाषा प्राथमिकता"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"भाषा जोड़ें"</string>
<string name="country_selection_title" msgid="2954859441620215513">"क्षेत्र प्राथमिकता"</string>
<string name="search_language_hint" msgid="7042102592055108574">"भाषा का नाम लिखें"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"सुझाए गए"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"पिन करें"</string>
<string name="unpin_target" msgid="3556545602439143442">"अनपिन करें"</string>
<string name="app_info" msgid="6856026610594615344">"ऐप की जानकारी"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 619e9b9..823181d 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -89,7 +89,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Zadana postavka ID-a pozivatelja nema ograničenje. Sljedeći poziv: Nije ograničen"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Usluga nije rezervirana."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Ne možete promijeniti postavku ID-a pozivatelja."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Promijenjen je ograničeni pristup"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Podatkovna usluga je blokirana."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Hitna usluga je blokirana."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Glasovna usluga je blokirana."</string>
@@ -923,7 +922,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Vrati aplikaciju na zadano i pokreni ponovo"</string>
<string name="aerr_report" msgid="5371800241488400617">"Pošalji povratne informacije"</string>
<string name="aerr_close" msgid="2991640326563991340">"Zatvori"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Zanemari"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Zanemari do ponovnog pokretanja uređaja"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Čekaj"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Zatvori aplikaciju"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1061,16 +1060,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Dodirnite za više opcija."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Priključen je alat za uklanjanje pogrešaka USB-om"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Dodirnite da se onemogući otklanjanje pogrešaka USB-om."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Želite li podijeliti izvješće o programskoj pogrešci?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Dijeljenje izvješća o programskoj pogrešci…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"IT administrator zatražio je izvješće o programskoj pogrešci radi lakšeg rješavanja problema na uređaju. Moguće je da će se aplikacije i podaci dijeliti, što bi moglo privremeno usporiti uređaj."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"IT administrator zatražio je izvješće o programskoj pogrešci radi lakšeg rješavanja problema na uređaju. Moguće je da će se aplikacije i podaci dijeliti."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"To bi moglo privremeno usporiti uređaj"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"PRIHVATI"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ODBIJ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Promjena tipkovnice"</string>
@@ -1483,7 +1477,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Traži PIN radi otkvačivanja"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Traži uzorak za otključavanje radi otkvačivanja"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Traži zaporku radi otkvačivanja"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Veličina aplikacije ne može se mijenjati, pomičite je s dva prsta."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikacija možda neće funkcionirati s podijeljenim zaslonom."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikacija ne podržava podijeljeni zaslon."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Instalirao administrator"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Ažurira vaš administrator"</string>
@@ -1562,12 +1556,11 @@
<item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> odabrane</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> odabranih</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Razno"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Postavili ste važnost tih obavijesti."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Postavili ste važnost tih obavijesti."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Važno je zbog uključenih osoba."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Želite li dopustiti aplikaciji <xliff:g id="APP">%1$s</xliff:g> da izradi novog korisnika s računom <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Želite li dopustiti aplikaciji <xliff:g id="APP">%1$s</xliff:g> da izradi novog korisnika s računom <xliff:g id="ACCOUNT">%2$s</xliff:g> (korisnik s tim računom već postoji)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Postavke jezika"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Dodavanje jezika"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Postavke regije"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Unesite naziv jezika"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Predloženo"</string>
@@ -1590,4 +1583,5 @@
<string name="pin_target" msgid="3052256031352291362">"Prikvači"</string>
<string name="unpin_target" msgid="3556545602439143442">"Otkvači"</string>
<string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index be2a3fd..015e13d 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"A hívóazonosító alapértelmezett értéke nem korlátozott. Következő hívás: nem korlátozott"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"A szolgáltatás nincs biztosítva."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Nem tudja módosítani a hívó fél azonosítója beállítást."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"A korlátozott hozzáférés módosítva"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Az adatszolgáltatás le van tiltva."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"A segélyszolgáltatás le van tiltva."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"A hangszolgáltatás letiltva."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Alkalmazás alaphelyzetbe állítása és újraindítása"</string>
<string name="aerr_report" msgid="5371800241488400617">"Visszajelzés küldése"</string>
<string name="aerr_close" msgid="2991640326563991340">"Bezárás"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Némítás"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Némítás az eszköz újraindulásáig"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Várakozás"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Alkalmazás bezárása"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Érintse meg a további lehetőségekhez."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB hibakereső csatlakoztatva"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Érintse meg az USB hibakeresés kikapcsolásához."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Megosztja a hibajelentést?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Hibajelentés megosztása…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"A rendszergazda hibajelentést kért, hogy segíthessen az eszközzel kapcsolatos probléma megoldásában. Előfordulhat, hogy a rendszer megosztja az alkalmazásokat és adatokat, továbbá eszköze átmenetileg lelassulhat."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"A rendszergazda hibajelentést kért, hogy segíthessen az eszközzel kapcsolatos probléma megoldásában. Előfordulhat, hogy a rendszer megosztja az alkalmazásokat és adatokat."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Előfordulhat, hogy eszköze emiatt átmenetileg lelassul"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ELFOGADOM"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ELUTASÍTOM"</string>
<string name="select_input_method" msgid="8547250819326693584">"Billentyűzet megváltoztatása"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"PIN-kód kérése a rögzítés feloldásához"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Feloldási minta kérése a rögzítés feloldásához"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Jelszó kérése a rögzítés feloldásához"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Az alkalmazást nem lehet átméretezni – két ujjal görgessen."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Lehet, hogy az alkalmazás nem működik osztott képernyős nézetben."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Az alkalmazás nem támogatja az osztott képernyős nézetet."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"A rendszergazda telepítette"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Frissítette a rendszergazda"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> kiválasztva</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> kiválasztva</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Vegyes"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Ön állította be ezen értesítések fontossági szintjét."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Ön állította be ezen értesítések fontossági szintjét."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Ez az üzenet a résztvevők miatt fontos."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Engedélyezi a(z) <xliff:g id="APP">%1$s</xliff:g> számára, hogy új felhasználót hozzon létre a(z) <xliff:g id="ACCOUNT">%2$s</xliff:g> fiókkal?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Engedélyezi a(z) <xliff:g id="APP">%1$s</xliff:g> számára, hogy új felhasználót hozzon létre a(z) <xliff:g id="ACCOUNT">%2$s</xliff:g> fiókkal? (Már létezik felhasználó ezzel a fiókkal.)"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Nyelvi beállítás"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Nyelv hozzáadása"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Régió beállítása"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Adja meg a nyelvet"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Javasolt"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Rögzítés"</string>
<string name="unpin_target" msgid="3556545602439143442">"Feloldás"</string>
<string name="app_info" msgid="6856026610594615344">"Alkalmazásinformáció"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index b436f3d..3a56491 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Զանգողի ID-ն լռելյայն չսահմանափակված է: Հաջորդ զանգը` չսահմանափակված"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Ծառայությունը չի տրամադրվում:"</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Դուք չեք կարող փոխել զանգողի ID-ի կարգավորումները:"</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Սահմանափակված մուտքը փոխված է"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Տվյալների ծառայությունն արգելափակված է:"</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Արտակարգ իրավիճակի ծառայությունն արգելափակված է:"</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Ձայնային ծառայությունը արգելափակված է:"</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Վերակայել և վերագործարկել հավելվածը"</string>
<string name="aerr_report" msgid="5371800241488400617">"Ուղարկել կարծիք"</string>
<string name="aerr_close" msgid="2991640326563991340">"Փակել"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Անջատել ձայնը"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Անջատել ձայնը մինչև սարքի վերագործարկումը"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Սպասել"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Փակել հավելվածը"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Հպեք՝ լրացուցիչ ընտրանքների համար:"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB վրիպազերծումը միացված է"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Հպեք` USB կարգաբերումը կասեցնելու համար:"</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"Այս սարքի անսարքությունների վերացման նպատակով ձեր ՏՏ ադմինիստրատորին անհրաժեշտ է վրիպակի զեկույց: Կարող են տրամադրվել տեղեկություններ ձեր հավելվածների մասին և այլ տվյալներ, իսկ սարքի աշխատանքը կարող է ժամանակավորապես դանդաղել:"</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Այս սարքի անսարքությունների վերացման նպատակով ձեր ՏՏ ադմինիստրատորին անհրաժեշտ է վրիպակի զեկույց: Կարող են տրամադրվել տեղեկություններ ձեր հավելվածներնի մասին և այլ տվյալներ:"</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Այդ ընթացքում ձեր սարքի աշխատանքը կարող է դանդաղել"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ԸՆԴՈՒՆԵԼ"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ՄԵՐԺԵԼ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Փոխել ստեղնաշարը"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Ապաամրացնելուց առաջ հարցնել PIN-կոդը"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Ապաամրացնելուց առաջ հարցնել ապակողպող նախշը"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Ապաամրացնելուց առաջ հարցնել գաղտնաբառը"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Հավելվածի չափը հնարավոր չէ փոխել, ոլորեք այն երկու մատի օգնությամբ:"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Հավելվածը չի կարող աշխատել տրոհված էկրանի ռեժիմում:"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Հավելվածը չի աջակցում էկրանի տրոհումը:"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Ադմինիստրատորը տեղադրել է այն"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Ադմինիստրատորը թարմացրել է այն"</string>
@@ -1543,12 +1537,11 @@
<item quantity="one">Ընտրված է՝ <xliff:g id="COUNT_1">%1$d</xliff:g></item>
<item quantity="other">Ընտրված է՝ <xliff:g id="COUNT_1">%1$d</xliff:g></item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Զանազան"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Դուք սահմանել եք այս ծանուցումների կարևորությունը:"</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Դուք սահմանել եք այս ծանուցումների կարևորությունը:"</string>
<string name="importance_from_person" msgid="9160133597262938296">"Կարևոր է, քանի որ որոշակի մարդիկ են ներգրավված:"</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Թույլ տա՞լ <xliff:g id="APP">%1$s</xliff:g> հավելվածին <xliff:g id="ACCOUNT">%2$s</xliff:g> հաշվով նոր Օգտվող ստեղծել:"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Թույլ տա՞լ <xliff:g id="APP">%1$s</xliff:g> հավելվածին <xliff:g id="ACCOUNT">%2$s</xliff:g> հաշվով նոր Օգտվող ստեղծել (նման հաշվով Օգտվող արդեն գոյություն ունի):"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Նախընտրելի լեզու"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Ավելացնել լեզու"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Նախընտրելի տարածաշրջան"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Մուտքագրեք լեզուն"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Առաջարկներ"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Ամրացնել"</string>
<string name="unpin_target" msgid="3556545602439143442">"Ապամրացնել"</string>
<string name="app_info" msgid="6856026610594615344">"Հավելվածի տվյալներ"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 7c18d24..2391ef7 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Nomor penelepon default tidak dibatasi. Panggilan selanjutnya: Tidak dibatasi"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Layanan tidak diperlengkapi."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Anda tidak dapat mengubah setelan nomor penelepon."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Akses terbatas berubah"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Layanan data dicekal."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Layanan darurat dicekal."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Layanan suara dicekal."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Setel ulang dan mulai ulang aplikasi"</string>
<string name="aerr_report" msgid="5371800241488400617">"Kirim masukan"</string>
<string name="aerr_close" msgid="2991640326563991340">"Tutup"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Bisukan"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Bisukan hingga perangkat dimulai ulang"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Tunggu"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Tutup aplikasi"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Sentuh untuk opsi lainnya."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Debugging USB terhubung"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Sentuh untuk menonaktifkan debugging USB."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Bagikan laporan bug?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Membagikan laporan bug..."</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Admin IT meminta laporan bug untuk membantu memecahkan masalah perangkat ini. Aplikasi dan data mungkin dibagikan dan untuk sementara perangkat mungkin menjadi lambat."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Admin IT meminta laporan bug untuk membantu memecahkan masalah perangkat ini. Aplikasi dan data mungkin dibagikan."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Tindakan ini mungkin memperlambat perangkat untuk sementara"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"SETUJU"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"TOLAK"</string>
<string name="select_input_method" msgid="8547250819326693584">"Ubah keyboard"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Meminta PIN sebelum melepas sematan"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Meminta pola pembukaan kunci sebelum melepas sematan"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Meminta sandi sebelum melepas sematan"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Aplikasi tidak dapat diubah ukurannya, gulir dengan dua jari."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikasi mungkin tidak berfungsi dengan layar terpisah."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"App tidak mendukung layar terpisah."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Dipasang oleh administrator"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Diperbarui oleh administrator"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> dipilih</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> dipilih</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Lain-Lain"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Anda menyetel tingkat kepentingan notifikasi ini."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Anda menyetel nilai penting notifikasi ini."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Ini penting karena orang-orang yang terlibat."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Izinkan <xliff:g id="APP">%1$s</xliff:g> membuat Pengguna baru dengan <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Izinkan <xliff:g id="APP">%1$s</xliff:g> membuat Pengguna baru dengan <xliff:g id="ACCOUNT">%2$s</xliff:g> (Pengguna dengan akun ini sudah ada) ?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Preferensi bahasa"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Tambahkan bahasa"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Preferensi wilayah"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Ketik nama bahasa"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Disarankan"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Pasang pin"</string>
<string name="unpin_target" msgid="3556545602439143442">"Lepas pin"</string>
<string name="app_info" msgid="6856026610594615344">"Info aplikasi"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index 79ef76b..8246584 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Númerabirting er sjálfgefið án takmarkana. Næsta símtal: Án takmarkana"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Þjónustu ekki útdeilt."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Þú getur ekki breytt stillingu númerabirtingar."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Takmörkuðum aðgangi breytt"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Lokað er fyrir gagnaþjónustu."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Lokað er fyrir neyðarþjónustu."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Lokað er fyrir raddþjónustu."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Endurstilla og endurræsa forritið"</string>
<string name="aerr_report" msgid="5371800241488400617">"Senda ábendingu"</string>
<string name="aerr_close" msgid="2991640326563991340">"Loka"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Þagga"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Þagga þangað til tæki er endurræst"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Bíða"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Loka forriti"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Snertu til að fá fleiri valkosti."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB-villuleit tengd"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Snertu til að slökkva á USB-villuleit."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Deila villutilkynningu?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Deilir villutilkynningu..."</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Kerfisstjórinn þinn óskaði eftir villutilkynningu til að auðvelda úrræðaleit á þessu tæki. Forritum og gögnum verður hugsanlega deilt og mögulegt er að þetta hægi tímabundið á tækinu."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Kerfisstjórinn þinn óskaði eftir villutilkynningu til að auðvelda úrræðaleit á þessu tæki. Forritum og gögnum verður hugsanlega deilt."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Hugsanlega hægir þetta tímabundið á tækinu þínu"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"SAMÞYKKJA"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"HAFNA"</string>
<string name="select_input_method" msgid="8547250819326693584">"Skipta um lyklaborð"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Biðja um PIN-númer til að losa"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Biðja um opnunarmynstur til að losa"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Biðja um aðgangsorð til að losa"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Ekki er hægt að breyta stærð forritsins; flettu upp og niður með tveimur fingrum."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Hugsanlega virkar forritið ekki ef skjánum er skipt upp."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Forritið styður ekki að skjánum sé skipt."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Uppsett af kerfisstjóra"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Uppfært af kerfisstjóranum"</string>
@@ -1543,12 +1537,11 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> valið</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> valin</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Ýmislegt"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Þú stilltir mikilvægi þessara tilkynninga."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Þú stilltir mikilvægi þessara tilkynninga."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Þetta er mikilvægt vegna fólksins sem tekur þátt í þessu."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Leyfa <xliff:g id="APP">%1$s</xliff:g> að stofna nýjan notanda með <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Leyfa <xliff:g id="APP">%1$s</xliff:g> að stofna nýjan notanda með <xliff:g id="ACCOUNT">%2$s</xliff:g> (notandi með þennan reikning er þegar fyrir hendi)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Val tungumáls"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Bæta við tungumáli"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Svæðisval"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Sláðu inn heiti tungumáls"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Tillögur"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Festa"</string>
<string name="unpin_target" msgid="3556545602439143442">"Losa"</string>
<string name="app_info" msgid="6856026610594615344">"Forritsupplýsingar"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 2ba3359..912f154 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"ID chiamante generalmente non limitato. Prossima chiamata: non limitato"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Servizio non fornito."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Non è possibile modificare l\'impostazione ID chiamante."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Accesso limitato modificato"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Il servizio dati è bloccato."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Il servizio di emergenza è bloccato."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Il servizio vocale è bloccato."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Reimposta e riavvia app"</string>
<string name="aerr_report" msgid="5371800241488400617">"Invia feedback"</string>
<string name="aerr_close" msgid="2991640326563991340">"Chiudi"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Disattiva"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Disattiva fino al riavvio del dispositivo"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Attendi"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Chiudi app"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Tocca per visualizzare più opzioni."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Debug USB collegato"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Tocca per disattivare il debug USB."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Condividere la segnalazione di bug?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Condivisione della segnalazione di bug…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"L\'amministratore IT ha richiesto una segnalazione di bug per poter risolvere più facilmente i problemi di questo dispositivo. Potrebbero essere condivisi dati e app e il dispositivo potrebbe rallentare temporaneamente."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"L\'amministratore IT ha richiesto una segnalazione di bug per poter risolvere più facilmente i problemi di questo dispositivo. Potrebbero essere condivisi dati e app."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Il dispositivo potrebbe rallentare temporaneamente"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACCETTO"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"RIFIUTO"</string>
<string name="select_input_method" msgid="8547250819326693584">"Cambia tastiera"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Richiedi il PIN per lo sblocco"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Richiedi sequenza di sblocco prima di sbloccare"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Richiedi password prima di sbloccare"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Non è possibile ridimensionare l\'app: scorri con due dita."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"L\'app potrebbe non funzionare con lo schermo diviso."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"L\'app non supporta la modalità Schermo diviso."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Installato dall\'amministratore"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Aggiornato dall\'amministratore"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> elementi selezionati</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> elemento selezionato</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Vari"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Stabilisci tu l\'importanza di queste notifiche."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Stabilisci tu l\'importanza di queste notifiche."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Importante a causa delle persone coinvolte."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Consentire a <xliff:g id="APP">%1$s</xliff:g> di creare un nuovo utente con <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Consentire a <xliff:g id="APP">%1$s</xliff:g> di creare un nuovo utente con <xliff:g id="ACCOUNT">%2$s</xliff:g>? (Esiste già un utente con questo account)"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Preferenza lingua"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Aggiungi una lingua"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Area geografica preferita"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Digita nome lingua"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Suggerite"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Blocca"</string>
<string name="unpin_target" msgid="3556545602439143442">"Sblocca"</string>
<string name="app_info" msgid="6856026610594615344">"Informazioni app"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index a67319c..c334a3c 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -90,7 +90,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"זיהוי מתקשר עובר כברירת מחדל למצב לא מוגבל. השיחה הבאה: לא מוגבלת"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"השירות לא הוקצה."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"אינך יכול לשנות את הגדרת זיהוי המתקשר."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"גישה מוגבלת השתנתה"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"שירות הנתונים חסום."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"שירות חירום חסום."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"השירות הקולי חסום."</string>
@@ -929,7 +928,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"אפס והפעל מחדש את האפליקציה"</string>
<string name="aerr_report" msgid="5371800241488400617">"שלח משוב"</string>
<string name="aerr_close" msgid="2991640326563991340">"סגור"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"השתק"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"השתק עד הפעלה מחדש של המכשיר"</string>
<string name="aerr_wait" msgid="3199956902437040261">"המתן"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"סגור את האפליקציה"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1069,16 +1068,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"גע להצגת עוד אפשרויות."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"ניפוי באגים של USB מחובר"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"גע כדי להשבית ניפוי באגים בהתקן ה-USB."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"מנהל ה-IT ביקש דוח על באג כדי לסייע בפתרון בעיות במכשיר זה. ייתכן שאפליקציות ונתונים ישותפו. פעילות המכשיר עשויה להאט באופן זמני."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"מנהל ה-IT שלך ביקש דוח על באג כדי לסייע בפתרון בעיות במכשיר זה. ייתכן שאפליקציות ונתונים ישותפו."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"קצב הפעולה של המכשיר עשוי להיות איטי יותר באופן זמני כתוצאה מכך"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"אישור"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"דחייה"</string>
<string name="select_input_method" msgid="8547250819326693584">"שינוי מקלדת"</string>
@@ -1493,7 +1487,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"בקש PIN לפני ביטול הצמדה"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"בקש קו ביטול נעילה לפני ביטול הצמדה"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"בקש סיסמה לפני ביטול הצמדה"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"אין אפשרות לשנות את גודל האפליקציה, גלול אותה בשתי אצבעות."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"ייתכן שהיישום לא יפעל עם מסך מפוצל."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"האפליקציה אינה תומכת במסך מפוצל."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"הותקנה על ידי מנהל המערכת שלך"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"עודכן על ידי מנהל המערכת שלך"</string>
@@ -1581,12 +1575,11 @@
<item quantity="other">בחרת <xliff:g id="COUNT_1">%1$d</xliff:g></item>
<item quantity="one">בחרת <xliff:g id="COUNT_0">%1$d</xliff:g></item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"שונות"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"אתה מגדיר את החשיבות של ההודעות האלה."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"אתה מגדיר את החשיבות של ההודעות האלה."</string>
<string name="importance_from_person" msgid="9160133597262938296">"ההודעה חשובה בשל האנשים המעורבים."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"האם לאפשר ל-<xliff:g id="APP">%1$s</xliff:g> ליצור משתמש חדש לחשבון <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"האם לאפשר ל-<xliff:g id="APP">%1$s</xliff:g> ליצור משתמש חדש לחשבון <xliff:g id="ACCOUNT">%2$s</xliff:g> (כבר קיים משתמש לחשבון הזה) ?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"העדפת שפה"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"הוספת שפה"</string>
<string name="country_selection_title" msgid="2954859441620215513">"העדפת אזור"</string>
<string name="search_language_hint" msgid="7042102592055108574">"הקלד שם שפה"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"הצעות"</string>
@@ -1609,4 +1602,5 @@
<string name="pin_target" msgid="3052256031352291362">"הצמד"</string>
<string name="unpin_target" msgid="3556545602439143442">"בטל הצמדה"</string>
<string name="app_info" msgid="6856026610594615344">"פרטי אפליקציה"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 166eca7..9ee8e0e 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"既定: 発信者番号通知、次の発信: 通知"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"提供可能なサービスがありません。"</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"発信者番号の設定は変更できません。"</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"アクセス制限が変更されました"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"データサービスがブロックされています。"</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"緊急サービスがブロックされています。"</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"音声サービスがブロックされています。"</string>
@@ -918,7 +917,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"アプリをリセットして再起動"</string>
<string name="aerr_report" msgid="5371800241488400617">"フィードバックを送信"</string>
<string name="aerr_close" msgid="2991640326563991340">"閉じる"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"ミュート"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"端末が再起動するまでミュート"</string>
<string name="aerr_wait" msgid="3199956902437040261">"待機"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"アプリを閉じる"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1054,16 +1053,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"タップしてその他のオプションを表示"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USBデバッグが接続されました"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"タップしてUSBデバッグを無効化"</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"IT 管理者からこの端末のトラブルシューティングに役立てるためバグレポートを共有するようリクエストがありました。アプリやデータが共有され、端末の動作が一時的に遅くなる場合があります。"</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"IT 管理者からこの端末のトラブルシューティングに役立てるためバグレポートを共有するようリクエストがありました。アプリやデータが共有されることがあります。"</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"共有によって端末の動作が一時的に遅くなる場合があります"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"同意する"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"同意しない"</string>
<string name="select_input_method" msgid="8547250819326693584">"キーボードの変更"</string>
@@ -1474,7 +1468,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"オフライン再生を解除する前にPINの入力を求める"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"画面固定を解除する前にロック解除パターンの入力を求める"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"オフライン再生を解除する前にパスワードの入力を求める"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"アプリのサイズは変更できません。2 本の指でスクロールしてください。"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"アプリは分割画面では動作しないことがあります。"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"アプリで分割画面がサポートされていません。"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"管理者によってインストールされました"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"管理者によって更新されています"</string>
@@ -1544,12 +1538,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>件選択済み</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g>件選択済み</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"その他"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"このような通知の重要度を設定します。"</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"このような通知の重要度を設定します。"</string>
<string name="importance_from_person" msgid="9160133597262938296">"関係するユーザーのため、この設定は重要です。"</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> が <xliff:g id="ACCOUNT">%2$s</xliff:g> で新しいユーザーを作成できるようにしますか?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> が <xliff:g id="ACCOUNT">%2$s</xliff:g> で新しいユーザーを作成できるようにしますか?(このアカウントのユーザーはすでに存在します)"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"言語設定"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"言語を追加"</string>
<string name="country_selection_title" msgid="2954859441620215513">"地域設定"</string>
<string name="search_language_hint" msgid="7042102592055108574">"言語名を入力"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"言語の候補"</string>
@@ -1577,4 +1570,5 @@
<string name="pin_target" msgid="3052256031352291362">"固定"</string>
<string name="unpin_target" msgid="3556545602439143442">"固定を解除"</string>
<string name="app_info" msgid="6856026610594615344">"アプリ情報"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 178e023..8e4e378 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"ნაგულისხმებად დაყენებულია ნომრის დაფარვის გამორთვა. შემდეგი ზარი: არ არის დაფარული."</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"სერვისი არ არის მიწოდებული."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"არ შეგიძლიათ აბონენტის ID პარამეტრების შეცვლა."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"წვდომის შეზღუდვები შეცვლილია"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"ინტერნეტი დაბლოკილია."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"გადაუდებელი სამსახური დაბლოკილია."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"ხმოვანი მომსახურება დაბლოკილია."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"გადაყენება და აპის გადატვირთვა"</string>
<string name="aerr_report" msgid="5371800241488400617">"გამოხმაურება"</string>
<string name="aerr_close" msgid="2991640326563991340">"დახურვა"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"დადუმება"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"დადუმება მოწყობილობის გადატვირთვამდე"</string>
<string name="aerr_wait" msgid="3199956902437040261">"მოცდა"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"აპის დახურვა"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"შეეხეთ დამატებითი პარამეტრებისთვის."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB გამართვა შეერთებულია"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"შეეხეთ, რათა შეწყვიტოთ USB-ის გამართვა."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"ამ მოწყობილობის პრობლემების აღმოფხვრაში დასახმარებლად, თქვენი IT ადმინისტრატორი ხარვეზის შესახებ ანგარიშს ითხოვს, რა დროსაც შეიძლება გაზიარდეს აპები და მონაცემები, ხოლო თქვენი მოწყობილობა დროებით შენელდეს."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"ამ მოწყობილობის პრობლემების აღმოფხვრაში დასახმარებლად, თქვენი IT ადმინისტრატორი ხარვეზის შესახებ ანგარიშს ითხოვს, რა დროსაც შეიძლება გაზიარდეს აპები და მონაცემები."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"ამან შეიძლება დროებით შეანელოს თქვენი მოწყობილობა"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"მიღება"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"უარყოფა"</string>
<string name="select_input_method" msgid="8547250819326693584">"კლავიატურის შეცვლა"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ფიქსაციის მოხსნამდე PIN-ის მოთხოვნა"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ფიქსაციის მოხსნამდე განბლოკვის ნიმუშის მოთხოვნა"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ფიქსაციის მოხსნამდე პაროლის მოთხოვნა"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"აპის ზომა ვერ შეიცვლება. გადაადგილდით მასში ორი თითის მეშვეობით."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"აპმა შეიძლება არ იმუშაოს გაყოფილი ეკრანის რეჟიმში."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ეკრანის გაყოფა არ არის მხარდაჭერილი აპის მიერ."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"თქვენი ადმინისტრატორის მიერ დაყენებული"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"განახლებულია თქვენი ადმინისტრატორის მიერ"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> შერჩეული</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> შერჩეული</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"სხვადასხვა"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"ამ შეტყობინებების მნიშვნელობის დონე განისაზღვრა თქვენ მიერ."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"ამ შეტყობინებების მნიშვნელობის დონე განისაზღვრა თქვენ მიერ."</string>
<string name="importance_from_person" msgid="9160133597262938296">"მნიშვნელოვანია ჩართული მომხმარებლების გამო."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"მიეცეს უფლება <xliff:g id="APP">%1$s</xliff:g>-ს, <xliff:g id="ACCOUNT">%2$s</xliff:g>-ის მეშვეობით ახალი მომხმარებელი შექმნას ?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"მიეცეს უფლება <xliff:g id="APP">%1$s</xliff:g>-ს, <xliff:g id="ACCOUNT">%2$s</xliff:g>-ის მეშვეობით ახალი მომხმარებელი შექმნას (ამ ანგარიშის მქონე მომხმარებელი უკვე არსებობს) ?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"ენის პარამეტრები"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"ენის დამატება"</string>
<string name="country_selection_title" msgid="2954859441620215513">"რეგიონის პარამეტრები"</string>
<string name="search_language_hint" msgid="7042102592055108574">"აკრიფეთ ენის სახელი"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"რეკომენდებული"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"ჩამაგრება"</string>
<string name="unpin_target" msgid="3556545602439143442">"ჩამაგრების მოხსნა"</string>
<string name="app_info" msgid="6856026610594615344">"აპის შესახებ"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 259278a..c14bc68 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Қоңырау шалушының жеке анықтағышы бастапқы бойынша шектелмеген. Келесі қоңырау: Шектелмеген"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Қызмет ұсынылмаған."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Қоңырау шалушы идентификаторы параметрін өзгерту мүмкін емес."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Шектелген қол жетімділік өзгертілген"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Дерекқор қызметі бөгелген."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Төтенше қызмет бөгелген."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Дауыс қызметі бөгелген."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Ысырып, қолданбаны қайта іске қосу"</string>
<string name="aerr_report" msgid="5371800241488400617">"Пікір жіберу"</string>
<string name="aerr_close" msgid="2991640326563991340">"Жабу"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Үнсіз"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Құрылғы қайта іске қосылғанша дыбысын өшіру"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Күту"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Қолданбаны жабу"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Қосымша параметрлер үшін түртіңіз."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB жөндеу қосылған"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB жөндеуді өшіру үшін түртіңіз."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"АТ әкімшісі осы құрылғы ақауларын жоюға көмектесу үшін қате туралы есепті сұрады. Қолданбалар және деректер бөлісілуі әрі құрылғының жұмысы уақытша баяулауы мүмкін."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"АТ әкімшісі осы құрылғы ақауларын жоюға көмектесу үшін қате туралы есепті сұрады. Қолданбалар және деректер бөлісілуі мүмкін."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Бұл құрылғы жұмысын уақытша баяулатуы мүмкін"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ҚАБЫЛДАУ"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ҚАБЫЛДАМАУ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Пернетақтаны өзгерту"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Босату алдында PIN кодын сұрау"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Босату алдында бекітпесін ашу өрнегін сұрау"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Босату алдында құпия сөзді сұрау"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Қолданба өлшемін өзгерту мүмкін емес, оны екі саусақпен айналдырыңыз."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Қолданба бөлінген экранда жұмыс істемеуі мүмкін."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Қодланба бөлінген экранды қолдамайды."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Әкімші орнатқан"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Әкімші жаңартты"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> таңдалды</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> таңдалды</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Әр түрлі"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Сіз осы хабарландырулардың маңыздылығын орнатасасыз."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Сіз осы хабарландырулардың маңыздылығын орнатасыз."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Қатысты адамдарға байланысты бұл маңызды."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACCOUNT">%2$s</xliff:g> есептік жазбасы бар жаңа пайдаланушы жасауға рұқсат ету керек пе?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACCOUNT">%2$s</xliff:g> есептік жазбасында жаңа пайдаланушы жасауға рұқсат ету керек пе (осы есептік жазбасы бар пайдаланушы әлдеқашан бар) ?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Тіл параметрі"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Тілді қосу"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Аймақ параметрі"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Тіл атауын теріңіз"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Ұсынылған"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"PIN код"</string>
<string name="unpin_target" msgid="3556545602439143442">"Босату"</string>
<string name="app_info" msgid="6856026610594615344">"Қолданба ақпараты"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 7390b6b..0becd32 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"មិនបានដាក់កម្រិតលំនាំដើមលេខសម្គាល់អ្នកហៅ។ ការហៅបន្ទាប់៖ មិនបានដាក់កម្រិត។"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"មិនបានផ្ដល់សេវាកម្ម។"</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"អ្នកមិនអាចប្ដូរការកំណត់លេខសម្គាល់អ្នកហៅបានទេ។"</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"បានប្ដូរការចូលដំណើរការដែលបានដាក់កម្រិត"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"បានទប់ស្កាត់សេវាកម្មទិន្នន័យ។"</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"បានទប់ស្កាត់សេវាកម្មពេលអាសន្ន។"</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"សេវាកម្មសំឡេងត្រូវបានទប់ស្កាត់។"</string>
@@ -919,7 +918,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"កំណត់ និងចាប់ផ្តើមកម្មវិធីឡើងវិញ"</string>
<string name="aerr_report" msgid="5371800241488400617">"ផ្ញើមតិ"</string>
<string name="aerr_close" msgid="2991640326563991340">"បិទ"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"បិទ"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"បិទរហូតដល់ឧបករណ៍ចាប់ផ្តើមឡើងវិញ"</string>
<string name="aerr_wait" msgid="3199956902437040261">"រង់ចាំ"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"បិទកម្មវិធី"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1055,16 +1054,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"ប៉ះដើម្បីបានជម្រើសថែមទៀត។"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"បានភ្ជាប់ការកែកំហុសយូអេសប៊ី"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"ប៉ះ ដើម្បីបិទការកែកំហុសយូអេសប៊ី។"</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"អ្នកគ្រប់គ្រងផ្នែកព័ត៌មានវិទ្យារបស់អ្នកបានស្នើរបាយការណ៍កំហុសដើម្បីដោះស្រាយកំហុសឧបករណ៍នេះ។ កម្មវិធី និងទិន្នន័យអាចនឹងត្រូវបានចែករំលែក ហើយឧបករណ៍របស់អ្នកអាចនឹងយឺតជាបណ្តោះអាសន្ន។"</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"អ្នកគ្រប់គ្រងផ្នែកព័ត៌មានវិទ្យារបស់អ្នកបានស្នើរបាយការណ៍កំហុសដើម្បីដោះស្រាយកំហុសឧបករណ៍នេះ។ កម្មវិធី និងទិន្នន័យអាចនឹងត្រូវបានចែករំលែក។"</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"វាអាចនឹងធ្វើឲ្យឧបករណ៍របស់អ្នកយឺតជាបណ្តោះអាសន្ន។"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ព្រមទទួល"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"បដិសេធ"</string>
<string name="select_input_method" msgid="8547250819326693584">"ប្ដូរក្ដារចុច"</string>
@@ -1475,7 +1469,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"សួររកកូដ PIN មុនពេលផ្ដាច់"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"សួររកលំនាំដោះសោមុនពេលផ្ដាច់"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"សួររកពាក្យសម្ងាត់មុនពេលផ្ដាច់"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"កម្មវិធីមិនអាចផ្លាស់ប្តូរទំហំបានទេ សូមរមូរវាដោយប្រើម្រាមដៃពីរ។"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"កម្មវិធីអាចនឹងមិនដំណើរការនៅលើអេក្រង់បំបែកទេ"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"កម្មវិធីមិនគាំទ្រអេក្រង់បំបែកជាពីរទេ"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"បានដំឡើងដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"បានធ្វើបច្ចុប្បន្នភាពដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
@@ -1545,12 +1539,11 @@
<item quantity="other">បានជ្រើស <xliff:g id="COUNT_1">%1$d</xliff:g></item>
<item quantity="one">បានជ្រើស <xliff:g id="COUNT_0">%1$d</xliff:g></item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"ផ្សេងៗ"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"អ្នកបានកំណត់សារៈសំខាន់នៃការជូនដំណឹងទាំងនេះ"</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"អ្នកបានកំណត់សារៈសំខាន់នៃការជូនដំណឹងទាំងនេះ"</string>
<string name="importance_from_person" msgid="9160133597262938296">"វាមានសារៈសំខាន់ដោយសារតែមនុស្សដែលពាក់ព័ន្ធ"</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"អនុញ្ញាតឲ្យ <xliff:g id="APP">%1$s</xliff:g> បង្កើតអ្នកប្រើថ្មីដោយប្រើ <xliff:g id="ACCOUNT">%2$s</xliff:g> ឬទេ?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"អនុញ្ញាតឲ្យ <xliff:g id="APP">%1$s</xliff:g> បង្កើតអ្នកប្រើថ្មីដោយប្រើ <xliff:g id="ACCOUNT">%2$s</xliff:g> (មានអ្នកប្រើសម្រាប់គណនីនេះរួចហើយ) ឬទេ?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"ចំណូលចិត្តភាសា"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"បន្ថែមភាសា"</string>
<string name="country_selection_title" msgid="2954859441620215513">"ចំណូលចិត្តតំបន់"</string>
<string name="search_language_hint" msgid="7042102592055108574">"វាយបញ្ចូលឈ្មោះភាសា"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"បានស្នើ"</string>
@@ -1573,4 +1566,5 @@
<string name="pin_target" msgid="3052256031352291362">"ខ្ទាស់"</string>
<string name="unpin_target" msgid="3556545602439143442">"មិនខ្ទាស់"</string>
<string name="app_info" msgid="6856026610594615344">"ព័ត៌មានកម្មវិធី"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index ff1d028..eeb156c 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"ಕರೆಮಾಡುವವರ ID ಅನ್ನು ನಿರ್ಬಂಧಿಸದಿರುವಂತೆ ಡೀಫಾಲ್ಟ್ ಮಾಡಲಾಗಿದೆ. ಮುಂದಿನ ಕರೆ: ನಿರ್ಬಂಧಿಸಲಾಗಿಲ್ಲ"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"ಸೇವೆಯನ್ನು ಪೂರೈಸಲಾಗಿಲ್ಲ."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"ನೀವು ಕಾಲರ್ ID ಸೆಟ್ಟಿಂಗ್ ಬದಲಾಯಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"ನಿರ್ಬಂಧಿತ ಪ್ರವೇಶವನ್ನು ಬದಲಿಸಲಾಗಿದೆ"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"ಡೇಟಾ ಸೇವೆಯನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"ತುರ್ತು ಸೇವೆಯನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"ಧ್ವನಿ ಸೇವೆಯನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"ಅಪ್ಲಿಕೇಶನ್ ಮರುಹೊಂದಿಸಿ ಮತ್ತು ಮರುಪ್ರಾರಂಭಿಸಿ"</string>
<string name="aerr_report" msgid="5371800241488400617">"ಪ್ರತಿಕ್ರಿಯೆ ಕಳುಹಿಸು"</string>
<string name="aerr_close" msgid="2991640326563991340">"ಮುಚ್ಚು"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"ಮ್ಯೂಟ್"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"ಸಾಧನವು ಮರುಪ್ರಾರಂಭವಾಗುವವರೆಗೂ ಮ್ಯೂಟ್ ಮಾಡಿ"</string>
<string name="aerr_wait" msgid="3199956902437040261">"ನಿರೀಕ್ಷಿಸು"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಮುಚ್ಚಿ"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"ಹೆಚ್ಚಿನ ಆಯ್ಕೆಗಳಿಗೆ ಸ್ಪರ್ಶಿಸಿ."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB ಡೀಬಗಿಂಗ್ ಸಂಪರ್ಕ"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB ಡೀಬಗಿಂಗ್ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಸ್ಪರ್ಶಿಸಿ."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"ಈ ಸಾಧನದ ಸಮಸ್ಯೆ ನಿವಾರಿಸುವುದಕ್ಕೆ ಸಹಾಯ ಮಾಡಲು ನಿಮ್ಮ IT ನಿರ್ವಾಹಕರು ಬಗ್ ವರದಿಯನ್ನು ವಿನಂತಿಸಿದ್ದಾರೆ. ಅಪ್ಲಿಕೇಶನ್ಗಳು ಮತ್ತು ಡೇಟಾವನ್ನು ಹಂಚಿಕೊಳ್ಳಬಹುದು ಹಾಗು ನಿಮ್ಮ ಸಾಧನವು ತಾತ್ಕಾಲಿಕವಾಗಿ ನಿಧಾನಗೊಳ್ಳಬಹುದು."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"ಈ ಸಾಧನದ ಸಮಸ್ಯೆ ನಿವಾರಿಸಲು ಸಹಾಯ ಮಾಡಲು ನಿಮ್ಮ IT ನಿರ್ವಾಹಕರು ಬಗ್ ವರದಿಯನ್ನು ವಿನಂತಿಸಿದ್ದಾರೆ. ಅಪ್ಲಿಕೇಶನ್ಗಳು ಮತ್ತು ಡೇಟಾವನ್ನು ಹಂಚಿಕೊಳ್ಳಬಹುದು."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"ಇದು ನಿಮ್ಮ ಸಾಧನವನ್ನು ತಾತ್ಕಾಲಿಕವಾಗಿ ನಿಧಾನಗೊಳಿಸಬಹುದು"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ಸಮ್ಮತಿಸು"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ತಿರಸ್ಕರಿಸು"</string>
<string name="select_input_method" msgid="8547250819326693584">"ಕೀಬೋರ್ಡ್ ಬದಲಿಸಿ"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ಅನ್ಪಿನ್ ಮಾಡಲು ಪಿನ್ ಕೇಳು"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ಅನ್ಪಿನ್ ಮಾಡಲು ಅನ್ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಕೇಳಿ"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ಅನ್ಪಿನ್ ಮಾಡಲು ಪಾಸ್ವರ್ಡ್ ಕೇಳು"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಮರುಗಾತ್ರಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ, ಅದನ್ನು ಎರಡು ಬೆರಳುಗಳಿಂದ ಸ್ಕ್ರಾಲ್ ಮಾಡಿ."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"ವಿಭಜಿಸಿದ ಪರದೆಯಲ್ಲಿ ಅಪ್ಲಿಕೇಶನ್ ಕೆಲಸ ಮಾಡದೇ ಇರಬಹುದು."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ಅಪ್ಲಿಕೇಶನ್ ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರಿಂದ ಸ್ಥಾಪಿಸಲಾಗಿದೆ"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರಿಂದ ನವೀಕರಿಸಲಾಗಿದೆ"</string>
@@ -1543,12 +1537,11 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"ಇತರೆ"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"ನೀವು ಈ ಅಧಿಸೂಚನೆಗಳ ಪ್ರಾಮುಖ್ಯತೆಯನ್ನು ಹೊಂದಿಸಿರುವಿರಿ."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"ನೀವು ಈ ಅಧಿಸೂಚನೆಗಳ ಪ್ರಾಮುಖ್ಯತೆಯನ್ನು ಹೊಂದಿಸಿರುವಿರಿ."</string>
<string name="importance_from_person" msgid="9160133597262938296">"ಜನರು ತೊಡಗಿಕೊಂಡಿರುವ ಕಾರಣ ಇದು ಅತ್ಯಂತ ಪ್ರಮುಖವಾಗಿದೆ."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="ACCOUNT">%2$s</xliff:g> ಮೂಲಕ ಹೊಸ ಬಳಕೆದಾರರನ್ನು ರಚಿಸಲು <xliff:g id="APP">%1$s</xliff:g> ಗೆ ಅನುಮತಿಸುವುದೇ ?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="ACCOUNT">%2$s</xliff:g> (ಈ ಖಾತೆಯ ಬಳಕೆದಾರರು ಈಗಾಗಲೇ ಅಸ್ತಿತ್ವದಲ್ಲಿದ್ದಾರೆ) ಮೂಲಕ ಹೊಸ ಬಳಕೆದಾರರನ್ನು ರಚಿಸಲು <xliff:g id="APP">%1$s</xliff:g> ಗೆ ಅನುಮತಿಸುವುದೇ ?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"ಭಾಷೆಯ ಪ್ರಾಶಸ್ತ್ಯ"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"ಭಾಷೆ ಸೇರಿಸಿ"</string>
<string name="country_selection_title" msgid="2954859441620215513">"ಪ್ರದೇಶ ಪ್ರಾಶಸ್ತ್ಯ"</string>
<string name="search_language_hint" msgid="7042102592055108574">"ಭಾಷೆ ಹೆಸರನ್ನು ಟೈಪ್ ಮಾಡಿ"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"ಸಲಹೆ ಮಾಡಿರುವುದು"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"ಪಿನ್ ಮಾಡು"</string>
<string name="unpin_target" msgid="3556545602439143442">"ಅನ್ಪಿನ್"</string>
<string name="app_info" msgid="6856026610594615344">"ಅಪ್ಲಿಕೇಶನ್ ಮಾಹಿತಿ"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index bc0228a..3496962 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"발신자 번호가 기본적으로 제한되지 않음으로 설정됩니다. 다음 통화: 제한되지 않음"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"서비스가 준비되지 않았습니다."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"발신자 번호 설정을 변경할 수 없습니다."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"제한된 액세스가 변경되었습니다."</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"데이터 서비스가 차단되었습니다."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"긴급 서비스가 차단되었습니다."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"음성 서비스가 차단되었습니다."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"앱 재설정 및 다시 시작"</string>
<string name="aerr_report" msgid="5371800241488400617">"의견 보내기"</string>
<string name="aerr_close" msgid="2991640326563991340">"닫기"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"숨기기"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"기기가 다시 시작될 때까지 알림 끄기"</string>
<string name="aerr_wait" msgid="3199956902437040261">"대기"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"앱 닫기"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"더 많은 옵션을 확인하려면 터치하세요."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB 디버깅 연결됨"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB 디버깅을 사용하지 않으려면 터치하세요."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"IT 관리자가 이 기기의 문제해결을 위해 버그 신고서를 요청했습니다. 앱과 데이터가 공유될 수 있으며 기기 속도가 일시적으로 느려질 수 있습니다."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"IT 관리자가 이 기기의 문제해결을 위해 버그 보고서를 요청했습니다. 앱과 데이터가 공유될 수 있습니다."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"이로 인해 일시적으로 기기 속도가 느려질 수 있습니다."</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"수락"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"거절"</string>
<string name="select_input_method" msgid="8547250819326693584">"키보드 변경"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"고정 해제 이전에 PIN 요청"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"고정 해제 이전에 잠금해제 패턴 요청"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"고정 해제 이전에 비밀번호 요청"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"앱에서 크기 조절이 불가능합니다. 두 손가락을 사용해 스크롤하세요."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"앱이 분할 화면에서 작동하지 않을 수 있습니다."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"앱이 화면 분할을 지원하지 않습니다."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"관리자가 설치함"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"관리자에 의해 업데이트됨"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>개 선택됨</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g>개 선택됨</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"기타"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"이러한 알림의 중요도를 설정했습니다."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"이러한 알림의 중요도를 설정했습니다."</string>
<string name="importance_from_person" msgid="9160133597262938296">"관련된 사용자가 있으므로 중요합니다."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g>이(가) <xliff:g id="ACCOUNT">%2$s</xliff:g>(으)로 신규 사용자를 만들도록 허용하시겠습니까?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g>이(가) <xliff:g id="ACCOUNT">%2$s</xliff:g>(이 계정의 사용자가 이미 있음)(으)로 신규 사용자를 만들도록 허용하시겠습니까?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"언어 환경설정"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"언어 추가"</string>
<string name="country_selection_title" msgid="2954859441620215513">"지역 환경설정"</string>
<string name="search_language_hint" msgid="7042102592055108574">"언어 이름 입력"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"추천"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"고정"</string>
<string name="unpin_target" msgid="3556545602439143442">"고정 해제"</string>
<string name="app_info" msgid="6856026610594615344">"앱 정보"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 5fc6a62..a6ee770 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Номурду аныктоонун демейки абалы \"чектелбейт\" деп коюлган. Кийинки чалуу: Чектелбейт"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Кызмат камсыздалган эмес."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Чалуучунун далдаштырма дайындары жөндөөлөрүн өзгөртө албайсыз."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Чектелген мүмкүнчүлүк өзгөртүлдү"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Мобилдик Интернет бөгөттөлгөн."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Өзгөчө кырдаал кызматы бөгөттөлгөн."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Үн кызматы бөгөттөлгөн."</string>
@@ -918,7 +917,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Колдонмону баштапкы абалга келтирип, кайра жүргүзүү"</string>
<string name="aerr_report" msgid="5371800241488400617">"Жооп пикир жөнөтүү"</string>
<string name="aerr_close" msgid="2991640326563991340">"Жабуу"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Үнсүз"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Түзмөк өчүрүлүп-күйгүзүлгүчө үнүн өчүрүү"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Күтүү"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Колдонмону жабуу"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1054,16 +1053,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Көбүрөөк параметр үчүн тийип коюңуз."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB мүчүлүштүктөрдү оңдоо туташтырылган"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB мүчүлүштүктөрдү жоюу мүмкүнчүлүгүн өчүрүү үчүн тийип коюңуз."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"Бул түзмөктүн бузулууларын аныктап оңдоо үчүн IT администраторуңуз мүчүлүштүктөр тууралуу маалыматты сурап жатат. Колдонмолор менен дайындар бөлүшүлүп, түзмөгүңүз жайыраак иштеп калышы мүмкүн."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Бул түзмөктүн бузулууларын аныктап оңдоо үчүн IT администраторуңуз мүчүлүштүктөр тууралуу маалыматты сурап жатат. Колдонмолор менен дайындар бөлүшүлүшү мүмкүн."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Ушуну менен түзмөгүңүздүн ылдамдыгы убактылуу төмөндөйт"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"КАБЫЛ АЛУУ"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ЧЕТКЕ КАГУУ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Баскычтопту өзгөртүү"</string>
@@ -1474,7 +1468,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Бошотуудан мурун PIN суралсын"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Бошотуудан мурун кулпуну ачкан үлгү суралсын"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Бошотуудан мурун сырсөз суралсын"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Колдонмонун көлөмүн өзгөртүүгө болбойт, андыктан эки манжаңыз менен сыдырып караңыз."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Колдонмодо экран бөлүнбөшү мүмкүн."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Колдонмодо экран бөлүнбөйт."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Администраторуңуз тарабынан орнотулган"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Администраторуңуз жаңырткан"</string>
@@ -1544,12 +1538,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> тандалды</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> тандалды</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Калган-каткандар"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Бул эскертмелердин маанилүүлүгүн белгиледиңиз."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Бул эскертмелердин маанилүүлүгүн белгиледиңиз."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Булар сиз үчүн маанилүү адамдар."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> колдонмосу <xliff:g id="ACCOUNT">%2$s</xliff:g> каттоо эсеби менен жаңы колдонуучу түзө берсинби ?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> колдонмосу <xliff:g id="ACCOUNT">%2$s</xliff:g> каттоо эсеби менен жаңы колдонуучу түзө берсинби (мындай каттоо эсеби бар колдонуучу мурунтан эле бар) ?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Тил жөндөөлөрү"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Тил кошуңуз"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Чөлкөмдүк жөндөөлөр"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Тилди киргизиңиз"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Сунушталган"</string>
@@ -1566,10 +1559,11 @@
<string name="user_encrypted_message" msgid="4923292604515744267">"Кулпусун ачуу үчүн таптаңыз"</string>
<string name="user_encrypted_detail" msgid="5708447464349420392">"Колдончнн дайындары кулпуланды"</string>
<string name="profile_encrypted_detail" msgid="3700965619978314974">"Жумуш профили кулпуланган"</string>
- <string name="profile_encrypted_message" msgid="6964994232310195874">"Таптап, жумуш профилин ачыңыз"</string>
+ <string name="profile_encrypted_message" msgid="6964994232310195874">"Таптап жумуш профилин ачыңыз"</string>
<string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> менен туташты"</string>
<string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Файлдарды көрүү үчүн таптап коюңуз"</string>
<string name="pin_target" msgid="3052256031352291362">"Кадоо"</string>
<string name="unpin_target" msgid="3556545602439143442">"Кадоодон алып коюу"</string>
<string name="app_info" msgid="6856026610594615344">"Колдонмо тууралуу"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-ldrtl-television/config.xml b/core/res/res/values-ldrtl-television/config.xml
new file mode 100644
index 0000000..e237acc
--- /dev/null
+++ b/core/res/res/values-ldrtl-television/config.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for TV products. Do not translate. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- Default bounds [left top right bottom] on screen for picture-in-picture windows. -->
+ <string translatable="false" name="config_defaultPictureInPictureBounds">"112 54 592 324"</string>
+
+</resources>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 0c146bd..abe9b3f 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"ໝາຍເລກຜູ່ໂທ ໄດ້ຮັບການຕັ້ງຄ່າເລີ່ມຕົ້ນເປັນ ບໍ່ຖືກຈຳກັດ. ການໂທຄັ້ງຕໍ່ໄປ: ບໍ່ຖືກຈຳກັດ."</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"ບໍ່ໄດ້ເປີດໃຊ້ບໍລິການ."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"ທ່ານບໍ່ສາມາດປ່ຽນແປງການຕັ້ງຄ່າ Caller ID"</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"ປ່ຽນການເຂົ້າເຖິງທີ່ຖືກຈຳກັດແລ້ວ"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"ບໍລິການຂໍ້ມູນຖືກບລັອກ."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"ບໍລິການສຸກເສີນຖືກບລັອກ."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"ບໍລິການການໂທຖືກປິດກັ້ນໄວ້."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"ຣີເຊັດ ແລະ ເລີ່ມແອັບໃໝ່"</string>
<string name="aerr_report" msgid="5371800241488400617">"ສົ່ງຄຳຕິຊົມ"</string>
<string name="aerr_close" msgid="2991640326563991340">"ປິດ"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"ປິດສຽງ"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"ປິດສຽງຈົນກວ່າວ່າອຸປະກອນເລີ່ມໃໝ່"</string>
<string name="aerr_wait" msgid="3199956902437040261">"ລໍຖ້າ"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"ປິດແອັບ"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"ສຳພັດສຳລັບທາງເລືອກເພີ່ມເຕີມ."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"ເຊື່ອມຕໍ່ການດີບັ໊ກຜ່ານ USB ແລ້ວ"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"ແຕະເພື່ອປິດການດີບັ໊ກຜ່ານ USB."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"ຜູ້ເບິ່ງແຍງລະບົບໄອທີຂອງທ່ານໄດ້ຮ້ອງຂໍລາຍງານຂໍ້ຜິດພາດເພື່ອຊ່ວຍແກ້ໄຂບັນຫາອຸປະກອນນີ້. ແອັບ ແລະ ຂໍ້ມູນອາດຖືກແບ່ງປັນ ແລະ ອຸປະກອນຂອງທ່ານອາດເຮັດວຽກຊ້າລົງຊົ່ວຄາວ."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"ຜູ້ເບິ່ງແຍງລະບົບໄອທີຂອງທ່ານໄດ້ຮ້ອງຂໍເອົາລາຍງານບັນຫາ ເພື່ອຊ່ວຍແກ້ໄຂບັນຫາໃຫ້ອຸປະກອນນີ້. ອາດຈະມີການແບ່ງປັນແອັບ ແລະ ຂໍ້ມູນນຳ."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"ນີ້ອາດຈະເຮັດໃຫ້ອຸປະກອນຂອງທ່ານຊ້າລົງຊົ່ວຄາວ"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ຍອມຮັບ"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ປະຕິເສດ"</string>
<string name="select_input_method" msgid="8547250819326693584">"ປ່ຽນແປ້ນພິມ"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ຖາມຫາ PIN ກ່ອນຍົກເລີກການປັກໝຸດ"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ຖາມຫາຮູບແບບປົດລັອກກ່ອນຍົກເລີກການປັກໝຸດ"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ຖາມຫາລະຫັດຜ່ານກ່ອນຍົກເລີກການປັກໝຸດ"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"ບໍ່ສາມາດປັບຂະໜາດແອັບໄດ້, ໃຫ້ເລື່ອນມັນໂດຍໃຊ້ນິ້ວມືສອງນິ້ວ."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"ແອັບອາດໃຊ້ບໍ່ໄດ້ກັບການແບ່ງໜ້າຈໍ."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ແອັບບໍ່ຮອງຮັບໜ້າຈໍແບບແຍກກັນ."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"ຜູ້ຄວບຄຸມຂອງທ່ານຕິດຕັ້ງໃສ່ແລ້ວ"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"ອັບເດດໂດຍຜູ້ຄວບຄຸມຂອງທ່ານແລ້ວ"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ຖືກເລືອກແລ້ວ</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ຖືກເລືອກແລ້ວ</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"ອື່ນໆ"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"ທ່ານຕັ້ງຄວາມສຳຄັນຂອງການແຈ້ງເຕືອນເຫຼົ່ານີ້."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"ທ່ານຕັ້ງຄວາມສຳຄັນຂອງການແຈ້ງເຕືອນເຫຼົ່ານີ້."</string>
<string name="importance_from_person" msgid="9160133597262938296">"ຂໍ້ຄວາມນີ້ສຳຄັນເນື່ອງຈາກບຸກຄົນທີ່ກ່ຽວຂ້ອງ."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"ອະນຸຍາດໃຫ້ <xliff:g id="APP">%1$s</xliff:g> ສ້າງຜູ້ໃຊ້ໃໝ່ສຳລັບ <xliff:g id="ACCOUNT">%2$s</xliff:g> ບໍ?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"ອະນຸຍາດໃຫ້ <xliff:g id="APP">%1$s</xliff:g> ສ້າງຜູ້ໃຊ້ໃໝ່ສຳລັບ <xliff:g id="ACCOUNT">%2$s</xliff:g> (ຜູ້ໃຊ້ສຳລັບບັນຊີນີ້ມີຢູ່ແລ້ວ) ບໍ?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"ການຕັ້ງຄ່າພາສາ"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"ເພີ່ມພາສາ"</string>
<string name="country_selection_title" msgid="2954859441620215513">"ການຕັ້ງຄ່າພາກພື້ນ"</string>
<string name="search_language_hint" msgid="7042102592055108574">"ພິມຊື່ພາສາ"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"ແນະນຳ"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"ປັກໝຸດ"</string>
<string name="unpin_target" msgid="3556545602439143442">"ຖອນປັກໝຸດ"</string>
<string name="app_info" msgid="6856026610594615344">"ຂໍ້ມູນແອັບ"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index e4d10ae..ecf45b7 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -90,7 +90,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Skambintojo ID pagal numatytuosius nustatymus yra neapribotas. Kitas skambutis: neapribotas"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Paslauga neteikiama."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Negalima pakeisti skambinančiojo ID nustatymo."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Apribota prieiga pakeista"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Duomenų paslauga užblokuota."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Pagalbos paslauga užblokuota."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Balso paslauga užblokuota."</string>
@@ -929,7 +928,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Nustatyti ir paleisti programą iš naujo"</string>
<string name="aerr_report" msgid="5371800241488400617">"Siųsti atsiliepimą"</string>
<string name="aerr_close" msgid="2991640326563991340">"Uždaryti"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Paslėpti"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Ignoruoti, kol įrenginys bus paleistas iš naujo"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Laukti"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Uždaryti programą"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1069,16 +1068,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Palieskite, kad būtų rodoma daugiau parinkčių."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB derinimas prijungtas"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Neleisti USB derinimo."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Bendrinti pranešimą apie riktą?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Bendrinamas pranešimas apie riktą..."</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Jūsų IT administratorius pateikė pranešimo apie riktą užklausą, kad galėtų padėti pašalinti triktis šiame įrenginyje. Programos bei duomenys gali būti bendrinami ir įrenginys gali laikinai lėčiau veikti."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Jūsų IT administratorius pateikė pranešimo apie riktą užklausą, kad galėtų padėti pašalinti triktis šiame įrenginyje. Programos ir duomenys gali būti bendrinami."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Dėl to įrenginys gali laikinai lėčiau veikti"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"SUTIKTI"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ATMESTI"</string>
<string name="select_input_method" msgid="8547250819326693584">"Klaviatūros keitimas"</string>
@@ -1493,7 +1487,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Prašyti PIN kodo prieš atsegant"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Prašyti atrakinimo piešinio prieš atsegant"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Prašyti slaptažodžio prieš atsegant"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Programos dydis nekeičiamas, slinkite dviem pirštais."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Programa gali neveikti naudojant skaidytą ekraną."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Programoje nepalaikomas skaidytas ekranas."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Įdiegė administratorius"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Atnaujino administratorius"</string>
@@ -1581,12 +1575,11 @@
<item quantity="many">Pasir. <xliff:g id="COUNT_1">%1$d</xliff:g> elem.</item>
<item quantity="other">Pasir. <xliff:g id="COUNT_1">%1$d</xliff:g> elem.</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Įvairūs"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Galite nustatyti šių pranešimų svarbą."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Galite nustatyti šių pranešimų svarbą."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Tai svarbu dėl susijusių žmonių."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Leisti „<xliff:g id="APP">%1$s</xliff:g>“ kurti naują <xliff:g id="ACCOUNT">%2$s</xliff:g> naudotoją?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Leisti „<xliff:g id="APP">%1$s</xliff:g>“ kurti naują <xliff:g id="ACCOUNT">%2$s</xliff:g> naudotoją (šią paskyrą naudojantis naudotojas jau yra)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Kalbos nuostata"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Pridėkite kalbą"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Regiono nuostata"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Įveskite kalbos pav."</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Siūloma"</string>
@@ -1609,4 +1602,5 @@
<string name="pin_target" msgid="3052256031352291362">"Prisegti"</string>
<string name="unpin_target" msgid="3556545602439143442">"Atsegti"</string>
<string name="app_info" msgid="6856026610594615344">"Programos informacija"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"–<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 2fda60c..a572093 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -89,7 +89,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Zvanītāja ID noklusējumi ir iestatīti uz Nav ierobežots. Nākamais zvans: nav ierobežots"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Pakalpojums netiek nodrošināts."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Zvanītāja ID iestatījumu nevar mainīt."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Ierobežotā piekļuve ir mainīta"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Datu pakalpojums ir bloķēts."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Ārkārtas pakalpojums ir bloķēts."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Balss pakalpojums ir bloķēts."</string>
@@ -923,7 +922,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Atiestatīt un restartēt lietotni"</string>
<string name="aerr_report" msgid="5371800241488400617">"Sūtīt atsauksmes"</string>
<string name="aerr_close" msgid="2991640326563991340">"Aizvērt"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Nerādīt"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Nerādīt, līdz ierīce tiks restartēta"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Gaidīt"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Aizvērt lietotni"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1061,16 +1060,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Citas opcijas"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB atkļūdošana ir pievienota."</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Iespējot USB atkļūdošanu."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vai kopīgot kļūdas pārskatu?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Notiek kļūdas pārskata kopīgošana…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Jūsu IT administrators pieprasīja kļūdas pārskatu, lai palīdzētu novērst problēmu šajā ierīcē. Var tikt kopīgotas lietotnes un dati, un jūsu ierīces darbība var īslaicīgi palēnināties."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Jūsu IT administrators pieprasīja kļūdas pārskatu, lai palīdzētu novērst problēmu šajā ierīcē. Var tikt kopīgotas lietotnes un dati."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Jūsu ierīces darbība var īslaicīgi palēnināties."</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"APSTIPRINĀT"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"NORAIDĪT"</string>
<string name="select_input_method" msgid="8547250819326693584">"Tastatūras maiņa"</string>
@@ -1483,7 +1477,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Prasīt PIN kodu pirms atspraušanas"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pirms atspraušanas pieprasīt grafisko atslēgu"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pirms atspraušanas pieprasīt paroli"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Lietotnes lielumu nevar mainīt. Ritiniet to ar diviem pirkstiem."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Iespējams, lietotnē nedarbosies ekrāna sadalīšana."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Lietotnē netiek atbalstīta ekrāna sadalīšana."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Instalēja jūsu administrators"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Atjaunināja administrators"</string>
@@ -1562,12 +1556,11 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> atlasīts</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> atlasīti</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Dažādi"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Jūs iestatījāt šo paziņojumu svarīguma līmeni."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Jūs iestatījāt šo paziņojumu svarīguma līmeni."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Tas ir svarīgi iesaistīto personu dēļ."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Vai atļaut lietotnei <xliff:g id="APP">%1$s</xliff:g> izveidot jaunu lietotāju, izmantojot e-pasta adresi <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Vai atļaut lietotnei <xliff:g id="APP">%1$s</xliff:g> izveidot jaunu lietotāju, izmantojot e-pasta adresi <xliff:g id="ACCOUNT">%2$s</xliff:g> (lietotājs ar šādu kontu jau pastāv)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Valodas preference"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Pievienot valodu"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Reģiona preference"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Ierakstiet valodas nosaukumu"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Ieteiktās"</string>
@@ -1590,4 +1583,5 @@
<string name="pin_target" msgid="3052256031352291362">"Piespraust"</string>
<string name="unpin_target" msgid="3556545602439143442">"Atspraust"</string>
<string name="app_info" msgid="6856026610594615344">"Lietotnes informācija"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index d4f1722..a5a4ba7 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Стандардно, повикувачот со овој ИД не е ограничен. Следен повик: не е ограничен"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Услугата не е предвидена."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Не може да го промените поставувањето за ИД на повикувач."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Ограничениот пристап е изменет"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Услугата за податоци е блокирана."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Услугата за итни повици е блокирана."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Услугата за гласовно бирање е блокирана."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Ресетирај ја и рестартирај ја апликацијата"</string>
<string name="aerr_report" msgid="5371800241488400617">"Испрати повратни информации"</string>
<string name="aerr_close" msgid="2991640326563991340">"Затвори"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Исклучи звук"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Исклучи го звукот додека уредот не се рестартира"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Почекај"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Затвори ја апликацијата"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Допри за повеќе опции."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Поврзано е отстранување грешки преку УСБ"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Допрете за да се оневозможи отстранувањето грешки преку USB."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"Администраторот за информатичка технологија побара извештај за грешки за да ви помогне во отстранувањето на грешките од уредот. Апликациите и податоците можеби ќе се споделат, а уредот можеби ќе биде привремено побавен при работата."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Вашиот администратор за информатичка технологија побара извештај за грешки за да помогне со отстранување на грешките на овој уред. Апликациите и податоците може да бидат споделени."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Ова може привремено да го забави уредот"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ПРИФАТИ"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ОДБИЈ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Измени тастатура"</string>
@@ -1475,7 +1469,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Прашај за ПИН пред откачување"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Прашај за шема за отклучување пред откачување"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Прашај за лозинка пред откачување"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Не може да се промени големината на апликацијата, лизгајте ја со два прста."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Апликацијата можеби нема да работи во поделен екран."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Апликацијата не поддржува поделен екран."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Инсталирано од администраторот"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Ажурирано од администраторот"</string>
@@ -1545,12 +1539,11 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> е избрана</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> се избрани</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Разно"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Ја поставивте важноста на известувањава."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Ја поставивте важноста на известувањава."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Ова е важно заради луѓето кои се вклучени."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Дозволувате ли <xliff:g id="APP">%1$s</xliff:g> да создаде нов корисник со <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Дозволувате ли <xliff:g id="APP">%1$s</xliff:g> да создаде нов корисник со <xliff:g id="ACCOUNT">%2$s</xliff:g> (веќе постои корисник со оваа сметка)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Претпочитувања за јазик"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Додај јазик"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Претпочитувања за регион"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Внеси име на јазик"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Предложени"</string>
@@ -1573,4 +1566,5 @@
<string name="pin_target" msgid="3052256031352291362">"Прикачете"</string>
<string name="unpin_target" msgid="3556545602439143442">"Откачете"</string>
<string name="app_info" msgid="6856026610594615344">"Информации за апликација"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index f4c7243..8a97930 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"നിയന്ത്രിക്കേണ്ടതല്ലാത്ത സ്ഥിര കോളർ ഐഡികൾ. അടുത്ത കോൾ: നിയന്ത്രിച്ചിട്ടില്ല"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"സേവനം വ്യവസ്ഥ ചെയ്തിട്ടില്ല."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"നിങ്ങൾക്ക് കോളർ ഐഡി ക്രമീകരണം മാറ്റാനാവില്ല."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"നിയന്ത്രിത ആക്സസ്സ് മാറ്റി"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"ഡാറ്റ സേവനം തടഞ്ഞു."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"അടിയന്തര സേവനം തടഞ്ഞു."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"വോയ്സ് സേവനം തടഞ്ഞു."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"ആപ്പ് പുനഃക്രമീകരിച്ച് പുനഃരാരംഭിക്കുക"</string>
<string name="aerr_report" msgid="5371800241488400617">"ഫീഡ്ബാക്ക് അയയ്ക്കുക"</string>
<string name="aerr_close" msgid="2991640326563991340">"അടയ്ക്കുക"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"മ്യൂട്ടുചെയ്യുക"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"ഉപകരണം പുനഃരാരംഭിക്കുന്നത് വരെ മ്യൂട്ടുചെയ്യുക"</string>
<string name="aerr_wait" msgid="3199956902437040261">"കാത്തിരിക്കുക"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"ആപ്പ് അടയ്ക്കുക"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"കൂടുതൽ ഓപ്ഷനുകൾക്ക് സ്പർശിക്കൂ."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB ഡീബഗ്ഗിംഗ് കണക്റ്റുചെയ്തു"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB ഡീബഗ്ഗിംഗ് ഓഫാക്കാൻ സ്പർശിക്കൂ."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"ഈ ഉപകരണവുമായി ബന്ധപ്പെട്ട പ്രശ്നം പരിഹരിക്കുന്നതിന് നിങ്ങളുടെ ഐടി അഡ്മിൻ ഒരു ബഗ് റിപ്പോർട്ട് അഭ്യർത്ഥിച്ചു. ആപ്സും ഡാറ്റയും പങ്കിടപ്പെട്ടേക്കും, നിങ്ങളുടെ ഉപകരണത്തെ ഇത് താൽക്കാലികമായി മന്ദഗതിയിലാക്കിയേക്കാം."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"ഈ ഉപകരണത്തിലെ പ്രശ്നം പരിഹരിക്കുന്നതിന് നിങ്ങളുടെ ഐടി അഡ്മിൻ ഒരു ബഗ് റിപ്പോർട്ട് അഭ്യർത്ഥിച്ചു. ആപ്സും ഡാറ്റയും പങ്കിടപ്പെട്ടേക്കും."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"നിങ്ങളുടെ ഉപകരണത്തെ ഇത് താൽക്കാലികമായി മന്ദഗതിയിലാക്കിയേക്കാം"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"അംഗീകരിക്കുക"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"നിരസിക്കുക"</string>
<string name="select_input_method" msgid="8547250819326693584">"കീബോഡ് മാറ്റുക"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ചെയ്യുംമുമ്പ് പിൻ ചോദിക്കൂ"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"അൺപിൻ ചെയ്യുന്നതിനുമുമ്പ് അൺലോക്ക് പാറ്റേൺ ആവശ്യപ്പെടുക"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"അൺപിൻ ചെയ്യുന്നതിനുമുമ്പ് പാസ്വേഡ് ആവശ്യപ്പെടുക"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"ആപ്പിന്റെ വലുപ്പം ക്രമീകരിക്കാൻ കഴിയില്ല, രണ്ട് വിരലുകൾ ഉപയോഗിച്ച് അത് സ്ക്രോൾ ചെയ്യുക."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"സ്പ്ലിറ്റ്-സ്ക്രീനിനൊപ്പം ആപ്പ് പ്രവർത്തിച്ചേക്കില്ല."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"സ്പ്ലിറ്റ്-സ്ക്രീനിനെ ആപ്പ് പിന്തുണയ്ക്കുന്നില്ല."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"നിങ്ങളുടെ അഡ്മിനിസ്ട്രേറ്റർ ഇൻസ്റ്റാളുചെയ്തു"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"നിങ്ങളുടെ അഡ്മിനിസ്ട്രേറ്റർ അപ്ഡേറ്റുചെയ്തു"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> തിരഞ്ഞെടുത്തു</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> തിരഞ്ഞെടുത്തു</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"പലവക"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"ഈ അറിയിപ്പുകളുടെ പ്രാധാന്യം നിങ്ങൾ സജ്ജീകരിച്ചു."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"ഈ അറിയിപ്പുകളുടെ പ്രാധാന്യം നിങ്ങൾ സജ്ജീകരിച്ചു."</string>
<string name="importance_from_person" msgid="9160133597262938296">"ഉൾപ്പെട്ടിട്ടുള്ള ആളുകളെ കണക്കിലെടുക്കുമ്പോള് ഇത് പ്രധാനപ്പെട്ടതാണ്."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="ACCOUNT">%2$s</xliff:g> എന്ന അക്കൗണ്ട് ഉപയോഗിച്ച് പുതിയൊരു ഉപയോക്താവിനെ സൃഷ്ടിക്കാൻ <xliff:g id="APP">%1$s</xliff:g> എന്ന ആപ്പിനെ അനുവദിക്കണോ?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="ACCOUNT">%2$s</xliff:g> എന്ന അക്കൗണ്ട് (ഈ അക്കൗണ്ട് ഉപയോഗിച്ചുള്ള ഒരു ഉപയോക്താവ് ഇതിനകം തന്നെ നിലവിലുണ്ട്) ഉപയോഗിച്ച് പുതിയൊരു ഉപയോക്താവിനെ സൃഷ്ടിക്കാൻ <xliff:g id="APP">%1$s</xliff:g> എന്ന ആപ്പിനെ അനുവദിക്കണോ?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"ഭാഷാ മുൻഗണന"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"ഒരു ഭാഷ ചേർക്കുക"</string>
<string name="country_selection_title" msgid="2954859441620215513">"മേഖലാ മുൻഗണന"</string>
<string name="search_language_hint" msgid="7042102592055108574">"ഭാഷയുടെ പേര് ടൈപ്പുചെയ്യുക"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"നിര്ദ്ദേശിച്ചത്"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"പിൻ ചെയ്യുക"</string>
<string name="unpin_target" msgid="3556545602439143442">"അൺപിൻ ചെയ്യുക"</string>
<string name="app_info" msgid="6856026610594615344">"ആപ്പ് വിവരം"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index aba5bc0..9950003 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Дуудлага хийгчийн ID хязгаарлагдсан. Дараагийн дуудлага: Хязгаарлагдсан"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Үйлчилгээ провишн хийгдээгүй ."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Та дуудлага хийгчийн ID тохиргоог солиж чадахгүй."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Хязгаарлагдсан хандалт өөрчлөгдөв"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Дата үйлчилгээ хаагдсан."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Яаралтай үйлчилгээ хаагдсан."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Дуут үйлчилгээ хориглогдсон."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Апп-ыг шинэчилж, дахин эхлүүлэх"</string>
<string name="aerr_report" msgid="5371800241488400617">"Санал хүсэлт илгээх"</string>
<string name="aerr_close" msgid="2991640326563991340">"Хаах"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Дуу хаах"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Төхөөрөмжийг дахин эхлүүлэх хүртэл дууг нь хаах"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Хүлээх"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Апп-ыг хаах"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Нэмэлт сонголтыг харахын тулд дарна."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB дебаг холбогдсон"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB дебагийг идэвхгүй болгох бол хүрнэ үү."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"Энэ төхөөрөмжийн асуудлыг шийдвэрлэхийнт тулд таны IT админ алдааны тайланг хүслээ. Апп болон өгөгдлийг хуваалцаж, таны төхөөрөмж бага зэрэг удаан ажиллаж болзошгүй."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Энэ төхөөрөмжийн асуудлыг шийдвэрлэхийн тулд таны IT админ алдааны тайланг хүслээ. Апп болон өгөгдлийг хуваалцсан байж болзошгүй."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Энэ нь таны төхөөрөмжийг түр хугацаанд удаашруулж болзошгүй"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ЗӨВШӨӨРӨХ"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ТАТГАЛЗАХ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Гарыг өөрчлөх"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Тогтоосныг суллахаас өмнө PIN асуух"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Тогтоосныг суллахаас өмнө түгжээ тайлах хээ асуух"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Тогтоосныг суллахаас өмнө нууц үг асуух"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Апп-ын хэмжээг өөрчлөх боломжгүй. Үүнийг 2 хуруугаар гүйлгэнэ үү."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Апп хуваагдсан дэлгэцэд ажиллахгүй."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Энэ апп нь дэлгэц хуваах тохиргоог дэмждэггүй."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Таны админ суулгасан байна"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Танай админ шинэчилсэн"</string>
@@ -1541,12 +1535,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> сонгосон</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> сонгосон</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Бусад"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Та эдгээр мэдэгдлийн ач холбогдлыг тогтоосон."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Та эдгээр мэдэгдлийн ач холбогдлыг тогтоосон."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Оролцсон хүмүүсээс шалтгаалан энэ нь өндөр ач холбогдолтой."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g>-г <xliff:g id="ACCOUNT">%2$s</xliff:g>-р шинэ Хэрэглэгч үүсгэхийг зөвшөөрөх үү?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g>-г <xliff:g id="ACCOUNT">%2$s</xliff:g>-р шинэ хэрэглэгч үүсгэхийг зөвшөөрөх үү (ийм бүртгэлтэй хэрэглэгч аль хэдийн байна) ?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Хэлний тохиргоо"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Хэл нэмэх"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Бүс нутгийн тохиргоо"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Улсын хэлийг бичнэ үү"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Санал болгосон"</string>
@@ -1569,4 +1562,5 @@
<string name="pin_target" msgid="3052256031352291362">"PIN"</string>
<string name="unpin_target" msgid="3556545602439143442">"Unpin"</string>
<string name="app_info" msgid="6856026610594615344">"Апп-н мэдээлэл"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index 1b1c7a8..968331a 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"कॉलर ID डीफॉल्ट रूपात प्रतिबंधित नाही वर सेट असतो. पुढील कॉल: प्रतिबंधित नाही"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"सेवेची तरतूद केलेली नाही."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"आपण कॉलर ID सेटिंग बदलू शकत नाही."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"प्रतिबंधित प्रवेश बदलला"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"डेटा सेवा अवरोधित केली आहे."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"आणीबाणी सेवा अवरोधित केली आहे."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"व्हॉइस सेवा अवरोधित केली आहे."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"अॅप रीसेट आणि रीस्टार्ट करा"</string>
<string name="aerr_report" msgid="5371800241488400617">"अभिप्राय पाठवा"</string>
<string name="aerr_close" msgid="2991640326563991340">"बंद करा"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"नि:शब्द करा"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"डिव्हाइस रीस्टार्ट होईपर्यंत नि:शब्द करा"</string>
<string name="aerr_wait" msgid="3199956902437040261">"प्रतीक्षा करा"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"अॅप बंद करा"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"अधिक पर्यायांसाठी स्पर्श करा."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB डीबग करणे कनेक्ट केले"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB डीबग करणे अक्षम करण्यासाठी स्पर्श करा."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"आपल्या IT प्रशासकाने या डिव्हाइसची समस्या निवारण करण्यात मदत करण्यासाठी एका दोष अहवालाची विनंती केली. अॅप्स आणि डेटा सामायिक केले जाऊ शकतात आणि आपले डिव्हाइस तात्पुरते धीमे होऊ शकते."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"आपल्या IT प्रशासकाने या डिव्हाइसच्या समस्येचे निवारण करण्यात मदत करण्यासाठी दोष अहवालाची विनंती केली. अॅप्स आणि डेटा सामायिक केला जाऊ शकतो."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"हे तात्पुरता आपले डिव्हाइस धिमे करू शकते."</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"स्वीकार करा"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"नकार द्या"</string>
<string name="select_input_method" msgid="8547250819326693584">"कीबोर्ड बदला"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"अनपिन करण्यापूर्वी पिन साठी विचारा"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"अनपिन करण्यापूर्वी अनलॉक नमुन्यासाठी विचारा"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"अनपिन करण्यापूर्वी संकेतशब्दासाठी विचारा"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"अॅपचा आकार बदलण्यायोग्य नाही, दोन बोटांनी तो स्क्रोल करा."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"अॅप कदाचित विभाजित-स्क्रीनसह कार्य करू शकत नाही."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"अॅप स्क्रीन-विभाजनास समर्थन देत नाही."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"आपल्या प्रशासकाद्वारे स्थापित केले आहे"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"आपल्या प्रशासकाद्वारे अद्यतनित केले"</string>
@@ -1543,12 +1537,11 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> निवडला</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> निवडले</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"संकीर्ण"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"आपण या सूचनांचे महत्त्व सेट केले."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"आपण या सूचनांचे महत्त्व सेट केले."</string>
<string name="importance_from_person" msgid="9160133597262938296">"सामील असलेल्या लोकांमुळे हे महत्वाचे आहे."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="ACCOUNT">%2$s</xliff:g> सह नवीन वापरकर्ता तयार करण्याची <xliff:g id="APP">%1$s</xliff:g> ला अनुमती द्यायची?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="ACCOUNT">%2$s</xliff:g> सह नवीन वापरकर्ता तयार करण्याची (हे खाते असलेला वापरकर्ता आधीपासून विद्यमान आहे) <xliff:g id="APP">%1$s</xliff:g> ला अनुमती द्यायची?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"भाषा प्राधान्य"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"एक भाषा जोडा"</string>
<string name="country_selection_title" msgid="2954859441620215513">"प्रदेश प्राधान्य"</string>
<string name="search_language_hint" msgid="7042102592055108574">"भाषा नाव टाइप करा"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"सूचित केलेले"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"पिन"</string>
<string name="unpin_target" msgid="3556545602439143442">"अनपिन करा"</string>
<string name="app_info" msgid="6856026610594615344">"अॅप माहिती"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index f174b7c..cd31b2b 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"ID pemanggil secara lalainya ditetapkan kepada tidak dihadkan. Panggilan seterusnya: Tidak terhad"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Perkhidmatan yang tidak diuntukkan."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Anda tidak boleh mengubah tetapan ID pemanggil."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Akses terhad diubah"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Perkhidmatan data disekat."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Perkhidmatan kecemasan disekat."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Perkhidmatan suara disekat."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Tetapkan semula dan mulakan semula apl"</string>
<string name="aerr_report" msgid="5371800241488400617">"Hantar maklum balas"</string>
<string name="aerr_close" msgid="2991640326563991340">"Tutup"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Redam"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Redam sehingga peranti dimulakan semula"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Tunggu"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Tutup apl"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Sentuh untuk mendapatkan lagi pilihan."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Penyahpepijatan USB disambungkan"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Sentuh untuk melumpuhkan penyahpepijatan USB."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Kongsi laporan pepijat?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Berkongsi laporan pepijat…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Pentadbir IT anda meminta laporan pepijat untuk membantu menyelesaikan masalah peranti ini. Apl dan data mungkin dikongsi dan peranti anda mungkin menjadi perlahan untuk sementara waktu."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Pentadbir IT anda meminta laporan pepijat untuk membantu menyelesaikan masalah peranti ini. Apl dan data mungkin dikongsi."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Proses ini mungkin memperlahankan peranti anda untuk sementara waktu"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"TERIMA"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"TOLAK"</string>
<string name="select_input_method" msgid="8547250819326693584">"Tukar papan kekunci"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Minta PIN sebelum menyahsemat"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Minta corak buka kunci sebelum menyahsemat"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Minta kata laluan sebelum menyahsemat"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Apl tidak boleh ditukar saiznya, tatal apl itu menggunakan dua jari."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Apl mungkin tidak berfungsi dengan skrin pisah."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Apl tidak menyokong skrin pisah."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Dipasang oleh pentadbir anda"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Dikemas kini oleh pentadbir anda"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> dipilih</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> dipilih</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Pelbagai"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Anda menetapkan kepentingan pemberitahuan ini."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Anda menetapkan kepentingan pemberitahuan ini."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Mesej ini penting disebabkan orang yang terlibat."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Benarkan <xliff:g id="APP">%1$s</xliff:g> membuat Pengguna baharu dengan <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Benarkan <xliff:g id="APP">%1$s</xliff:g> membuat Pengguna baharu dengan <xliff:g id="ACCOUNT">%2$s</xliff:g> (Pengguna dengan akaun ini sudah wujud)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Pilihan bahasa"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Tambahkan bahasa"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Pilihan wilayah"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Taipkan nama bahasa"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Dicadangkan"</string>
@@ -1561,7 +1554,7 @@
<string name="suspended_package_message" msgid="6341091587106868601">"Dilumpuhkan oleh pentadbir %1$s. Hubungi mereka untuk mengetahui lebih lanjut."</string>
<string name="new_sms_notification_title" msgid="8442817549127555977">"Anda mempunyai mesej baharu"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Buka apl SMS untuk melihat"</string>
- <string name="user_encrypted_title" msgid="9054897468831672082">"Beberapa fungsi mungkin terhad"</string>
+ <string name="user_encrypted_title" msgid="9054897468831672082">"Sesetengah fungsi mungkin terhad"</string>
<string name="user_encrypted_message" msgid="4923292604515744267">"Ketik untuk membuka kunci"</string>
<string name="user_encrypted_detail" msgid="5708447464349420392">"Data pengguna dikunci"</string>
<string name="profile_encrypted_detail" msgid="3700965619978314974">"Profil kerja dikunci"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Semat"</string>
<string name="unpin_target" msgid="3556545602439143442">"Nyahsemat"</string>
<string name="app_info" msgid="6856026610594615344">"Maklumat apl"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 6fe0c88..5cf2bd3 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"ပုံသေအားဖြင့် ခေါ်ဆိုသူအိုင်ဒီ(Caller ID)အား ကန့်သတ်မထားပါ။ နောက်ထပ်အဝင်ခေါ်ဆိုမှု-ကန့်သတ်မထားပါ။"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"ဝန်ဆောင်မှုအား ကန့်သတ်မထားပါ"</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"သင်သည် ခေါ်ဆိုသူ ID ဆက်တင်ကို မပြောင်းလဲနိုင်ပါ။"</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"ဝင်ရောက်ကြည့်ရှုခြင်းကန့်သတ်ချက်အားပြောင်းထားသည်"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"ဒေတာဝန်ဆောင်မှုပိတ်ထားသည်။"</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"အရေးပေါ်ဝန်ဆောင်မှုပိတ်ထားသည်။"</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"အသံဝန်ဆောင်မှုပိတ်ထားသည်။"</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"အက်ပ်ကို ပြန်လည်ပြင်ဆင်သတ်မှတ်ပြီး ပြန်လည်စတင်ပါ"</string>
<string name="aerr_report" msgid="5371800241488400617">"တုံ့ပြန်ချက်ပို့ပါ"</string>
<string name="aerr_close" msgid="2991640326563991340">"ပိတ်ပါ"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"အသံတိတ်ပါ"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"စက်ပစ္စည်း ပြန်လည်စတင်သည့်တိုင် အသံတိတ်ပါ"</string>
<string name="aerr_wait" msgid="3199956902437040261">"စောင့်ပါ"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"အက်ပ်ကိုပိတ်ပါ"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"ထပ်မံရွေးချယ်စရာများအတွက် ထိပါ"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB အမှားစစ်ခြင်းအား ချိတ်ဆက်ထားသည်"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB ဒီဘာဂင် ပိတ်ရန် ထိပါ။"</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"ဤစက်ပစ္စည်းကို ပြဿနာအဖြေရှာရာတွင် ကူညီရန် သင့်အိုင်တီစီမံခန့်ခွဲသူသည် ချွတ်ယွင်းချက်အစီရင်ခံစာကို တောင်းဆိုထားသည်။ အက်ပ်များနှင့် ဒေတာကိုမျှဝေထားနိုင်ပြီး သင့်စက်ပစ္စည်းကို ခေတ္တနှေးကွေးသွားစေနိုင်သည်။"</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"ဤစက်ပစ္စည်းကို ပြဿနာအဖြေရှာရာတွင် ကူညီရန် သင့်အိုင်တီစီမံခန့်ခွဲသူသည် ချွတ်ယွင်းချက်အစီရင်ခံစာကို တောင်းဆိုထားသည်။ အက်ပ်များနှင့် ဒေတာကိုမျှဝေထားနိုင်ပါသည်။"</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"၎င်းသည်သင့်စက်ပစ္စည်းကို ခေတ္တနှေးကွေးသွားစေနိုင်သည်"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"လက်ခံပါ"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ငြင်းပယ်ပါ"</string>
<string name="select_input_method" msgid="8547250819326693584">"ကီးဘုတ် ပြောင်းလဲရန်"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ပင်မဖြုတ်မီမှာ PIN ကို မေးကြည့်ရန်"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ပင်မဖြုတ်မီမှာ သော့ဖွင့် ရေးဆွဲမှုပုံစံကို မေးကြည့်ရန်"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ပင်မဖြုတ်မီမှာ စကားဝှက်ကို မေးကြည့်ရန်"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"အက်ပ်ကို အရွယ်အစားချိန်၍မရပါ၊ လက်ချောင်းနှစ်ချောင်းဖြင့် အပေါ်အောက်ဆွဲပါ။"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"မျက်နှာပြင် ခွဲခြမ်းပြသမှုဖြင့် အက်ပ်သည် အလုပ်လုပ်မည် မဟုတ်ပါ။"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"အက်ပ်သည် မျက်နှာပြင်ခွဲပြရန် ပံ့ပိုးထားခြင်းမရှိပါ။"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"သင့် အက်ဒမင်မှ သွင်းယူထား၏"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"သင့်စီမံခန့်ခွဲသူမှ အဆင့်မြှင့်ထားပါသည်။"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ရွေးချယ်ပြီးပါပြီ</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ရွေးချယ်ပြီးပါပြီ</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"အထွေထွေ"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"ဤအသိပေးချက်များ၏ အရေးပါမှုကိုသင်သတ်မှတ်ပြီးပါပြီ။"</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"ဤသတိပေးချက်များ၏ အရေးပါမှုကိုသတ်မှတ်ပြီးပါပြီ။"</string>
<string name="importance_from_person" msgid="9160133597262938296">"ပါဝင်သည့်လူများကြောင့် အရေးပါပါသည်။"</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> ကို <xliff:g id="ACCOUNT">%2$s</xliff:g> ဖြင့်အသုံးပြုသူအသစ်ဖန်တီးခွင့်ပြုမလား။"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> ကို <xliff:g id="ACCOUNT">%2$s</xliff:g> ဖြင့်အသုံးပြုသူအသစ် ဖန်တီးခွင့်ပြုမလား (ဤအကောင့်ဖြင့် အသုံးပြုသူ ရှိနှင့်ပြီးဖြစ်သည်)။"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"ဘာသာစကားရွေးချယ်မှု"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"ဘာသာစကားတစ်ခု ထည့်ပါ"</string>
<string name="country_selection_title" msgid="2954859441620215513">"ဒေသရွေးချယ်မှု"</string>
<string name="search_language_hint" msgid="7042102592055108574">"ဘာသာစကားအမည် ထည့်ပါ"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"အကြံပြုထားသော"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"တွဲပါ"</string>
<string name="unpin_target" msgid="3556545602439143442">"ဖြုတ်ပါ"</string>
<string name="app_info" msgid="6856026610594615344">"အက်ပ်အချက်အလက်"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 3c7bfe3..7ed5518 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Nummervisning er ikke begrenset som standard. Neste anrop: Ikke begrenset"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"SIM-kortet er ikke tilrettelagt for tjenesten."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Du kan ikke endre innstillingen for anrops-ID."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Tilgangsbegrensning endret"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Datatjenesten er blokkert."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Nødtjenesten er blokkert."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Taletjenesten er blokkert."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Tilbakestill appen, og start den på nytt"</string>
<string name="aerr_report" msgid="5371800241488400617">"Send tilbakemelding"</string>
<string name="aerr_close" msgid="2991640326563991340">"Lukk"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Ignorer"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Ignorer frem til enheten starter på nytt"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Vent"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Lukk app"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Trykk for å se flere alternativer."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB-feilsøking tilkoblet"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Trykk for å slå av USB-feilsøking."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vil du dele feilrapporten?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Deler feilrapporten …"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"IT-administratoren har bedt om en feilrapport for å hjelpe med feilsøkingen på denne enheten. Appene og dataene kan bli delt. Dette kan midlertidig gjøre enheten din tregere."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"IT-administratoren har bedt om en feilrapport for å hjelpe med feilsøkingen på denne enheten. Appene og dataene kan bli delt."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Dette kan midlertidig gjøre enheten din tregere"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"GODTA"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"AVSLÅ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Endre tastatur"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"PIN-kode for å løsne apper"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Krev bruk av opplåsningsmønster for å løsne apper"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Krev passord for å løsne apper"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Du kan ikke endre størrelse på appen – rull med to fingre."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Det kan hende at appen ikke fungerer med delt skjerm."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Appen støtter ikke delt skjerm."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Installert av administratoren"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Oppdatert av administratoren"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> er valgt</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> er valgt</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Diverse"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Du angir viktigheten for disse varslene."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Du angir viktigheten for disse varslene."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Dette er viktig på grunn av folkene som er involvert."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Vil du la <xliff:g id="APP">%1$s</xliff:g> opprette en ny bruker med <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Vil du la <xliff:g id="APP">%1$s</xliff:g> opprette en ny bruker med <xliff:g id="ACCOUNT">%2$s</xliff:g>? (Det finnes allerede en bruker med denne kontoen.)"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Språkinnstilling"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Legg til et språk"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Regionsinnstilling"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Skriv inn språknavn"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Foreslått"</string>
@@ -1573,4 +1566,5 @@
<string name="pin_target" msgid="3052256031352291362">"Fest"</string>
<string name="unpin_target" msgid="3556545602439143442">"Løsne"</string>
<string name="app_info" msgid="6856026610594615344">"Info om appen"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index 3379af7..6291551 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"कलर ID पूर्वनिर्धारितको लागि रोकावट छैन। अर्को कल: रोकावट छैन"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"सेवाको व्यवस्था छैन।"</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"तपाईँ कलर ID सेटिङ परिवर्तन गर्न सक्नुहुन्न।"</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"प्रतिबन्धित पहुँच परिवर्तन भएको छ"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"डेटा सेवा रोकिएको छ।"</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"आपतकालीन सेवा रोकिएको छ।"</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"भ्वाइस सेवा ब्लक भएको छ।"</string>
@@ -923,7 +922,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"अनुप्रयोगलाई रिसेट गरी पुन: सुरु गर्नुहोस्"</string>
<string name="aerr_report" msgid="5371800241488400617">"प्रतिक्रिया पठाउनुहोस्"</string>
<string name="aerr_close" msgid="2991640326563991340">"बन्द गर्नुहोस्"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"म्यूट गर्नुहोस्"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"यन्त्र पुनः सुरु नभएसम्म म्यूट गर्नुहोस्"</string>
<string name="aerr_wait" msgid="3199956902437040261">"पर्खनुहोस्"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"अनुप्रयोग बन्द गर्नुहोस्"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1059,16 +1058,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"थप विकल्पहरूका लागि छुनुहोस्।"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB डिबग गर्ने जडित छ"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB डिबग गर्ने असक्षम पार्न छुनुहोस्।"</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"तपाईंको IT प्रशासकले यो यन्त्रको समस्या निवारण गर्नमा मद्दत गर्न बग रिपोर्टहरूका लागि अनुरोध गर्नु भएको छ । अनुप्रयोगहरू र डेटा साझेदारी गर्न सकिन्छ र तपाईंको यन्त्र अस्थायी रूपमा सुस्त हुन सक्छ।"</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"तपाईंको IT प्रशासकले यो यन्त्रको समस्या निवारण गर्नमा मदत गर्न बग रिपोर्टहरूका लागि अनुरोध गर्नु भएको छ । Apps र डेटा साझेदारी गर्न सक्नुहुन्छ ।"</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"यसले अस्थायी रूपमा तपाईंको यन्त्रलाई सुस्त बनाउन सक्छ"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"स्वीकार गर्नुहोस्"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"अस्वीकार गर्नुहोस्"</string>
<string name="select_input_method" msgid="8547250819326693584">"कुञ्जीपाटी परिवर्तन गर्नुहोस्"</string>
@@ -1479,7 +1473,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"पिन निकाल्नुअघि PIN सोध्नुहोस्"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"पिन निकाल्नुअघि खोल्ने रूपरेखा सोध्नुहोस्"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"पिन निकाल्नुअघि पासवर्ड सोध्नुहोस्"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"अनुप्रयोगको आकार सानो-ठूलो बनाउन मिल्दैन, दुई औँलाले यसलाई स्क्रोल गर्नुहोस्।"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"अनुप्रयोगले विभाजित-स्क्रिनमा काम नगर्न सक्छ।"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"अनुप्रयोगले विभाजित-स्क्रिनलाई समर्थन गर्दैन।"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"तपाईँको प्रशासकद्वारा स्थापना गरिएको"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"तपाईँको प्रशासकद्वारा अद्यावधिक गरिएको"</string>
@@ -1549,12 +1543,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> चयन गरियो</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> चयन गरियो</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"विविध"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"तपाईंले यी सूचनाहरूको महत्त्व सेट गर्नुहुन्छ।"</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"तपाईंले यी सूचनाहरूको महत्त्व सेट गर्नुहोस् ।"</string>
<string name="importance_from_person" msgid="9160133597262938296">"यसमा सङ्लग्न भएका मानिसहरूको कारणले गर्दा यो महत्वपूर्ण छ।"</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="ACCOUNT">%2$s</xliff:g> सँगै नयाँ प्रयोगकर्ता सिर्जना गर्न <xliff:g id="APP">%1$s</xliff:g> लाई अनुमति दिने हो?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="ACCOUNT">%2$s</xliff:g> सँगै नयाँ प्रयोगकर्ता सिर्जना गर्न <xliff:g id="APP">%1$s</xliff:g> लाई अनुमति दिने (यस खाताको प्रयोगकर्ता पहिले नै अवस्थित छ) ?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"भाषाको प्राथमिकता"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"भाषा थप्नुहोस्"</string>
<string name="country_selection_title" msgid="2954859441620215513">"क्षेत्रको प्राथमिकता"</string>
<string name="search_language_hint" msgid="7042102592055108574">"भाषाको नाम टाइप गर्नुहोस्"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"सुझाव दिइयो"</string>
@@ -1570,11 +1563,12 @@
<string name="user_encrypted_title" msgid="9054897468831672082">"केही कार्य सीमित हुनसक्छ"</string>
<string name="user_encrypted_message" msgid="4923292604515744267">"अनलक गर्न ट्याप गर्नुहोस्"</string>
<string name="user_encrypted_detail" msgid="5708447464349420392">"प्रयोगकर्ताको डेटा लक गरियो"</string>
- <string name="profile_encrypted_detail" msgid="3700965619978314974">"कार्य प्रोफाइल बन्द भयो"</string>
+ <string name="profile_encrypted_detail" msgid="3700965619978314974">"कार्य प्रोफाइल लक भयो"</string>
<string name="profile_encrypted_message" msgid="6964994232310195874">"कार्य प्रोफाइल अनलक गर्न ट्याप गर्नुहोस्"</string>
<string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> मा जडान गरिएको छ"</string>
<string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"फाइलहरू हेर्न ट्याप गर्नुहोस्"</string>
<string name="pin_target" msgid="3052256031352291362">"पिन गर्नुहोस्"</string>
<string name="unpin_target" msgid="3556545602439143442">"अनपिन गर्नुहोस्"</string>
<string name="app_info" msgid="6856026610594615344">"अनुप्रयोगका बारे जानकारी"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index ad987a2..404fdb4 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Beller-id standaard ingesteld op \'onbeperkt\'. Volgende oproep: onbeperkt."</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Service niet voorzien."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"U kunt de instelling voor de beller-id niet wijzigen."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Beperkte toegang gewijzigd"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Gegevensservice is geblokkeerd."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Alarmservice is geblokkeerd."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Spraakservice is geblokkeerd."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"App resetten en opnieuw starten"</string>
<string name="aerr_report" msgid="5371800241488400617">"Feedback verzenden"</string>
<string name="aerr_close" msgid="2991640326563991340">"Sluiten"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Negeren"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Verbergen tot apparaat opnieuw wordt opgestart"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Wachten"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"App sluiten"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Tik voor meer opties."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB-foutopsporing verbonden"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Tik om USB-foutopsporing uit te schakelen."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Bugrapport delen?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Bugrapport delen…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Je IT-beheerder heeft een bugrapport aangevraagd om problemen met dit apparaat op te lossen. Apps en gegevens kunnen worden gedeeld en je apparaat kan hierdoor tijdelijk worden vertraagd."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Je IT-beheerder heeft een bugrapport aangevraagd om problemen met dit apparaat op te lossen. Apps en gegevens kunnen worden gedeeld."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Dit kan je apparaat tijdelijk vertragen"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACCEPTEREN"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"WEIGEREN"</string>
<string name="select_input_method" msgid="8547250819326693584">"Toetsenbord wijzigen"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Vraag pin voor losmaken"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Vraag patroon voor losmaken"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Vraag wachtwoord voor losmaken"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Formaat van app kan niet worden aangepast, scrol met twee vingers."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"App werkt mogelijk niet met gesplitst scherm."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"App biedt geen ondersteuning voor gesplitst scherm."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Geïnstalleerd door je beheerder"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Geüpdatet door je beheerder"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> geselecteerd</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> geselecteerd</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Diversen"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Je stelt het belang van deze meldingen in."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Je stelt het belang van deze meldingen in."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Dit is belangrijk vanwege de betrokken mensen."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Toestaan dat <xliff:g id="APP">%1$s</xliff:g> een nieuwe gebruiker met <xliff:g id="ACCOUNT">%2$s</xliff:g> maakt?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Toestaan dat <xliff:g id="APP">%1$s</xliff:g> een nieuwe gebruiker met <xliff:g id="ACCOUNT">%2$s</xliff:g> maakt (er is al een gebruiker met dit account)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Taalvoorkeur"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Een taal toevoegen"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Regiovoorkeur"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Typ een taalnaam"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Voorgesteld"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Vastzetten"</string>
<string name="unpin_target" msgid="3556545602439143442">"Losmaken"</string>
<string name="app_info" msgid="6856026610594615344">"App-info"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index be6ddde..fa181da 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"ਪ੍ਰਤਿਬੰਧਿਤ ਨਾ ਕਰਨ ਲਈ ਕਾਲਰ ID ਡਿਫੌਲਟਸ। ਅਗਲੀ ਕਾਲ: ਪ੍ਰਤਿਬੰਧਿਤ ਨਹੀਂ"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"ਸੇਵਾ ਪ੍ਰਬੰਧਿਤ ਨਹੀਂ ਹੈ।"</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"ਤੁਸੀਂ ਕਾਲਰ ID ਸੈਟਿੰਗ ਨਹੀਂ ਬਦਲ ਸਕਦੇ।"</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"ਪ੍ਰਤਿਬੰਧਿਤ ਪਹੁੰਚ ਬਦਲੀ ਗਈ"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"ਡਾਟਾ ਸੇਵਾ ਬਲੌਕ ਕੀਤੀ ਹੋਈ ਹੈ।"</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"ਐਮਰਜੈਂਸੀ ਸੇਵਾ ਬਲੌਕ ਕੀਤੀ ਹੋਈ ਹੈ।"</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"ਵੌਇਸ ਸੇਵਾ ਬਲੌਕ ਕੀਤੀ ਹੋਈ ਹੈ।"</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"ਐਪ ਨੂੰ ਰੀਸੈੱਟ ਅਤੇ ਮੁੜ-ਚਾਲੂ ਕਰੋ"</string>
<string name="aerr_report" msgid="5371800241488400617">"ਪ੍ਰਤੀਕਰਮ ਭੇਜੋ"</string>
<string name="aerr_close" msgid="2991640326563991340">"ਬੰਦ ਕਰੋ"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"ਮਿਊਟ ਕਰੋ"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"ਡੀਵਾਈਸ ਦੇ ਮੁੜ-ਚਾਲੂ ਹੋਣ ਤੱਕ ਮਿਊਟ ਕਰੋ"</string>
<string name="aerr_wait" msgid="3199956902437040261">"ਉਡੀਕ ਕਰੋ"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"ਐਪ ਬੰਦ ਕਰੋ"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"ਹੋਰ ਵਿਕਲਪਾਂ ਲਈ ਸਪਰਸ਼ ਕਰੋ।"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB ਡੀਬਗਿੰਗ ਕਨੈਕਟ ਕੀਤੀ"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB ਡੀਬਗਿੰਗ ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਉਣ ਲਈ ਛੋਹਵੋ।"</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"ਤੁਹਾਡੇ IT ਪ੍ਰਸ਼ਾਸਕ ਨੇ ਇਸ ਡੀਵਾਈਸ ਦੀ ਸਮੱਸਿਆ ਨੂੰ ਠੀਕ ਕਰਨ ਵਿੱਚ ਮਦਦ ਲਈ ਬੱਗ ਰਿਪੋਰਟ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਹੈ। ਐਪਾਂ ਅਤੇ ਡੈਟੇ ਨੂੰ ਸਾਂਝਾ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ ਅਤੇ ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਆਰਜ਼ੀ ਤੌਰ \'ਤੇ ਹੌਲੀ ਹੋ ਸਕਦੀ ਹੈ।"</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"ਤੁਹਾਡੇ IT ਪ੍ਰਸ਼ਾਸਕ ਨੇ ਇਸ ਡੀਵਾਈਸ ਦੀ ਸਮੱਸਿਆ ਨੂੰ ਠੀਕ ਕਰਨ ਵਿੱੱਚ ਮਦਦ ਲਈ ਬੱਗ ਰਿਪੋਰਟ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਹੈ। ਐਪਾਂ ਅਤੇ ਡੈਟੇ ਨੂੰ ਸਾਂਝਾ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ।"</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"ਇਹ ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਨੂੰ ਆਰਜ਼ੀ ਤੌਰ \'ਤੇ ਹੌਲੀ ਕਰ ਸਕਦਾ ਹੈ"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ਸਵੀਕਾਰ ਕਰੋ"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ਅਸਵੀਕਾਰ ਕਰੋ"</string>
<string name="select_input_method" msgid="8547250819326693584">"ਕੀਬੋਰਡ ਬਦਲੋ"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ਅਨਪਿਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ PIN ਮੰਗੋ"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ਅਨਪਿਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਪੈਟਰਨ ਅਨਲੌਕ ਕਰਨ ਲਈ ਪੁੱਛੋ"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ਅਨਪਿਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਪਾਸਵਰਡ ਮੰਗੋ"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"ਐਪ ਦਾ ਆਕਾਰ ਬਦਲਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ, ਇਸ ਨੂੰ ਦੋ ਉਂਗਲਾਂ ਨਾਲ ਸਕਰੋਲ ਕਰੋ।"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਐਪ ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਨਾਲ ਕੰਮ ਨਾ ਕਰੇ।"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ਐਪ ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਨੂੰ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੀ।"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"ਤੁਹਾਡੇ ਪ੍ਰਬੰਧਕ ਵੱਲੋਂ ਇੰਸਟੌਲ ਕੀਤਾ ਗਿਆ"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਦੁਆਰਾ ਅਪਡੇਟ ਕੀਤਾ ਗਿਆ"</string>
@@ -1543,12 +1537,11 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ਚੁਣਿਆ ਗਿਆ</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ਚੁਣਿਆ ਗਿਆ</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"ਵਿਵਿਧ"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"ਤੁਸੀਂ ਇਹਨਾਂ ਸੂਚਨਾਵਾਂ ਦੀ ਮਹੱਤਤਾ ਸੈੱਟ ਕੀਤੀ।"</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"ਤੁਸੀਂ ਇਹਨਾਂ ਸੂਚਨਾਵਾਂ ਦੀ ਮਹੱਤਤਾ ਸੈੱਟ ਕੀਤੀ।"</string>
<string name="importance_from_person" msgid="9160133597262938296">"ਇਹ ਸ਼ਾਮਲ ਲੋਕਾਂ ਦੇ ਕਾਰਨ ਮਹੱਤਵਪੂਰਨ ਹੈ।"</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"ਕੀ <xliff:g id="APP">%1$s</xliff:g> ਨੂੰ <xliff:g id="ACCOUNT">%2$s</xliff:g> ਨਾਲ ਇੱਕ ਨਵਾਂ ਵਰਤੋਂਕਾਰ ਬਣਾਉਣ ਦੀ ਮਨਜ਼ੂਰੀ ਦੇਣੀ ਹੈ?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"ਕੀ <xliff:g id="APP">%1$s</xliff:g> ਨੂੰ <xliff:g id="ACCOUNT">%2$s</xliff:g> ਨਾਲ ਇੱਕ ਨਵਾਂ ਵਰਤੋਂਕਾਰ ਬਣਾਉਣ ਦੀ ਮਨਜ਼ੂਰੀ ਦੇਣੀ ਹੈ (ਇਸ ਖਾਤੇ ਨਾਲ ਇੱਕ ਵਰਤੋਂਕਾਰ ਪਹਿਲਾਂ ਤੋਂ ਹੀ ਮੌਜੂਦ ਹੈ) ?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"ਭਾਸ਼ਾ ਤਰਜੀਹ"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"ਇੱਕ ਭਾਸ਼ਾ ਸ਼ਾਮਲ ਕਰੋ"</string>
<string name="country_selection_title" msgid="2954859441620215513">"ਖੇਤਰ ਤਰਜੀਹ"</string>
<string name="search_language_hint" msgid="7042102592055108574">"ਭਾਸ਼ਾ ਨਾਮ ਟਾਈਪ ਕਰੋ"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"ਸੁਝਾਈਆਂ ਗਈਆਂ"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"ਪਿੰਨ ਕਰੋ"</string>
<string name="unpin_target" msgid="3556545602439143442">"ਅਨਪਿੰਨ ਕਰੋ"</string>
<string name="app_info" msgid="6856026610594615344">"ਐਪ ਜਾਣਕਾਰੀ"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 4700873..d1441bd 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -90,7 +90,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"ID rozmówcy ustawiony jest domyślnie na „nie zastrzeżony”. Następne połączenie: nie zastrzeżony"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Usługa nie jest świadczona."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Nie możesz zmienić ustawienia ID rozmówcy."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Zmieniono ograniczenie dostępu"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Usługa transmisji danych jest zablokowana."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Usługa połączeń alarmowych jest zablokowana."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Usługa głosowa jest zablokowana."</string>
@@ -929,7 +928,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Zresetuj aplikację i uruchom ją ponownie"</string>
<string name="aerr_report" msgid="5371800241488400617">"Prześlij opinię"</string>
<string name="aerr_close" msgid="2991640326563991340">"Zamknij"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Ignoruj"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Ignoruj do momentu ponownego uruchomienia urządzenia"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Zaczekaj"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Zamknij aplikację"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1069,16 +1068,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Kliknij, by zobaczyć więcej opcji."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Podłączono moduł debugowania USB"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Dotknij, aby wyłączyć debugowanie USB."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Udostępnić raport o błędzie?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Udostępniam raport o błędzie…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Administrator poprosił o raport o błędzie, by szybciej rozwiązać problemy na tym urządzeniu. Raport może zawierać informacje o aplikacjach i inne dane. Urządzenie może przez chwilę działać wolniej."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Administrator poprosił o raport o błędzie, który pomoże w rozwiązaniu problemów na tym urządzeniu. Mogą zostać udostępnione aplikacje i dane."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Urządzenie może przez chwilę działać wolniej"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"AKCEPTUJ"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ODRZUĆ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Zmień klawiaturę"</string>
@@ -1493,7 +1487,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Podaj PIN, aby odpiąć"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Aby odpiąć, poproś o wzór odblokowania"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Aby odpiąć, poproś o hasło"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Rozmiaru tej aplikacji nie można zmienić. Przewiń ją dwoma palcami."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikacja może nie działać przy podzielonym ekranie."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikacja nie obsługuje dzielonego ekranu."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Zainstalowany przez administratora"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Zaktualizowane przez administratora"</string>
@@ -1581,12 +1575,11 @@
<item quantity="other">Wybrano <xliff:g id="COUNT_1">%1$d</xliff:g></item>
<item quantity="one">Wybrano <xliff:g id="COUNT_0">%1$d</xliff:g></item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Inne"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Ustawiłeś ważność tych powiadomień."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Ustawiłeś ważność tych powiadomień."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Ta wiadomość jest ważna ze względu na osoby uczestniczące w wątku."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Zezwalasz aplikacji <xliff:g id="APP">%1$s</xliff:g> na utworzenie nowego użytkownika dla konta <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Zezwalasz aplikacji <xliff:g id="APP">%1$s</xliff:g> na utworzenie nowego użytkownika dla konta <xliff:g id="ACCOUNT">%2$s</xliff:g>)? Użytkownik z tym kontem już istnieje."</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Ustawienie języka"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Dodaj język"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Ustawienie regionu"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Wpisz nazwę języka"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugerowane"</string>
@@ -1609,4 +1602,5 @@
<string name="pin_target" msgid="3052256031352291362">"Przypnij"</string>
<string name="unpin_target" msgid="3556545602439143442">"Odepnij"</string>
<string name="app_info" msgid="6856026610594615344">"O aplikacji"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 478165c..b444e0a 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"O ID do chamador assume o padrão de não restrito. Próxima chamada: Não restrita"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"O serviço não foi habilitado."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Não é possível alterar a configuração de identificação de chamadas."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Acesso restrito alterado"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"O serviço de dados está bloqueado."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"O serviço de emergência está bloqueado."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"O serviço de voz está bloqueado."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Redefinir e reiniciar app"</string>
<string name="aerr_report" msgid="5371800241488400617">"Enviar feedback"</string>
<string name="aerr_close" msgid="2991640326563991340">"Fechar"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Ignorar"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Desativar até que dispositivo seja reiniciado"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Aguarde"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Fechar app"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Toque para ver mais opções."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Depuração USB conectada"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Toque para desativar a depuração do USB."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Compartilhar relatório do bug?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartilhando relatório do bug…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Seu administrador de TI solicitou um relatório de bug para ajudar a resolver problemas deste dispositivo. É possível que apps e dados sejam compartilhados, o que pode deixar seu dispositivo temporariamente mais lento."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Seu administrador de TI solicitou um relatório de bug para ajudar a resolver problemas deste dispositivo. É possível que apps e dados sejam compartilhados."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Isso pode deixar seu dispositivo temporariamente mais lento"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACEITAR"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"RECUSAR"</string>
<string name="select_input_method" msgid="8547250819326693584">"Alterar teclado"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Pedir PIN antes de liberar"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pedir padrão de desbloqueio antes de liberar"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pedir senha antes de liberar"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"O app não é redimensionável. Desloque-o com dois dedos."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"É possível que o app não funcione com o recurso de divisão de tela."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"O app não é compatível com a divisão de tela."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Instalado pelo seu administrador"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Atualizado pelo administrador"</string>
@@ -1543,12 +1537,11 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Diversos"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Você definiu a importância dessas notificações."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Você definiu a importância dessas notificações."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Isso é importante por causa das pessoas envolvidas."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Permitir que <xliff:g id="APP">%1$s</xliff:g> crie um novo usuário com <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Permitir que <xliff:g id="APP">%1$s</xliff:g> crie um novo usuário com <xliff:g id="ACCOUNT">%2$s</xliff:g> (já existe um usuário com essa conta)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Preferência de idioma"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Adicionar um idioma"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Preferência de região"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Digitar nome do idioma"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugeridos"</string>
@@ -1565,10 +1558,11 @@
<string name="user_encrypted_message" msgid="4923292604515744267">"Toque para desbloquear"</string>
<string name="user_encrypted_detail" msgid="5708447464349420392">"Dados do usuário bloqueados"</string>
<string name="profile_encrypted_detail" msgid="3700965619978314974">"Perfil de trabalho bloqueado"</string>
- <string name="profile_encrypted_message" msgid="6964994232310195874">"Toque para desbloquear perfil de trabalho"</string>
+ <string name="profile_encrypted_message" msgid="6964994232310195874">"Toque p/ desbl. perfil de trab."</string>
<string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Conectado a <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Toque para ver os arquivos"</string>
<string name="pin_target" msgid="3052256031352291362">"Fixar guia"</string>
<string name="unpin_target" msgid="3556545602439143442">"Liberar guia"</string>
<string name="app_info" msgid="6856026610594615344">"Informações do app"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 038bfe9..4a5b005 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"ID do autor da chamada é predefinido com não restrito. Chamada seguinte: Não restrita"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Serviço não fornecido."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Não pode alterar a definição da identificação de chamadas."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Acesso restrito modificado"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"O serviço de dados está bloqueado."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"O serviço de emergência está bloqueado."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"O serviço de voz está bloqueado."</string>
@@ -339,7 +338,7 @@
<string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Permite à aplicação modificar o registo de chamadas do tablet, incluindo os dados sobre as chamadas recebidas e efetuadas. As aplicações maliciosas podem utilizar esta funcionalidade para apagar ou modificar o registo de chamadas."</string>
<string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"Permite à aplicação modificar o registo de chamadas da sua TV, incluindo os dados sobre as chamadas recebidas e efetuadas. As aplicações maliciosas podem utilizar esta funcionalidade para apagar ou modificar o registo de chamadas."</string>
<string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Permite à aplicação modificar o registo de chamadas do telemóvel, incluindo os dados sobre as chamadas recebidas e efetuadas. As aplicações maliciosas podem utilizar esta funcionalidade para apagar ou modificar o seu registo de chamadas."</string>
- <string name="permlab_bodySensors" msgid="4683341291818520277">"aceder a sensores corp. (como monit. do ritmo cardíaco)"</string>
+ <string name="permlab_bodySensors" msgid="4683341291818520277">"aceder a sensores corporais (como monitores do ritmo cardíaco)"</string>
<string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Permite que a aplicação aceda a dados de sensores que monitorizam a sua condição física, como o ritmo cardíaco."</string>
<string name="permlab_readCalendar" msgid="5972727560257612398">"ler eventos do calendário, para além de informações confidenciais"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"Permite que a aplicação leia todos os eventos do calendário guardados no tablet, incluindo os de amigos ou colegas de trabalho. Pode permitir que a aplicação partilhe ou guarde dados do calendário, independentemente da confidencialidade ou sensibilidade."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Repor e reiniciar aplicação"</string>
<string name="aerr_report" msgid="5371800241488400617">"Enviar comentários"</string>
<string name="aerr_close" msgid="2991640326563991340">"Fechar"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Ignorar"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Desativar som até o dispositivo reiniciar"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Aguardar"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Fechar aplicação"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Toque para ver mais opções."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Depuração USB ligada"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Toque para desat. a depuração USB."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Pretende partilhar o relatório de erro?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"A partilhar relatório de erro…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"O seu administrador de TI solicitou um relatório de erro para ajudar na resolução de problemas deste dispositivo. As aplicações e os dados podem ser partilhados e o dispositivo pode tornar-se temporariamente mais lento."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"O seu administrador de TI solicitou um relatório de erro para ajudar na resolução de problemas deste dispositivo. As aplicações e os dados podem ser partilhados."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Esta ação pode tornar o dispositivo mais lento temporariamente"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACEITAR"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"RECUSAR"</string>
<string name="select_input_method" msgid="8547250819326693584">"Alterar teclado"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Pedir PIN antes de soltar"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pedir sequência de desbloqueio antes de soltar"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pedir palavra-passe antes de soltar"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"A aplicação não é redimensionável. Desloque-a com dois dedos."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"A aplicação pode não funcionar com o ecrã dividido."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"A aplicação não é compatível com o ecrã dividido."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Instalado pelo administrador"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Atualizado pelo administrador"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selecionado</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Diversos"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Definiu a importância destas notificações."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Definiu a importância destas notificações."</string>
<string name="importance_from_person" msgid="9160133597262938296">"É importante devido às pessoas envolvidas."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Pretende permitir que o <xliff:g id="APP">%1$s</xliff:g> crie um novo utilizador com <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Pretende permitir que o <xliff:g id="APP">%1$s</xliff:g> crie um novo utilizador com <xliff:g id="ACCOUNT">%2$s</xliff:g> (já existe um utilizador com esta conta)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Preferência de idioma"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Adicionar um idioma"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Preferência de região"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Intr. nome do idioma"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugeridos"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Fixar"</string>
<string name="unpin_target" msgid="3556545602439143442">"Soltar"</string>
<string name="app_info" msgid="6856026610594615344">"Informações da aplicação"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 478165c..b444e0a 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"O ID do chamador assume o padrão de não restrito. Próxima chamada: Não restrita"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"O serviço não foi habilitado."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Não é possível alterar a configuração de identificação de chamadas."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Acesso restrito alterado"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"O serviço de dados está bloqueado."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"O serviço de emergência está bloqueado."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"O serviço de voz está bloqueado."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Redefinir e reiniciar app"</string>
<string name="aerr_report" msgid="5371800241488400617">"Enviar feedback"</string>
<string name="aerr_close" msgid="2991640326563991340">"Fechar"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Ignorar"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Desativar até que dispositivo seja reiniciado"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Aguarde"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Fechar app"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Toque para ver mais opções."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Depuração USB conectada"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Toque para desativar a depuração do USB."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Compartilhar relatório do bug?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartilhando relatório do bug…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Seu administrador de TI solicitou um relatório de bug para ajudar a resolver problemas deste dispositivo. É possível que apps e dados sejam compartilhados, o que pode deixar seu dispositivo temporariamente mais lento."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Seu administrador de TI solicitou um relatório de bug para ajudar a resolver problemas deste dispositivo. É possível que apps e dados sejam compartilhados."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Isso pode deixar seu dispositivo temporariamente mais lento"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACEITAR"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"RECUSAR"</string>
<string name="select_input_method" msgid="8547250819326693584">"Alterar teclado"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Pedir PIN antes de liberar"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pedir padrão de desbloqueio antes de liberar"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pedir senha antes de liberar"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"O app não é redimensionável. Desloque-o com dois dedos."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"É possível que o app não funcione com o recurso de divisão de tela."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"O app não é compatível com a divisão de tela."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Instalado pelo seu administrador"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Atualizado pelo administrador"</string>
@@ -1543,12 +1537,11 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Diversos"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Você definiu a importância dessas notificações."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Você definiu a importância dessas notificações."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Isso é importante por causa das pessoas envolvidas."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Permitir que <xliff:g id="APP">%1$s</xliff:g> crie um novo usuário com <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Permitir que <xliff:g id="APP">%1$s</xliff:g> crie um novo usuário com <xliff:g id="ACCOUNT">%2$s</xliff:g> (já existe um usuário com essa conta)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Preferência de idioma"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Adicionar um idioma"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Preferência de região"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Digitar nome do idioma"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugeridos"</string>
@@ -1565,10 +1558,11 @@
<string name="user_encrypted_message" msgid="4923292604515744267">"Toque para desbloquear"</string>
<string name="user_encrypted_detail" msgid="5708447464349420392">"Dados do usuário bloqueados"</string>
<string name="profile_encrypted_detail" msgid="3700965619978314974">"Perfil de trabalho bloqueado"</string>
- <string name="profile_encrypted_message" msgid="6964994232310195874">"Toque para desbloquear perfil de trabalho"</string>
+ <string name="profile_encrypted_message" msgid="6964994232310195874">"Toque p/ desbl. perfil de trab."</string>
<string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Conectado a <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Toque para ver os arquivos"</string>
<string name="pin_target" msgid="3052256031352291362">"Fixar guia"</string>
<string name="unpin_target" msgid="3556545602439143442">"Liberar guia"</string>
<string name="app_info" msgid="6856026610594615344">"Informações do app"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index f707822..a89f1b3 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -45,7 +45,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Mesaj vocal"</string>
<string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
<string name="mmiError" msgid="5154499457739052907">"Problemă de conexiune sau cod MMI nevalid."</string>
- <string name="mmiFdnError" msgid="5224398216385316471">"Operația este limitată la numerele cu apelări restricţionate."</string>
+ <string name="mmiFdnError" msgid="5224398216385316471">"Operația este limitată la numerele cu apelări restricționate."</string>
<string name="serviceEnabled" msgid="8147278346414714315">"Serviciul a fost activat."</string>
<string name="serviceEnabledFor" msgid="6856228140453471041">"Serviciul a fost activat pentru:"</string>
<string name="serviceDisabled" msgid="1937553226592516411">"Serviciul a fost dezactivat."</string>
@@ -56,9 +56,9 @@
<string name="badPin" msgid="9015277645546710014">"Codul PIN vechi introdus nu este corect."</string>
<string name="badPuk" msgid="5487257647081132201">"Codul PUK introdus nu este corect."</string>
<string name="mismatchPin" msgid="609379054496863419">"Codurile PIN introduse nu se potrivesc."</string>
- <string name="invalidPin" msgid="3850018445187475377">"Introduceţi un cod PIN alcătuit din 4 până la 8 cifre."</string>
- <string name="invalidPuk" msgid="8761456210898036513">"Introduceţi un cod PUK care să aibă 8 cifre sau mai mult."</string>
- <string name="needPuk" msgid="919668385956251611">"Cardul SIM este blocat cu codul PUK. Introduceţi codul PUK pentru a-l debloca."</string>
+ <string name="invalidPin" msgid="3850018445187475377">"Introduceți un cod PIN alcătuit din 4 până la 8 cifre."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Introduceți un cod PUK care să aibă 8 cifre sau mai mult."</string>
+ <string name="needPuk" msgid="919668385956251611">"Cardul SIM este blocat cu codul PUK. Introduceți codul PUK pentru a-l debloca."</string>
<string name="needPuk2" msgid="4526033371987193070">"Introduceți codul PUK2 pentru a debloca cardul SIM."</string>
<string name="enablePin" msgid="209412020907207950">"Operațiunea nu a reușit. Activați blocarea cardului SIM/RUIM."</string>
<plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
@@ -78,18 +78,17 @@
<string name="PwdMmi" msgid="7043715687905254199">"Modificare parolă"</string>
<string name="PinMmi" msgid="3113117780361190304">"Cod PIN modificat"</string>
<string name="CnipMmi" msgid="3110534680557857162">"Se apelează numărul prezent"</string>
- <string name="CnirMmi" msgid="3062102121430548731">"Se apelează un număr restricţionat"</string>
+ <string name="CnirMmi" msgid="3062102121430548731">"Se apelează un număr restricționat"</string>
<string name="ThreeWCMmi" msgid="9051047170321190368">"Apelare de tip conferință"</string>
<string name="RuacMmi" msgid="7827887459138308886">"Respingere apeluri supărătoare nedorite"</string>
<string name="CndMmi" msgid="3116446237081575808">"Se apelează serviciul de furnizare a numerelor"</string>
<string name="DndMmi" msgid="1265478932418334331">"Nu deranjați"</string>
- <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"ID-ul apelantului este restricţionat în mod prestabilit. Apelul următor: restricţionat"</string>
+ <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"ID-ul apelantului este restricționat în mod prestabilit. Apelul următor: restricționat"</string>
<string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"ID-ul apelantului este restricționat în mod prestabilit. Apelul următor: nerestricționat"</string>
<string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"ID-ul apelantului este nerestricționat în mod prestabilit. Apelul următor: Restricționat."</string>
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"ID-ul apelantului este nerestricționat în mod prestabilit. Apelul următor: nerestricționat"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Nu se asigură accesul la acest serviciu."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Nu puteți să modificați setarea pentru ID-ul apelantului."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Acces restricționat modificat"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Serviciul de date este blocat."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Serviciul de urgență este blocat."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Serviciul de voce este blocat."</string>
@@ -119,8 +118,8 @@
<string name="roamingText6" msgid="2059440825782871513">"Roaming - sistem disponibil"</string>
<string name="roamingText7" msgid="7112078724097233605">"Roaming - partenerAlliance"</string>
<string name="roamingText8" msgid="5989569778604089291">"Roaming - partener Premium"</string>
- <string name="roamingText9" msgid="7969296811355152491">"Roaming - funcţionalitate completă a serviciului"</string>
- <string name="roamingText10" msgid="3992906999815316417">"Roaming - funcţionalitate parțială a serviciului"</string>
+ <string name="roamingText9" msgid="7969296811355152491">"Roaming - funcționalitate completă a serviciului"</string>
+ <string name="roamingText10" msgid="3992906999815316417">"Roaming - funcționalitate parțială a serviciului"</string>
<string name="roamingText11" msgid="4154476854426920970">"Banner roaming activat"</string>
<string name="roamingText12" msgid="1189071119992726320">"Banner roaming dezactivat"</string>
<string name="roamingTextSearching" msgid="8360141885972279963">"Se caută serviciul"</string>
@@ -155,13 +154,13 @@
<string name="httpErrorUnsupportedScheme" msgid="5015730812906192208">"Protocolul nu este acceptat."</string>
<string name="httpErrorFailedSslHandshake" msgid="96549606000658641">"Nu s-a putut stabili o conexiune securizată."</string>
<string name="httpErrorBadUrl" msgid="3636929722728881972">"Pagina nu a putut fi deschisă, deoarece adresa URL nu este validă."</string>
- <string name="httpErrorFile" msgid="2170788515052558676">"Fişierul nu a putut fi accesat."</string>
- <string name="httpErrorFileNotFound" msgid="6203856612042655084">"Nu s-a putut găsi fişierul solicitat."</string>
+ <string name="httpErrorFile" msgid="2170788515052558676">"Fișierul nu a putut fi accesat."</string>
+ <string name="httpErrorFileNotFound" msgid="6203856612042655084">"Nu s-a putut găsi fișierul solicitat."</string>
<string name="httpErrorTooManyRequests" msgid="1235396927087188253">"Există prea multe solicitări în curs de procesare. Încercați din nou mai târziu."</string>
<string name="notification_title" msgid="8967710025036163822">"Eroare de conectare pentru <xliff:g id="ACCOUNT">%1$s</xliff:g>"</string>
<string name="contentServiceSync" msgid="8353523060269335667">"Sincronizare"</string>
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sincronizare"</string>
- <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Prea multe ştergeri <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
+ <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Prea multe ștergeri <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Stocarea pe tabletă este plină. Ștergeți câteva fișiere pentru a elibera spațiu."</string>
<string name="low_memory" product="watch" msgid="4415914910770005166">"Spațiul de stocare de pe ceas este plin! Ștergeți câteva fișiere pentru a elibera spațiu."</string>
<string name="low_memory" product="tv" msgid="516619861191025923">"Spațiul de stocare al televizorului este plin. Ștergeți câteva fișiere pentru a elibera spațiu."</string>
@@ -177,9 +176,9 @@
<string name="factory_reset_warning" msgid="5423253125642394387">"Datele de pe dispozitiv vor fi șterse"</string>
<string name="factory_reset_message" msgid="4905025204141900666">"Aplicația de administrare nu poate fi utilizată, deoarece este deteriorată sau îi lipsesc componente. Datele de pe dispozitiv vor fi șterse. Pentru asistență, contactați administratorul."</string>
<string name="me" msgid="6545696007631404292">"Eu"</string>
- <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opţiuni tablet PC"</string>
+ <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opțiuni tablet PC"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Opțiuni TV"</string>
- <string name="power_dialog" product="default" msgid="1319919075463988638">"Opţiuni telefon"</string>
+ <string name="power_dialog" product="default" msgid="1319919075463988638">"Opțiuni telefon"</string>
<string name="silent_mode" msgid="7167703389802618663">"Mod Silențios"</string>
<string name="turn_on_radio" msgid="3912793092339962371">"Activați funcția wireless"</string>
<string name="turn_off_radio" msgid="8198784949987062346">"Dezactivați funcția wireless"</string>
@@ -200,11 +199,11 @@
<string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Ceasul dvs. se va închide."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefonul dvs. se va închide."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Doriți să închideți?"</string>
- <string name="reboot_safemode_title" msgid="7054509914500140361">"Reporniţi în modul sigur"</string>
- <string name="reboot_safemode_confirm" msgid="55293944502784668">"Doriți să reporniţi în modul sigur? Astfel vor fi dezactivate toate aplicațiile terță parte pe care le-ați instalat. Acestea vor fi restabilite când reporniţi din nou."</string>
+ <string name="reboot_safemode_title" msgid="7054509914500140361">"Reporniți în modul sigur"</string>
+ <string name="reboot_safemode_confirm" msgid="55293944502784668">"Doriți să reporniți în modul sigur? Astfel vor fi dezactivate toate aplicațiile terță parte pe care le-ați instalat. Acestea vor fi restabilite când reporniți din nou."</string>
<string name="recent_tasks_title" msgid="3691764623638127888">"Recente"</string>
<string name="no_recent_tasks" msgid="8794906658732193473">"Nu există aplicații recente."</string>
- <string name="global_actions" product="tablet" msgid="408477140088053665">"Opţiuni tablet PC"</string>
+ <string name="global_actions" product="tablet" msgid="408477140088053665">"Opțiuni tablet PC"</string>
<string name="global_actions" product="tv" msgid="7240386462508182976">"Opțiuni TV"</string>
<string name="global_actions" product="default" msgid="2406416831541615258">"Opțiuni telefon"</string>
<string name="global_action_lock" msgid="2844945191792119712">"Blocați ecranul"</string>
@@ -281,30 +280,30 @@
<string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Permite aplicației să elimine comenzi rapide de pe ecranul de pornire, fără intervenția utilizatorului."</string>
<string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"redirecționează apelurile efectuate"</string>
<string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Permite aplicației să vadă numărul format în timpul unui apel de ieșire, cu opțiunea de a redirecționa apelul către un alt număr sau de a întrerupe apelul."</string>
- <string name="permlab_receiveSms" msgid="8673471768947895082">"primeşte mesaje text (SMS)"</string>
+ <string name="permlab_receiveSms" msgid="8673471768947895082">"primește mesaje text (SMS)"</string>
<string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite aplicației să primească și să proceseze mesaje SMS. Acest lucru înseamnă că aplicația ar putea monitoriza sau șterge mesajele trimise pe dispozitivul dvs. fără a vi le arăta."</string>
- <string name="permlab_receiveMms" msgid="1821317344668257098">"primeşte mesaje text (MMS)"</string>
+ <string name="permlab_receiveMms" msgid="1821317344668257098">"primește mesaje text (MMS)"</string>
<string name="permdesc_receiveMms" msgid="533019437263212260">"Permite aplicației să primească și să proceseze mesaje MMS. Acest lucru înseamnă că aplicația ar putea monitoriza sau șterge mesajele trimise pe dispozitivul dvs. fără a vi le arăta."</string>
<string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"citește mesajele cu transmisie celulară"</string>
- <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permite aplicației să citească mesajele primite prin transmisie celulară de dispozitivul dvs. Alertele cu transmisie celulară sunt difuzate în unele locații pentru a vă avertiza cu privire la situațiile de urgenţă. Aplicațiile rău intenţionate pot afecta performanța sau funcționarea dispozitivului dvs. când este primită o transmisie celulară de urgenţă."</string>
+ <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permite aplicației să citească mesajele primite prin transmisie celulară de dispozitivul dvs. Alertele cu transmisie celulară sunt difuzate în unele locații pentru a vă avertiza cu privire la situațiile de urgență. Aplicațiile rău intenționate pot afecta performanța sau funcționarea dispozitivului dvs. când este primită o transmisie celulară de urgență."</string>
<string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"citire feeduri abonat"</string>
- <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"Permite aplicației să obţină detalii despre feedurile sincronizate în prezent."</string>
+ <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"Permite aplicației să obțină detalii despre feedurile sincronizate în prezent."</string>
<string name="permlab_sendSms" msgid="7544599214260982981">"trimită și să vadă mesajele SMS"</string>
- <string name="permdesc_sendSms" msgid="7094729298204937667">"Permite aplicației să trimită mesaje SMS, ceea ce ar putea determina apariția unor taxe neașteptate. Aplicațiile rău intenţionate pot acumula costuri prin trimiterea mesajelor fără confirmarea dvs."</string>
+ <string name="permdesc_sendSms" msgid="7094729298204937667">"Permite aplicației să trimită mesaje SMS, ceea ce ar putea determina apariția unor taxe neașteptate. Aplicațiile rău intenționate pot acumula costuri prin trimiterea mesajelor fără confirmarea dvs."</string>
<string name="permlab_readSms" msgid="8745086572213270480">"citește mesajele text (SMS sau MMS)"</string>
- <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"Permite aplicației să citească mesajele SMS stocate pe tabletă sau pe cardul SIM. În acest fel, aplicația poate citi toate mesajele SMS, indiferent de conţinutul sau de gradul de confidențialitate al acestora."</string>
+ <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"Permite aplicației să citească mesajele SMS stocate pe tabletă sau pe cardul SIM. În acest fel, aplicația poate citi toate mesajele SMS, indiferent de conținutul sau de gradul de confidențialitate al acestora."</string>
<string name="permdesc_readSms" product="tv" msgid="5102425513647038535">"Permite aplicației să citească mesajele SMS stocate pe televizor sau pe cardul SIM. Cu această permisiune, aplicația poate citi toate mesajele SMS, indiferent de conținutul sau de gradul de confidențialitate al acestora."</string>
- <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"Permite aplicației să citească mesajele SMS stocate pe telefon sau pe cardul SIM. În acest fel, aplicația poate citi toate mesajele SMS, indiferent de conţinutul sau de gradul de confidențialitate al acestora."</string>
- <string name="permlab_receiveWapPush" msgid="5991398711936590410">"primeşte mesaje text (WAP)"</string>
+ <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"Permite aplicației să citească mesajele SMS stocate pe telefon sau pe cardul SIM. În acest fel, aplicația poate citi toate mesajele SMS, indiferent de conținutul sau de gradul de confidențialitate al acestora."</string>
+ <string name="permlab_receiveWapPush" msgid="5991398711936590410">"primește mesaje text (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Permite aplicației să primească și să proceseze mesaje WAP. Această permisiune include capacitatea de a monitoriza sau șterge mesajele care v-au fost trimise fără a vi le arăta."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"preluare aplicații care rulează"</string>
- <string name="permdesc_getTasks" msgid="7454215995847658102">"Permite aplicației să preia informațiile despre activităţile care rulează în prezent și care au rulat recent. În acest fel, aplicația poate descoperi informații despre aplicațiile care sunt utilizate pe dispozitiv."</string>
+ <string name="permdesc_getTasks" msgid="7454215995847658102">"Permite aplicației să preia informațiile despre activitățile care rulează în prezent și care au rulat recent. În acest fel, aplicația poate descoperi informații despre aplicațiile care sunt utilizate pe dispozitiv."</string>
<string name="permlab_manageProfileAndDeviceOwners" msgid="7918181259098220004">"să gestioneze profilul și proprietarii dispozitivului"</string>
<string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"Permite aplicațiilor să seteze proprietarii de profiluri și proprietarul dispozitivului."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"reordonare aplicații care rulează"</string>
- <string name="permdesc_reorderTasks" msgid="7734217754877439351">"Permite aplicației să mute activităţile în prim-plan și în fundal. Aplicația poate face acest lucru fără aportul dvs."</string>
- <string name="permlab_enableCarMode" msgid="5684504058192921098">"activare mod Maşină"</string>
- <string name="permdesc_enableCarMode" msgid="4853187425751419467">"Permite aplicației să activeze modul Maşină."</string>
+ <string name="permdesc_reorderTasks" msgid="7734217754877439351">"Permite aplicației să mute activitățile în prim-plan și în fundal. Aplicația poate face acest lucru fără aportul dvs."</string>
+ <string name="permlab_enableCarMode" msgid="5684504058192921098">"activare mod Mașină"</string>
+ <string name="permdesc_enableCarMode" msgid="4853187425751419467">"Permite aplicației să activeze modul Mașină."</string>
<string name="permlab_killBackgroundProcesses" msgid="3914026687420177202">"închide alte aplicații"</string>
<string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Permite aplicației să oprească procesele derulate în fundal de alte aplicații. Acest lucru poate face ca respectivele aplicații să nu mai ruleze."</string>
<string name="permlab_systemAlertWindow" msgid="3543347980839518613">"suprapune elemente vizuale peste alte aplicații"</string>
@@ -316,7 +315,7 @@
<string name="permlab_getPackageSize" msgid="7472921768357981986">"măsurare spațiu de stocare al aplicației"</string>
<string name="permdesc_getPackageSize" msgid="3921068154420738296">"Permite aplicației să preia dimensiunile codului, ale datelor și ale memoriei cache"</string>
<string name="permlab_writeSettings" msgid="2226195290955224730">"modifică setări de sistem"</string>
- <string name="permdesc_writeSettings" msgid="7775723441558907181">"Permite aplicației să modifice datele din setările sistemului. Aplicațiile rău intenţionate pot corupe configuraţia sistemului dvs."</string>
+ <string name="permdesc_writeSettings" msgid="7775723441558907181">"Permite aplicației să modifice datele din setările sistemului. Aplicațiile rău intenționate pot corupe configurația sistemului dvs."</string>
<string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"rulează la pornire"</string>
<string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"Permite aplicației să pornească imediat ce s-a terminat încărcarea sistemului. Din acest motiv, pornirea tabletei poate dura mai mult timp, iar rularea continuă a aplicației poate încetini dispozitivul."</string>
<string name="permdesc_receiveBootCompleted" product="tv" msgid="4525890122209673621">"Permite aplicației să pornească imediat ce s-a terminat încărcarea sistemului. Din acest motiv, pornirea televizorului poate dura mai mult timp, iar funcționarea continuă a aplicației poate încetini televizorul."</string>
@@ -326,27 +325,27 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="6839285697565389467">"Permite aplicației să trimită mesaje difuzate persistente, care se păstrează după terminarea difuzării mesajului. Utilizarea excesivă a acestei funcții poate să încetinească sau să destabilizeze televizorul, determinându-l să utilizeze prea multă memorie."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"Permite aplicației să trimită mesaje difuzate persistente, care se păstrează după terminarea difuzării mesajului. Utilizarea excesivă a acestei funcții poate să încetinească sau să destabilizeze telefonul, determinându-l să utilizeze prea multă memorie."</string>
<string name="permlab_readContacts" msgid="8348481131899886131">"citește agenda"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"Permite aplicației să citească datele despre persoanele din agenda stocată pe tabletă, inclusiv frecvența cu care ați apelat, ați trimis e-mailuri sau ați comunicat în alte moduri cu anumite persoane. Cu această permisiune aplicația salvează datele dvs. de contact, iar aplicațiile rău intenţionate pot distribui datele de contact fără știrea dvs."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"Permite aplicației să citească datele despre persoanele din agenda stocată pe tabletă, inclusiv frecvența cu care ați apelat, ați trimis e-mailuri sau ați comunicat în alte moduri cu anumite persoane. Cu această permisiune aplicația salvează datele dvs. de contact, iar aplicațiile rău intenționate pot distribui datele de contact fără știrea dvs."</string>
<string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"Permite aplicației să citească datele despre persoanele de contact salvate pe televizor, inclusiv frecvența cu care ați apelat, ați trimis e-mailuri sau ați comunicat în alte moduri cu anumite persoane. Cu această permisiune, aplicațiile pot salva datele de contact, iar aplicațiile rău-intenționate pot permite accesul la datele de contact fără cunoștința dvs."</string>
- <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"Permite aplicației să citească datele despre persoanele din agenda stocată pe telefon, inclusiv frecvența cu care ați apelat, ați trimis e-mailuri sau ați comunicat în alte moduri cu anumite persoane. Cu această permisiune aplicația salvează datele dvs. de contact, iar aplicațiile rău intenţionate pot distribui datele de contact fără știrea dvs."</string>
+ <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"Permite aplicației să citească datele despre persoanele din agenda stocată pe telefon, inclusiv frecvența cu care ați apelat, ați trimis e-mailuri sau ați comunicat în alte moduri cu anumite persoane. Cu această permisiune aplicația salvează datele dvs. de contact, iar aplicațiile rău intenționate pot distribui datele de contact fără știrea dvs."</string>
<string name="permlab_writeContacts" msgid="5107492086416793544">"modifică agenda"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Permite aplicației să modifice datele despre persoanele din agenda stocată pe tabletă, inclusiv frecvența cu care ați apelat, ați trimis e-mailuri sau ați comunicat în alte moduri cu anumite persoane din agendă. Cu această permisiune aplicația poate șterge datele de contact."</string>
<string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"Permite aplicației să modifice datele despre persoanele de contact salvate pe televizor, inclusiv frecvența cu care ați apelat, ați trimis e-mailuri sau ați comunicat în alte moduri cu anumite persoane de contact. Cu această permisiune, aplicația poate șterge datele de contact."</string>
<string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Permite aplicației să modifice datele despre persoanele din agenda stocată pe telefon, inclusiv frecvența cu care ați apelat, ați trimis e-mailuri sau ați comunicat în alte moduri cu anumite persoane din agendă. Cu această permisiune aplicația poate șterge datele de contact."</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"citește jurnalul de apeluri"</string>
- <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"Permite aplicației să citească jurnalul de apeluri al tabletei, inclusiv datele despre apelurile primite și efectuate. Cu această permisiune aplicația salvează datele dvs. din jurnalul de apeluri, iar aplicațiile rău intenţionate pot distribui aceste date fără știrea dvs."</string>
+ <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"Permite aplicației să citească jurnalul de apeluri al tabletei, inclusiv datele despre apelurile primite și efectuate. Cu această permisiune aplicația salvează datele dvs. din jurnalul de apeluri, iar aplicațiile rău intenționate pot distribui aceste date fără știrea dvs."</string>
<string name="permdesc_readCallLog" product="tv" msgid="5611770887047387926">"Permite aplicației să citească jurnalul de apeluri al televizorului, inclusiv datele despre apelurile primite și efectuate. Cu această permisiune, aplicațiile pot să salveze datele din jurnalul de apeluri, iar aplicațiile rău-intenționate pot permite accesul la datele din jurnalul de apeluri fără cunoștința dvs."</string>
- <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"Permite aplicației să citească jurnalul de apeluri al telefonului, inclusiv datele despre apelurile primite și efectuate. Cu această permisiune aplicația salvează datele dvs. din jurnalul de apeluri, iar aplicațiile rău intenţionate pot distribui aceste date fără știrea dvs."</string>
+ <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"Permite aplicației să citească jurnalul de apeluri al telefonului, inclusiv datele despre apelurile primite și efectuate. Cu această permisiune aplicația salvează datele dvs. din jurnalul de apeluri, iar aplicațiile rău intenționate pot distribui aceste date fără știrea dvs."</string>
<string name="permlab_writeCallLog" msgid="8552045664743499354">"scrie jurnalul de apeluri"</string>
- <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Permite aplicației să modifice jurnalul de apeluri al tabletei dvs., inclusiv datele despre apelurile primite sau efectuate. Aplicațiile rău intenţionate pot utiliza această permisiune pentru a șterge sau pentru a modifica jurnalul dvs. de apeluri."</string>
+ <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Permite aplicației să modifice jurnalul de apeluri al tabletei dvs., inclusiv datele despre apelurile primite sau efectuate. Aplicațiile rău intenționate pot utiliza această permisiune pentru a șterge sau pentru a modifica jurnalul dvs. de apeluri."</string>
<string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"Permite aplicației să modifice jurnalul de apeluri al televizorului, inclusiv datele despre apelurile primite sau efectuate. Aplicațiile rău-intenționate pot utiliza această permisiune pentru a șterge sau pentru a modifica jurnalul de apeluri."</string>
- <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Permite aplicației să modifice jurnalul de apeluri al telefonului dvs., inclusiv datele despre apelurile primite sau efectuate. Aplicațiile rău intenţionate pot utiliza această permisiune pentru a șterge sau pentru a modifica jurnalul dvs. de apeluri."</string>
+ <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Permite aplicației să modifice jurnalul de apeluri al telefonului dvs., inclusiv datele despre apelurile primite sau efectuate. Aplicațiile rău intenționate pot utiliza această permisiune pentru a șterge sau pentru a modifica jurnalul dvs. de apeluri."</string>
<string name="permlab_bodySensors" msgid="4683341291818520277">"să acceseze senzorii corporali (cum ar fi monitoarele cardiace)"</string>
<string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Permite aplicației să acceseze date de la senzorii care vă monitorizează starea fizică, cum ar fi ritmul cardiac."</string>
- <string name="permlab_readCalendar" msgid="5972727560257612398">"citirea evenimentelor din calendar și a informațiilor confidenţiale"</string>
- <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"Permite aplicației să citească toate evenimentele din calendar stocate pe tabletă, inclusiv cele ale prietenilor sau colegilor. Acest lucru poate permite aplicației să distribuie sau să salveze datele din calendar, indiferent dacă acestea sunt confidenţiale sau sensibile."</string>
+ <string name="permlab_readCalendar" msgid="5972727560257612398">"citirea evenimentelor din calendar și a informațiilor confidențiale"</string>
+ <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"Permite aplicației să citească toate evenimentele din calendar stocate pe tabletă, inclusiv cele ale prietenilor sau colegilor. Acest lucru poate permite aplicației să distribuie sau să salveze datele din calendar, indiferent dacă acestea sunt confidențiale sau sensibile."</string>
<string name="permdesc_readCalendar" product="tv" msgid="3191352452242394196">"Permite aplicației să citească toate evenimentele din calendar stocate pe televizor, inclusiv cele ale prietenilor sau colegilor. Cu această permisiune, aplicația poate să permită accesul la datele din calendar sau să le salveze, indiferent dacă acestea sunt confidențiale sau sensibile."</string>
- <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"Permite aplicației să citească toate evenimentele din calendar stocate pe telefon, inclusiv cele ale prietenilor sau colegilor. Acest lucru poate permite aplicației să distribuie sau să salveze datele din calendar, indiferent dacă acestea sunt confidenţiale sau sensibile."</string>
+ <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"Permite aplicației să citească toate evenimentele din calendar stocate pe telefon, inclusiv cele ale prietenilor sau colegilor. Acest lucru poate permite aplicației să distribuie sau să salveze datele din calendar, indiferent dacă acestea sunt confidențiale sau sensibile."</string>
<string name="permlab_writeCalendar" msgid="8438874755193825647">"adăugarea sau modificarea evenimentelor din calendar și trimiterea de e-mailuri invitaților fără știrea proprietarului"</string>
<string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"Permite aplicației să adauge, să elimine și să modifice evenimentele pe care le puteți modifica pe tabletă, inclusiv cele ale prietenilor sau colegilor dvs. În acest fel, aplicația poate trimite mesaje care par să vină de la proprietarii calendarelor sau să modifice evenimentele fără știrea proprietarilor."</string>
<string name="permdesc_writeCalendar" product="tv" msgid="1273290605500902507">"Permite aplicației să adauge, să elimine și să modifice evenimentele pe care le puteți modifica pe televizor, inclusiv pe cele ale prietenilor sau ale colegilor. Cu această permisiune, aplicația poate să trimită mesaje care par că vin din partea proprietarilor calendarului sau să modifice evenimentele fără cunoștința acestora."</string>
@@ -354,9 +353,9 @@
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"accesare comenzi suplimentare ale furnizorului locației"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Permite aplicației să acceseze comenzi suplimentare pentru furnizorul locației. Aplicația ar putea să utilizeze această permisiune pentru a influența operațiile GPS sau ale altor surse de locații."</string>
<string name="permlab_accessFineLocation" msgid="251034415460950944">"să acceseze locația exactă (bazată pe GPS și pe rețea)"</string>
- <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Permite aplicației să obţină locația dvs. exactă utilizând sistemul GPS (Global Positioning System) sau surse de localizare prin rețele, cum ar fi cele prin turn de celule și Wi-Fi. Pentru a fi utilizate de aplicație, aceste servicii de localizare trebuie să fie activate și disponibile pe dispozitivul dvs. Aplicațiile pot utiliza această permisiune pentru a determina locația dvs. și pot să consume mai multă energie a bateriei."</string>
+ <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Permite aplicației să obțină locația dvs. exactă utilizând sistemul GPS (Global Positioning System) sau surse de localizare prin rețele, cum ar fi cele prin turn de celule și Wi-Fi. Pentru a fi utilizate de aplicație, aceste servicii de localizare trebuie să fie activate și disponibile pe dispozitivul dvs. Aplicațiile pot utiliza această permisiune pentru a determina locația dvs. și pot să consume mai multă energie a bateriei."</string>
<string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"să acceseze locația aproximativă (bazată pe rețea)"</string>
- <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Permite aplicației să obţină locația dvs. aproximativă. Această locație este dedusă de serviciile de localizare utilizând surse de localizare prin rețele, cum ar fi cele prin turn de celule și Wi-Fi. Pentru a fi utilizate de aplicație, aceste servicii de localizare trebuie să fie activate și disponibile pe dispozitivul dvs. Aplicațiile pot utiliza această permisiune pentru a determina locația dvs. aproximativă."</string>
+ <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Permite aplicației să obțină locația dvs. aproximativă. Această locație este dedusă de serviciile de localizare utilizând surse de localizare prin rețele, cum ar fi cele prin turn de celule și Wi-Fi. Pentru a fi utilizate de aplicație, aceste servicii de localizare trebuie să fie activate și disponibile pe dispozitivul dvs. Aplicațiile pot utiliza această permisiune pentru a determina locația dvs. aproximativă."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"modificare setări audio"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permite aplicației să modifice setările audio globale, cum ar fi volumul și difuzorul care este utilizat pentru ieșire."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"înregistreze sunet"</string>
@@ -368,11 +367,11 @@
<string name="permlab_vibrate" msgid="7696427026057705834">"controlează vibrarea"</string>
<string name="permdesc_vibrate" msgid="6284989245902300945">"Permite aplicației să controleze mecanismul de vibrare."</string>
<string name="permlab_callPhone" msgid="3925836347681847954">"apelare directă numere de telefon"</string>
- <string name="permdesc_callPhone" msgid="3740797576113760827">"Permite aplicației să apeleze numere de telefon fără intervenţia dvs. Acest lucru poate determina apariția unor taxe sau a unor apeluri neașteptate. Cu această permisiune aplicația nu poate apela numerele de urgenţă. Aplicațiile rău intenţionate pot acumula costuri prin efectuarea unor apeluri fără confirmare."</string>
+ <string name="permdesc_callPhone" msgid="3740797576113760827">"Permite aplicației să apeleze numere de telefon fără intervenția dvs. Acest lucru poate determina apariția unor taxe sau a unor apeluri neașteptate. Cu această permisiune aplicația nu poate apela numerele de urgență. Aplicațiile rău intenționate pot acumula costuri prin efectuarea unor apeluri fără confirmare."</string>
<string name="permlab_accessImsCallService" msgid="3574943847181793918">"accesează serviciul de apelare IMS"</string>
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Permite aplicației să folosească serviciul IMS pentru apeluri, fără intervenția dvs."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"citește starea și identitatea telefonului"</string>
- <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite aplicației să acceseze funcţiile de telefon ale dispozitivului. Cu această permisiune aplicația stabilește numărul de telefon și ID-urile de dispozitiv, dacă un apel este activ, precum și numărul de la distanță conectat printr-un apel."</string>
+ <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite aplicației să acceseze funcțiile de telefon ale dispozitivului. Cu această permisiune aplicația stabilește numărul de telefon și ID-urile de dispozitiv, dacă un apel este activ, precum și numărul de la distanță conectat printr-un apel."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"împiedicarea computerului tablet PC să intre în repaus"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"împiedică intrarea televizorului în stare de inactivitate"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"împiedicare intrare telefon în repaus"</string>
@@ -392,11 +391,11 @@
<string name="permdesc_setTimeZone" product="tv" msgid="888864653946175955">"Permite aplicației să modifice fusul orar al televizorului."</string>
<string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"Permite aplicației să schimbe fusul orar al telefonului."</string>
<string name="permlab_getAccounts" msgid="1086795467760122114">"găsește conturi pe dispozitiv"</string>
- <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Permite aplicației să obţină lista de conturi cunoscute de tabletă. Aceasta poate include conturile create de aplicațiile pe care le-ați instalat."</string>
+ <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Permite aplicației să obțină lista de conturi cunoscute de tabletă. Aceasta poate include conturile create de aplicațiile pe care le-ați instalat."</string>
<string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"Permite aplicației să obțină lista de conturi cunoscute de televizor. Aceasta poate include conturile create de aplicațiile pe care le-ați instalat."</string>
- <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Permite aplicației să obţină lista de conturi cunoscute de telefon. Aceasta poate include conturile create de aplicațiile pe care le-ați instalat."</string>
+ <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Permite aplicației să obțină lista de conturi cunoscute de telefon. Aceasta poate include conturile create de aplicațiile pe care le-ați instalat."</string>
<string name="permlab_accessNetworkState" msgid="4951027964348974773">"vizualizează conexiunile la rețea"</string>
- <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"Permite aplicației să vadă informațiile despre conexiunile la rețea, cum ar fi reţelele existente și cele care sunt conectate."</string>
+ <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"Permite aplicației să vadă informațiile despre conexiunile la rețea, cum ar fi rețelele existente și cele care sunt conectate."</string>
<string name="permlab_createNetworkSockets" msgid="7934516631384168107">"să aibă acces deplin la rețea"</string>
<string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"Permite aplicației să creeze socluri de rețea și să utilizeze protocoale de rețea personalizate. Browserul și alte aplicații oferă mijloacele de trimitere a datelor pe internet, astfel încât această permisiune nu este necesară pentru trimiterea datelor pe internet."</string>
<string name="permlab_changeNetworkState" msgid="958884291454327309">"modificare conectivitate în rețea"</string>
@@ -404,9 +403,9 @@
<string name="permlab_changeTetherState" msgid="5952584964373017960">"modificare conectivitate tethering"</string>
<string name="permdesc_changeTetherState" msgid="1524441344412319780">"Permite aplicației să modifice starea de conectivitate prin tethering la rețea."</string>
<string name="permlab_accessWifiState" msgid="5202012949247040011">"vizualizează conexiunile Wi-Fi"</string>
- <string name="permdesc_accessWifiState" msgid="5002798077387803726">"Permite aplicației să vadă informațiile despre reţelele Wi-Fi, de ex. dacă o rețea Wi-Fi este activată, precum și numele dispozitivelor conectate la rețeaua Wi-Fi."</string>
+ <string name="permdesc_accessWifiState" msgid="5002798077387803726">"Permite aplicației să vadă informațiile despre rețelele Wi-Fi, de ex. dacă o rețea Wi-Fi este activată, precum și numele dispozitivelor conectate la rețeaua Wi-Fi."</string>
<string name="permlab_changeWifiState" msgid="6550641188749128035">"se conectează și se deconectează de la Wi-Fi"</string>
- <string name="permdesc_changeWifiState" msgid="7137950297386127533">"Permite aplicației să se conecteze și să se deconecteze de la punctele de acces Wi-Fi, precum și să efectueze modificări în configuraţia dispozitivului pentru reţelele Wi-Fi."</string>
+ <string name="permdesc_changeWifiState" msgid="7137950297386127533">"Permite aplicației să se conecteze și să se deconecteze de la punctele de acces Wi-Fi, precum și să efectueze modificări în configurația dispozitivului pentru rețelele Wi-Fi."</string>
<string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"permitere recepționare difuzare multiplă Wi-Fi"</string>
<string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"Permite aplicației să primească pachetele trimise către toate dispozitivele dintr-o rețea Wi-Fi, utilizând adrese cu difuzare multiplă, nu doar tableta dvs. Această funcție utilizează mai multă energie decât modul fără difuzare multiplă."</string>
<string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"Permite aplicației să primească pachetele trimise către toate dispozitivele dintr-o rețea Wi-Fi, utilizând adrese cu difuzare multiplă, nu doar televizorul dvs. Această funcție utilizează mai multă energie decât modul fără difuzare multiplă."</string>
@@ -416,19 +415,19 @@
<string name="permdesc_bluetoothAdmin" product="tv" msgid="3373125682645601429">"Permite aplicației să configureze televizorul Bluetooth local, precum și să descopere și să se asocieze cu dispozitive la distanță."</string>
<string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Permite aplicației să configureze telefonul Bluetooth local, să descopere și să se împerecheze cu dispozitive la distanță."</string>
<string name="permlab_accessWimaxState" msgid="4195907010610205703">"se conectează și se deconectează de la WiMAX"</string>
- <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Permite aplicației să stabilească dacă o rețea WiMAX este activată și să vadă informațiile cu privire la toate reţelele WiMAX conectate."</string>
+ <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Permite aplicației să stabilească dacă o rețea WiMAX este activată și să vadă informațiile cu privire la toate rețelele WiMAX conectate."</string>
<string name="permlab_changeWimaxState" msgid="340465839241528618">"schimbați starea WiMAX"</string>
- <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permite aplicației să conecteze și să deconecteze tableta la și de la reţelele WiMAX."</string>
+ <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permite aplicației să conecteze și să deconecteze tableta la și de la rețelele WiMAX."</string>
<string name="permdesc_changeWimaxState" product="tv" msgid="6022307083934827718">"Permite aplicației să conecteze și să deconecteze televizorul la și de la rețelele WiMAX."</string>
- <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Permite aplicației să conecteze și să deconecteze telefonul la și de la reţelele WiMAX."</string>
+ <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Permite aplicației să conecteze și să deconecteze telefonul la și de la rețelele WiMAX."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"conectează dispozitive Bluetooth"</string>
- <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Permite aplicației să vadă configuraţia tabletei Bluetooth, să efectueze și să accepte conexiuni cu dispozitive împerecheate."</string>
+ <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Permite aplicației să vadă configurația tabletei Bluetooth, să efectueze și să accepte conexiuni cu dispozitive împerecheate."</string>
<string name="permdesc_bluetooth" product="tv" msgid="3974124940101104206">"Permite aplicației să vadă configurația funcției Bluetooth a televizorului, precum și să efectueze și să accepte conexiuni cu dispozitive asociate."</string>
- <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Permite aplicației să vadă configuraţia telefonului Bluetooth, să efectueze și să accepte conexiuni cu dispozitive împerecheate."</string>
+ <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Permite aplicației să vadă configurația telefonului Bluetooth, să efectueze și să accepte conexiuni cu dispozitive împerecheate."</string>
<string name="permlab_nfc" msgid="4423351274757876953">"controlare schimb de date prin Near Field Communication"</string>
<string name="permdesc_nfc" msgid="7120611819401789907">"Permite aplicației să comunice cu etichetele, cardurile și cititoarele NFC (Near Field Communication)."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"dezactivează blocarea ecranului"</string>
- <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Permite aplicației să dezactiveze blocarea tastelor și orice modalitate asociată de securizare prin parolă. De exemplu, telefonul dezactivează blocarea tastelor când se primeşte un apel telefonic și reactivează blocarea tastelor la terminarea apelului."</string>
+ <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Permite aplicației să dezactiveze blocarea tastelor și orice modalitate asociată de securizare prin parolă. De exemplu, telefonul dezactivează blocarea tastelor când se primește un apel telefonic și reactivează blocarea tastelor la terminarea apelului."</string>
<string name="permlab_manageFingerprint" msgid="5640858826254575638">"gestionează hardware-ul pentru amprentă"</string>
<string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permite aplicației să invoce metode pentru a adăuga și pentru a șterge șabloane de amprentă pentru utilizare."</string>
<string name="permlab_useFingerprint" msgid="3150478619915124905">"folosește hardware-ul pentru amprentă"</string>
@@ -456,12 +455,12 @@
<string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"Permite unei aplicații să modifice setările de sincronizare ale unui cont. De exemplu, cu această permisiune aplicația poate activa sincronizarea aplicației Persoane cu un anumit cont."</string>
<string name="permlab_readSyncStats" msgid="7396577451360202448">"citire statistici privind sincronizarea"</string>
<string name="permdesc_readSyncStats" msgid="1510143761757606156">"Permite unei aplicații să citească statisticile de sincronizare ale unui cont, inclusiv istoricul evenimentelor de sincronizare și volumul datelor sincronizate."</string>
- <string name="permlab_sdcardRead" product="nosdcard" msgid="367275095159405468">"citește conţinutul stocării USB"</string>
- <string name="permlab_sdcardRead" product="default" msgid="2188156462934977940">"citește conţinutul cardului SD"</string>
+ <string name="permlab_sdcardRead" product="nosdcard" msgid="367275095159405468">"citește conținutul stocării USB"</string>
+ <string name="permlab_sdcardRead" product="default" msgid="2188156462934977940">"citește conținutul cardului SD"</string>
<string name="permdesc_sdcardRead" product="nosdcard" msgid="3446988712598386079">"Permite aplic. citirea conținutului stoc. USB."</string>
<string name="permdesc_sdcardRead" product="default" msgid="2607362473654975411">"Permite aplicației citirea conținutul cardului SD."</string>
- <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"modifică sau șterge conţinutul stocării USB"</string>
- <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"modifică sau șterge conţinutul cardului SD"</string>
+ <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"modifică sau șterge conținutul stocării USB"</string>
+ <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"modifică sau șterge conținutul cardului SD"</string>
<string name="permdesc_sdcardWrite" product="nosdcard" msgid="6175406299445710888">"Permite scriere în stoc. USB."</string>
<string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Permite aplicației să scrie pe cardul SD."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"efectuarea/primirea apelurilor SIP"</string>
@@ -483,7 +482,7 @@
<string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"gestionează politica de rețea"</string>
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Permite aplicației să gestioneze politicile de rețea și să definească regulile specifice aplicațiilor."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modificați modul de calcul al utilizării rețelei"</string>
- <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permite aplicației să modifice modul în care este calculată utilizarea rețelei pentru aplicații. Nu se utilizează de aplicațiile obişnuite."</string>
+ <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permite aplicației să modifice modul în care este calculată utilizarea rețelei pentru aplicații. Nu se utilizează de aplicațiile obișnuite."</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"accesare notificări"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite aplicației să recupereze, să examineze și să șteargă notificări, inclusiv pe cele postate de alte aplicații."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"conectare la un serviciu de citire a notificărilor"</string>
@@ -513,7 +512,7 @@
<string name="policylab_limitPassword" msgid="4497420728857585791">"Setați reguli pentru parolă"</string>
<string name="policydesc_limitPassword" msgid="2502021457917874968">"Stabiliți lungimea și tipul de caractere permise pentru parolele și codurile PIN de blocare a ecranului."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitorizați încercările de deblocare a ecranului"</string>
- <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Monitorizați numărul de parole incorecte introduse la deblocarea ecranului și blocaţi tableta sau ștergeți datele acesteia dacă sunt introduse prea multe parole incorecte."</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Monitorizați numărul de parole incorecte introduse la deblocarea ecranului și blocați tableta sau ștergeți datele acesteia dacă sunt introduse prea multe parole incorecte."</string>
<string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"Monitorizați numărul de parole incorecte introduse la deblocarea ecranului și blocați televizorul sau ștergeți toate datele acestuia dacă sunt introduse prea multe parole incorecte."</string>
<string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Monitorizați numărul de parole incorecte introduse la deblocarea ecranului și blocați telefonul sau ștergeți toate datele acestuia dacă sunt introduse prea multe parole incorecte."</string>
<string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"Monitorizați numărul de parole incorecte introduse la deblocarea ecranului și blocați tableta sau ștergeți toate datele acestui utilizator dacă se introduc prea multe parole incorecte."</string>
@@ -593,7 +592,7 @@
<string name="phoneTypePager" msgid="7582359955394921732">"Pager"</string>
<string name="phoneTypeOther" msgid="1544425847868765990">"Altele"</string>
<string name="phoneTypeCallback" msgid="2712175203065678206">"Apelare inversă"</string>
- <string name="phoneTypeCar" msgid="8738360689616716982">"Maşină"</string>
+ <string name="phoneTypeCar" msgid="8738360689616716982">"Mașină"</string>
<string name="phoneTypeCompanyMain" msgid="540434356461478916">"Numărul de telefon principal al companiei"</string>
<string name="phoneTypeIsdn" msgid="8022453193171370337">"ISDN"</string>
<string name="phoneTypeMain" msgid="6766137010628326916">"Număr de telefon principal"</string>
@@ -606,7 +605,7 @@
<string name="phoneTypeAssistant" msgid="5596772636128562884">"Asistent"</string>
<string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
<string name="eventTypeCustom" msgid="7837586198458073404">"Personalizate"</string>
- <string name="eventTypeBirthday" msgid="2813379844211390740">"Zi de naştere"</string>
+ <string name="eventTypeBirthday" msgid="2813379844211390740">"Zi de naștere"</string>
<string name="eventTypeAnniversary" msgid="3876779744518284000">"Zi aniversară"</string>
<string name="eventTypeOther" msgid="7388178939010143077">"Altul"</string>
<string name="emailTypeCustom" msgid="8525960257804213846">"Personalizat"</string>
@@ -655,13 +654,13 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Serviciu"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Altul"</string>
<string name="quick_contacts_not_available" msgid="746098007828579688">"Nu s-a găsit nicio aplicație pentru a afișa această persoană de contact."</string>
- <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Introduceţi codul PIN"</string>
- <string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Introduceţi codul PUK și noul cod PIN"</string>
+ <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Introduceți codul PIN"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Introduceți codul PUK și noul cod PIN"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Codul PUK"</string>
<string name="keyguard_password_enter_pin_prompt" msgid="8027680321614196258">"Noul cod PIN"</string>
- <string name="keyguard_password_entry_touch_hint" msgid="7858547464982981384"><font size="17">"Atingeți și introduceţi parola"</font></string>
- <string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"Introduceţi parola pentru a debloca"</string>
- <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"Introduceţi codul PIN pentru a debloca"</string>
+ <string name="keyguard_password_entry_touch_hint" msgid="7858547464982981384"><font size="17">"Atingeți și introduceți parola"</font></string>
+ <string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"Introduceți parola pentru a debloca"</string>
+ <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"Introduceți codul PIN pentru a debloca"</string>
<string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"Cod PIN incorect."</string>
<string name="keyguard_label_text" msgid="861796461028298424">"Pentru a debloca, apăsați Meniu, apoi 0."</string>
<string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Număr de urgență"</string>
@@ -669,43 +668,43 @@
<string name="lockscreen_screen_locked" msgid="7288443074806832904">"Ecranul este blocat."</string>
<string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Apăsați Meniu pentru a debloca sau pentru a efectua apeluri de urgență."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Apăsați Meniu pentru deblocare."</string>
- <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Desenaţi modelul pentru a debloca"</string>
+ <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Desenați modelul pentru a debloca"</string>
<string name="lockscreen_emergency_call" msgid="5298642613417801888">"Urgență"</string>
- <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Reveniţi la apel"</string>
+ <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Reveniți la apel"</string>
<string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Corect!"</string>
<string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Încercați din nou"</string>
<string name="lockscreen_password_wrong" msgid="5737815393253165301">"Încercați din nou"</string>
- <string name="faceunlock_multiple_failures" msgid="754137583022792429">"S-a depăşit numărul maxim de încercări pentru Deblocare facială"</string>
+ <string name="faceunlock_multiple_failures" msgid="754137583022792429">"S-a depășit numărul maxim de încercări pentru Deblocare facială"</string>
<string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"Niciun card SIM"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nu există card SIM în computerul tablet PC."</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="1943633865476989599">"Niciun card SIM în televizor."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Telefonul nu are card SIM."</string>
- <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Introduceţi un card SIM."</string>
- <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"Cardul SIM lipsește sau nu poate fi citit. Introduceţi un card SIM."</string>
+ <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Introduceți un card SIM."</string>
+ <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"Cardul SIM lipsește sau nu poate fi citit. Introduceți un card SIM."</string>
<string name="lockscreen_permanent_disabled_sim_message_short" msgid="5096149665138916184">"Card SIM inutilizabil."</string>
- <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"Cardul dvs. SIM este dezactivat definitiv.\n Contactaţi furnizorul de servicii wireless pentru a obţine un alt card SIM."</string>
+ <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"Cardul dvs. SIM este dezactivat definitiv.\n Contactați furnizorul de servicii wireless pentru a obține un alt card SIM."</string>
<string name="lockscreen_transport_prev_description" msgid="6300840251218161534">"Melodia anterioară"</string>
<string name="lockscreen_transport_next_description" msgid="573285210424377338">"Melodia următoare"</string>
<string name="lockscreen_transport_pause_description" msgid="3980308465056173363">"Pauză"</string>
<string name="lockscreen_transport_play_description" msgid="1901258823643886401">"Redați"</string>
<string name="lockscreen_transport_stop_description" msgid="5907083260651210034">"Opriți"</string>
- <string name="lockscreen_transport_rew_description" msgid="6944412838651990410">"Derulaţi"</string>
- <string name="lockscreen_transport_ffw_description" msgid="42987149870928985">"Derulaţi rapid înainte"</string>
+ <string name="lockscreen_transport_rew_description" msgid="6944412838651990410">"Derulați"</string>
+ <string name="lockscreen_transport_ffw_description" msgid="42987149870928985">"Derulați rapid înainte"</string>
<string name="emergency_calls_only" msgid="6733978304386365407">"Numai apeluri de urgență"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Rețea blocată"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Cardul SIM este blocat cu codul PUK."</string>
- <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"Consultați Ghidul de utilizare sau contactaţi Serviciul de relații cu clienții."</string>
+ <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"Consultați Ghidul de utilizare sau contactați Serviciul de relații cu clienții."</string>
<string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"Cardul SIM este blocat."</string>
<string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Se deblochează cardul SIM..."</string>
<string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"Ați desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. \n\nÎncercați din nou peste <xliff:g id="NUMBER_1">%2$d</xliff:g> (de) secunde."</string>
<string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"Ați introdus incorect parola de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. \n\nÎncercați din nou peste <xliff:g id="NUMBER_1">%2$d</xliff:g> (de) secunde."</string>
<string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"Ați introdus incorect codul PIN de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori.\n\nÎncercați din nou peste <xliff:g id="NUMBER_1">%2$d</xliff:g> (de) secunde."</string>
- <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"Ați desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereuşite, vi se va solicita să deblocați tableta cu ajutorul datelor de conectare la Google.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> (de) secunde."</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"Ați desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, vi se va solicita să deblocați tableta cu ajutorul datelor de conectare la Google.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> (de) secunde."</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"Ați desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, vi se va solicita să deblocați televizorul cu ajutorul datelor de conectare la Google.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> (de) secunde."</string>
- <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"Ați desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereuşite, vi se va solicita să deblocați telefonul cu ajutorul datelor de conectare la Google.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> (de) secunde."</string>
- <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"Ați efectuat <xliff:g id="NUMBER_0">%1$d</xliff:g> încercări incorecte de deblocare a tabletei. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereuşite, aceasta va fi resetată la setările prestabilite din fabrică, iar toate datele de utilizator vor fi pierdute."</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"Ați desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, vi se va solicita să deblocați telefonul cu ajutorul datelor de conectare la Google.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> (de) secunde."</string>
+ <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"Ați efectuat <xliff:g id="NUMBER_0">%1$d</xliff:g> încercări incorecte de deblocare a tabletei. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, aceasta va fi resetată la setările prestabilite din fabrică, iar toate datele de utilizator vor fi pierdute."</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="950408382418270260">"Ați efectuat <xliff:g id="NUMBER_0">%1$d</xliff:g> încercări incorecte de deblocare a televizorului. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, televizorul va reveni la setările prestabilite din fabrică, iar toate datele de utilizator se vor pierde."</string>
- <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"Ați efectuat <xliff:g id="NUMBER_0">%1$d</xliff:g> încercări incorecte de deblocare a telefonului. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereuşite, acesta va fi resetat la setările prestabilite din fabrică, iar toate datele de utilizator vor fi pierdute."</string>
+ <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"Ați efectuat <xliff:g id="NUMBER_0">%1$d</xliff:g> încercări incorecte de deblocare a telefonului. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, acesta va fi resetat la setările prestabilite din fabrică, iar toate datele de utilizator vor fi pierdute."</string>
<string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"Ați efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a tabletei. Tableta va fi acum resetată la setările prestabilite din fabrică."</string>
<string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="3195755534096192191">"Ați efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a televizorului. Televizorul va reveni acum la setările prestabilite din fabrică."</string>
<string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"Ați efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a telefonului. Acesta va fi acum resetat la setările prestabilite din fabrică."</string>
@@ -713,14 +712,14 @@
<string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Ați uitat modelul?"</string>
<string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Deblocare cont"</string>
<string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"Prea multe încercări de desenare a modelului"</string>
- <string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"Pentru a debloca, conectaţi-vă folosind Contul Google."</string>
+ <string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"Pentru a debloca, conectați-vă folosind Contul Google."</string>
<string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"Nume de utilizator (e-mail)"</string>
<string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"Parolă"</string>
<string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"Conectați-vă"</string>
<string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"Nume de utilizator sau parolă nevalide."</string>
<string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"Ați uitat numele de utilizator sau parola?\nAccesați "<b>"google.com/accounts/recovery"</b>"."</string>
<string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"Se verifică..."</string>
- <string name="lockscreen_unlock_label" msgid="737440483220667054">"Deblocaţi"</string>
+ <string name="lockscreen_unlock_label" msgid="737440483220667054">"Deblocați"</string>
<string name="lockscreen_sound_on_label" msgid="9068877576513425970">"Sunet activat"</string>
<string name="lockscreen_sound_off_label" msgid="996822825154319026">"Sunet dezactivat"</string>
<string name="lockscreen_access_pattern_start" msgid="3941045502933142847">"Desenarea modelului a început"</string>
@@ -758,7 +757,7 @@
<string name="granularity_label_link" msgid="5815508880782488267">"link"</string>
<string name="granularity_label_line" msgid="5764267235026120888">"rând"</string>
<string name="factorytest_failed" msgid="5410270329114212041">"Testarea de fabrică nu a reușit"</string>
- <string name="factorytest_not_system" msgid="4435201656767276723">"Acţiunea FACTORY_TEST este acceptată doar pentru pachetele instalate în /system/app."</string>
+ <string name="factorytest_not_system" msgid="4435201656767276723">"Acțiunea FACTORY_TEST este acceptată doar pentru pachetele instalate în /system/app."</string>
<string name="factorytest_no_action" msgid="872991874799998561">"Nu s-a găsit niciun pachet care să ofere acțiunea FACTORY_TEST."</string>
<string name="factorytest_reboot" msgid="6320168203050791643">"Reporniți"</string>
<string name="js_dialog_title" msgid="1987483977834603872">"La pagina de la „<xliff:g id="TITLE">%s</xliff:g>” apare:"</string>
@@ -776,7 +775,7 @@
<string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
<string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
<string name="autofill_province" msgid="2231806553863422300">"Provincie"</string>
- <string name="autofill_postal_code" msgid="4696430407689377108">"Cod poştal"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Cod poștal"</string>
<string name="autofill_state" msgid="6988894195520044613">"Stat"</string>
<string name="autofill_zip_code" msgid="8697544592627322946">"Cod ZIP"</string>
<string name="autofill_county" msgid="237073771020362891">"Județ"</string>
@@ -798,10 +797,10 @@
<string name="permlab_addVoicemail" msgid="5525660026090959044">"adăugare mesagerie vocală"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permite aplicației să adauge mesaje în Mesaje primite în mesageria vocală."</string>
<string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"modificare permisiuni pentru locația geografică a browserului"</string>
- <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Permite aplicației să modifice permisiunile privind locația geografică a browserului. Aplicațiile rău intenţionate pot utiliza această permisiune pentru a permite trimiterea informațiilor privind locația către site-uri web arbitrare."</string>
+ <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Permite aplicației să modifice permisiunile privind locația geografică a browserului. Aplicațiile rău intenționate pot utiliza această permisiune pentru a permite trimiterea informațiilor privind locația către site-uri web arbitrare."</string>
<string name="save_password_message" msgid="767344687139195790">"Doriți ca browserul să rețină această parolă?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Nu acum"</string>
- <string name="save_password_remember" msgid="6491879678996749466">"Reţineţi"</string>
+ <string name="save_password_remember" msgid="6491879678996749466">"Rețineți"</string>
<string name="save_password_never" msgid="8274330296785855105">"Niciodată"</string>
<string name="open_permission_deny" msgid="7374036708316629800">"Nu aveți permisiunea de a deschide această pagină."</string>
<string name="text_copied" msgid="4985729524670131385">"Text copiat în clipboard."</string>
@@ -818,8 +817,8 @@
<string name="searchview_description_submit" msgid="2688450133297983542">"Trimiteți interogarea"</string>
<string name="searchview_description_voice" msgid="2453203695674994440">"Căutare vocală"</string>
<string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"Activați Explorați prin atingere?"</string>
- <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> dorește să activeze funcția Explorați prin atingere. Când această funcție este activată, puteți auzi sau vedea descrieri pentru ceea ce se află sub degetul dvs. sau puteți efectua gesturi pentru a interacţiona cu tableta."</string>
- <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> dorește să activeze funcția Explorați prin atingere. Când această funcție este activată, puteți auzi sau vedea descrieri pentru ceea ce se află sub degetul dvs. sau puteți efectua gesturi pentru a interacţiona cu telefonul."</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> dorește să activeze funcția Explorați prin atingere. Când această funcție este activată, puteți auzi sau vedea descrieri pentru ceea ce se află sub degetul dvs. sau puteți efectua gesturi pentru a interacționa cu tableta."</string>
+ <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> dorește să activeze funcția Explorați prin atingere. Când această funcție este activată, puteți auzi sau vedea descrieri pentru ceea ce se află sub degetul dvs. sau puteți efectua gesturi pentru a interacționa cu telefonul."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"cu 1 lună în urmă"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Cu mai mult de 1 lună în urmă"</string>
<plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
@@ -866,8 +865,8 @@
<string name="relative_time" msgid="1818557177829411417">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="noon" msgid="7245353528818587908">"prânz"</string>
<string name="Noon" msgid="3342127745230013127">"Prânz"</string>
- <string name="midnight" msgid="7166259508850457595">"miezul nopţii"</string>
- <string name="Midnight" msgid="5630806906897892201">"Miezul nopţii"</string>
+ <string name="midnight" msgid="7166259508850457595">"miezul nopții"</string>
+ <string name="Midnight" msgid="5630806906897892201">"Miezul nopții"</string>
<string name="elapsed_time_short_format_mm_ss" msgid="4431555943828711473">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
<string name="elapsed_time_short_format_h_mm_ss" msgid="1846071997616654124">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
<string name="selectAll" msgid="6876518925844129331">"Selectați-le pe toate"</string>
@@ -882,12 +881,12 @@
<string name="undo" msgid="7905788502491742328">"Anulați"</string>
<string name="redo" msgid="7759464876566803888">"Repetați"</string>
<string name="textSelectionCABTitle" msgid="5236850394370820357">"Selectare text"</string>
- <string name="addToDictionary" msgid="4352161534510057874">"Adăugați în dicţionar"</string>
+ <string name="addToDictionary" msgid="4352161534510057874">"Adăugați în dicționar"</string>
<string name="deleteText" msgid="6979668428458199034">"Ștergeți"</string>
<string name="inputMethod" msgid="1653630062304567879">"Metodă de intrare"</string>
- <string name="editTextMenuTitle" msgid="4909135564941815494">"Acţiuni pentru text"</string>
- <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Spaţiul de stocare aproape ocupat"</string>
- <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Este posibil ca unele funcții de sistem să nu funcţioneze"</string>
+ <string name="editTextMenuTitle" msgid="4909135564941815494">"Acțiuni pentru text"</string>
+ <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Spațiul de stocare aproape ocupat"</string>
+ <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Este posibil ca unele funcții de sistem să nu funcționeze"</string>
<string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Spațiu de stocare insuficient pentru sistem. Asigurați-vă că aveți 250 MB de spațiu liber și reporniți."</string>
<string name="app_running_notification_title" msgid="8718335121060787914">"<xliff:g id="APP_NAME">%1$s</xliff:g> rulează acum"</string>
<string name="app_running_notification_text" msgid="4653586947747330058">"Atingeți pentru mai multe informații sau pentru a opri aplicația."</string>
@@ -923,7 +922,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Resetați și reporniți aplicația"</string>
<string name="aerr_report" msgid="5371800241488400617">"Trimiteți feedback"</string>
<string name="aerr_close" msgid="2991640326563991340">"Închideți"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Dezactivați"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Dezactivați până la repornirea dispozitivului"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Așteptați"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Închideți aplicația"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -933,11 +932,11 @@
<string name="anr_process" msgid="6156880875555921105">"Procesul <xliff:g id="PROCESS">%1$s</xliff:g> nu răspunde"</string>
<string name="force_close" msgid="8346072094521265605">"OK"</string>
<string name="report" msgid="4060218260984795706">"Raportați"</string>
- <string name="wait" msgid="7147118217226317732">"Aşteptaţi"</string>
+ <string name="wait" msgid="7147118217226317732">"Așteptați"</string>
<string name="webpage_unresponsive" msgid="3272758351138122503">"Pagina a devenit inactivă.\n\nDoriți să o închideți?"</string>
- <string name="launch_warning_title" msgid="1547997780506713581">"Aplicaţie redirecționată"</string>
- <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> funcţionează acum."</string>
- <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> a fost lansată iniţial."</string>
+ <string name="launch_warning_title" msgid="1547997780506713581">"Aplicație redirecționată"</string>
+ <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> funcționează acum."</string>
+ <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> a fost lansată inițial."</string>
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Scară"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Afișați întotdeauna"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Reactivați acest mod din Setări de sistem > Aplicații > Descărcate."</string>
@@ -952,11 +951,11 @@
<string name="android_upgrading_complete" msgid="1405954754112999229">"Se finalizează pornirea."</string>
<string name="heavy_weight_notification" msgid="9087063985776626166">"Rulează <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="heavy_weight_notification_detail" msgid="1721681741617898865">"Atingeți pentru a comuta la aplicație"</string>
- <string name="heavy_weight_switcher_title" msgid="7153167085403298169">"Comutaţi între aplicații?"</string>
+ <string name="heavy_weight_switcher_title" msgid="7153167085403298169">"Comutați între aplicații?"</string>
<string name="heavy_weight_switcher_text" msgid="7022631924534406403">"O altă aplicație rulează deja și trebuie oprită înainte a putea porni o aplicație nouă."</string>
- <string name="old_app_action" msgid="493129172238566282">"Reveniţi la <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+ <string name="old_app_action" msgid="493129172238566282">"Reveniți la <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
<string name="old_app_description" msgid="2082094275580358049">"Nu porniți aplicația nouă."</string>
- <string name="new_app_action" msgid="5472756926945440706">"Porniţi <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+ <string name="new_app_action" msgid="5472756926945440706">"Porniți <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
<string name="new_app_description" msgid="1932143598371537340">"Opriți vechea aplicație fără să salvați."</string>
<string name="dump_heap_notification" msgid="2618183274836056542">"<xliff:g id="PROC">%1$s</xliff:g> a depășit limita de memorie"</string>
<string name="dump_heap_notification_detail" msgid="2075673362317481664">"Datele privind memoria au fost culese; atingeți pentru a trimite"</string>
@@ -992,7 +991,7 @@
<item quantity="other">Rețele Wi-Fi deschise disponibile</item>
<item quantity="one">Rețea Wi-Fi deschisă disponibilă</item>
</plurals>
- <string name="wifi_available_sign_in" msgid="9157196203958866662">"Conectați-vă la reţeaua Wi-Fi"</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) -->
<skip />
@@ -1004,26 +1003,26 @@
<string name="wifi_connect_alert_message" msgid="6451273376815958922">"Aplicația %1$s dorește să se conecteze la rețeaua Wi-Fi %2$s"</string>
<string name="wifi_connect_default_application" msgid="7143109390475484319">"O aplicație"</string>
<string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
- <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Porniţi Wi-Fi Direct. Acest lucru va dezactiva clientul/hotspotul Wi-Fi."</string>
+ <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Porniți Wi-Fi Direct. Acest lucru va dezactiva clientul/hotspotul Wi-Fi."</string>
<string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Wi-Fi Direct nu a putut porni."</string>
<string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct este activat"</string>
<string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Atingeți pentru setări"</string>
- <string name="accept" msgid="1645267259272829559">"Acceptaţi"</string>
- <string name="decline" msgid="2112225451706137894">"Refuzaţi"</string>
+ <string name="accept" msgid="1645267259272829559">"Acceptați"</string>
+ <string name="decline" msgid="2112225451706137894">"Refuzați"</string>
<string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Invitația a fost trimisă."</string>
<string name="wifi_p2p_invitation_to_connect_title" msgid="4958803948658533637">"Invitație pentru conectare"</string>
<string name="wifi_p2p_from_message" msgid="570389174731951769">"De la:"</string>
<string name="wifi_p2p_to_message" msgid="248968974522044099">"Către:"</string>
- <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Introduceţi codul PIN necesar:"</string>
+ <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Introduceți codul PIN necesar:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"Cod PIN:"</string>
<string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="8012981257742232475">"Tableta se va deconecta temporar de la rețeaua Wi-Fi cât timp este conectată la <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="3087858235069421128">"Televizorul se va deconecta temporar de la rețeaua Wi-Fi cât timp este conectat la <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
- <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Telefonul se va deconecta temporar de la reţeaua Wi-Fi cât timp este conectat la <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
- <string name="select_character" msgid="3365550120617701745">"Introduceţi caracterul"</string>
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"Telefonul se va deconecta temporar de la rețeaua Wi-Fi cât timp este conectat la <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+ <string name="select_character" msgid="3365550120617701745">"Introduceți caracterul"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Se trimit mesaje SMS"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> trimite un număr mare de mesaje SMS. Permiteți acestei aplicații să trimită în continuare mesaje?"</string>
<string name="sms_control_yes" msgid="3663725993855816807">"Permiteți"</string>
- <string name="sms_control_no" msgid="625438561395534982">"Refuzaţi"</string>
+ <string name="sms_control_no" msgid="625438561395534982">"Refuzați"</string>
<string name="sms_short_code_confirm_message" msgid="1645436466285310855">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> intenționează să trimită un mesaj la <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b>."</string>
<string name="sms_short_code_details" msgid="5873295990846059400">"Acest lucru "<b>"poate genera costuri"</b>" în contul dvs. mobil."</string>
<string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"Acest lucru va genera costuri în contul dvs. mobil."</b></string>
@@ -1038,14 +1037,14 @@
<string name="sim_done_button" msgid="827949989369963775">"Terminat"</string>
<string name="sim_added_title" msgid="3719670512889674693">"Card SIM adăugat"</string>
<string name="sim_added_message" msgid="7797975656153714319">"Reporniți dispozitivul pentru a accesa rețeaua mobilă."</string>
- <string name="sim_restart_button" msgid="4722407842815232347">"Reporniţi"</string>
+ <string name="sim_restart_button" msgid="4722407842815232347">"Reporniți"</string>
<string name="carrier_app_dialog_message" msgid="7066156088266319533">"Pentru ca noul SIM să funcționeze corect, va trebui să instalați și să deschideți o aplicație de la operatorul dvs."</string>
<string name="carrier_app_dialog_button" msgid="7900235513678617329">"DESCĂRCAȚI APLICAȚIA"</string>
<string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"NU ACUM"</string>
<string name="carrier_app_notification_title" msgid="8921767385872554621">"S-a introdus un card SIM nou"</string>
<string name="carrier_app_notification_text" msgid="1132487343346050225">"Atingeți pentru a-l configura"</string>
- <string name="time_picker_dialog_title" msgid="8349362623068819295">"Setaţi ora"</string>
- <string name="date_picker_dialog_title" msgid="5879450659453782278">"Setaţi data"</string>
+ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Setați ora"</string>
+ <string name="date_picker_dialog_title" msgid="5879450659453782278">"Setați data"</string>
<string name="date_time_set" msgid="5777075614321087758">"Setați"</string>
<string name="date_time_done" msgid="2507683751759308828">"Terminat"</string>
<string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NOU: "</font></string>
@@ -1061,16 +1060,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Atingeți pentru mai multe opțiuni."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Depanarea USB este conectată"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Atingeți pentru a dezactiva depanarea USB."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Trimiteți raportul de eroare?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Se trimite raportul de eroare…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Administratorul IT a solicitat un raport de eroare pentru a remedia problemele acestui dispozitiv. Este posibil să se permită accesul la date și aplicații, iar funcționarea dispozitivului poate fi încetinită temporar."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Administratorul IT a solicitat un raport de eroare pentru a remedia problemele acestui dispozitiv. Este posibil să se permită accesul la date și aplicații."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Acest proces poate încetini temporar funcționarea dispozitivului"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ACCEPTAȚI"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"REFUZAȚI"</string>
<string name="select_input_method" msgid="8547250819326693584">"Schimbați tastatura"</string>
@@ -1125,7 +1119,7 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Permite unei aplicații accesul la citirea sesiunilor de instalare. Aceasta poate vedea detalii despre instalările de pachete active."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"să solicite pachete de instalare"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permite unei aplicații să solicite instalarea pachetelor."</string>
- <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Atingeți de două ori pentru a mări/micşora"</string>
+ <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Atingeți de două ori pentru a mări/micșora"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Nu s-a putut adăuga widgetul."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Accesați"</string>
<string name="ime_action_search" msgid="658110271822807811">"Căutați"</string>
@@ -1134,13 +1128,13 @@
<string name="ime_action_done" msgid="8971516117910934605">"Terminat"</string>
<string name="ime_action_previous" msgid="1443550039250105948">"Înapoi"</string>
<string name="ime_action_default" msgid="2840921885558045721">"Executați"</string>
- <string name="dial_number_using" msgid="5789176425167573586">"Formaţi numărul\nutilizând <xliff:g id="NUMBER">%s</xliff:g>"</string>
+ <string name="dial_number_using" msgid="5789176425167573586">"Formați numărul\nutilizând <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="create_contact_using" msgid="4947405226788104538">"Creați contactul\nutilizând <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"Următoarele aplicații solicită permisiunea de a accesa contul dvs. acum și în viitor."</string>
<string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"Permiteți această solicitare?"</string>
<string name="grant_permissions_header_text" msgid="6874497408201826708">"Solicitare de acces"</string>
<string name="allow" msgid="7225948811296386551">"Permiteți"</string>
- <string name="deny" msgid="2081879885755434506">"Refuzaţi"</string>
+ <string name="deny" msgid="2081879885755434506">"Refuzați"</string>
<string name="permission_request_notification_title" msgid="6486759795926237907">"Permisiune solicitată"</string>
<string name="permission_request_notification_with_subtitle" msgid="8530393139639560189">"Permisiune solicitată\npentru contul <xliff:g id="ACCOUNT">%s</xliff:g>."</string>
<string name="forward_intent_to_owner" msgid="1207197447013960896">"Utilizați această aplicație în afara profilului de serviciu"</string>
@@ -1149,29 +1143,29 @@
<string name="sync_binding_label" msgid="3687969138375092423">"Sincronizare"</string>
<string name="accessibility_binding_label" msgid="4148120742096474641">"Accesibilitate"</string>
<string name="wallpaper_binding_label" msgid="1240087844304687662">"Imagine de fundal"</string>
- <string name="chooser_wallpaper" msgid="7873476199295190279">"Modificaţi imaginea de fundal"</string>
+ <string name="chooser_wallpaper" msgid="7873476199295190279">"Modificați imaginea de fundal"</string>
<string name="notification_listener_binding_label" msgid="2014162835481906429">"Serviciu de citire a notificărilor"</string>
<string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Furnizor de condiții"</string>
<string name="notification_assistant_binding_label" msgid="909456055569102952">"Asistent pentru notificări"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN activat"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"VPN este activată de <xliff:g id="APP">%s</xliff:g>"</string>
- <string name="vpn_text" msgid="3011306607126450322">"Atingeți pentru a gestiona reţeaua."</string>
- <string name="vpn_text_long" msgid="6407351006249174473">"Conectat la <xliff:g id="SESSION">%s</xliff:g>. Atingeți pentru a gestiona reţeaua."</string>
- <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Se efectuează conectarea la reţeaua VPN activată permanent…"</string>
- <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Conectat(ă) la reţeaua VPN activată permanent"</string>
+ <string name="vpn_text" msgid="3011306607126450322">"Atingeți pentru a gestiona rețeaua."</string>
+ <string name="vpn_text_long" msgid="6407351006249174473">"Conectat la <xliff:g id="SESSION">%s</xliff:g>. Atingeți pentru a gestiona rețeaua."</string>
+ <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Se efectuează conectarea la rețeaua VPN activată permanent…"</string>
+ <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Conectat(ă) la rețeaua VPN activată permanent"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Eroare de rețea VPN activată permanent"</string>
<string name="vpn_lockdown_config" msgid="6415899150671537970">"Atingeți pentru a configura"</string>
<string name="upload_file" msgid="2897957172366730416">"Alegeți un fișier"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Nu au fost găsite fișiere"</string>
- <string name="reset" msgid="2448168080964209908">"Resetaţi"</string>
+ <string name="reset" msgid="2448168080964209908">"Resetați"</string>
<string name="submit" msgid="1602335572089911941">"Trimiteți"</string>
- <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Mod Maşină activat"</string>
- <string name="car_mode_disable_notification_message" msgid="8035230537563503262">"Atingeți pentru a ieşi din modul Maşină."</string>
+ <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Mod Mașină activat"</string>
+ <string name="car_mode_disable_notification_message" msgid="8035230537563503262">"Atingeți pentru a ieși din modul Mașină."</string>
<string name="tethered_notification_title" msgid="3146694234398202601">"Tethering sau hotspot activ"</string>
<string name="tethered_notification_message" msgid="6857031760103062982">"Atingeți pentru a configura."</string>
<string name="back_button_label" msgid="2300470004503343439">"Înapoi"</string>
<string name="next_button_label" msgid="1080555104677992408">"Înainte"</string>
- <string name="skip_button_label" msgid="1275362299471631819">"Omiteţi"</string>
+ <string name="skip_button_label" msgid="1275362299471631819">"Omiteți"</string>
<string name="no_matches" msgid="8129421908915840737">"Nicio potrivire"</string>
<string name="find_on_page" msgid="1946799233822820384">"Găsiți pe pagină"</string>
<plurals name="matches_found" formatted="false" msgid="1210884353962081884">
@@ -1192,10 +1186,10 @@
<string name="gpsNotifMessage" msgid="1374718023224000702">"Solicitat de <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"Da"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"Nu"</string>
- <string name="sync_too_many_deletes" msgid="5296321850662746890">"Limita pentru ştergere a fost depăşită"</string>
- <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"Există <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> (de) elemente şterse pentru <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>, contul <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g>. Ce doriți să faceți?"</string>
+ <string name="sync_too_many_deletes" msgid="5296321850662746890">"Limita pentru ștergere a fost depășită"</string>
+ <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"Există <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> (de) elemente șterse pentru <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>, contul <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g>. Ce doriți să faceți?"</string>
<string name="sync_really_delete" msgid="2572600103122596243">"Ștergeți elementele"</string>
- <string name="sync_undo_deletes" msgid="2941317360600338602">"Anulați aceste ştergeri"</string>
+ <string name="sync_undo_deletes" msgid="2941317360600338602">"Anulați aceste ștergeri"</string>
<string name="sync_do_nothing" msgid="3743764740430821845">"Nu trebuie să luați nicio măsură deocamdată"</string>
<string name="choose_account_label" msgid="5655203089746423927">"Alegeți un cont"</string>
<string name="add_account_label" msgid="2935267344849993553">"Adăugați un cont"</string>
@@ -1203,13 +1197,13 @@
<string name="number_picker_increment_button" msgid="2412072272832284313">"Creșteți"</string>
<string name="number_picker_decrement_button" msgid="476050778386779067">"Reduceți"</string>
<string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Atingeți și țineți apăsat <xliff:g id="VALUE">%s</xliff:g>."</string>
- <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Glisaţi în sus pentru a creşte și în jos pentru a reduce."</string>
+ <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Glisați în sus pentru a crește și în jos pentru a reduce."</string>
<string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Creșteți valoarea pentru minute"</string>
<string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Reduceți valoarea pentru minute"</string>
<string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Creșteți valoarea pentru oră"</string>
<string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Reduceți valoarea pentru oră"</string>
- <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Setaţi valoarea PM"</string>
- <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Setaţi valoarea AM"</string>
+ <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Setați valoarea PM"</string>
+ <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Setați valoarea AM"</string>
<string name="date_picker_increment_month_button" msgid="5369998479067934110">"Creșteți valoarea pentru lună"</string>
<string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Reduceți valoarea pentru lună"</string>
<string name="date_picker_increment_day_button" msgid="7130465412308173903">"Creșteți valoarea pentru zi"</string>
@@ -1230,11 +1224,11 @@
<string name="shareactionprovider_share_with" msgid="806688056141131819">"Permiteți accesul pentru"</string>
<string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Permiteți accesul pentru <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
<string name="content_description_sliding_handle" msgid="415975056159262248">"Mâner glisant. Atingeți și țineți apăsat."</string>
- <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Glisaţi pentru a debloca."</string>
- <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Conectaţi un set căşti-microfon pentru a auzi tastele apăsate când introduceţi parola."</string>
+ <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Glisați pentru a debloca."</string>
+ <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Conectați un set căști-microfon pentru a auzi tastele apăsate când introduceți parola."</string>
<string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punct."</string>
- <string name="action_bar_home_description" msgid="5293600496601490216">"Navigaţi la ecranul de pornire"</string>
- <string name="action_bar_up_description" msgid="2237496562952152589">"Navigaţi în sus"</string>
+ <string name="action_bar_home_description" msgid="5293600496601490216">"Navigați la ecranul de pornire"</string>
+ <string name="action_bar_up_description" msgid="2237496562952152589">"Navigați în sus"</string>
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Mai multe opțiuni"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
@@ -1252,12 +1246,12 @@
<string name="data_usage_mobile_limit_title" msgid="557158376602636112">"Ați atins limita de date mobile"</string>
<string name="data_usage_wifi_limit_title" msgid="5803363779034792676">"Ați atins limita de date Wi-Fi"</string>
<string name="data_usage_limit_body" msgid="291731708279614081">"S-au întrerupt datele pentru restul ciclului"</string>
- <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"S-a depăşit limita de date 2G-3G"</string>
- <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"S-a depăşit limita de date 4G"</string>
+ <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"S-a depășit limita de date 2G-3G"</string>
+ <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"S-a depășit limita de date 4G"</string>
<string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"Limită de date mobile depășită"</string>
- <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"S-a depăşit limita de date Wi-Fi"</string>
+ <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"S-a depășit limita de date Wi-Fi"</string>
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> peste limita specificată."</string>
- <string name="data_usage_restricted_title" msgid="5965157361036321914">"Datele de fundal restricţionate"</string>
+ <string name="data_usage_restricted_title" msgid="5965157361036321914">"Datele de fundal restricționate"</string>
<string name="data_usage_restricted_body" msgid="6741521330997452990">"Atingeți pt. a elimina limita."</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Certificat de securitate"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Certificatul este valid."</string>
@@ -1308,25 +1302,25 @@
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
<string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", securizat"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Model uitat"</string>
- <string name="kg_wrong_pattern" msgid="1850806070801358830">"Model greşit"</string>
+ <string name="kg_wrong_pattern" msgid="1850806070801358830">"Model greșit"</string>
<string name="kg_wrong_password" msgid="2333281762128113157">"Parolă greșită"</string>
- <string name="kg_wrong_pin" msgid="1131306510833563801">"Cod PIN greşit"</string>
+ <string name="kg_wrong_pin" msgid="1131306510833563801">"Cod PIN greșit"</string>
<string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Încercați din nou peste <xliff:g id="NUMBER">%1$d</xliff:g> (de) secunde."</string>
- <string name="kg_pattern_instructions" msgid="398978611683075868">"Desenaţi modelul"</string>
- <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Introduceţi codul PIN al cardului SIM"</string>
- <string name="kg_pin_instructions" msgid="2377242233495111557">"Introduceţi codul PIN"</string>
- <string name="kg_password_instructions" msgid="5753646556186936819">"Introduceţi parola"</string>
- <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"Cardul SIM este acum dezactivat. Introduceţi codul PUK pentru a continua. Contactaţi operatorul pentru mai multe detalii."</string>
- <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Introduceţi codul PIN dorit"</string>
+ <string name="kg_pattern_instructions" msgid="398978611683075868">"Desenați modelul"</string>
+ <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Introduceți codul PIN al cardului SIM"</string>
+ <string name="kg_pin_instructions" msgid="2377242233495111557">"Introduceți codul PIN"</string>
+ <string name="kg_password_instructions" msgid="5753646556186936819">"Introduceți parola"</string>
+ <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"Cardul SIM este acum dezactivat. Introduceți codul PUK pentru a continua. Contactați operatorul pentru mai multe detalii."</string>
+ <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Introduceți codul PIN dorit"</string>
<string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Confirmați codul PIN dorit"</string>
<string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Se deblochează cardul SIM..."</string>
<string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Cod PIN incorect."</string>
- <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Introduceţi un cod PIN format din 4 până la 8 cifre."</string>
+ <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Introduceți un cod PIN format din 4 până la 8 cifre."</string>
<string name="kg_invalid_sim_puk_hint" msgid="6025069204539532000">"Codul PUK trebuie să conțină 8 numere."</string>
- <string name="kg_invalid_puk" msgid="3638289409676051243">"Reintroduceţi codul PUK corect. Încercările repetate vor dezactiva definitiv cardul SIM."</string>
+ <string name="kg_invalid_puk" msgid="3638289409676051243">"Reintroduceți codul PUK corect. Încercările repetate vor dezactiva definitiv cardul SIM."</string>
<string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"Codurile PIN nu coincid"</string>
<string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Prea multe încercări de desenare a modelului"</string>
- <string name="kg_login_instructions" msgid="1100551261265506448">"Pentru a debloca, conectaţi-vă cu Contul dvs. Google."</string>
+ <string name="kg_login_instructions" msgid="1100551261265506448">"Pentru a debloca, conectați-vă cu Contul dvs. Google."</string>
<string name="kg_login_username_hint" msgid="5718534272070920364">"Nume de utilizator (e-mail)"</string>
<string name="kg_login_password_hint" msgid="9057289103827298549">"Parolă"</string>
<string name="kg_login_submit_button" msgid="5355904582674054702">"Conectați-vă"</string>
@@ -1336,17 +1330,17 @@
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Ați introdus incorect codul PIN de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori.\n\nÎncercați din nou peste <xliff:g id="NUMBER_1">%2$d</xliff:g> (de) secunde."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Ați introdus incorect parola de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. \n\nÎncercați din nou peste <xliff:g id="NUMBER_1">%2$d</xliff:g> (de) secunde."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Ați desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. \n\nÎncercați din nou peste <xliff:g id="NUMBER_1">%2$d</xliff:g> (de) secunde."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Ați efectuat <xliff:g id="NUMBER_0">%1$d</xliff:g> încercări incorecte de deblocare a tabletei. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereuşite, aceasta va fi resetată la setările prestabilite din fabrică, iar toate datele de utilizator se vor pierde."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Ați efectuat <xliff:g id="NUMBER_0">%1$d</xliff:g> încercări incorecte de deblocare a tabletei. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, aceasta va fi resetată la setările prestabilite din fabrică, iar toate datele de utilizator se vor pierde."</string>
<string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="5621231220154419413">"Ați efectuat <xliff:g id="NUMBER_0">%1$d</xliff:g> încercări incorecte de deblocare a televizorului. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, televizorul va reveni la setările prestabilite din fabrică, iar toate datele de utilizator se vor pierde."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Ați efectuat <xliff:g id="NUMBER_0">%1$d</xliff:g> încercări incorecte de deblocare a telefonului. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereuşite, acesta va fi resetat la setările prestabilite din fabrică, iar toate datele de utilizator se vor pierde."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Ați efectuat <xliff:g id="NUMBER_0">%1$d</xliff:g> încercări incorecte de deblocare a telefonului. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, acesta va fi resetat la setările prestabilite din fabrică, iar toate datele de utilizator se vor pierde."</string>
<string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Ați efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a tabletei. Tableta va fi acum resetată la setările prestabilite din fabrică."</string>
<string name="kg_failed_attempts_now_wiping" product="tv" msgid="4987878286750741463">"Ați efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a televizorului. Televizorul va reveni acum la setările prestabilite din fabrică."</string>
<string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Ați efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a telefonului. Telefonul va fi acum resetat la setările prestabilite din fabrică."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Ați desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereuşite, vi se va solicita să deblocați tableta cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> (de) secunde."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Ați desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, vi se va solicita să deblocați tableta cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> (de) secunde."</string>
<string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4224651132862313471">"Ați desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, vi se va solicita să deblocați televizorul cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> (de) secunde."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Ați desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereuşite, vi se va solicita să deblocați telefonul cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> (de) secunde."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Ați desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, vi se va solicita să deblocați telefonul cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> (de) secunde."</string>
<string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
- <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Eliminaţi"</string>
+ <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Eliminați"</string>
<string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"Ridicați volumul mai sus de nivelul recomandat?\n\nAscultarea la volum ridicat pe perioade lungi de timp vă poate afecta auzul."</string>
<string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Mențineți două degete pe ecran pentru a activa accesibilitatea."</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"S-a activat accesibilitatea."</string>
@@ -1483,7 +1477,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Solicită codul PIN înainte de a anula fixarea"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Solicită modelul pentru deblocare înainte de a anula fixarea"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicită parola înainte de a anula fixarea"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Aplicația nu poate fi redimensionată. Derulați în ea cu două degete."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Este posibil ca aplicația să nu funcționeze cu ecranul împărțit."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplicația nu acceptă ecranul împărțit."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Instalat de administrator"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Actualizat de un administrator"</string>
@@ -1562,12 +1556,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selectate</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selectat</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Diverse"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Dvs. setați importanța acestor notificări."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Dvs. setați importanța acestor notificări."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Notificarea este importantă având în vedere persoanele implicate."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Permiteți ca <xliff:g id="APP">%1$s</xliff:g> să creeze un nou utilizator folosind <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Permiteți ca <xliff:g id="APP">%1$s</xliff:g> să creeze un nou utilizator folosind <xliff:g id="ACCOUNT">%2$s</xliff:g>? (există deja un utilizator cu acest cont)"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Limba preferată"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Adăugați o limbă"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Regiunea preferată"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Numele limbii"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugerate"</string>
@@ -1584,10 +1577,11 @@
<string name="user_encrypted_message" msgid="4923292604515744267">"Atingeți pentru a debloca"</string>
<string name="user_encrypted_detail" msgid="5708447464349420392">"Datele utilizatorului: blocate"</string>
<string name="profile_encrypted_detail" msgid="3700965619978314974">"Profil de serviciu blocat"</string>
- <string name="profile_encrypted_message" msgid="6964994232310195874">"Atingeți ca să deblocați profilul de serviciu"</string>
+ <string name="profile_encrypted_message" msgid="6964994232310195874">"Atingeți ca să deblocați"</string>
<string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Conectat la <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Atingeți pentru a vedea fișierele"</string>
<string name="pin_target" msgid="3052256031352291362">"Fixați"</string>
<string name="unpin_target" msgid="3556545602439143442">"Anulați fixarea"</string>
<string name="app_info" msgid="6856026610594615344">"Informații despre aplicație"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 8ed321f..85cbdc4 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -90,7 +90,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Идентификация абонента по умолчанию не запрещена. След. вызов: разрешена"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Услуга не предоставляется."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Невозможно изменить параметр идентификатора вызывающего абонента."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Ограничения доступа изменены"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Служба данных заблокирована."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Служба экстренной помощи заблокирована."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Служба передачи голосовых сообщений заблокирована."</string>
@@ -929,7 +928,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Сбросить и перезапустить"</string>
<string name="aerr_report" msgid="5371800241488400617">"Отправить отзыв"</string>
<string name="aerr_close" msgid="2991640326563991340">"Закрыть"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Скрыть"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Отключить до перезагрузки устройства"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Подождать"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Закрыть приложение"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1069,16 +1068,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Нажмите, чтобы настроить."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Отладка по USB разрешена"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Нажмите, чтобы отключить отладку по USB."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"Администратор запросил отчет об ошибке, чтобы устранить неполадку. Он может получить доступ к приложениям и данным. Возможно временное снижение скорости работы вашего устройства."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Администратор запросил отчет об ошибке, чтобы устранить неполадку. Он может получить доступ к приложениям и данным."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Скорость работы устройства может быть временно снижена."</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ПРИНЯТЬ"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ОТКЛОНИТЬ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Выбор раскладки"</string>
@@ -1493,7 +1487,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"PIN-код для отключения"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Запрашивать графический ключ для отключения блокировки"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Запрашивать пароль для отключения блокировки"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Размер окна нельзя изменить. Прокрутите страницу двумя пальцами."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Приложение не поддерживает разделение экрана."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Приложение не поддерживает разделение экрана."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Установлено администратором"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Обновлено администратором"</string>
@@ -1581,12 +1575,11 @@
<item quantity="many">Выбрано: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
<item quantity="other">Выбрано: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Другое"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Вы определяете важность этих уведомлений."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Вы определяете важность этих уведомлений."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Важное (люди)"</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Разрешить приложению \"<xliff:g id="APP">%1$s</xliff:g>\" создать пользователя для аккаунта <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Разрешить приложению \"<xliff:g id="APP">%1$s</xliff:g>\" создать нового пользователя для аккаунта <xliff:g id="ACCOUNT">%2$s</xliff:g> (пользователь c таким аккаунтом уже есть)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Языковые настройки"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Добавьте язык"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Региональные настройки"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Введите язык"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Рекомендуемые"</string>
@@ -1609,4 +1602,5 @@
<string name="pin_target" msgid="3052256031352291362">"Закрепить"</string>
<string name="unpin_target" msgid="3556545602439143442">"Открепить"</string>
<string name="app_info" msgid="6856026610594615344">"О приложении"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index ee0afad..f37eb58 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"අමතන්නාගේ ID සුපුරුදු අනුව සීමා වී නැත. මීළඟ ඇමතුම: සීමා කර ඇත"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"සේවාවන් සපයා නැත."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"අමතන්නාගේ ID සැකසීම ඔබට වෙනස්කල නොහැක."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"සීමිත ප්රවේශය වෙනස් කෙරිණි"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"දත්ත සේවාව අවහිර කර ඇත."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"හදිසි සේවාව අවහිර කර ඇත."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"හඬ සේවාව බාධා කර ඇත."</string>
@@ -919,7 +918,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"යෙදුම නැවත සකසා නැවත ආරම්භ කරන්න"</string>
<string name="aerr_report" msgid="5371800241488400617">"ප්රතිපෝෂණය යවන්න"</string>
<string name="aerr_close" msgid="2991640326563991340">"වසන්න"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"නිහඬ කරන්න"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"උපාංගය නැවත ආරම්භ වන තෙක් නිහඬ කරන්න"</string>
<string name="aerr_wait" msgid="3199956902437040261">"රැඳී සිටින්න"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"යෙදුම වසන්න"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1055,16 +1054,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"වඩා වැඩි විකල්ප සඳහා ස්පර්ශ කරන්න."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB නිදොස්කරණය සම්බන්ධිතයි"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB නිදොස්කරණය අබල කිරීමට ස්පර්ශ කරන්න."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"මෙම උපාංගය දෝෂාවේක්ෂණය සඳහා උදවු කිරීමට ඔබේ IT පරිපාලක දෝෂ වාර්තාවක් ඉල්ලා ඇත. යෙදුම් සහ දත්ත බෙදා ගත හැකි අතර ඔබේ උපාංගය තාවකාලිකව මන්දගාමී විය හැකිය."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"මෙම උපාංගය දෝෂාවේක්ෂණය සඳහා උදවු කිරීමට ඔබේ IT පරිපාලක දෝෂ වාර්තාවක් ඉල්ලා ඇත. යෙදුම් සහ දත්ත බෙදා ගත හැකිය."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"මෙය ඔබේ උපාංගය තාවකාලිකව මන්දගාමී කළ හැකිය"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"පිළිගන්න"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ප්රතික්ෂේප කරන්න"</string>
<string name="select_input_method" msgid="8547250819326693584">"යතුරු පුවරු වෙනස් කිරීම"</string>
@@ -1475,7 +1469,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ගැලවීමට පෙර PIN විමසන්න"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ගැලවීමට පෙර අගුළු අරින රටාව සඳහා අසන්න"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ගැලවීමට පෙර මුරපදය විමසන්න"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"යෙදුම ප්රතිප්රමාණ කළ හැකි නොවේ, එය ඇඟිලි දෙකකින් අනුචලනය කරන්න."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"යෙදුම බෙදුම්-තිරය සමග ක්රියා නොකළ හැකිය."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"යෙදුම බෙදුණු-තිරය සඳහා සහාය නොදක්වයි."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"ඔබගේ පරිපාලක විසින් ස්ථාපනය කරන ලද"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"ඔබගේ පරිපාලක විසින් යාවත්කාලීන කරන ලදී"</string>
@@ -1545,12 +1539,11 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ක් තෝරන ලදි</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ක් තෝරන ලදි</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"විවිධාකාර"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"ඔබ මෙම දැනුම්දීම්වල වැදගත්කම සකසා ඇත."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"ඔබ මෙම දැනුම්දීම්වල වැදගත්කම සකසා ඇත."</string>
<string name="importance_from_person" msgid="9160133597262938296">"සම්බන්ධ වූ පුද්ගලයන් නිසා මෙය වැදගත් වේ."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> හට <xliff:g id="ACCOUNT">%2$s</xliff:g> සමගින් නව පරිශීලකයෙකු සෑදීමට ඉඩ දෙන්නද?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> හට <xliff:g id="ACCOUNT">%2$s</xliff:g> සමගින් නව පරිශීලකයෙකු සෑදීමට ඉඩ දෙන්නද (මෙම ගිණුම සහිත පරිශීලකයෙකු දැනටමත් සිටී) ?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"භාෂා මනාප"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"භාෂාවක් එක් කරන්න"</string>
<string name="country_selection_title" msgid="2954859441620215513">"ප්රදේශ මනාපය"</string>
<string name="search_language_hint" msgid="7042102592055108574">"භාෂා නම ටයිප් කරන්න"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"යෝජිත"</string>
@@ -1573,4 +1566,5 @@
<string name="pin_target" msgid="3052256031352291362">"අමුණන්න"</string>
<string name="unpin_target" msgid="3556545602439143442">"ගලවන්න"</string>
<string name="app_info" msgid="6856026610594615344">"යෙදුම් තොරතුරු"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 88e3939..ddb162a 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -90,7 +90,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"V predvolenom nastavení nie je identifikácia volajúceho obmedzená. Ďalší hovor: Bez obmedzenia"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Služba nie je poskytovaná."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Nemôžete meniť nastavenia identifikácie volajúceho."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Obmedzený prístup bol zmenený"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Údajová služba je zablokovaná."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Tiesňová služba je zablokovaná."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Hlasová služba je zablokovaná."</string>
@@ -929,7 +928,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Resetovať a reštartovať aplikáciu"</string>
<string name="aerr_report" msgid="5371800241488400617">"Odoslať spätnú väzbu"</string>
<string name="aerr_close" msgid="2991640326563991340">"Zavrieť"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Ignorovať"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Ignorovať do reštartu zariadenia"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Čakať"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Zavrieť aplikáciu"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1069,16 +1068,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Ďalšie možnosti zobrazíte klepnutím."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Ladenie cez USB pripojené"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Klepnutím zakážete ladenie cez USB"</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Chcete zdieľať hlásenie chyby?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Zdieľa sa hlásenie chyby…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Správca IT si vyžiadal hlásenie chyby, aby mohol vyriešiť problém na tomto zariadení. Aplikácie a dáta môžu byť zdieľané. Môže to dočasne spomaliť vaše zariadenie."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Správca IT si vyžiadal hlásenie chyby, aby mohol vyriešiť problém na tomto zariadení. Aplikácie a dáta môžu byť zdieľané."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Môže to dočasne spomaliť vaše zariadenie."</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"PRIJAŤ"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ODMIETNUŤ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Zmeniť klávesnicu"</string>
@@ -1493,7 +1487,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Pred uvoľnením požiadať o číslo PIN"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pred uvoľnením požiadať o bezpečnostný vzor"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pred uvoľnením požiadať o heslo"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Veľkosť aplikácie nie je možné zmeniť. Zobrazenie môžete posúvať dvoma prstami."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikácia nemusí fungovať so zapnutou rozdelenou obrazovkou."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikácia nepodporuje rozdelenú obrazovku."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Inštalovaný správcom"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Aktualizované správcom"</string>
@@ -1581,12 +1575,11 @@
<item quantity="other">Vybrané: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
<item quantity="one">Vybrané: <xliff:g id="COUNT_0">%1$d</xliff:g></item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Rôzne"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Nastavili ste dôležitosť týchto upozornení."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Nastavili ste dôležitosť týchto upozornení."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Táto správa je dôležitá vzhľadom na osoby, ktorých sa to týka."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Povoliť aplikácii <xliff:g id="APP">%1$s</xliff:g> vytvoriť nového používateľa pomocou účtu <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Povoliť aplikácii <xliff:g id="APP">%1$s</xliff:g> vytvoriť nového používateľa pomocou účtu <xliff:g id="ACCOUNT">%2$s</xliff:g> (používateľ s týmto účtom už existuje)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Jazykové predvoľby"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Pridať jazyk"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Preferovaný región"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Zadajte názov jazyka"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Navrhované"</string>
@@ -1609,4 +1602,5 @@
<string name="pin_target" msgid="3052256031352291362">"Pripnúť"</string>
<string name="unpin_target" msgid="3556545602439143442">"Uvoľniť"</string>
<string name="app_info" msgid="6856026610594615344">"Info o aplikácii"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index e821a7f..47330fb 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -90,7 +90,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"ID klicatelja je ponastavljen na neomejeno. Naslednji klic: ni omejeno"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Storitev ni nastavljena in omogočena."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Ne morete spremeniti nastavitve ID-ja klicatelja."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Omejen dostop je spremenjen"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Podatkovna storitev je blokirana."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Klic v sili je blokiran."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Glasovna storitev je blokirana."</string>
@@ -929,7 +928,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Ponastavitev in vnovični zagon aplikacije"</string>
<string name="aerr_report" msgid="5371800241488400617">"Pošlji povratne informacije"</string>
<string name="aerr_close" msgid="2991640326563991340">"Zapri"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Prezri"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Prezri do vnovičnega zagona naprave"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Počakajte"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Zapri aplikacijo"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1069,16 +1068,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Za več možnosti se dotaknite."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Iskanje in odpravljanje napak USB je povezano"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Dotaknite se, če želite onemogočiti iskanje in odpravljanje napak prek vrat USB."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Želite poslati poročilo o napakah?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Pošiljanje poročila o napakah …"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Skrbnik za IT je zahteval poročilo o napakah za pomoč pri odpravljanju napak v tej napravi. Aplikacije in podatki bodo morda dani v skupno rabo in delovanje naprave bo morda začasno upočasnjeno."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Skrbnik za IT je zahteval poročilo o napakah za pomoč pri odpravljanju napak v tej napravi. Aplikacije in podatki bodo morda dani v skupno rabo."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"To bo morda začasno upočasnilo delovanje naprave"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"SPREJMEM"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"NE SPREJMEM"</string>
<string name="select_input_method" msgid="8547250819326693584">"Sprememba tipkovnice"</string>
@@ -1493,7 +1487,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Zahtevaj PIN pred odpenjanjem"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pred odpenjanjem vprašaj za vzorec za odklepanje"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pred odpenjanjem vprašaj za geslo"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Velikosti aplikacije ni mogoče spremeniti. Po njej se pomikajte z dvema prstoma."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikacija morda ne deluje v načinu razdeljenega zaslona."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikacija ne podpira načina razdeljenega zaslona."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Namestil skrbnik"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Posodobil skrbnik"</string>
@@ -1581,12 +1575,11 @@
<item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> izbrani</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> izbranih</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Razno"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Vi določite raven pomembnosti teh obvestil."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Vi določite raven pomembnosti teh obvestil."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Pomembno zaradi udeleženih ljudi."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Dovolite, da aplikacija <xliff:g id="APP">%1$s</xliff:g> ustvari novega uporabnika za račun <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Dovolite aplikaciji <xliff:g id="APP">%1$s</xliff:g>, da ustvari novega uporabnika za račun <xliff:g id="ACCOUNT">%2$s</xliff:g> (uporabnik s tem računom že obstaja)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Nastavitev jezika"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Dodajanje jezika"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Nastavitev območja"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Vnesite ime jezika"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Predlagano"</string>
@@ -1609,4 +1602,5 @@
<string name="pin_target" msgid="3052256031352291362">"Pripenjanje"</string>
<string name="unpin_target" msgid="3556545602439143442">"Odpenjanje"</string>
<string name="app_info" msgid="6856026610594615344">"Podatki o aplikaciji"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index ed2c066..db46b89 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"ID-ja e telefonuesit kalon me paracaktim në listën e të telefonuesve të pakufizuar. Telefonata e radhës: e pakufizuar!"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Shërbimi nuk është përgatitur."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Nuk mund ta ndryshosh cilësimin e ID-së së telefonuesit."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Qasja e kufizuar u ndryshua"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Shërbimi i të dhënave është i bllokuar."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Shërbimi i urgjencës është i bllokuar."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Shërbimi me zë është bllokuar."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Rivendos dhe rinis aplikacionin"</string>
<string name="aerr_report" msgid="5371800241488400617">"Dërgo komentin"</string>
<string name="aerr_close" msgid="2991640326563991340">"Mbyll"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Çaktivizo audion"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Vendose në heshtje deri kur të riniset pajisja"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Prit!"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Mbyll aplikacionin"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Prek për më shumë opsione."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Korrigjuesi i USB-së i lidhur"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Prek për të çaktivizuar korrigjimin e gabimeve të USB-së."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Të ndahet raporti i defektit në kod?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Po ndan raportin e defekteve në kod..."</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Administratori i teknologjisë së informacionit kërkoi një raport të defekteve në kod për të ndihmuar me zgjidhjen e problemeve. Aplikacioni dhe të dhënat mund të ndahen dhe kjo mund të ngadalësojë përkohësisht pajisjen tënde."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Administratori i teknologjisë së informacionit kërkoi një raport të defekteve në kod për të ndihmuar me zgjidhjen e problemeve. Aplikacioni dhe të dhënat mund të ndahen."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Kjo mund të ngadalësojë përkohësisht pajisjen tënde"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"PRANO"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"REFUZO"</string>
<string name="select_input_method" msgid="8547250819326693584">"Ndërro tastierë"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Zhgozhdimi kërkon PIN-in"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Kërko model shkyçjeje para heqjes së gozhdimit"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Kërko fjalëkalim para heqjes nga gozhdimi."</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Përmasa e apl. nuk mund të ndryshohet, lëvize atë me të dy gishtat."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Aplikacioni mund të mos funksionojë me ekranin e ndarë."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikacioni nuk mbështet ekranin e ndarë."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"U instalua nga administratori yt"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Përditësuar nga administratori"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> të zgjedhura</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> i zgjedhur</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Të ndryshme"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Ke caktuar rëndësinë e këtyre njoftimeve."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Ke caktuar rëndësinë e këtyre njoftimeve."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Është i rëndësishëm për shkak të personave të përfshirë."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Dëshiron të lejosh <xliff:g id="APP">%1$s</xliff:g> që të krijojë një përdorues të ri me <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Dëshiron të lejosh <xliff:g id="APP">%1$s</xliff:g> që të krijojë një përdorues të ri me <xliff:g id="ACCOUNT">%2$s</xliff:g> (një përdorues me këtë llogari ekziston tashmë) ?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Preferenca për gjuhën"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Shto një gjuhë"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Preferenca e rajonit"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Shkruaj emrin e gjuhës"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugjeruar"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Gozhdo"</string>
<string name="unpin_target" msgid="3556545602439143442">"Zhgozhdo"</string>
<string name="app_info" msgid="6856026610594615344">"Informacioni mbi aplikacionin"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 2212c98..1e3a886 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -89,7 +89,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"ИД позиваоца подразумевано није ограничен. Следећи позив: Није ограничен."</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Услуга није добављена."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Не можете да промените подешавање ИД-а корисника."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Ограничени приступ је промењен"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Услуга за податке је блокирана."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Услуга за хитне случајеве је блокирана."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Гласовна услуга је блокирана."</string>
@@ -164,7 +163,7 @@
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Превише <xliff:g id="CONTENT_TYPE">%s</xliff:g> избрисаних ставки."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Меморија таблета је пуна! Избришите неке датотеке да бисте ослободили простор."</string>
<string name="low_memory" product="watch" msgid="4415914910770005166">"Меморија сата је пуна. Избришите неке датотеке да бисте ослободили простор."</string>
- <string name="low_memory" product="tv" msgid="516619861191025923">"Складишни простор на ТВ-у је попуњен. Избришите неке датотеке да бисте ослободили простор."</string>
+ <string name="low_memory" product="tv" msgid="516619861191025923">"Меморијски простор на ТВ-у је попуњен. Избришите неке датотеке да бисте ослободили простор."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Складиште телефона је пуно! Избришите неке датотеке како бисте ослободили простор."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Мрежа се можда надгледа"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Од стране непознате треће стране"</string>
@@ -313,7 +312,7 @@
<string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Дозвољава апликацији да учини сопствене компоненте трајним у меморији. Ово може да ограничи меморију доступну другим апликацијама и успори таблет."</string>
<string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Дозвољава апликацији да неке своје делове трајно задржи у меморији. То може да ограничи меморију доступну другим апликацијама и успори ТВ."</string>
<string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Дозвољава апликацији да учини сопствене компоненте трајним у меморији. Ово може да ограничи меморију доступну другим апликацијама и успори телефон."</string>
- <string name="permlab_getPackageSize" msgid="7472921768357981986">"мерење простора за складиштење у апликацији"</string>
+ <string name="permlab_getPackageSize" msgid="7472921768357981986">"мерење меморијског простора у апликацији"</string>
<string name="permdesc_getPackageSize" msgid="3921068154420738296">"Дозвољава апликацији да преузме величине кôда, података и кеша."</string>
<string name="permlab_writeSettings" msgid="2226195290955224730">"измена подешавања система"</string>
<string name="permdesc_writeSettings" msgid="7775723441558907181">"Дозвољава апликацији да мења податке о подешавању система. Злонамерне апликације могу да оштете конфигурацију система."</string>
@@ -886,9 +885,9 @@
<string name="deleteText" msgid="6979668428458199034">"Избриши"</string>
<string name="inputMethod" msgid="1653630062304567879">"Метод уноса"</string>
<string name="editTextMenuTitle" msgid="4909135564941815494">"Радње у вези са текстом"</string>
- <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Простор за складиштење је на измаку"</string>
+ <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Меморијски простор је на измаку"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Неке системске функције можда не функционишу"</string>
- <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Нема довољно складишног простора за систем. Уверите се да имате 250 MB слободног простора и поново покрените."</string>
+ <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Нема довољно меморијског простора за систем. Уверите се да имате 250 MB слободног простора и поново покрените."</string>
<string name="app_running_notification_title" msgid="8718335121060787914">"Апликација <xliff:g id="APP_NAME">%1$s</xliff:g> је покренута"</string>
<string name="app_running_notification_text" msgid="4653586947747330058">"Додирните за више информација или заустављање апликације."</string>
<string name="ok" msgid="5970060430562524910">"Потврди"</string>
@@ -923,7 +922,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Ресетуј и поново покрени апликацију"</string>
<string name="aerr_report" msgid="5371800241488400617">"Пошаљите повратне информације"</string>
<string name="aerr_close" msgid="2991640326563991340">"Затвори"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Игнориши"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Игнориши док се уређај не покрене поново"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Чекај"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Затвори апликацију"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1061,16 +1060,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Додирните за још опција."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Отклањање грешака са USB-а је успостављено"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Додирните да бисте онемогућили отклањање грешака са USB-а."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"ИТ администратор је затражио извештај о грешци ради лакшег решавања проблема у вези са овим уређајем. Апликације и подаци могу да се деле, а уређај ће се привремено успорити."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"ИТ администратор је затражио извештај о грешци ради лакшег решавања проблема у вези са овим уређајем. Апликације и подаци могу да се деле."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Ово ће привремено успорити уређај"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ПРИХВАТИ"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ОДБИЈ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Промените тастатуру"</string>
@@ -1483,7 +1477,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Тражи PIN пре откачињања"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Тражи шаблон за откључавање пре откачињања"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Тражи лозинку пре откачињања"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Величина апликације не може да се мења. Померајте је помоћу два прста."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Апликација можда неће функционисати са подељеним екраном."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Апликација не подржава подељени екран."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Инсталирао је ваш администратор"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Ажурирао је администратор"</string>
@@ -1562,12 +1556,11 @@
<item quantity="few">Изабране су <xliff:g id="COUNT_1">%1$d</xliff:g> ставке</item>
<item quantity="other">Изабрано је <xliff:g id="COUNT_1">%1$d</xliff:g> ставки</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Разно"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Ви подешавате важност ових обавештења."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Ви подешавате важност ових обавештења."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Ово је важно због људи који учествују."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Желите ли да дозволите апликацији <xliff:g id="APP">%1$s</xliff:g> да направи новог корисника за <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Желите ли да дозволите апликацији <xliff:g id="APP">%1$s</xliff:g> да направи новог корисника за <xliff:g id="ACCOUNT">%2$s</xliff:g> (корисник са овим налогом већ постоји)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Подешавање језика"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Додајте језик"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Подешавање региона"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Унесите назив језика"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Предложени"</string>
@@ -1590,4 +1583,5 @@
<string name="pin_target" msgid="3052256031352291362">"Закачи"</string>
<string name="unpin_target" msgid="3556545602439143442">"Откачи"</string>
<string name="app_info" msgid="6856026610594615344">"Информације о апликацији"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 8483eaa..ab61097 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Nummerpresentatörens standardinställning är inte begränsad. Nästa samtal: Inte begränsad"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Tjänsten är inte etablerad."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Det går inte att ändra inställningen för nummerpresentatör."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Begränsad åtkomst har ändrats"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Datatjänsten är blockerad."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Räddningstjänsten är blockerad."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Rösttjänsten är blockerad."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Återställ och starta om appen"</string>
<string name="aerr_report" msgid="5371800241488400617">"Skicka feedback"</string>
<string name="aerr_close" msgid="2991640326563991340">"Stäng"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Dölj"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Ignorera tills enheten har startat om"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Vänta"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Stäng appen"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Visa fler alternativ genom att trycka."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB-felsökning ansluten"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Tryck om du vill inaktivera USB-felsökning."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vill du dela felrapporten?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Felrapporten delas …"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"IT-administratören har bett om en felrapport som hjälp vid felsökningen av den här enheten. Appar och data kan komma att delas. Detta kan tillfälligt göra enheten långsammare."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"IT-administratören har bett om en felrapport som hjälp vid felsökningen av den här enheten. Appar och data kan komma att delas."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Detta kan tillfälligt göra enheten långsammare"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"GODKÄNN"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"AVVISA"</string>
<string name="select_input_method" msgid="8547250819326693584">"Byt tangentbord"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Be om pinkod innan skärmen slutar fästas"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Be om upplåsningsmönster innan skärmen slutar fästas"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Be om lösenord innan skärmen slutar fästas"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Det går inte att ändra appens storlek. Rulla med två fingrar."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Appen kanske inte fungerar med delad skärm."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Appen har inte stöd för delad skärm."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Paketet har installerats av administratören"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Uppdaterat av administratören"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> har valts</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> har valts</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Diverse"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Du anger hur viktiga aviseringarna är."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Du anger hur viktiga aviseringarna är."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Detta är viktigt på grund av personerna som deltar."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Tillåter du att <xliff:g id="APP">%1$s</xliff:g> skapar en ny användare för <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Tillåter du att <xliff:g id="APP">%1$s</xliff:g> skapar en ny användare för <xliff:g id="ACCOUNT">%2$s</xliff:g> (det finns redan en användare med det här kontot)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Språkinställning"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Lägg till ett språk"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Regionsinställningar"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Ange språket"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Förslag"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Fäst"</string>
<string name="unpin_target" msgid="3556545602439143442">"Lossa"</string>
<string name="app_info" msgid="6856026610594615344">"Info om appen"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 8564764..271c48d 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Chaguo-msingi za ID ya mpigaji simu za kutozuia. Simu ifuatayo: Haijazuiliwa"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Huduma haitathminiwi."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Hauwezi kubadilisha mpangilio wa kitambulisho cha anayepiga."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Ufikiaji uliozuiwa umebadilishwa"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Huduma ya data imezuiwa."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Huduma ya dharura imezuiwa."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Huduma ya sauti imezuiwa."</string>
@@ -919,7 +918,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Weka na uanzishe upya programu"</string>
<string name="aerr_report" msgid="5371800241488400617">"Tuma maoni yako"</string>
<string name="aerr_close" msgid="2991640326563991340">"Funga"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Komesha"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Komesha hadi kifaa kianze upya"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Subiri"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Funga programu"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1055,16 +1054,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Gusa kwa chaguo zaidi."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Utatuaji wa USB umeunganishwa"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Gusa ili uzime utatuaji wa USB."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Ungependa kushiriki ripoti ya hitilafu?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Inashiriki ripoti ya hitilafu…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Msimamizi wako wa Teknolojia ya Habari ameomba ripoti ya hitilafu ili kusaidia katika utatuzi wa kifaa hiki. Huenda hatua hii ikasababisha programu na data kushirikiwa na kupunguza kasi ya kifaa chako kwa muda."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Msimamizi wako wa TEHAMA ameomba ripoti ya hitilafu ili kusaidia katika utatuzi wa hitilafu kwenye kifaa hiki. Programu na data zinaweza kushirikiwa."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Hatua hii inaweza kupunguza kasi ya kifaa chako kwa muda"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"KUBALI"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"KATAA"</string>
<string name="select_input_method" msgid="8547250819326693584">"Badilisha kibodi"</string>
@@ -1475,7 +1469,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Omba PIN kabla hujabandua"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Omba mchoro wa kufungua kabla hujabandua"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Omba nenosiri kabla hujabandua"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Programu haiwezi kurekebishwa ukubwa, sogeza kwa kutumia vidole viwili."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Huenda programu isifanye kazi kwenye skrini inayogawanywa."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Programu haiwezi kutumia skrini iliyogawanywa."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Kilisakinishwa na msimamizi wako"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Kimesasiswa na msimamizi wako"</string>
@@ -1545,12 +1539,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> vimechaguliwa</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> kimechaguliwa</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Anuwai"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Uliweka umuhimu wa arifa hizi."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Uliweka mipangilio ya umuhimu wa arifa hizi."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Hii ni muhimu kwa sababu ya watu waliohusika."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Ungependa kuruhusu <xliff:g id="APP">%1$s</xliff:g> iunde Mtumiaji mpya ikitumia <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Ungependa kuruhusu <xliff:g id="APP">%1$s</xliff:g> iunde Mtumiaji mpya ikitumia <xliff:g id="ACCOUNT">%2$s</xliff:g> (Je, akaunti hii tayari ina Mtumiaji)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Lugha ninayopendelea"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Ongeza lugha"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Mapendeleo ya eneo"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Weka jina la lugha"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Inayopendekezwa"</string>
@@ -1573,4 +1566,5 @@
<string name="pin_target" msgid="3052256031352291362">"Bandika"</string>
<string name="unpin_target" msgid="3556545602439143442">"Bandua"</string>
<string name="app_info" msgid="6856026610594615344">"Maelezo ya programu"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index b5f3673..f49c1b5 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"அழைப்பாளர் ஐடி ஆனது வரையறுக்கப்படவில்லை என்பதற்கு இயல்பாக அமைக்கப்பட்டது. அடுத்த அழைப்பு: வரையறுக்கப்படவில்லை"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"சேவை ஒதுக்கப்படவில்லை."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"அழைப்பாளர் ஐடி அமைப்பை மாற்ற முடியாது."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"வரையறுக்கப்பட்ட அணுகல் மாற்றப்பட்டது"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"தரவு சேவை தடைசெய்யப்பட்டுள்ளது."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"அவசர சேவை தடைசெய்யப்பட்டுள்ளது."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"குரல் சேவை தடைசெய்யப்பட்டுள்ளது."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"பயன்பாட்டை மீட்டமைத்து மீண்டும் தொடங்கு"</string>
<string name="aerr_report" msgid="5371800241488400617">"கருத்து தெரிவி"</string>
<string name="aerr_close" msgid="2991640326563991340">"மூடு"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"முடக்கு"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"சாதனம் மீண்டும் தொடங்கும் வரை முடக்கு"</string>
<string name="aerr_wait" msgid="3199956902437040261">"காத்திரு"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"பயன்பாட்டை மூடு"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"கூடுதல் விருப்பங்களுக்காகத் தொடவும்."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB பிழைதிருத்தம் இணைக்கப்பட்டது"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB பிழைத்திருத்தத்தை முடக்க, தொடவும்."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"இந்தச் சாதனத்தின் பிழைகாண்பதற்கு உதவ, உங்கள் ஐடி நிர்வாகி பிழை அறிக்கையைக் கோரியுள்ளார். பயன்பாடுகளும் தரவும் பகிரப்படலாம். தற்காலிகமாக சாதனத்தின் வேகம் குறையலாம்."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"இந்தச் சாதனத்தின் பிழைகாண்பதற்கு உதவ, உங்கள் ஐடி நிர்வாகி பிழை அறிக்கையைக் கோரியுள்ளார். பயன்பாடுகளும் தரவும் பகிரப்படலாம்."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"இது தற்காலிகமாக சாதனத்தின் வேகத்தைக் குறைக்கலாம்"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"சரி"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"வேண்டாம்"</string>
<string name="select_input_method" msgid="8547250819326693584">"விசைப்பலகையை மாற்று"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"அகற்றும் முன் PINஐக் கேள்"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"அகற்றும் முன் திறத்தல் வடிவத்தைக் கேள்"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"அகற்றும் முன் கடவுச்சொல்லைக் கேள்"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"பயன்பாட்டின் அளவை மாற்ற முடியாது. இருவிரல்களைப் பயன்படுத்தி, அதை உருட்டவும்."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"திரைப் பிரிப்பில் பயன்பாடு வேலைசெய்யாமல் போகக்கூடும்."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"திரையைப் பிரிப்பதைப் பயன்பாடு ஆதரிக்கவில்லை."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"நிர்வாகி நிறுவினார்"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"உங்கள் நிர்வாகி புதுப்பித்துள்ளார்"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> தேர்ந்தெடுக்கப்பட்டன</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> தேர்ந்தெடுக்கப்பட்டது</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"இதர அமைப்பு"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"இந்த அறிவிப்புகளின் முக்கியத்துவத்தை அமைத்துள்ளீர்கள்."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"இந்த அறிவிப்புகளின் முக்கியத்துவத்தை அமைத்துள்ளீர்கள்."</string>
<string name="importance_from_person" msgid="9160133597262938296">"ஈடுபட்டுள்ளவர்களின் காரணமாக, இது முக்கியமானது."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="ACCOUNT">%2$s</xliff:g> மூலம் புதிய பயனரை உருவாக்க <xliff:g id="APP">%1$s</xliff:g>ஐ அனுமதிக்கவா?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="ACCOUNT">%2$s</xliff:g> (இந்தக் கணக்கில் ஏற்கனவே ஒரு பயனர் உள்ளார்) மூலம் புதிய பயனரை உருவாக்க <xliff:g id="APP">%1$s</xliff:g>ஐ அனுமதிக்கவா?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"மொழி விருப்பம்"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"மொழியைச் சேர்"</string>
<string name="country_selection_title" msgid="2954859441620215513">"மண்டல விருப்பம்"</string>
<string name="search_language_hint" msgid="7042102592055108574">"மொழி பெயரை உள்ளிடுக"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"பரிந்துரைகள்"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"பின் செய்"</string>
<string name="unpin_target" msgid="3556545602439143442">"பின்னை அகற்று"</string>
<string name="app_info" msgid="6856026610594615344">"பயன்பாட்டுத் தகவல்"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index e7d0fa8..8047621 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"కాలర్ ID డిఫాల్ట్గా అపరిమితానికి ఉంటుంది. తదుపరి కాల్: అపరిమితం"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"సేవ కేటాయించబడలేదు."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"మీరు కాలర్ ID సెట్టింగ్ను మార్చలేరు."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"పరిమితం చేయబడిన ప్రాప్యత మార్చబడింది"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"డేటా సేవ బ్లాక్ చేయబడింది."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"అత్యవసర సేవ బ్లాక్ చేయబడింది."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"వాయిస్ సేవ బ్లాక్ చేయబడింది."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"రీసెట్ చేసి, అనువర్తనాన్ని పునఃప్రారంభించు"</string>
<string name="aerr_report" msgid="5371800241488400617">"అభిప్రాయాన్ని పంపు"</string>
<string name="aerr_close" msgid="2991640326563991340">"మూసివేయి"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"మ్యూట్ చేయి"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"పరికరం పునఃప్రారంభమయ్యే వరకు మ్యూట్ చేయి"</string>
<string name="aerr_wait" msgid="3199956902437040261">"వేచి ఉండండి"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"అనువర్తనాన్ని మూసివేయి"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"మరిన్ని ఎంపికల కోసం తాకండి."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB డీబగ్గింగ్ కనెక్ట్ చేయబడింది"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB డీబగ్గింగ్ను నిలిపివేయడానికి తాకండి."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"మీ ఐటి నిర్వాహకులు ఈ పరికరం సమస్యకు పరిష్కారాన్ని కనుగొనడంలో సహాయం కోసం బగ్ నివేదికను అభ్యర్థించారు. అనువర్తనాలు మరియు డేటా భాగస్వామ్యం చేయబడవచ్చు మరియు మీ పరికరం పనితీరు తాత్కాలికంగా నెమ్మదించవచ్చు."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"మీ ఐటి నిర్వాహకులు ఈ పరికరం సమస్యకు పరిష్కారాన్ని కనుగొనడంలో సహాయం కోసం బగ్ నివేదికను అభ్యర్థించారు. అనువర్తనాలు మరియు డేటా భాగస్వామ్యం చేయబడవచ్చు."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"దీని వల్ల మీ పరికరం పనితీరు తాత్కాలికంగా నెమ్మదించవచ్చు"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ఆమోదిస్తున్నాను"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"తిరస్కరిస్తున్నాను"</string>
<string name="select_input_method" msgid="8547250819326693584">"కీబోర్డ్ను మార్చు"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"అన్పిన్ చేయడానికి ముందు పిన్ కోసం అడుగు"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"అన్పిన్ చేయడానికి ముందు అన్లాక్ నమూనా కోసం అడుగు"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"అన్పిన్ చేయడానికి ముందు పాస్వర్డ్ కోసం అడుగు"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"అనువర్తన పరిమాణాన్ని మార్చడం సాధ్యపడదు, రెండు వేళ్లతో దీన్ని స్క్రోల్ చేయండి."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"స్క్రీన్ విభజనతో అనువర్తనం పని చేయకపోవచ్చు."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"అనువర్తనంలో స్క్రీన్ విభజనకు మద్దతు లేదు."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"మీ నిర్వాహకులు ఇన్స్టాల్ చేసారు"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"మీ నిర్వాహకుడు నవీకరించారు"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ఎంచుకోబడ్డాయి</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ఎంచుకోబడింది</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"ఇతరాలు"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"మీరు ఈ నోటిఫికేషన్ల ప్రాముఖ్యతను సెట్ చేసారు."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"మీరు ఈ నోటిఫికేషన్ల ప్రాముఖ్యతను సెట్ చేసారు."</string>
<string name="importance_from_person" msgid="9160133597262938296">"ఇందులో పేర్కొనబడిన వ్యక్తులను బట్టి ఇది చాలా ముఖ్యమైనది."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="ACCOUNT">%2$s</xliff:g>తో కొత్త వినియోగదారుని సృష్టించడానికి <xliff:g id="APP">%1$s</xliff:g>ని అనుమతించాలా ?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="ACCOUNT">%2$s</xliff:g>తో (ఈ ఖాతాతో ఇప్పటికే ఒక వినియోగదారు ఉన్నారు) కొత్త వినియోగదారుని సృష్టించడానికి <xliff:g id="APP">%1$s</xliff:g>ని అనుమతించాలా?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"భాష ప్రాధాన్యత"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"భాషను జోడించండి"</string>
<string name="country_selection_title" msgid="2954859441620215513">"ప్రాంతం ప్రాధాన్యత"</string>
<string name="search_language_hint" msgid="7042102592055108574">"భాష పేరును టైప్ చేయండి"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"సూచించినవి"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"పిన్ చేయి"</string>
<string name="unpin_target" msgid="3556545602439143442">"అన్పిన్ చేయి"</string>
<string name="app_info" msgid="6856026610594615344">"అనువర్తన సమాచారం"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-television/config.xml b/core/res/res/values-television/config.xml
index 0f98cfb..ae19150 100644
--- a/core/res/res/values-television/config.xml
+++ b/core/res/res/values-television/config.xml
@@ -29,6 +29,9 @@
<!-- Bounds [left top right bottom] on screen for picture-in-picture (PIP) windows, when the PIP
is located in center. -->
- <string translatable="false" name="config_centeredPictureInPictureBounds">"600 331 1320 749"</string>
+ <string translatable="false" name="config_centeredPictureInPictureBounds">"596 280 1324 690"</string>
+ <!-- Bounds [left top right bottom] on screen for picture-in-picture (PIP) windows,
+ when the PIP is shown with Recents. -->
+ <string translatable="false" name="config_pictureInPictureBoundsInRecents">"1480 123 1760 303"</string>
</resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 8486c7be..114b31b 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"หมายเลขผู้โทรได้รับการตั้งค่าเริ่มต้นเป็นไม่จำกัด การโทรครั้งต่อไป: ไม่จำกัด"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"ไม่มีการนำเสนอบริการ"</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"คุณไม่สามารถเปลี่ยนการตั้งค่าหมายเลขผู้โทร"</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"เปลี่ยนแปลงการเข้าถึงอย่างจำกัดแล้ว"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"บริการข้อมูลถูกปิดกั้น"</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"บริการฉุกเฉินถูกปิดกั้น"</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"บริการเสียงถูกปิดกั้น"</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"รีเซ็ตแอปและเปิดใหม่"</string>
<string name="aerr_report" msgid="5371800241488400617">"ส่งความคิดเห็น"</string>
<string name="aerr_close" msgid="2991640326563991340">"ปิด"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"ปิด"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"ปิดการแจ้งเตือนจนกว่าอุปกรณ์จะรีสตาร์ท"</string>
<string name="aerr_wait" msgid="3199956902437040261">"รอ"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"ปิดแอป"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"แตะเพื่อดูตัวเลือกเพิ่มเติม"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"เชื่อมต่อการแก้ไขข้อบกพร่อง USB แล้ว"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"แตะเพื่อปิดใช้งานการแก้ไขข้อบกพร่อง USB"</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"ผู้ดูแลระบบไอทีของคุณขอรายงานข้อบกพร่องเพื่อช่วยในการแก้ปัญหาอุปกรณ์นี้ อาจมีการแชร์แอปและข้อมูล ซึ่งอาจทำให้อุปกรณ์ทำงานช้าลงชั่วคราว"</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"ผู้ดูแลระบบไอทีของคุณขอรายงานข้อบกพร่องเพื่อช่วยในการแก้ปัญหาอุปกรณ์นี้ อาจมีการแชร์แอปและข้อมูล"</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"การดำเนินการนี้อาจทำให้อุปกรณ์ทำงานช้าลงชั่วคราว"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ยอมรับ"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ปฏิเสธ"</string>
<string name="select_input_method" msgid="8547250819326693584">"เปลี่ยนแป้นพิมพ์"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ขอ PIN ก่อนเลิกตรึง"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ขอรูปแบบการปลดล็อกก่อนเลิกตรึง"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ขอรหัสผ่านก่อนเลิกตรึง"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"แอปไม่สามารถปรับขนาดได้ เลื่อนแอปด้วยนิ้ว 2 นิ้ว"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"แอปอาจใช้ไม่ได้กับโหมดแยกหน้าจอ"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"แอปไม่สนับสนุนการแยกหน้าจอ"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"ติดตั้งโดยผู้ดูแลระบบของคุณ"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"อัปเดตโดยผู้ดูแลระบบ"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other">เลือกไว้ <xliff:g id="COUNT_1">%1$d</xliff:g> รายการ</item>
<item quantity="one">เลือกไว้ <xliff:g id="COUNT_0">%1$d</xliff:g> รายการ</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"เบ็ดเตล็ด"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"คุณตั้งค่าความสำคัญของการแจ้งเตือนเหล่านี้"</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"คุณตั้งค่าความสำคัญของการแจ้งเตือนเหล่านี้"</string>
<string name="importance_from_person" msgid="9160133597262938296">"ข้อความนี้สำคัญเนื่องจากบุคคลที่เกี่ยวข้อง"</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"อนุญาตให้ <xliff:g id="APP">%1$s</xliff:g> สร้างผู้ใช้ใหม่ด้วย <xliff:g id="ACCOUNT">%2$s</xliff:g> ไหม"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"อนุญาตให้ <xliff:g id="APP">%1$s</xliff:g> สร้างผู้ใช้ใหม่ด้วย <xliff:g id="ACCOUNT">%2$s</xliff:g> (มีผู้ใช้ที่มีบัญชีนี้อยู่แล้ว) ไหม"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"ค่ากำหนดภาษา"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"เพิ่มภาษา"</string>
<string name="country_selection_title" msgid="2954859441620215513">"ค่ากำหนดภูมิภาค"</string>
<string name="search_language_hint" msgid="7042102592055108574">"พิมพ์ชื่อภาษา"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"แนะนำ"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"ปักหมุด"</string>
<string name="unpin_target" msgid="3556545602439143442">"เลิกปักหมุด"</string>
<string name="app_info" msgid="6856026610594615344">"ข้อมูลแอป"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 70b32c7..1e2a606 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Naka-default na hindi pinaghihigpitan ang Caller ID. Susunod na tawag: Hindi pinaghihigpitan"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Hindi naprobisyon ang serbisyo."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Hindi mo mababago ang setting ng caller ID."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Nabago ang pinaghihigpitang access"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Naka-block ang serbisyo ng data."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Naka-block ang pang-emergency na serbisyo."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Naka-block ang serbisyo ng voice."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"I-reset at i-restart ang app"</string>
<string name="aerr_report" msgid="5371800241488400617">"Magpadala ng feedback"</string>
<string name="aerr_close" msgid="2991640326563991340">"Isara"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"I-mute"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"I-mute hanggang sa mag-restart ang device"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Maghintay"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Isara ang app"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Pindutin para sa higit pang mga opsyon."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Konektado ang debugging ng USB"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Pindutin upang i-disable ang pagde-debug ng USB."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Gusto mo bang ibahagi ang ulat ng bug?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Ibinabahagi ang ulat ng bug…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Humiling ang iyong IT admin ng isang ulat ng bug upang makatulong sa pag-troubleshoot sa device na ito. Maaaring ibahagi ang mga app at data at maaaring pansamantalang bumagal ang iyong device."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Humiling ang iyong IT admin ng isang ulat ng bug upang makatulong sa pag-troubleshoot sa device na ito. Maaaring ibahagi ang mga app at data."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Maaaring pansamantalang bumagal ang iyong device dahil dito"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"TANGGAPIN"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"TANGGIHAN"</string>
<string name="select_input_method" msgid="8547250819326693584">"Baguhin ang keyboard"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Humingi ng PIN bago mag-unpin"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Humingi ng pattern sa pag-unlock bago mag-unpin"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Humingi ng password bago mag-unpin"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Hindi nare-resize ang app, mag-scroll dito gamit ang dalawang daliri."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Maaaring hindi gumana ang app sa split-screen."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Hindi sinusuportahan ng app ang split-screen."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Na-install ng iyong administrator"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Na-update ng iyong administrator"</string>
@@ -1543,12 +1537,11 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ang napili</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ang napili</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Iba Pa"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Ikaw ang magtatakda ng kahalagahan ng mga notification na ito."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Ikaw ang magtatakda sa kahalagahan ng mga notification na ito."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Mahalaga ito dahil sa mga taong kasangkot."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Payagan ang <xliff:g id="APP">%1$s</xliff:g> na gumawa ng bagong User sa <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Payagan ang <xliff:g id="APP">%1$s</xliff:g> na gumawa ng bagong User sa <xliff:g id="ACCOUNT">%2$s</xliff:g> (mayroon nang User sa account na ito) ?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Kagustuhan sa wika"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Magdagdag ng wika"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Kagustuhan sa rehiyon"</string>
<string name="search_language_hint" msgid="7042102592055108574">"I-type ang wika"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Iminumungkahi"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"I-pin"</string>
<string name="unpin_target" msgid="3556545602439143442">"I-unpin"</string>
<string name="app_info" msgid="6856026610594615344">"Impormasyon ng app"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index ee55277..ab0781b 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Arayan kimliği varsayılanları kısıtlanmamıştır. Sonraki çağrı: Kısıtlanmamış"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Hizmet sağlanamadı."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Arayanın kimliği ayarını değiştiremezsiniz."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Kısıtlanmış erişim değiştirildi"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Veri hizmeti engellendi."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Acil durum hizmeti engellendi."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Ses hizmeti engellendi."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Uygulamayı sıfırla ve yeniden başlat"</string>
<string name="aerr_report" msgid="5371800241488400617">"Geri bildirim gönder"</string>
<string name="aerr_close" msgid="2991640326563991340">"Kapat"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Yok say"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Cihaz yeniden başlatılana kadar bir daha gösterme"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Bekle"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Uygulamayı kapat"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Daha fazla seçenek için dokunun."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB hata ayıklaması bağlandı"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB hata ayıklama özelliğini devre dışı bırakmak için dokunun."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Hata raporu paylaşılsın mı?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Hata raporu paylaşılıyor..."</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"BT yöneticiniz, bu cihazda sorun gidermeye yardımcı olması için bir hata raporu istedi. Uygulamalar ve veriler paylaşılabilir. Bu durum, cihazınızı geçici olarak yavaşlatabilir."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"BT yöneticiniz, bu cihazda sorun gidermeye yardımcı olması için bir hata raporu istedi. Uygulamalar ve veriler paylaşılabilir."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Bu durum, cihazınızı geçici olarak yavaşlatabilir"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"KABUL ET"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"REDDET"</string>
<string name="select_input_method" msgid="8547250819326693584">"Klavyeyi değiştir"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Sabitlemeyi kaldırmadan önce PIN\'i sor"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Sabitlemeyi kaldırmadan önce kilit açma desenini sor"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Sabitlemeyi kaldırmadan önce şifre sor"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Uygulama yeniden boyutlandırılamaz. İki parmağınızla kaydırın."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Uygulama bölünmüş ekranda çalışmayabilir."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Uygulama bölünmüş ekranı desteklemiyor."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Yöneticiniz tarafından yüklendi"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Yöneticiniz tarafından güncellendi"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> öğe seçildi</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> öğe seçildi</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Çeşitli"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Bu bildirimlerin önem derecesini ayarladınız."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Bu bildirimlerin önem derecesini ayarladınız."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Bu, dahil olan kişiler nedeniyle önemlidir."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> uygulamasının <xliff:g id="ACCOUNT">%2$s</xliff:g> hesabına sahip yeni bir Kullanıcı eklemesine izin verilsin mi?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> uygulamasının <xliff:g id="ACCOUNT">%2$s</xliff:g> hesabına sahip yeni bir Kullanıcı eklemesine izin verilsin mi (bu hesaba sahip bir kullanıcı zaten var)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Dil tercihi"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Dil ekleyin"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Bölge tercihi"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Dil adını yazın"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Önerilen"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Sabitle"</string>
<string name="unpin_target" msgid="3556545602439143442">"Sabitlemeyi kaldır"</string>
<string name="app_info" msgid="6856026610594615344">"Uygulama bilgileri"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index f546d56..439d68f 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -90,7 +90,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Ідентиф. абонента за умовч. не обмеж. Наст. дзвінок: не обмежений"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Службу не ініціалізовано."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Ви не можете змінювати налаштування ідентифікатора абонента."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Обмежений доступ змінено"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Службу даних заблоковано."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Аварійну службу заблоковано."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Голосову службу заблоковано."</string>
@@ -929,7 +928,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Скинути та перезапустити додаток"</string>
<string name="aerr_report" msgid="5371800241488400617">"Надіслати відгук"</string>
<string name="aerr_close" msgid="2991640326563991340">"Закрити"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Вимкнути звук"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Вимкнути звук до перезавантаження пристрою"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Чекати"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Закрити додаток"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1069,16 +1068,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Торкніться, щоб побачити більше опцій."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Налагодження USB завершено"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Торкніться, щоб вимкнути налагодження USB."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"Ваш IT-адміністратор просить надіслати повідомлення про помилку, щоб вирішити проблему з пристроєм. Він може отримати доступ до ваших додатків і даних. Це також може тимчасово сповільнити роботу вашого пристрою."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Ваш IT-адміністратор просить надіслати повідомлення про помилку, щоб вирішити проблему з пристроєм. Він може отримати доступ до ваших додатків і даних."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Це може тимчасово сповільнити роботу вашого пристрою"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"ПРИЙНЯТИ"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"ВІДХИЛИТИ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Змінити клавіатуру"</string>
@@ -1493,7 +1487,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"PIN-код для відкріплення"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Запитувати ключ розблокування перед відкріпленням"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Запитувати пароль перед відкріпленням"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Розмір додатка не можна змінити. Прокручуйте його двома пальцями."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Додаток може не працювати в режимі розділеного екрана."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Додаток не підтримує розділення екрана."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Установив адміністратор"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Оновлено адміністратором"</string>
@@ -1581,12 +1575,11 @@
<item quantity="many">Вибрано <xliff:g id="COUNT_1">%1$d</xliff:g></item>
<item quantity="other">Вибрано <xliff:g id="COUNT_1">%1$d</xliff:g></item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Інше"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Ви вказуєте пріоритет цих сповіщень."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Ви вказуєте пріоритет цих сповіщень."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Важливе з огляду на учасників."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Дозволити додатку <xliff:g id="APP">%1$s</xliff:g> створити нового користувача з обліковим записом <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Дозволити додатку <xliff:g id="APP">%1$s</xliff:g> створити нового користувача з обліковим записом <xliff:g id="ACCOUNT">%2$s</xliff:g> (користувач із таким обліковим записом уже існує)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Вибір мови"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Додати мову"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Вибір регіону"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Введіть назву мови"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Пропозиції"</string>
@@ -1609,4 +1602,5 @@
<string name="pin_target" msgid="3052256031352291362">"Закріпити"</string>
<string name="unpin_target" msgid="3556545602439143442">"Відкріпити"</string>
<string name="app_info" msgid="6856026610594615344">"Про додаток"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index 80d4c85..1bf224b 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"کالر ID کی ڈیفالٹ ترتیب غیر محدود کردہ ہے۔ اگلی کال: غیر محدود کردہ"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"سروس فراہم نہیں کی گئی۔"</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"آپ کالر ID کی ترتیبات تبدیل نہیں کر سکتے ہیں۔"</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"محدود رسائی تبدیل ہو گئی"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"ڈیٹا سروس مسدود ہے۔"</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"ہنگامی سروس مسدود ہے۔"</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"صوتی سروس مسدود ہے۔"</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"ایپ کو دوبارہ ترتیب دیں اور دوبارہ شروع کریں"</string>
<string name="aerr_report" msgid="5371800241488400617">"تاثرات بھیجیں"</string>
<string name="aerr_close" msgid="2991640326563991340">"بند کریں"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"خاموش کریں"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"آلہ دوبارہ اسٹارٹ ہونے تک خاموش رکھیں"</string>
<string name="aerr_wait" msgid="3199956902437040261">"انتظار کریں"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"ایپ بند کریں"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"مزید اختیارات کیلئے ٹچ کریں۔"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB ڈیبگ کرنا مربوط ہو گیا"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"USB ڈیبگنگ کو غیر فعال کرنے کیلئے ٹچ کریں۔"</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"آپ کے IT منتظم نے اس آلہ کا مسئلہ حل کرنے میں مدد کیلئے ایک بگ رپورٹ کی درخواست کی ہے۔ ایپس اور ڈیٹا کا اشتراک ہو سکتا ہے اور آپ کا آلہ عارضی طور پر سست ہو سکتا ہے۔"</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"آپ کے IT منتظم نے اس آلہ کا مسئلہ حل کرنے میں مدد کیلئے ایک بگ رپورٹ کی درخواست کی ہے۔ ایپس اور ڈیٹا کا اشتراک ہو سکتا ہے۔"</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"اس سے آپ کا آلہ عارضی طور پر سست ہو سکتا ہے"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"قبول کریں"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"مسترد کریں"</string>
<string name="select_input_method" msgid="8547250819326693584">"کی بورڈ تبدیل کریں"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"پن ہٹانے سے پہلے PIN طلب کریں"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"پن ہٹانے سے پہلے غیر مقفل کرنے کا پیٹرن طلب کریں"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"پن ہٹانے سے پہلے پاس ورڈ طلب کریں"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"ایپ ری سائز ایبل نہیں ہے، اسے دو انگلیوں کے ساتھ سکرول کریں۔"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"ممکن ہے کہ ایپ سپلٹ اسکرین کے ساتھ کام نہ کرے۔"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ایپ سپلٹ اسکرین کو سپورٹ نہیں کرتی۔"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"آپ کے منتظم کی جانب سے انسٹال کر دیا گیا"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"آپ کے منتظم نے اپ ڈيٹ کر دیا"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> منتخب کردہ</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> منتخب کردہ</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"متفرقات"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"ان اطلاعات کی اہمیت آپ مقرر کرتے ہیں۔"</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"ان اطلاعات کی اہمیت آپ مقرر کرتے ہیں۔"</string>
<string name="importance_from_person" msgid="9160133597262938296">"اس میں موجود لوگوں کی وجہ سے یہ اہم ہے۔"</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> کو <xliff:g id="ACCOUNT">%2$s</xliff:g> کے ساتھ ایک نیا صارف بنانے کی اجازت دیں؟"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> کو <xliff:g id="ACCOUNT">%2$s</xliff:g> کے ساتھ ایک نیا صارف بنانے کی اجازت دیں (اس اکاؤنٹ کے ساتھ ایک صارف پہلے سے موجود ہے) ؟"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"زبان کی ترجیح"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"ایک زبان شامل کریں"</string>
<string name="country_selection_title" msgid="2954859441620215513">"علاقہ کی ترجیح"</string>
<string name="search_language_hint" msgid="7042102592055108574">"زبان کا نام ٹائپ کریں"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"تجویز کردہ"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"پن کریں"</string>
<string name="unpin_target" msgid="3556545602439143442">"پن ہٹائیں"</string>
<string name="app_info" msgid="6856026610594615344">"ایپ کی معلومات"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index 8b5e230..d862036 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Qo‘ng‘iroq qiluvchi ma’lumotlari cheklanmagan. Keyingi qo‘ng‘iroq: cheklanmagan"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Xizmat ishalamaydi."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Qo‘ng‘iroq qiluvchining ID raqami sozlamasini o‘zgartirib bo‘lmaydi."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Cheklangan ruxsatlar o‘zgartirildi"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Ma’lumot xizmati bloklandi."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Favqulodda xizmati bloklandi."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Ovoz xizmati bloklandi."</string>
@@ -894,7 +893,7 @@
<string name="capital_on" msgid="1544682755514494298">"I"</string>
<string name="capital_off" msgid="6815870386972805832">"O"</string>
<string name="whichApplication" msgid="4533185947064773386">"Ilovani tanlang"</string>
- <string name="whichApplicationNamed" msgid="8260158865936942783">"“%1$s” ilovasi yordamida bajarish"</string>
+ <string name="whichApplicationNamed" msgid="8260158865936942783">"“%1$s” bilan ochish"</string>
<string name="whichViewApplication" msgid="3272778576700572102">"Ochish…"</string>
<string name="whichViewApplicationNamed" msgid="2286418824011249620">"“%1$s” yordamida ochish"</string>
<string name="whichEditApplication" msgid="144727838241402655">"Tahrirlash…"</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Ilovani qayta tiklash va qayta ishga tushirish"</string>
<string name="aerr_report" msgid="5371800241488400617">"Fikr-mulohaza yuborish"</string>
<string name="aerr_close" msgid="2991640326563991340">"Yopish"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"E’tiborsiz qoldirish"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Qurilma o‘chib yonguncha e’tiborsiz qoldirish"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Kuting"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Ilovani yopish"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -998,7 +997,7 @@
<string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
<string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi Direct’ni ishga tushirish. Bu Wi-Fi mijoz/ulanish nuqtasini o‘chiradi."</string>
<string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Wi-Fi Direct ishga tushirilmadi."</string>
- <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct yoqilgan"</string>
+ <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct yoniq"</string>
<string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Sozlamalarga kirish uchun bosing"</string>
<string name="accept" msgid="1645267259272829559">"Qabul qilish"</string>
<string name="decline" msgid="2112225451706137894">"Rad qilish"</string>
@@ -1019,7 +1018,7 @@
<string name="sms_short_code_confirm_message" msgid="1645436466285310855">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b>ga xabar jo‘natishni xohlaydi."</string>
<string name="sms_short_code_details" msgid="5873295990846059400">"Bunda, mobil hisobingizdan "<b>"to‘lov olinishi mumkin"</b>"."</string>
<string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"Bunda, mobil hisobingizdan to‘lov olinishi mumkin."</b></string>
- <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Jo‘natish"</string>
+ <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Yuborish"</string>
<string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Bekor qilish"</string>
<string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Tanlovim eslab qolinsin"</string>
<string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Siz buni keyinroq sozlamalar > ilovalar menusidan o‘zgartirishingiz mumkin"</string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Sozlash uchun bosing."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB orqali nosozliklarni tuzatish"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"O‘chirib qo‘yish uchun bosing."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Xatoliklar hisoboti yuborilsinmi?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Xatoliklar hisoboti yuborilmoqda…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Administratoringiz bu qurilma nosozliklarini tuzatish uchun xatoliklar hisobotini so‘ramoqda. Ilova va ma’lumotlardan foydalanilishi va bu vaqtincha qurilmangizni sekinlashtirishi ham mumkin."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Administratoringiz bu qurilma nosozliklarini tuzatish uchun xatoliklar hisobotini so‘ramoqda. Ilova va ma’lumotlardan foydalanilishi mumkin."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Qurilmaning ishlash tezligi vaqtincha pasayishi mumkin."</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"QABUL QILISH"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"RAD ETISH"</string>
<string name="select_input_method" msgid="8547250819326693584">"Klaviaturani o‘zgartirish"</string>
@@ -1121,7 +1115,7 @@
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Vidjet qo‘shilmadi."</string>
<string name="ime_action_go" msgid="8320845651737369027">"O‘tish"</string>
<string name="ime_action_search" msgid="658110271822807811">"Qidirish"</string>
- <string name="ime_action_send" msgid="2316166556349314424">"Jo‘natish"</string>
+ <string name="ime_action_send" msgid="2316166556349314424">"Yuborish"</string>
<string name="ime_action_next" msgid="3138843904009813834">"Keyingi"</string>
<string name="ime_action_done" msgid="8971516117910934605">"Tayyor"</string>
<string name="ime_action_previous" msgid="1443550039250105948">"Old."</string>
@@ -1156,7 +1150,7 @@
<string name="upload_file" msgid="2897957172366730416">"Faylni tanlash"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Hech qanday fayl tanlanmadi"</string>
<string name="reset" msgid="2448168080964209908">"Tiklash"</string>
- <string name="submit" msgid="1602335572089911941">"Jo‘natish"</string>
+ <string name="submit" msgid="1602335572089911941">"Yuborish"</string>
<string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Mashina usuli yoqilgan"</string>
<string name="car_mode_disable_notification_message" msgid="8035230537563503262">"Avtomashina rejimidan chiqish uchun bosing."</string>
<string name="tethered_notification_title" msgid="3146694234398202601">"Modem rejimi yoniq"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Yechishda PIN-kod so‘ralsin"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Bo‘shatishdan oldin chizmali parol so‘ralsin"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Bo‘shatishdan oldin parol so‘ralsin"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Oyna o‘lchamini o‘zgartirib bo‘lmaydi. Sahifani ikkita barmoq bilan aylantiring."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Ilova ekranni ikkiga bo‘lish rejimini qo‘llab-quvvatlamaydi."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Bu ilova ekranni bo‘lish xususiyatini qo‘llab-quvvatlamaydi."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Administratoringiz tomonidan o‘rnatilgan"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Administratoringiz tomonidan yangilandi"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ta tanlandi</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ta tanlandi</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Boshqa belgilar"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Siz ushbu bildirishnomalarning muhimligini belgilagansiz."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Siz ushbu bildirishnomalarning muhimligini belgilagansiz."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Bu odamlar siz uchun muhim."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> ilovasiga <xliff:g id="ACCOUNT">%2$s</xliff:g> hisobi bilan yangi foydalanuvchi yaratishiga ruxsat berilsinmi ?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> ilovasiga <xliff:g id="ACCOUNT">%2$s</xliff:g> hisobi bilan yangi foydalanuvchi yaratishiga ruxsat berilsinmi (bunday hisobdagi foydalanuvchi allaqachon mavjud) ?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Til sozlamalari"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Tilni qo‘shing"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Hudud sozlamalari"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Til nomini kiriting"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Taklif etiladi"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Qadash"</string>
<string name="unpin_target" msgid="3556545602439143442">"Olib tashlash"</string>
<string name="app_info" msgid="6856026610594615344">"Ilova haqida"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 7d4e43f..af69c31 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Số gọi đến mặc định thành không bị giới hạn. Cuộc gọi tiếp theo. Không bị giới hạn"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Dịch vụ không được cấp phép."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Bạn không thể thay đổi cài đặt ID người gọi."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Quyền truy cập bị giới hạn đã thay đổi"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Dịch vụ dữ liệu bị chặn."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Dịch vụ khẩn cấp đã bị chặn."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Dịch vụ thoại đã bị chặn."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Đặt lại và khởi động lại ứng dụng"</string>
<string name="aerr_report" msgid="5371800241488400617">"Gửi phản hồi"</string>
<string name="aerr_close" msgid="2991640326563991340">"Đóng"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Bỏ qua"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Tắt tiếng cho đến khi thiết bị khởi động lại"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Đợi"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Đóng ứng dụng"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Chạm để có các tùy chọn khác."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Gỡ lỗi USB đã được kết nối"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Chạm để vô hiệu hóa gỡ lỗi USB."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Chia sẻ báo cáo lỗi?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Đang chia sẻ báo cáo lỗi…"</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Quản trị viên CNTT của bạn đã yêu cầu báo cáo lỗi để giúp khắc phục sự cố thiết bị này. Bạn có thể chia sẻ ứng dụng, đồng thời dữ liệu và thiết bị của bạn tạm thời có thể bị chậm."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Quản trị viên CNTT của bạn đã yêu cầu báo cáo lỗi để giúp khắc phục sự cố thiết bị này. Bạn có thể chia sẻ ứng dụng và dữ liệu."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Tác vụ này tạm thời có thể làm chậm thiết bị của bạn"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"CHẤP NHẬN"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"TỪ CHỐI"</string>
<string name="select_input_method" msgid="8547250819326693584">"Thay đổi bàn phím"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Hỏi mã PIN trước khi bỏ ghim"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Hỏi hình mở khóa trước khi bỏ ghim"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Hỏi mật khẩu trước khi bỏ ghim"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Ứng dụng không đổi kích thước được, hãy cuộn ứng dụng bằng hai ngón tay."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Ứng dụng có thể không hoạt động với tính năng chia đôi màn hình."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Ứng dụng không hỗ trợ chia đôi màn hình."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Được cài đặt bởi quản trị viên của bạn"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Được cập nhật bởi quản trị viên của bạn"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other">Đã chọn <xliff:g id="COUNT_1">%1$d</xliff:g></item>
<item quantity="one">Đã chọn <xliff:g id="COUNT_0">%1$d</xliff:g></item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Khác"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Bạn đặt tầm quan trọng của các thông báo này."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Bạn đặt tầm quan trọng của các thông báo này."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Thông báo này quan trọng vì những người có liên quan."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Cho phép <xliff:g id="APP">%1$s</xliff:g> tạo người dùng mới bằng <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Cho phép <xliff:g id="APP">%1$s</xliff:g> tạo người dùng mới bằng <xliff:g id="ACCOUNT">%2$s</xliff:g> (người dùng có tài khoản này đã tồn tại)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Tùy chọn ngôn ngữ"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Thêm ngôn ngữ"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Tùy chọn khu vực"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Nhập tên ngôn ngữ"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Ðược đề xuất"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Ghim"</string>
<string name="unpin_target" msgid="3556545602439143442">"Bỏ ghim"</string>
<string name="app_info" msgid="6856026610594615344">"Thông tin ứng dụng"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-w426dp-land/integers.xml b/core/res/res/values-w426dp-land/integers.xml
new file mode 100644
index 0000000..94abbec
--- /dev/null
+++ b/core/res/res/values-w426dp-land/integers.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+ <integer name="date_picker_mode">2</integer>
+ <integer name="time_picker_mode">2</integer>
+</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index b8ea898..24a5b79 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"默认显示本机号码,在下一次通话中也显示"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"未提供服务。"</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"您无法更改来电显示设置。"</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"网络可用情况发生变化"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"数据网络服务已停用。"</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"紧急服务已停用。"</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"语音服务已停用。"</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"重置并重启应用"</string>
<string name="aerr_report" msgid="5371800241488400617">"发送反馈"</string>
<string name="aerr_close" msgid="2991640326563991340">"关闭"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"忽略"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"忽略(直到设备重启)"</string>
<string name="aerr_wait" msgid="3199956902437040261">"等待"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"关闭应用"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"触摸以查看更多选项。"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"已连接到USB调试"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"触摸可停用USB调试。"</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"您的 IT 管理员希望获取错误报告,以便排查此设备的问题。报告可能会透露您设备上的应用和数据,设备运行速度也可能会因此而暂时减慢。"</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"您的 IT 管理员希望获取错误报告,以便排查此设备的问题。报告可能会透露您设备上的应用和数据。"</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"这可能会暂时减慢您设备的运行速度"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"接受"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"拒绝"</string>
<string name="select_input_method" msgid="8547250819326693584">"更改键盘"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"取消时要求输入PIN码"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"取消时要求绘制解锁图案"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"取消时要求输入密码"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"无法调整该应用的大小,请用双指滚动该应用。"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"应用可能无法在分屏模式下正常运行。"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"应用不支持分屏。"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"已由管理员安装"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"由您单位的管理员更新"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other">已选择 <xliff:g id="COUNT_1">%1$d</xliff:g> 项</item>
<item quantity="one">已选择 <xliff:g id="COUNT_0">%1$d</xliff:g> 项</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"其他"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"这些通知的重要性由您来设置。"</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"这些通知的重要性由您来设置。"</string>
<string name="importance_from_person" msgid="9160133597262938296">"这条通知涉及特定的人,因此被归为重要通知。"</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"允许<xliff:g id="APP">%1$s</xliff:g>使用 <xliff:g id="ACCOUNT">%2$s</xliff:g> 创建新用户吗?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"允许<xliff:g id="APP">%1$s</xliff:g>使用 <xliff:g id="ACCOUNT">%2$s</xliff:g>(目前已有用户使用此帐号)创建新用户吗?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"语言偏好设置"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"添加语言"</string>
<string name="country_selection_title" msgid="2954859441620215513">"区域偏好设置"</string>
<string name="search_language_hint" msgid="7042102592055108574">"输入语言名称"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"建议语言"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"固定"</string>
<string name="unpin_target" msgid="3556545602439143442">"取消固定"</string>
<string name="app_info" msgid="6856026610594615344">"应用信息"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 5464fbf..4c46574 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"預設顯示來電號碼,下一通電話也繼續顯示。"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"未提供此服務。"</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"您無法更改來電顯示設定。"</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"受限存取已更改"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"已封鎖數據傳輸服務。"</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"已封鎖緊急服務。"</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"已封鎖語音服務。"</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"重設並重新啟動應用程式"</string>
<string name="aerr_report" msgid="5371800241488400617">"傳送意見反映"</string>
<string name="aerr_close" msgid="2991640326563991340">"關閉"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"忽略"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"忽略直至裝置重新啟動"</string>
<string name="aerr_wait" msgid="3199956902437040261">"等一下"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"關閉應用程式"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"輕觸以瀏覽更多選項。"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"已連接 USB 偵錯工具"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"輕觸即可停用 USB 偵錯。"</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"您的 IT 管理員要求您提供錯誤報告,以協助解決此裝置的問題。報告可能包含應用程式和相關資料,裝置的運作速度也可能暫時減慢。"</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"您的 IT 管理員要求您提供錯誤報告,以協助解決此裝置的問題。報告可能會披露裝置中的應用程式和相關資料。"</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"裝置的運作速度可能因而減慢"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"接受"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"拒絕"</string>
<string name="select_input_method" msgid="8547250819326693584">"變更鍵盤"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"取消固定時必須輸入 PIN"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"取消固定時必須畫出解鎖圖案"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"取消固定時必須輸入密碼"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"無法調整應用程式的大小,請用兩隻手指捲動此應用程式。"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"應用程式可能無法在分割畫面中運作。"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"應用程式不支援分割畫面。"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"已由管理員安裝"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"已由您的管理員更新"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other">已選取 <xliff:g id="COUNT_1">%1$d</xliff:g> 個項目</item>
<item quantity="one">已選取 <xliff:g id="COUNT_0">%1$d</xliff:g> 個項目</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"其他"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"您可以為這些通知設定重要性。"</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"您可以設定這些通知的重要性。"</string>
<string name="importance_from_person" msgid="9160133597262938296">"列為重要的原因:涉及的人。"</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"要允許 <xliff:g id="APP">%1$s</xliff:g> 使用 <xliff:g id="ACCOUNT">%2$s</xliff:g> 建立新使用者嗎?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"要允許 <xliff:g id="APP">%1$s</xliff:g> 使用 <xliff:g id="ACCOUNT">%2$s</xliff:g> 建立新使用者 (此帳戶目前已有此使用者) 嗎?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"語言偏好設定"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"新增語言"</string>
<string name="country_selection_title" msgid="2954859441620215513">"地區偏好設定"</string>
<string name="search_language_hint" msgid="7042102592055108574">"輸入語言名稱"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"推薦"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"固定"</string>
<string name="unpin_target" msgid="3556545602439143442">"取消固定"</string>
<string name="app_info" msgid="6856026610594615344">"應用程式資料"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index ff6dc23..7db8794 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"預設顯示本機號碼,下一通電話也繼續顯示。"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"無法提供此服務。"</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"您無法變更來電顯示設定。"</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"受限存取已變更"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"已封鎖數據傳輸服務。"</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"已封鎖緊急服務。"</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"已封鎖語音服務。"</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"重設並重新啟動應用程式"</string>
<string name="aerr_report" msgid="5371800241488400617">"提供意見"</string>
<string name="aerr_close" msgid="2991640326563991340">"關閉"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"忽略"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"略過直到裝置重新啟動"</string>
<string name="aerr_wait" msgid="3199956902437040261">"等候"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"關閉應用程式"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"輕觸即可顯示更多選項。"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"已連接 USB 偵錯工具"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"輕觸即可停用 USB 偵錯。"</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <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" msgid="752583906074230920">"您的 IT 管理員要求您提供錯誤報告,以便排解這個裝置發生的問題。報告可能會揭露裝置中的應用程式和相關資料,裝置運行速度也可能會因此暫時減慢。"</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"您的 IT 管理員要求您提供錯誤報告,以便排解這個裝置發生的問題。報告可能會揭露裝置中的應用程式和相關資料。"</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"這可能會暫時減慢裝置運行速度"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"接受"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"拒絕"</string>
<string name="select_input_method" msgid="8547250819326693584">"變更鍵盤"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"取消固定時必須輸入 PIN"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"取消固定時必須畫出解鎖圖案"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"取消固定時必須輸入密碼"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"無法調整這個應用程式的大小,請用雙指捲動該應用程式。"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"應用程式可能無法在分割畫面中運作。"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"這個應用程式不支援分割畫面。"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"已由管理員安裝"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"由您的管理員更新"</string>
@@ -1543,12 +1537,11 @@
<item quantity="other">已選取 <xliff:g id="COUNT_1">%1$d</xliff:g> 個項目</item>
<item quantity="one">已選取 <xliff:g id="COUNT_0">%1$d</xliff:g> 個項目</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"其他"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"這些通知的重要性由您決定。"</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"這些通知的重要性由您決定。"</string>
<string name="importance_from_person" msgid="9160133597262938296">"這則通知涉及特定人士,因此被歸為重要通知。"</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"要允許 <xliff:g id="APP">%1$s</xliff:g> 為 <xliff:g id="ACCOUNT">%2$s</xliff:g> 建立新使用者嗎?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"要允許 <xliff:g id="APP">%1$s</xliff:g> 為 <xliff:g id="ACCOUNT">%2$s</xliff:g> 建立新使用者嗎 (這個帳戶目前已有使用者)?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"語言偏好設定"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"新增語言"</string>
<string name="country_selection_title" msgid="2954859441620215513">"地區偏好設定"</string>
<string name="search_language_hint" msgid="7042102592055108574">"請輸入語言名稱"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"建議語言"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"固定"</string>
<string name="unpin_target" msgid="3556545602439143442">"取消固定"</string>
<string name="app_info" msgid="6856026610594615344">"應用程式資訊"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 6793a9a..9432024 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -88,7 +88,6 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"I-ID Yomshayeli ishintshela kokungavinjelwe. Ucingo olulandelayo: Aluvinjelwe"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Isevisi ayilungiselelwe."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Ngeke ukwazi ukuguqul izilungiselelo zemininingwane yoshayayo."</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Ukufinyelela okuvinjelwe kushintshiwe"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Isevisi yedatha ivaliwe."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Isevisi ephuthumayo ivimbelwe."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"Isevisi yezwi ivimbelwe."</string>
@@ -917,7 +916,7 @@
<string name="aerr_reset" msgid="7645427603514220451">"Setha kabusha uphinde uqalise kabusha uhlelo lokusebenza"</string>
<string name="aerr_report" msgid="5371800241488400617">"Thumela impendulo"</string>
<string name="aerr_close" msgid="2991640326563991340">"Vala"</string>
- <string name="aerr_mute" msgid="7698966346654789433">"Thulisa"</string>
+ <string name="aerr_mute" msgid="1974781923723235953">"Thulisa ize iqalise kabusha idivayisi"</string>
<string name="aerr_wait" msgid="3199956902437040261">"Linda"</string>
<string name="aerr_close_app" msgid="3269334853724920302">"Vala uhlelo lokusebenza"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
@@ -1053,16 +1052,11 @@
<string name="usb_notification_message" msgid="7347368030849048437">"Thinta ukuze uthole ezinye izinketho."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Ukulungisa iphutha le-USB kuxhunyiwe"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"Thinta ukwenza ukuthi ukudibhaga kwe-USB kungasebenzi."</string>
- <!-- no translation found for share_remote_bugreport_notification_title (4987095013583691873) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_title (7692523022154791488) -->
- <skip />
- <!-- no translation found for share_remote_bugreport_notification_message (8643704339578372992) -->
- <skip />
- <!-- no translation found for share_finished_remote_bugreport_notification_message (4627312060769912353) -->
- <skip />
- <!-- no translation found for sharing_remote_bugreport_notification_message (673106383408474893) -->
- <skip />
+ <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Yabelana ngombiko wesiphazamisi?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Yabelana ngombiko wesiphazamisi..."</string>
+ <string name="share_remote_bugreport_notification_message" msgid="752583906074230920">"Umlawuli wakho we-IT ucele umbiko wesiphazamisi ukusiza ukuxazulula inkinga yale divayisi. Izinhlelo zokusebenza zingabelwana futhi idivayisi yakho ingahle yehle kancane."</string>
+ <string name="share_finished_remote_bugreport_notification_message" msgid="4627312060769912353">"Umqondisi wakho we-IT ucele umbiko wesiphazamisi ukukusiza ukuxazulula inkinga kule divayisi. Izinhlelo zokusebenza nedatha ingabiwa."</string>
+ <string name="sharing_remote_bugreport_notification_message" msgid="673106383408474893">"Lokhu kungahambisa kancane idivayisi yakho okwesikhashana"</string>
<string name="share_remote_bugreport_notification_accept" msgid="8203856129078669677">"YAMUKELA"</string>
<string name="share_remote_bugreport_notification_decline" msgid="6337969352057443969">"YENQABA"</string>
<string name="select_input_method" msgid="8547250819326693584">"Shintsha ikhibhodi"</string>
@@ -1473,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Cela iphinikhodi ngaphambi kokuphina"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Cela iphethini yokuvula ngaphambi kokususa ukuphina"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Cela iphasiwedi ngaphambi kokususa ukuphina"</string>
- <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Uhlelo lokusebenza alukwazi ukunikezwa usayizi omusha, liskrole ngeminwe emibili."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Izinhlelo zokusebenza kungenzeka zingasebenzi ngesikrini esihlukanisiwe."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Uhlelo lokusebenza alusekeli isikrini esihlukanisiwe."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Ifakwe ngumlawuli wakho"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Ibuyekezwe ngumqondisi wakho"</string>
@@ -1543,12 +1537,11 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> okukhethiwe</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> okukhethiwe</item>
</plurals>
- <string name="default_notification_topic_label" msgid="227586145791870829">"Okwahlukahlukene"</string>
- <string name="importance_from_topic" msgid="3572280439880023233">"Usethe ukubaluleka kwalezi zaziso."</string>
+ <string name="importance_from_user" msgid="7318955817386549931">"Usethe ukubaluleka kwalezi zaziso."</string>
<string name="importance_from_person" msgid="9160133597262938296">"Lokhu kubalulekile ngenxa yabantu ababandakanyekayo."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Vumela i-<xliff:g id="APP">%1$s</xliff:g> ukudala umsebenzisi omusha nge-<xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Vumela i-<xliff:g id="APP">%1$s</xliff:g> ukudala umsebenzisi omusha nge-<xliff:g id="ACCOUNT">%2$s</xliff:g> (umsebenzisi onale akhawunti usuvel ukhona) ?"</string>
- <string name="language_selection_title" msgid="7181332986330337171">"Okuncamelayo kolimi"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Engeza ulwimi"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Okuncamelayo kwesifunda"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Thayipha igama lolimi"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Okuphakanyisiwe"</string>
@@ -1571,4 +1564,5 @@
<string name="pin_target" msgid="3052256031352291362">"Phina"</string>
<string name="unpin_target" msgid="3556545602439143442">"Susa ukuphina"</string>
<string name="app_info" msgid="6856026610594615344">"Ulwazi lohlelo lokusebenza"</string>
+ <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 4480944..90a573b 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3539,6 +3539,9 @@
If no format string is specified, the Chronometer will simply display
"MM:SS" or "H:MM:SS". -->
<attr name="format" format="string" localization="suggested" />
+ <!-- Specifies whether this Chronometer counts down or counts up from the base.
+ If not specified this is false and the Chronometer counts up. -->
+ <attr name="countDown" format="boolean" />
</declare-styleable>
<declare-styleable name="CompoundButton">
<!-- Indicates the initial checked state of this button. -->
@@ -8045,12 +8048,19 @@
{@link android.media.tv.TvInputService#SERVICE_META_DATA} meta-data entry.
Described here are the attributes that can be included in that tag. -->
<declare-styleable name="TvInputService">
- <!-- Component name of an activity for setup of this service.
- The setup includes scanning channels and registering EPG data. -->
+ <!-- Component name of an activity that allows the user to set up this service. -->
<attr name="setupActivity" format="string" />
- <!-- Component name of an activity that allows the user to modify
- the settings for this service. -->
+ <!-- Component name of an activity that allows the user to modify the settings for this
+ service. -->
<attr name="settingsActivity" />
+ <!-- Attribute whether the TV input service can record programs. This value can be changed
+ at runtime by calling
+ {@link android.media.tv.TvInputService#updateTvInputInfo(android.content.Context, android.media.tv.TvInputInfo)}. -->
+ <attr name="canRecord" format="boolean" />
+ <!-- The number of tuners that the TV input service is associated with. This value can be
+ changed at runtime by calling
+ {@link android.media.tv.TvInputService#updateTvInputInfo(android.content.Context, android.media.tv.TvInputInfo)}. -->
+ <attr name="tunerCount" format="integer" />
</declare-styleable>
<!-- Attributes that can be used with <code>rating-system-definition</code> tags inside of the
@@ -8172,4 +8182,15 @@
<!-- The current color for the offset inside the gradient. -->
<attr name="color" />
</declare-styleable>
+
+ <!-- @hide Attributes which will be read by the Activity to intialize the
+ base activity TaskDescription. -->
+ <declare-styleable name="ActivityTaskDescription">
+ <!-- @hide From Theme.colorPrimary, used for the TaskDescription primary
+ color. -->
+ <attr name="colorPrimary" />
+ <!-- @hide From Theme.colorBackground, used for the TaskDescription background
+ color. -->
+ <attr name="colorBackground" />
+ </declare-styleable>
</resources>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index f91bcd0..d0d1d5a 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -248,9 +248,12 @@
may cost the user money. Such permissions may be highlighted
when shown to the user with this additional information. -->
<flag name="costsMoney" value="0x0001" />
- <!-- Additional flag from base permission type: this permission is hidden
- and should not show in the UI. -->
- <flag name="hidden" value="0x2" />
+ <!-- Additional flag from base permission type: this permission has been
+ removed and it is no longer enforced. It shouldn't be shown in the
+ UI. Removed permissions are kept as normal permissions for backwards
+ compatibility as apps may be checking them before calling an API.
+ -->
+ <flag name="removed" value="0x2" />
</attr>
<!-- Specified the name of a group that this permission is associated
@@ -914,6 +917,17 @@
<p>The default value of this attribute is <code>false</code>. -->
<attr name="restoreAnyVersion" format="boolean" />
+ <!-- Indicates that full-data backup operations for this application may
+ be performed even if the application is in a foreground-equivalent
+ state. <em>Use with caution!</em> Setting this flag to <code>true</code>
+ can impact app behavior while the user is interacting with the device.
+
+ <p>If unspecified, the default value of this attribute is <code>false</code>,
+ which means that the OS will avoid backing up the application while it is
+ running in the foreground (such as a music app that is actively playing
+ music via a service in the startForeground() state). -->
+ <attr name="backupInForeground" format="boolean" />
+
<!-- The default install location defined by an application. -->
<attr name="installLocation">
<!-- Let the system decide ideal install location -->
@@ -1247,6 +1261,7 @@
<attr name="killAfterRestore" />
<attr name="restoreNeedsApplication" />
<attr name="restoreAnyVersion" />
+ <attr name="backupInForeground" />
<attr name="neverEncrypt" />
<!-- Request that your application's processes be created with
a large Dalvik heap. This applies to <em>all</em> processes
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 016ed60..7857107 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -29,6 +29,7 @@
<string-array name="config_statusBarIcons">
<item><xliff:g id="id">@string/status_bar_rotate</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_headset</xliff:g></item>
+ <item><xliff:g id="id">@string/status_bar_data_saver</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_managed_profile</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_ime</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_sync_failing</xliff:g></item>
@@ -56,6 +57,7 @@
<string translatable="false" name="status_bar_rotate">rotate</string>
<string translatable="false" name="status_bar_headset">headset</string>
+ <string translatable="false" name="status_bar_data_saver">data_saver</string>
<string translatable="false" name="status_bar_managed_profile">managed_profile</string>
<string translatable="false" name="status_bar_ime">ime</string>
<string translatable="false" name="status_bar_sync_failing">sync_failing</string>
@@ -441,6 +443,9 @@
<!-- Boolean indicating whether or not wifi firmware debugging is enabled -->
<bool translatable="false" name="config_wifi_enable_wifi_firmware_debugging">true</bool>
+ <!-- Integer size limit, in KB, for a single WifiLogger ringbuffer -->
+ <integer translatable="false" name="config_wifi_logger_ring_buffer_size_limit_kb">32</integer>
+
<!-- Boolean indicating whether or not wifi should turn off when emergency call is made -->
<bool translatable="false" name="config_wifi_turn_off_during_emergency_call">false</bool>
@@ -1992,10 +1997,10 @@
See {@link com.android.server.notification.NotificationSignalExtractor} -->
<string-array name="config_notificationSignalExtractors">
<item>com.android.server.notification.ValidateNotificationPeople</item>
- <item>com.android.server.notification.TopicPriorityExtractor</item>
- <item>com.android.server.notification.TopicImportanceExtractor</item>
+ <item>com.android.server.notification.PriorityExtractor</item>
+ <item>com.android.server.notification.ImportanceExtractor</item>
<item>com.android.server.notification.NotificationIntrusivenessExtractor</item>
- <item>com.android.server.notification.TopicVisibilityExtractor</item>
+ <item>com.android.server.notification.VisibilityExtractor</item>
</string-array>
<!-- Flag indicating that this device does not rotate and will always remain in its default
@@ -2435,6 +2440,10 @@
flag). -->
<bool name="config_forceWindowDrawsStatusBarBackground">true</bool>
+ <!-- If set, this will force the navigation bar to always be drawn with an opaque
+ background. -->
+ <bool name="config_forceNavBarAlwaysOpaque">false</bool>
+
<!-- Default bounds [left top right bottom] on screen for picture-in-picture windows. -->
<string translatable="false" name="config_defaultPictureInPictureBounds">"0 0 100 100"</string>
@@ -2442,6 +2451,10 @@
is located in center. -->
<string translatable="false" name="config_centeredPictureInPictureBounds">"0 0 300 300"</string>
+ <!-- Bounds [left top right bottom] on screen for picture-in-picture (PIP) windows,
+ when the PIP is shown with Recents. -->
+ <string translatable="false" name="config_pictureInPictureBoundsInRecents">"0 0 100 100"</string>
+
<!-- Controls the snap mode for the docked stack divider
0 - 3 snap targets: left/top has 16:9 ratio, 1:1, and right/bottom has 16:9 ratio
1 - 3 snap targets: fixed ratio, 1:1, (1 - fixed ratio)
@@ -2468,4 +2481,13 @@
much in the way of user data.
-->
<bool name="config_strongAuthRequiredOnBoot">true</bool>
+
+ <!-- Wallpaper cropper package. Used as the default cropper if the active launcher doesn't
+ handle wallpaper cropping.
+ -->
+ <string name="config_wallpaperCropperPackage" translatable="false">com.android.wallpapercropper</string>
+
+ <!-- True if the device supports at least one form of multi-window.
+ E.g. freeform, split-screen, picture-in-picture. -->
+ <bool name="config_supportsMultiWindow">true</bool>
</resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 8e86f78..152473a 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -56,6 +56,10 @@
calculate the bounds of the stacks-->
<dimen name="docked_stack_divider_insets">19dp</dimen>
+ <!-- To how much the docked stack gets reduced when we decide to minimize the docked stack, i.e.
+ when the user opens homescreen. -->
+ <dimen name="docked_stack_minimize_thickness">8dp</dimen>
+
<!-- Min width for a tablet device -->
<dimen name="min_xlarge_screen_width">800dp</dimen>
@@ -146,9 +150,6 @@
<!-- The margin on the end of the content view with a picture.-->
<dimen name="notification_content_picture_margin">56dp</dimen>
- <!-- The margin on the end of the content view with a picture in the compact media.-->
- <dimen name="notification_content_picture_margin_media">72dp</dimen>
-
<!-- height of the content margin to accomodate for the header -->
<dimen name="notification_content_margin_top">30dp</dimen>
@@ -267,7 +268,7 @@
<!-- Size of notification text (see TextAppearance.StatusBar.EventContent) -->
<dimen name="notification_text_size">14sp</dimen>
<!-- Size of notification text titles (see TextAppearance.StatusBar.EventContent.Title) -->
- <dimen name="notification_title_text_size">16sp</dimen>
+ <dimen name="notification_title_text_size">14sp</dimen>
<!-- Size of smaller notification text (see TextAppearance.StatusBar.EventContent.Line2, Info, Time) -->
<dimen name="notification_subtext_size">12sp</dimen>
diff --git a/core/res/res/values/integers.xml b/core/res/res/values/integers.xml
index 8e27226..8f8d59e 100644
--- a/core/res/res/values/integers.xml
+++ b/core/res/res/values/integers.xml
@@ -23,4 +23,7 @@
<integer name="button_pressed_animation_delay">100</integer>
<integer name="disabled_alpha_animation_duration">100</integer>
<integer name="dock_enter_exit_duration">250</integer>
+
+ <integer name="date_picker_mode">1</integer>
+ <integer name="time_picker_mode">1</integer>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 894fd37..06e2248 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2701,6 +2701,10 @@
<public type="attr" name="hotSpotX" />
<public type="attr" name="hotSpotY" />
<public type="attr" name="version" />
+ <public type="attr" name="backupInForeground" />
+ <public type="attr" name="countDown" />
+ <public type="attr" name="canRecord" />
+ <public type="attr" name="tunerCount" />
<public type="style" name="Theme.Material.Light.DialogWhenLarge.DarkActionBar" />
<public type="style" name="Widget.Material.SeekBar.Discrete" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 1f0e96d..d8efd63 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -185,8 +185,6 @@
<!-- Displayed to tell the user that they cannot change the caller ID setting. -->
<string name="CLIRPermanent">You can\'t change the caller ID setting.</string>
- <!-- Notification title to tell the user that restricted state is changed by access control. -->
- <string name="RestrictedChangedTitle">Restricted access changed</string>
<!-- Displayed to tell the user that data service is blocked by access control. -->
<string name="RestrictedOnData">Data service is blocked.</string>
<!-- Displayed to tell the user that emergency service is blocked by access control. -->
@@ -2919,20 +2917,18 @@
<!-- Message of notification shown when ADB is actively connected to the phone. -->
<string name="adb_active_notification_message">Touch to disable USB debugging.</string>
+ <!-- Title of notification shown to indicate that bug report is being collected. -->
+ <string name="taking_remote_bugreport_notification_title">Taking bug report\u2026</string>
<!-- Title of notification shown to ask for user consent for sharing a bugreport that was requested remotely by the IT administrator. -->
<string name="share_remote_bugreport_notification_title">Share bug report?</string>
<!-- Title of notification shown to indicate that bug report is still being collected after sharing was accepted. -->
<string name="sharing_remote_bugreport_notification_title">Sharing bug report\u2026</string>
- <!-- Message of notification shown to ask for user consent for sharing a bugreport that was requested remotely by the IT administrator. -->
- <string name="share_remote_bugreport_notification_message">Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared and your device may temporarily slow down.</string>
- <!-- Message of notification shown to ask for user consent for sharing a bugreport that was requested remotely by the IT administrator. -->
- <string name="share_finished_remote_bugreport_notification_message">Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared.</string>
- <!-- Message of notification shown to shown to indicate that bug report is still being collected after sharing was accepted. -->
- <string name="sharing_remote_bugreport_notification_message">This may temporarily slow down your device</string>
+ <!-- Message of a notification shown to ask for user consent for sharing a bugreport that was requested remotely by the IT administrator. -->
+ <string name="share_remote_bugreport_notification_message_finished">Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared.</string>
<!-- Acceptance label of notification shown to ask for user consent for sharing the remote bugreport. -->
- <string name="share_remote_bugreport_notification_accept">ACCEPT</string>
+ <string name="share_remote_bugreport_action">SHARE</string>
<!-- Decline label of notification shown to ask for user consent for sharing the remote bugreport. -->
- <string name="share_remote_bugreport_notification_decline">DECLINE</string>
+ <string name="decline_remote_bugreport_action">DECLINE</string>
<!-- Used to replace %s in urls retreived from the signin server with locales. For Some -->
<!-- devices we don't support all the locales we ship to and need to replace the '%s' with a -->
@@ -4016,8 +4012,8 @@
<string name="lock_to_app_unlock_password">Ask for password before unpinning</string>
<!-- Multi-Window strings -->
- <!-- Warning message when a non-resizeble tasks is docked whose display windows are cropped. -->
- <string name="dock_cropped_windows_text">App is not resizeable, scroll it with two fingers.</string>
+ <!-- Warning message when an app that got forced to be resizable gets shown in split-screen -->
+ <string name="dock_forced_resizable">App may not work with split-screen.</string>
<!-- Warning message when we try to dock a non-resizeble tasks and launch it in fullscreen instead. -->
<string name="dock_non_resizeble_failed_to_dock_text">App does not support split-screen.</string>
@@ -4162,9 +4158,7 @@
<item quantity="other"><xliff:g id="count" example="3">%1$d</xliff:g> selected</item>
</plurals>
- <string name="default_notification_topic_label">Miscellaneous</string>
-
- <string name="importance_from_topic">You set the importance of these notifications.</string>
+ <string name="importance_from_user">You set the importance of these notifications.</string>
<string name="importance_from_person">This is important because of the people involved.</string>
<!-- Message to user that app trying to create user for an account that already exists. [CHAR LIMIT=none] -->
@@ -4175,7 +4169,7 @@
<!-- Locale picker strings -->
<!-- Title for the language selection screen [CHAR LIMIT=25] -->
- <string name="language_selection_title">Language preference</string>
+ <string name="language_selection_title">Add a language</string>
<!-- Title for the region selection screen [CHAR LIMIT=25] -->
<string name="country_selection_title">Region preference</string>
<!-- Hint text in a search edit box (used to filter long language / country lists) [CHAR LIMIT=25] -->
@@ -4232,4 +4226,7 @@
<!-- View application info for a target. -->
<string name="app_info">App info</string>
+ <!-- The representation of a time duration when negative. An example is -1:14. This can be used with a countdown timer for example.-->
+ <string name="negative_duration">\u2212<xliff:g id="time" example="1:14">%1$s</xliff:g></string>
+
</resources>
diff --git a/core/res/res/values/styles_holo.xml b/core/res/res/values/styles_holo.xml
index 6c69141..fdf9e31 100644
--- a/core/res/res/values/styles_holo.xml
+++ b/core/res/res/values/styles_holo.xml
@@ -1175,7 +1175,6 @@
<style name="Widget.Holo.SuggestionItem" parent="TextAppearance.Holo.Medium">
<item name="background">@color/white</item>
<item name="drawablePadding">8dip</item>
- <item name="ellipsize">marquee</item>
<item name="gravity">start|center_vertical</item>
<item name="layout_gravity">start|center_vertical</item>
<item name="layout_height">wrap_content</item>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 9efcfda..a9c8a06 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -652,7 +652,7 @@
</style>
<style name="Widget.Material.TimePicker">
- <item name="timePickerMode">clock</item>
+ <item name="timePickerMode">@integer/time_picker_mode</item>
<item name="legacyLayout">@layout/time_picker_legacy_material</item>
<!-- Attributes for new-style TimePicker. -->
<item name="internalLayout">@layout/time_picker_material</item>
@@ -666,7 +666,7 @@
</style>
<style name="Widget.Material.DatePicker">
- <item name="datePickerMode">calendar</item>
+ <item name="datePickerMode">@integer/date_picker_mode</item>
<item name="legacyLayout">@layout/date_picker_legacy_holo</item>
<item name="calendarViewShown">true</item>
<!-- Attributes for new-style DatePicker. -->
@@ -996,7 +996,6 @@
<item name="alpha">.87</item>
<item name="textColor">@color/black</item>
<item name="drawablePadding">8dip</item>
- <item name="ellipsize">marquee</item>
<item name="gravity">start|center_vertical</item>
<item name="layout_gravity">start|center_vertical</item>
<item name="layout_height">48dip</item>
@@ -1017,7 +1016,6 @@
<item name="alpha">.87</item>
<item name="textColor">#009688</item>
<item name="drawablePadding">8dip</item>
- <item name="ellipsize">marquee</item>
<item name="gravity">start|center_vertical</item>
<item name="layout_gravity">start|center_vertical</item>
<item name="layout_height">48dip</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 2d3ad17..15521e4 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -298,14 +298,17 @@
<java-symbol type="bool" name="config_wifi_enable_5GHz_preference" />
<java-symbol type="bool" name="config_wifi_revert_country_code_on_cellular_loss" />
<java-symbol type="bool" name="config_wifi_enable_wifi_firmware_debugging" />
+ <java-symbol type="integer" name="config_wifi_logger_ring_buffer_size_limit_kb" />
<java-symbol type="bool" name="config_wifi_turn_off_during_emergency_call" />
<java-symbol type="bool" name="config_supportMicNearUltrasound" />
<java-symbol type="bool" name="config_supportSpeakerNearUltrasound" />
<java-symbol type="bool" name="config_supportAudioSourceUnprocessed" />
<java-symbol type="bool" name="config_freeformWindowManagement" />
+ <java-symbol type="bool" name="config_supportsMultiWindow" />
<java-symbol type="bool" name="config_guestUserEphemeral" />
<java-symbol type="string" name="config_defaultPictureInPictureBounds" />
<java-symbol type="string" name="config_centeredPictureInPictureBounds" />
+ <java-symbol type="string" name="config_pictureInPictureBoundsInRecents" />
<java-symbol type="integer" name="config_wifi_framework_5GHz_preference_boost_threshold" />
<java-symbol type="integer" name="config_wifi_framework_5GHz_preference_boost_factor" />
<java-symbol type="integer" name="config_wifi_framework_5GHz_preference_penalty_threshold" />
@@ -484,7 +487,6 @@
<java-symbol type="string" name="Noon" />
<java-symbol type="string" name="PinMmi" />
<java-symbol type="string" name="PwdMmi" />
- <java-symbol type="string" name="RestrictedChangedTitle" />
<java-symbol type="string" name="RestrictedOnAllVoice" />
<java-symbol type="string" name="RestrictedOnData" />
<java-symbol type="string" name="RestrictedOnEmergency" />
@@ -610,7 +612,7 @@
<java-symbol type="string" name="display_manager_overlay_display_name" />
<java-symbol type="string" name="display_manager_overlay_display_secure_suffix" />
<java-symbol type="string" name="display_manager_overlay_display_title" />
- <java-symbol type="string" name="dock_cropped_windows_text" />
+ <java-symbol type="string" name="dock_forced_resizable" />
<java-symbol type="string" name="dock_non_resizeble_failed_to_dock_text" />
<java-symbol type="string" name="double_tap_toast" />
<java-symbol type="string" name="durationDays" />
@@ -1506,6 +1508,7 @@
<java-symbol type="bool" name="target_honeycomb_needs_options_menu" />
<java-symbol type="dimen" name="docked_stack_divider_thickness" />
<java-symbol type="dimen" name="docked_stack_divider_insets" />
+ <java-symbol type="dimen" name="docked_stack_minimize_thickness" />
<java-symbol type="integer" name="config_dockedStackDividerSnapMode" />
<java-symbol type="fraction" name="docked_stack_divider_fixed_ratio" />
<java-symbol type="dimen" name="navigation_bar_height" />
@@ -1768,13 +1771,12 @@
<java-symbol type="string" name="accessibility_binding_label" />
<java-symbol type="string" name="adb_active_notification_message" />
<java-symbol type="string" name="adb_active_notification_title" />
+ <java-symbol type="string" name="taking_remote_bugreport_notification_title" />
<java-symbol type="string" name="share_remote_bugreport_notification_title" />
- <java-symbol type="string" name="share_remote_bugreport_notification_message" />
- <java-symbol type="string" name="share_finished_remote_bugreport_notification_message" />
<java-symbol type="string" name="sharing_remote_bugreport_notification_title" />
- <java-symbol type="string" name="sharing_remote_bugreport_notification_message" />
- <java-symbol type="string" name="share_remote_bugreport_notification_accept" />
- <java-symbol type="string" name="share_remote_bugreport_notification_decline" />
+ <java-symbol type="string" name="share_remote_bugreport_notification_message_finished" />
+ <java-symbol type="string" name="share_remote_bugreport_action" />
+ <java-symbol type="string" name="decline_remote_bugreport_action" />
<java-symbol type="string" name="aerr_application" />
<java-symbol type="string" name="aerr_process" />
<java-symbol type="string" name="aerr_application_repeated" />
@@ -2388,8 +2390,8 @@
<java-symbol type="string" name="config_iccHotswapPromptForRestartDialogComponent" />
<java-symbol type="string" name="config_packagedKeyboardName" />
- <java-symbol type="string" name="default_notification_topic_label" />
<java-symbol type="bool" name="config_forceWindowDrawsStatusBarBackground" />
+ <java-symbol type="bool" name="config_forceNavBarAlwaysOpaque" />
<java-symbol type="color" name="system_bar_background_semi_transparent" />
<!-- EditText suggestion popup. -->
@@ -2427,12 +2429,13 @@
<java-symbol type="dimen" name="notification_content_margin_end" />
<java-symbol type="dimen" name="notification_content_picture_margin" />
<java-symbol type="dimen" name="notification_content_margin_top" />
- <java-symbol type="string" name="importance_from_topic" />
+ <java-symbol type="string" name="importance_from_user" />
<java-symbol type="string" name="importance_from_person" />
<java-symbol type="layout" name="work_widget_mask_view" />
+ <java-symbol type="id" name="work_widget_mask_frame" />
<java-symbol type="id" name="work_widget_app_icon" />
- <java-symbol type="drawable" name="work_widget_mask_view_background" />
+ <java-symbol type="id" name="work_widget_badge_icon" />
<java-symbol type="id" name="aerr_report" />
<java-symbol type="id" name="aerr_reset" />
@@ -2460,6 +2463,7 @@
<java-symbol type="string" name="status_bar_rotate" />
<java-symbol type="string" name="status_bar_headset" />
+ <java-symbol type="string" name="status_bar_data_saver" />
<java-symbol type="string" name="status_bar_managed_profile" />
<java-symbol type="string" name="status_bar_ime" />
<java-symbol type="string" name="status_bar_sync_failing" />
@@ -2485,7 +2489,6 @@
<java-symbol type="string" name="status_bar_clock" />
<!-- Locale picker -->
- <java-symbol type="id" name="l10nWarn" />
<java-symbol type="id" name="locale_search_menu" />
<java-symbol type="layout" name="language_picker_item" />
<java-symbol type="layout" name="language_picker_section_header" />
@@ -2512,13 +2515,14 @@
<java-symbol type="dimen" name="media_notification_expanded_image_max_size" />
<java-symbol type="dimen" name="media_notification_expanded_image_margin_bottom" />
<java-symbol type="dimen" name="notification_content_image_margin_end" />
- <java-symbol type="dimen" name="notification_content_picture_margin_media" />
<java-symbol type="bool" name="config_strongAuthRequiredOnBoot" />
<java-symbol type="layout" name="app_anr_dialog" />
<java-symbol type="id" name="aerr_wait" />
+ <java-symbol type="id" name="notification_content_container" />
+
<!-- Encryption notification while accounts are locked by credential encryption -->
<java-symbol type="string" name="user_encrypted_title" />
<java-symbol type="string" name="user_encrypted_message" />
@@ -2539,4 +2543,8 @@
<java-symbol type="string" name="carrier_app_dialog_not_now" />
<java-symbol type="string" name="carrier_app_notification_title" />
<java-symbol type="string" name="carrier_app_notification_text" />
+ <java-symbol type="string" name="negative_duration" />
+
+ <!-- WallpaperManager config -->
+ <java-symbol type="string" name="config_wallpaperCropperPackage" />
</resources>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index dd8baa7..11bb106 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -544,9 +544,7 @@
<item name="windowNoTitle">true</item>
<item name="windowBackground">@color/transparent</item>
<item name="backgroundDimEnabled">true</item>
- <item name="windowTranslucentStatus">false</item>
- <item name="windowTranslucentNavigation">false</item>
- <item name="windowDrawsSystemBarBackgrounds">false</item>
+ <item name="statusBarColor">@color/transparent</item>
<item name="windowContentOverlay">@null</item>
<item name="colorControlActivated">?attr/colorControlHighlight</item>
<item name="listPreferredItemPaddingStart">?attr/dialogPreferredPadding</item>
diff --git a/core/res/res/values/themes_micro.xml b/core/res/res/values/themes_micro.xml
index 8bf635e..478d66c 100644
--- a/core/res/res/values/themes_micro.xml
+++ b/core/res/res/values/themes_micro.xml
@@ -24,7 +24,6 @@
<item name="windowBackground">@color/black</item>
<item name="windowContentOverlay">@null</item>
<item name="windowIsFloating">false</item>
- <item name="windowSwipeToDismiss">true</item>
<!-- Required to force windowInsets dispatch through application UI. -->
<item name="windowOverscan">true</item>
</style>
@@ -42,7 +41,6 @@
<item name="windowBackground">@color/white</item>
<item name="windowContentOverlay">@null</item>
<item name="windowIsFloating">false</item>
- <item name="windowSwipeToDismiss">true</item>
<!-- Required to force windowInsets dispatch through application UI. -->
<item name="windowOverscan">true</item>
</style>
diff --git a/core/tests/coretests/apks/install_jni_lib/Android.mk b/core/tests/coretests/apks/install_jni_lib/Android.mk
index 7322e8d..9e45d09 100644
--- a/core/tests/coretests/apks/install_jni_lib/Android.mk
+++ b/core/tests/coretests/apks/install_jni_lib/Android.mk
@@ -22,6 +22,8 @@
LOCAL_SHARED_LIBRARIES := \
libnativehelper
+LOCAL_CFLAGS += -Wall -Werror
+
LOCAL_MODULE := libframeworks_coretests_jni
# this does not prevent build system
diff --git a/core/tests/coretests/apks/install_jni_lib/com_android_frameworks_coretests_JNITest.cpp b/core/tests/coretests/apks/install_jni_lib/com_android_frameworks_coretests_JNITest.cpp
index 3e83010..8d91192 100644
--- a/core/tests/coretests/apks/install_jni_lib/com_android_frameworks_coretests_JNITest.cpp
+++ b/core/tests/coretests/apks/install_jni_lib/com_android_frameworks_coretests_JNITest.cpp
@@ -37,7 +37,7 @@
/*
* JNI Initialization
*/
-jint JNI_OnLoad(JavaVM *jvm, void *reserved) {
+jint JNI_OnLoad(JavaVM *jvm, void */* reserved */) {
JNIEnv *e;
int status;
diff --git a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
index 998c72a..c92863d 100644
--- a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
+++ b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
@@ -328,7 +328,12 @@
// Only a1's pause listener should be called.
assertTrue(l1.pauseCalled);
assertFalse(l1.resumeCalled);
- a1.resume();
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ a1.resume();
+ }
+ });
Thread.sleep(a1.getTotalDuration());
diff --git a/core/tests/coretests/src/android/content/pm/ContainerEncryptionParamsTest.java b/core/tests/coretests/src/android/content/pm/ContainerEncryptionParamsTest.java
deleted file mode 100644
index 7deaa9a..0000000
--- a/core/tests/coretests/src/android/content/pm/ContainerEncryptionParamsTest.java
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm;
-
-import android.os.Parcel;
-import android.test.AndroidTestCase;
-
-import java.util.Arrays;
-
-import javax.crypto.SecretKey;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
-
-public class ContainerEncryptionParamsTest extends AndroidTestCase {
- private static final String ENC_ALGORITHM = "AES/CBC/PKCS7Padding";
-
- private static final byte[] IV_BYTES = "FOOBAR".getBytes();
-
- private static final IvParameterSpec ENC_PARAMS = new IvParameterSpec(IV_BYTES);
-
- private static final byte[] ENC_KEY_BYTES = "abcd1234wxyz7890".getBytes();
-
- private static final SecretKey ENC_KEY = new SecretKeySpec(ENC_KEY_BYTES, "RAW");
-
- private static final String MAC_ALGORITHM = "HMAC-SHA1";
-
- private static final byte[] MAC_KEY_BYTES = "4wxyzabcd1237890".getBytes();
-
- private static final SecretKey MAC_KEY = new SecretKeySpec(MAC_KEY_BYTES, "RAW");
-
- private static final byte[] MAC_TAG = "faketag".getBytes();
-
- private static final int AUTHENTICATED_START = 5;
-
- private static final int ENCRYPTED_START = 11;
-
- private static final int DATA_END = 19;
-
- public void testParcel() throws Exception {
- ContainerEncryptionParams expected = new ContainerEncryptionParams(ENC_ALGORITHM,
- ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- Parcel parcel = Parcel.obtain();
- expected.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
-
- ContainerEncryptionParams actual = ContainerEncryptionParams.CREATOR
- .createFromParcel(parcel);
-
- assertEquals(ENC_ALGORITHM, actual.getEncryptionAlgorithm());
-
- if (!(actual.getEncryptionSpec() instanceof IvParameterSpec)) {
- fail("encryption parameters should be IvParameterSpec");
- } else {
- IvParameterSpec actualParams = (IvParameterSpec) actual.getEncryptionSpec();
- assertTrue(Arrays.equals(IV_BYTES, actualParams.getIV()));
- }
-
- assertEquals(ENC_KEY, actual.getEncryptionKey());
-
- assertEquals(MAC_ALGORITHM, actual.getMacAlgorithm());
-
- assertNull(actual.getMacSpec());
-
- assertEquals(MAC_KEY, actual.getMacKey());
-
- assertTrue(Arrays.equals(MAC_TAG, actual.getMacTag()));
-
- assertEquals(AUTHENTICATED_START, actual.getAuthenticatedDataStart());
-
- assertEquals(ENCRYPTED_START, actual.getEncryptedDataStart());
-
- assertEquals(DATA_END, actual.getDataEnd());
- }
-
- public void testEquals_Success() throws Exception {
- ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
- ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- ContainerEncryptionParams params2 = new ContainerEncryptionParams(
- new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
- new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
- new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- assertEquals(params1, params2);
- }
-
- public void testEquals_EncAlgo_Failure() throws Exception {
- ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
- ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- ContainerEncryptionParams params2 = new ContainerEncryptionParams(new String(
- "AES-256/CBC/PKCS7Padding"), new IvParameterSpec(IV_BYTES.clone()),
- new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
- new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- assertFalse(params1.equals(params2));
- }
-
- public void testEquals_EncParams_Failure() throws Exception {
- ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
- ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- ContainerEncryptionParams params2 = new ContainerEncryptionParams(
- new String(ENC_ALGORITHM), new IvParameterSpec("BLAHBLAH".getBytes()),
- new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
- new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- assertFalse(params1.equals(params2));
- }
-
- public void testEquals_EncKey_Failure() throws Exception {
- ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
- ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- ContainerEncryptionParams params2 = new ContainerEncryptionParams(
- new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
- new SecretKeySpec("BLAHBLAH".getBytes(), "RAW"), new String(MAC_ALGORITHM), null,
- new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- assertFalse(params1.equals(params2));
- }
-
- public void testEquals_MacAlgo_Failure() throws Exception {
- ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
- ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- ContainerEncryptionParams params2 = new ContainerEncryptionParams(
- new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
- new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), "BLAHBLAH", null,
- new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- assertFalse(params1.equals(params2));
- }
-
- public void testEquals_MacKey_Failure() throws Exception {
- ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
- ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- ContainerEncryptionParams params2 = new ContainerEncryptionParams(
- new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
- new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
- new SecretKeySpec("FAKE_MAC_KEY".getBytes(), "RAW"), MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- assertFalse(params1.equals(params2));
- }
-
- public void testEquals_MacTag_Failure() throws Exception {
- ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
- ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- ContainerEncryptionParams params2 = new ContainerEncryptionParams(
- new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
- new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
- new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), "broken".getBytes(),
- AUTHENTICATED_START, ENCRYPTED_START, DATA_END);
-
- assertFalse(params1.equals(params2));
- }
-
- public void testEquals_AuthenticatedStart_Failure() throws Exception {
- ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
- ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- ContainerEncryptionParams params2 = new ContainerEncryptionParams(
- new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
- new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
- new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START - 1,
- ENCRYPTED_START, DATA_END);
-
- assertFalse(params1.equals(params2));
- }
-
- public void testEquals_EncryptedStart_Failure() throws Exception {
- ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
- ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- ContainerEncryptionParams params2 = new ContainerEncryptionParams(
- new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
- new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
- new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START - 1, DATA_END);
-
- assertFalse(params1.equals(params2));
- }
-
- public void testEquals_DataEnd_Failure() throws Exception {
- ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
- ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- ContainerEncryptionParams params2 = new ContainerEncryptionParams(
- new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
- new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
- new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END + 1);
-
- assertFalse(params1.equals(params2));
- }
-
- public void testHashCode_Success() throws Exception {
- ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
- ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- ContainerEncryptionParams params2 = new ContainerEncryptionParams(
- new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
- new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
- new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- assertEquals(params1.hashCode(), params2.hashCode());
- }
-
- public void testHashCode_EncAlgo_Failure() throws Exception {
- ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
- ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- ContainerEncryptionParams params2 = new ContainerEncryptionParams(new String(
- "AES-256/CBC/PKCS7Padding"), new IvParameterSpec(IV_BYTES.clone()),
- new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
- new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- assertFalse(params1.hashCode() == params2.hashCode());
- }
-
- public void testHashCode_EncParams_Failure() throws Exception {
- ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
- ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- ContainerEncryptionParams params2 = new ContainerEncryptionParams(
- new String(ENC_ALGORITHM), new IvParameterSpec("BLAHBLAH".getBytes()),
- new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
- new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- assertFalse(params1.hashCode() == params2.hashCode());
- }
-
- public void testHashCode_EncKey_Failure() throws Exception {
- ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
- ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- ContainerEncryptionParams params2 = new ContainerEncryptionParams(
- new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
- new SecretKeySpec("BLAHBLAH".getBytes(), "RAW"), new String(MAC_ALGORITHM), null,
- new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- assertFalse(params1.hashCode() == params2.hashCode());
- }
-
- public void testHashCode_MacAlgo_Failure() throws Exception {
- ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
- ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- ContainerEncryptionParams params2 = new ContainerEncryptionParams(
- new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
- new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), "BLAHBLAH", null,
- new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- assertFalse(params1.hashCode() == params2.hashCode());
- }
-
- public void testHashCode_MacKey_Failure() throws Exception {
- ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
- ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- ContainerEncryptionParams params2 = new ContainerEncryptionParams(
- new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
- new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
- new SecretKeySpec("FAKE_MAC_KEY".getBytes(), "RAW"), MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- assertFalse(params1.hashCode() == params2.hashCode());
- }
-
- public void testHashCode_MacTag_Failure() throws Exception {
- ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
- ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- ContainerEncryptionParams params2 = new ContainerEncryptionParams(
- new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
- new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
- new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), "broken".getBytes(),
- AUTHENTICATED_START, ENCRYPTED_START, DATA_END);
-
- assertFalse(params1.hashCode() == params2.hashCode());
- }
-
- public void testHashCode_AuthenticatedStart_Failure() throws Exception {
- ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
- ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- ContainerEncryptionParams params2 = new ContainerEncryptionParams(
- new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
- new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
- new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START - 1,
- ENCRYPTED_START, DATA_END);
-
- assertFalse(params1.hashCode() == params2.hashCode());
- }
-
- public void testHashCode_EncryptedStart_Failure() throws Exception {
- ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
- ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- ContainerEncryptionParams params2 = new ContainerEncryptionParams(
- new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
- new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
- new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START - 1, DATA_END);
-
- assertFalse(params1.hashCode() == params2.hashCode());
- }
-
- public void testHashCode_DataEnd_Failure() throws Exception {
- ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
- ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END);
-
- ContainerEncryptionParams params2 = new ContainerEncryptionParams(
- new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
- new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
- new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
- ENCRYPTED_START, DATA_END + 1);
-
- assertFalse(params1.hashCode() == params2.hashCode());
- }
-}
diff --git a/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java b/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
index e9fd5fb..5d46489 100644
--- a/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
+++ b/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
@@ -38,7 +38,7 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- mCache = new ConfigurationBoundResourceCache<Float>(getActivity().getResources());
+ mCache = new ConfigurationBoundResourceCache<>();
}
public void testGetEmpty() {
diff --git a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
new file mode 100644
index 0000000..da17045
--- /dev/null
+++ b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
@@ -0,0 +1,472 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text.method;
+
+import android.app.Activity;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.Suppress;
+import android.text.InputType;
+import android.text.method.BaseKeyListener;
+import android.text.method.KeyListenerTestCase;
+import android.view.KeyEvent;
+import android.widget.EditText;
+import android.widget.TextView.BufferType;
+
+/**
+ * Test forward delete key handling of {@link android.text.method.BaseKeyListener}.
+ *
+ * TODO: Move some of test cases to the CTS.
+ */
+public class ForwardDeleteTest extends KeyListenerTestCase {
+ private static final BaseKeyListener mKeyListener = new BaseKeyListener() {
+ public int getInputType() {
+ return InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL;
+ }
+ };
+
+ // Sync the state to the TextView and call onKeyDown with KEYCODE_FORWARD_DEL key event.
+ // Then update the state to the result of TextView.
+ private void forwardDelete(final EditorState state, int modifiers) {
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ mTextView.setText(state.mText, BufferType.EDITABLE);
+ mTextView.setKeyListener(mKeyListener);
+ mTextView.setSelection(state.mSelectionStart, state.mSelectionEnd);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ assertTrue(mTextView.hasWindowFocus());
+
+ final KeyEvent keyEvent = getKey(KeyEvent.KEYCODE_FORWARD_DEL, modifiers);
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ mTextView.onKeyDown(keyEvent.getKeyCode(), keyEvent);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ state.mText = mTextView.getText();
+ state.mSelectionStart = mTextView.getSelectionStart();
+ state.mSelectionEnd = mTextView.getSelectionEnd();
+ }
+
+ @SmallTest
+ public void testSurrogatePairs() {
+ EditorState state = new EditorState();
+
+ // U+1F441 is EYE
+ state.setByString("| U+1F441");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // U+1F5E8 is LEFT SPEECH BUBBLE
+ state.setByString("| U+1F441 U+1F5E8");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F5E8");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // TODO: introduce edge cases.
+ }
+
+ @SmallTest
+ public void testReplacementSpan() {
+ EditorState state = new EditorState();
+
+ state.setByString("| 'abc' ( 'de' ) 'fg'");
+ forwardDelete(state, 0);
+ state.assertEquals("| 'bc' ( 'de' ) 'fg'");
+ forwardDelete(state, 0);
+ state.assertEquals("| 'c' ( 'de' ) 'fg'");
+ forwardDelete(state, 0);
+ state.assertEquals("| ( 'de' ) 'fg'");
+ forwardDelete(state, 0);
+ state.assertEquals("| 'fg'");
+ forwardDelete(state, 0);
+ state.assertEquals("| 'g'");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("'abc' [ ( 'de' ) ] 'fg'");
+ forwardDelete(state, 0);
+ state.assertEquals("'abc' | 'fg'");
+ forwardDelete(state, 0);
+ state.assertEquals("'abc' | 'g'");
+ forwardDelete(state, 0);
+ state.assertEquals("'abc' |");
+ forwardDelete(state, 0);
+ state.assertEquals("'abc' |");
+
+ state.setByString("'ab' [ 'c' ( 'de' ) 'f' ] 'g'");
+ forwardDelete(state, 0);
+ state.assertEquals("'ab' | 'g'");
+ forwardDelete(state, 0);
+ state.assertEquals("'ab' |");
+ forwardDelete(state, 0);
+ state.assertEquals("'ab' |");
+
+ // TODO: introduce edge cases.
+ }
+
+ @SmallTest
+ public void testCombiningEnclosingKeycaps() {
+ EditorState state = new EditorState();
+
+ // U+20E3 is COMBINING ENCLOSING KEYCAP.
+ state.setByString("| '1' U+20E3");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Edge cases
+ // multiple COMBINING ENCLOSING KEYCAP
+ state.setByString("| '1' U+20E3 U+20E3");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Isolated COMBINING ENCLOSING KEYCAP
+ state.setByString("| U+20E3");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Isolated multiple COMBINING ENCLOSING KEYCAP
+ state.setByString("| U+20E3 U+20E3");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+ }
+
+ @SmallTest
+ public void testVariationSelector() {
+ EditorState state = new EditorState();
+
+ // U+FE0F is VARIATION SELECTOR-16.
+ state.setByString("| '#' U+FE0F");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // U+E0100 is VARIATION SELECTOR-17.
+ state.setByString("| U+845B U+E0100");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Edge cases
+ // Isolated variation selectors
+ state.setByString("| U+FE0F");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("| U+E0100");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Isolated multiple variation selectors
+ state.setByString("| U+FE0F U+FE0F");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("| U+FE0F U+E0100");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("| U+E0100 U+FE0F");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("| U+E0100 U+E0100");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Multiple variation selectors
+ state.setByString("| '#' U+FE0F U+FE0F");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("| '#' U+FE0F U+E0100");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("| U+845B U+E0100 U+FE0F");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("| U+845B U+E0100 U+E0100");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+ }
+
+ @SmallTest
+ public void testEmojiZeroWidthJoinerSequence() {
+ EditorState state = new EditorState();
+
+ // U+200D is ZERO WIDTH JOINER.
+ state.setByString("| U+1F441 U+200D U+1F5E8");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("| U+1F468 U+200D U+2764 U+FE0F U+200D U+1F48B U+200D U+1F468");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Edge cases
+ // End with ZERO WIDTH JOINER
+ state.setByString("| U+1F441 U+200D");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Start with ZERO WIDTH JOINER
+ state.setByString("| U+200D U+1F5E8");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F5E8");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Multiple ZERO WIDTH JOINER
+ state.setByString("| U+1F441 U+200D U+200D U+1F5E8");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F5E8");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Isolated ZERO WIDTH JOINER
+ state.setByString("| U+200D");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Isolated multiple ZERO WIDTH JOINER
+ state.setByString("| U+200D U+200D");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+ }
+
+ @SmallTest
+ public void testFlags() {
+ EditorState state = new EditorState();
+
+ // U+1F1FA is REGIONAL INDICATOR SYMBOL LETTER U.
+ // U+1F1F8 is REGIONAL INDICATOR SYMBOL LETTER S.
+ state.setByString("| U+1F1FA U+1F1F8");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("| U+1F1FA U+1F1F8 U+1F1FA U+1F1F8");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F1FA U+1F1F8");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Edge cases
+ // Isolated regional indicator symbol
+ state.setByString("| U+1F1FA");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Odd numbered regional indicator symbols
+ state.setByString("| U+1F1FA U+1F1F8 U+1F1FA");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F1FA");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+ }
+
+ @SmallTest
+ public void testEmojiModifier() {
+ EditorState state = new EditorState();
+
+ // U+1F3FB is EMOJI MODIFIER FITZPATRICK TYPE-1-2.
+ state.setByString("| U+1F466 U+1F3FB");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Edge cases
+ // Isolated emoji modifier
+ state.setByString("| U+1F3FB");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Isolated multiple emoji modifier
+ state.setByString("| U+1F3FB U+1F3FB");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F3FB");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Multiple emoji modifiers
+ state.setByString("| U+1F466 U+1F3FB U+1F3FB");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F3FB");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+ }
+
+ @SmallTest
+ public void testMixedEdgeCases() {
+ EditorState state = new EditorState();
+
+ // COMBINING ENCLOSING KEYCAP + variation selector
+ state.setByString("| '1' U+20E3 U+FE0F");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Variation selector + COMBINING ENCLOSING KEYCAP
+ state.setByString("| U+2665 U+FE0F U+20E3");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // COMBINING ENCLOSING KEYCAP + ending with ZERO WIDTH JOINER
+ state.setByString("| '1' U+20E3 U+200D");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // COMBINING ENCLOSING KEYCAP + ZERO WIDTH JOINER
+ state.setByString("| '1' U+20E3 U+200D U+1F5E8");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F5E8 ");
+
+ // Start with ZERO WIDTH JOINER + COMBINING ENCLOSING KEYCAP
+ state.setByString("| U+200D U+20E3");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // ZERO WIDTH JOINER + COMBINING ENCLOSING KEYCAP
+ state.setByString("| U+1F441 U+200D U+20E3");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // COMBINING ENCLOSING KEYCAP + regional indicator symbol
+ state.setByString("| '1' U+20E3 U+1F1FA");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F1FA");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Regional indicator symbol + COMBINING ENCLOSING KEYCAP
+ state.setByString("| U+1F1FA U+20E3");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // COMBINING ENCLOSING KEYCAP + emoji modifier
+ state.setByString("| '1' U+20E3 U+1F3FB");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F3FB");
+
+ // Emoji modifier + COMBINING ENCLOSING KEYCAP
+ state.setByString("| U+1F466 U+1F3FB U+20E3");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Variation selector + end with ZERO WIDTH JOINER
+ state.setByString("| U+2665 U+FE0F U+200D");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Variation selector + ZERO WIDTH JOINER
+ state.setByString("| U+1F469 U+200D U+2764 U+FE0F U+200D U+1F469");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Start with ZERO WIDTH JOINER + variation selector
+ state.setByString("| U+200D U+FE0F");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // ZERO WIDTH JOINER + variation selector
+ state.setByString("| U+1F469 U+200D U+FE0F");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Variation selector + regional indicator symbol
+ state.setByString("| U+2665 U+FE0F U+1F1FA");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F1FA");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Regional indicator symbol + variation selector
+ state.setByString("| U+1F1FA U+FE0F");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Variation selector + emoji modifier
+ state.setByString("| U+2665 U+FE0F U+1F3FB");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F3FB");
+
+ // Emoji modifier + variation selector
+ state.setByString("| U+1F466 U+1F3FB U+FE0F");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Start with ZERO WIDTH JOINER + regional indicator symbol
+ state.setByString("| U+200D U+1F1FA");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F1FA");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // ZERO WIDTH JOINER + regional indicator symbol
+ state.setByString("| U+1F469 U+200D U+1F1FA");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F1FA");
+
+ // Regional indicator symbol + end with ZERO WIDTH JOINER
+ state.setByString("| U+1F1FA U+200D");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Regional indicator symbol + ZERO WIDTH JOINER
+ state.setByString("| U+1F1FA U+200D U+1F469");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F469");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Start with ZERO WIDTH JOINER + emoji modifier
+ state.setByString("| U+200D U+1F3FB");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F3FB");
+
+ // ZERO WIDTH JOINER + emoji modifier
+ state.setByString("| U+1F469 U+200D U+1F3FB");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F3FB");
+
+ // Emoji modifier + end with ZERO WIDTH JOINER
+ state.setByString("| U+1F466 U+1F3FB U+200D");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Emoji modifier + ZERO WIDTH JOINER
+ state.setByString("| U+1F466 U+1F3FB U+200D U+1F469");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F469");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Regional indicator symbol + emoji modifier
+ state.setByString("| U+1F1FA U+1F3FB");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F3FB");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Emoji modifier + regional indicator symbol
+ state.setByString("| U+1F466 U+1F3FB U+1F1FA");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F1FA");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+ }
+}
diff --git a/core/tests/coretests/src/android/util/PatternsTest.java b/core/tests/coretests/src/android/util/PatternsTest.java
index d383775..348f8fd 100644
--- a/core/tests/coretests/src/android/util/PatternsTest.java
+++ b/core/tests/coretests/src/android/util/PatternsTest.java
@@ -25,7 +25,7 @@
public class PatternsTest extends TestCase {
- //Tests for Patterns.TOP_LEVEL_DOMAIN
+ // Tests for Patterns.TOP_LEVEL_DOMAIN
@SmallTest
public void testTldPattern() throws Exception {
@@ -56,7 +56,7 @@
assertFalse("Matched invalid TLD!", t);
}
- //Tests for Patterns.IANA_TOP_LEVEL_DOMAINS
+ // Tests for Patterns.IANA_TOP_LEVEL_DOMAINS
@SmallTest
public void testIanaTopLevelDomains_matchesValidTld() throws Exception {
@@ -94,7 +94,7 @@
assertFalse("Should not match invalid Punycode TLD", pattern.matcher("xn").matches());
}
- //Tests for Patterns.WEB_URL
+ // Tests for Patterns.WEB_URL
@SmallTest
public void testWebUrl_matchesValidUrlWithSchemeAndHostname() throws Exception {
@@ -208,7 +208,7 @@
Patterns.WEB_URL.matcher(url).matches());
}
- //Tests for Patterns.AUTOLINK_WEB_URL
+ // Tests for Patterns.AUTOLINK_WEB_URL
@SmallTest
public void testAutoLinkWebUrl_matchesValidUrlWithSchemeAndHostname() throws Exception {
@@ -419,7 +419,7 @@
Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
}
- //Tests for Patterns.IP_ADDRESS
+ // Tests for Patterns.IP_ADDRESS
@SmallTest
public void testIpPattern() throws Exception {
@@ -432,7 +432,7 @@
assertFalse("Invalid IP", t);
}
- //Tests for Patterns.DOMAIN_NAME
+ // Tests for Patterns.DOMAIN_NAME
@SmallTest
public void testDomain_matchesPunycodeTld() throws Exception {
@@ -508,7 +508,227 @@
Patterns.DOMAIN_NAME.matcher(domain).matches());
}
- //Tests for Patterns.PHONE
+ // Tests for Patterns.AUTOLINK_EMAIL_ADDRESS
+
+ public void testAutoLinkEmailAddress_matchesShortValidEmail() throws Exception {
+ String email = "a@a.co";
+ assertTrue("Should match short valid email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesRegularEmail() throws Exception {
+ String email = "email@android.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesEmailWithMultipleSubdomains() throws Exception {
+ String email = "email@e.somelongdomainnameforandroid.abc.uk";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesLocalPartWithDot() throws Exception {
+ String email = "e.mail@android.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesLocalPartWithPlus() throws Exception {
+ String email = "e+mail@android.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesLocalPartWithUnderscore() throws Exception {
+ String email = "e_mail@android.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesLocalPartWithDash() throws Exception {
+ String email = "e-mail@android.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesLocalPartWithApostrophe() throws Exception {
+ String email = "e'mail@android.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesLocalPartWithDigits() throws Exception {
+ String email = "123@android.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesUnicodeLocalPart() throws Exception {
+ String email = "\uD604\uAE08\uC601\uC218\uC99D@android.kr";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesLocalPartWithEmoji() throws Exception {
+ String email = "smiley\u263A@android.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesLocalPartWithSurrogatePairs() throws Exception {
+ String email = "\uD83C\uDF38@android.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesDomainWithDash() throws Exception {
+ String email = "email@an-droid.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesUnicodeDomain() throws Exception {
+ String email = "email@\uD604\uAE08\uC601\uC218\uC99D.kr";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesUnicodeLocalPartAndDomain() throws Exception {
+ String email = "\uD604\uAE08\uC601\uC218\uC99D@\uD604\uAE08\uC601\uC218\uC99D.kr";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesDomainWithEmoji() throws Exception {
+ String email = "smiley@\u263Aandroid.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesDomainWithSurrogatePairs() throws Exception {
+ String email = "email@\uD83C\uDF38android.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesLocalPartAndDomainWithSurrogatePairs()
+ throws Exception {
+ String email = "\uD83C\uDF38@\uD83C\uDF38android.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_doesNotMatchStringWithoutAtSign() throws Exception {
+ String email = "android.com";
+ assertFalse("Should not match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_doesNotMatchPlainString() throws Exception {
+ String email = "email";
+ assertFalse("Should not match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_doesNotMatchStringWithMultipleAtSigns() throws Exception {
+ String email = "email@android@android.com";
+ assertFalse("Should not match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_doesNotMatchEmailWithoutTld() throws Exception {
+ String email = "email@android";
+ assertFalse("Should not match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_doesNotMatchLocalPartEndingWithDot() throws Exception {
+ String email = "email.@android.com";
+ assertFalse("Should not match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_doesNotMatchLocalPartStartingWithDot() throws Exception {
+ String email = ".email@android.com";
+ assertFalse("Should not match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_doesNotMatchDomainStartingWithDash() throws Exception {
+ String email = "email@-android.com";
+ assertFalse("Should not match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_doesNotMatchDomainWithConsecutiveDots() throws Exception {
+ String email = "email@android..com";
+ assertFalse("Should not match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_doesNotMatchEmailWithIpAsDomain() throws Exception {
+ String email = "email@127.0.0.1";
+ assertFalse("Should not match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_doesNotMatchEmailWithInvalidTld() throws Exception {
+ String email = "email@android.c";
+ assertFalse("Should not match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesLocalPartUpTo64Chars() throws Exception {
+ String localPart = "";
+ for (int i = 0; i < 64; i++) {
+ localPart += "a";
+ }
+ String email = localPart + "@android.com";
+
+ assertTrue("Should match local part of length: " + localPart.length(),
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+
+ email = localPart + "a@android.com";
+ assertFalse("Should not match local part of length: " + localPart.length(),
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesSubdomainUpTo63Chars() throws Exception {
+ String subdomain = "";
+ for (int i = 0; i < 63; i++) {
+ subdomain += "a";
+ }
+ String email = "email@" + subdomain + ".com";
+
+ assertTrue("Should match subdomain of length: " + subdomain.length(),
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+
+ subdomain += "a";
+ email = "email@" + subdomain + ".com";
+ assertFalse("Should not match local part of length: " + subdomain.length(),
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesDomainUpTo255Chars() throws Exception {
+ String longDomain = "";
+ while (longDomain.length() <= 250) {
+ longDomain += "d.";
+ }
+ longDomain += "com";
+ assertEquals(255, longDomain.length());
+ String email = "a@" + longDomain;
+
+ assertTrue("Should match domain of length: " + longDomain.length(),
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+
+ email = email + "m";
+ assertEquals(258, email.length());
+ assertFalse("Should not match domain of length: " + longDomain.length(),
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ // Tests for Patterns.PHONE
@SmallTest
public void testPhonePattern() throws Exception {
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
index f962a43..719b274 100644
--- a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
@@ -21,6 +21,7 @@
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.os.Parcel;
import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.SmallTest;
@@ -36,6 +37,10 @@
import java.util.Locale;
import java.util.Objects;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.isIn;
+import static org.hamcrest.Matchers.not;
+
public class InputMethodUtilsTest extends InstrumentationTestCase {
private static final boolean IS_AUX = true;
private static final boolean IS_DEFAULT = true;
@@ -65,6 +70,7 @@
private static final Locale LOCALE_TH_TH_TH = new Locale("ht", "TH", "TH");
private static final String SUBTYPE_MODE_KEYBOARD = "keyboard";
private static final String SUBTYPE_MODE_VOICE = "voice";
+ private static final String SUBTYPE_MODE_HANDWRITING = "handwriting";
private static final String SUBTYPE_MODE_ANY = null;
private static final String EXTRA_VALUE_PAIR_SEPARATOR = ",";
private static final String EXTRA_VALUE_ASCII_CAPABLE = "AsciiCapable";
@@ -186,6 +192,9 @@
final InputMethodSubtype nonAutoEnGB = createDummyInputMethodSubtype("en_GB",
SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoEnIN = createDummyInputMethodSubtype("en_IN",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
final InputMethodSubtype nonAutoFrCA = createDummyInputMethodSubtype("fr_CA",
SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
@@ -207,6 +216,12 @@
final InputMethodSubtype nonAutoJa = createDummyInputMethodSubtype("ja",
SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
!IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoHi = createDummyInputMethodSubtype("hi",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoHandwritingEn = createDummyInputMethodSubtype("en",
+ SUBTYPE_MODE_HANDWRITING, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
final InputMethodSubtype nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype =
createDummyInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
!IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
@@ -233,9 +248,7 @@
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
- createTargetContextWithLocales(new LocaleList(LOCALE_EN_US))
- .getResources(),
- imi);
+ getResourcesForLocales(LOCALE_EN_US), imi);
assertEquals(1, result.size());
verifyEquality(autoSubtype, result.get(0));
}
@@ -257,9 +270,7 @@
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
- createTargetContextWithLocales(new LocaleList(LOCALE_EN_US))
- .getResources(),
- imi);
+ getResourcesForLocales(LOCALE_EN_US), imi);
verifyEquality(nonAutoEnUS, result.get(0));
}
@@ -279,9 +290,7 @@
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
- createTargetContextWithLocales(new LocaleList(LOCALE_EN_GB))
- .getResources(),
- imi);
+ getResourcesForLocales(LOCALE_EN_GB), imi);
assertEquals(1, result.size());
verifyEquality(nonAutoEnGB, result.get(0));
}
@@ -303,9 +312,7 @@
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
- createTargetContextWithLocales(new LocaleList(LOCALE_FR))
- .getResources(),
- imi);
+ getResourcesForLocales(LOCALE_FR), imi);
assertEquals(1, result.size());
verifyEquality(nonAutoFrCA, result.get(0));
}
@@ -323,9 +330,7 @@
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
- createTargetContextWithLocales(new LocaleList(LOCALE_FR_CA))
- .getResources(),
- imi);
+ getResourcesForLocales(LOCALE_FR_CA), imi);
assertEquals(1, result.size());
verifyEquality(nonAutoFrCA, result.get(0));
}
@@ -344,15 +349,64 @@
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
- createTargetContextWithLocales(new LocaleList(LOCALE_JA_JP))
- .getResources(),
- imi);
+ getResourcesForLocales(LOCALE_JA_JP), imi);
assertEquals(3, result.size());
verifyEquality(nonAutoJa, result.get(0));
verifyEquality(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype, result.get(1));
verifyEquality(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2, result.get(2));
}
+ // Make sure that if there is no subtype that matches the language requested, then we just
+ // use the first keyboard subtype.
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
+ subtypes.add(nonAutoHi);
+ subtypes.add(nonAutoEnUS);
+ subtypes.add(nonAutoHandwritingEn);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+ getResourcesForLocales(LOCALE_JA_JP), imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoHi, result.get(0));
+ }
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
+ subtypes.add(nonAutoEnUS);
+ subtypes.add(nonAutoHi);
+ subtypes.add(nonAutoHandwritingEn);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+ getResourcesForLocales(LOCALE_JA_JP), imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoEnUS, result.get(0));
+ }
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
+ subtypes.add(nonAutoHandwritingEn);
+ subtypes.add(nonAutoEnUS);
+ subtypes.add(nonAutoHi);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+ getResourcesForLocales(LOCALE_JA_JP), imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoEnUS, result.get(0));
+ }
+
// Make sure that 3-letter language code can be handled.
{
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
@@ -364,9 +418,7 @@
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
- createTargetContextWithLocales(new LocaleList(LOCALE_FIL_PH))
- .getResources(),
- imi);
+ getResourcesForLocales(LOCALE_FIL_PH), imi);
assertEquals(1, result.size());
verifyEquality(nonAutoFil, result.get(0));
}
@@ -384,9 +436,7 @@
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
- createTargetContextWithLocales(new LocaleList(LOCALE_FI))
- .getResources(),
- imi);
+ getResourcesForLocales(LOCALE_FI), imi);
assertEquals(1, result.size());
verifyEquality(nonAutoJa, result.get(0));
}
@@ -402,9 +452,7 @@
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
- createTargetContextWithLocales(new LocaleList(LOCALE_IN))
- .getResources(),
- imi);
+ getResourcesForLocales(LOCALE_IN), imi);
assertEquals(1, result.size());
verifyEquality(nonAutoIn, result.get(0));
}
@@ -418,9 +466,7 @@
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
- createTargetContextWithLocales(new LocaleList(LOCALE_ID))
- .getResources(),
- imi);
+ getResourcesForLocales(LOCALE_ID), imi);
assertEquals(1, result.size());
verifyEquality(nonAutoIn, result.get(0));
}
@@ -434,9 +480,7 @@
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
- createTargetContextWithLocales(new LocaleList(LOCALE_IN))
- .getResources(),
- imi);
+ getResourcesForLocales(LOCALE_IN), imi);
assertEquals(1, result.size());
verifyEquality(nonAutoId, result.get(0));
}
@@ -450,12 +494,36 @@
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
- createTargetContextWithLocales(new LocaleList(LOCALE_ID))
- .getResources(),
- imi);
+ getResourcesForLocales(LOCALE_ID), imi);
assertEquals(1, result.size());
verifyEquality(nonAutoId, result.get(0));
}
+
+ // If there is no automatic subtype (overridesImplicitlyEnabledSubtype:true) and the system
+ // provides multiple locales, we try to enable multiple subtypes.
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
+ subtypes.add(nonAutoEnUS);
+ subtypes.add(nonAutoFrCA);
+ subtypes.add(nonAutoIn);
+ subtypes.add(nonAutoJa);
+ subtypes.add(nonAutoFil);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+ getResourcesForLocales(LOCALE_FR, LOCALE_EN_US, LOCALE_JA_JP), imi);
+ assertThat(nonAutoFrCA, isIn(result));
+ assertThat(nonAutoEnUS, isIn(result));
+ assertThat(nonAutoJa, isIn(result));
+ assertThat(nonAutoIn, not(isIn(result)));
+ assertThat(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype, not(isIn(result)));
+ assertThat(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype, not(isIn(result)));
+ }
}
@SmallTest
@@ -638,6 +706,10 @@
.createConfigurationContext(resourceConfiguration);
}
+ private Resources getResourcesForLocales(Locale... locales) {
+ return createTargetContextWithLocales(new LocaleList(locales)).getResources();
+ }
+
private String[] getPackageNames(final ArrayList<InputMethodInfo> imis) {
final String[] packageNames = new String[imis.size()];
for (int i = 0; i < imis.size(); ++i) {
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/LocaleUtilsTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/LocaleUtilsTest.java
new file mode 100644
index 0000000..b9c2da7
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/inputmethod/LocaleUtilsTest.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.inputmethod;
+
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.LocaleList;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+public class LocaleUtilsTest extends InstrumentationTestCase {
+
+ private static final LocaleUtils.LocaleExtractor<Locale> sIdentityMapper =
+ new LocaleUtils.LocaleExtractor<Locale>() {
+ @Override
+ public Locale get(Locale source) {
+ return source;
+ }
+ };
+
+ @SmallTest
+ public void testFilterByLanguageEmptyLanguageList() throws Exception {
+ final ArrayList<Locale> availableLocales = new ArrayList<>();
+ availableLocales.add(Locale.forLanguageTag("en-US"));
+ availableLocales.add(Locale.forLanguageTag("fr-CA"));
+ availableLocales.add(Locale.forLanguageTag("in"));
+ availableLocales.add(Locale.forLanguageTag("ja"));
+ availableLocales.add(Locale.forLanguageTag("fil"));
+
+ final LocaleList preferredLocales = LocaleList.getEmptyLocaleList();
+
+ final ArrayList<Locale> dest = new ArrayList<>();
+ LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+ assertEquals(0, dest.size());
+ }
+
+ @SmallTest
+ public void testFilterByLanguageEmptySource() throws Exception {
+ final ArrayList<Locale> availableLocales = new ArrayList<>();
+
+ final LocaleList preferredLocales = LocaleList.forLanguageTags("fr,en-US,ja-JP");
+
+ final ArrayList<Locale> dest = new ArrayList<>();
+ LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+ assertEquals(0, dest.size());
+ }
+
+ @SmallTest
+ public void testFilterByLanguageNullAvailableLocales() throws Exception {
+ {
+ final LocaleList preferredLocales =
+ LocaleList.forLanguageTags("en-AU,en-GB,en-US,en,en-IN");
+ final ArrayList<Locale> availableLocales = new ArrayList<>();
+ availableLocales.add(null);
+ final ArrayList<Locale> dest = new ArrayList<>();
+ LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+ assertEquals(0, dest.size());
+ }
+ {
+ final LocaleList preferredLocales =
+ LocaleList.forLanguageTags("en-AU,en-GB,en-US,en,en-IN");
+ final ArrayList<Locale> availableLocales = new ArrayList<>();
+ availableLocales.add(null);
+ availableLocales.add(null);
+ availableLocales.add(null);
+ final ArrayList<Locale> dest = new ArrayList<>();
+ LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+ assertEquals(0, dest.size());
+ }
+ {
+ final LocaleList preferredLocales =
+ LocaleList.forLanguageTags("en-AU,en-GB,en-US,en,en-IN");
+ final ArrayList<Locale> availableLocales = new ArrayList<>();
+ availableLocales.add(null);
+ availableLocales.add(Locale.forLanguageTag("en-US"));
+ availableLocales.add(null);
+ availableLocales.add(null);
+ final ArrayList<Locale> dest = new ArrayList<>();
+ LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+ assertEquals(1, dest.size());
+ assertEquals(availableLocales.get(1), dest.get(0)); // "en-US"
+ }
+ {
+ final LocaleList preferredLocales =
+ LocaleList.forLanguageTags("en-AU,en-GB,en-US,en,en-IN");
+ final ArrayList<Locale> availableLocales = new ArrayList<>();
+ availableLocales.add(null);
+ availableLocales.add(Locale.forLanguageTag("en"));
+ availableLocales.add(null);
+ availableLocales.add(null);
+ final ArrayList<Locale> dest = new ArrayList<>();
+ LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+ assertEquals(1, dest.size());
+ assertEquals(availableLocales.get(1), dest.get(0)); // "en"
+ }
+ {
+ final LocaleList preferredLocales =
+ LocaleList.forLanguageTags("en-AU,en-GB,en-US,en,en-IN");
+ final ArrayList<Locale> availableLocales = new ArrayList<>();
+ availableLocales.add(null);
+ availableLocales.add(Locale.forLanguageTag("ja-JP"));
+ availableLocales.add(null);
+ availableLocales.add(null);
+ final ArrayList<Locale> dest = new ArrayList<>();
+ LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+ assertEquals(0, dest.size());
+ }
+ }
+
+ @SmallTest
+ public void testFilterByLanguage() throws Exception {
+ final ArrayList<Locale> availableLocales = new ArrayList<>();
+ availableLocales.add(Locale.forLanguageTag("en-US"));
+ availableLocales.add(Locale.forLanguageTag("fr-CA"));
+ availableLocales.add(Locale.forLanguageTag("in"));
+ availableLocales.add(Locale.forLanguageTag("ja"));
+ availableLocales.add(Locale.forLanguageTag("fil"));
+
+ final LocaleList preferredLocales = LocaleList.forLanguageTags("fr,en-US,ja-JP");
+
+ final ArrayList<Locale> dest = new ArrayList<>();
+ LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+ assertEquals(3, dest.size());
+ assertEquals(availableLocales.get(1), dest.get(0)); // "fr-CA"
+ assertEquals(availableLocales.get(0), dest.get(1)); // "en-US"
+ assertEquals(availableLocales.get(3), dest.get(2)); // "ja"
+ }
+
+ @SmallTest
+ public void testFilterByLanguageTheSameLanguage() throws Exception {
+ {
+ final LocaleList preferredLocales =
+ LocaleList.forLanguageTags("en-AU,en-GB,en-US,en,en-IN");
+ final ArrayList<Locale> availableLocales = new ArrayList<>();
+ availableLocales.add(Locale.forLanguageTag("fr-CA"));
+ availableLocales.add(Locale.forLanguageTag("en-US"));
+ final ArrayList<Locale> dest = new ArrayList<>();
+ LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+ assertEquals(1, dest.size());
+ assertEquals(availableLocales.get(1), dest.get(0)); // "en-US"
+ }
+ {
+ final LocaleList preferredLocales =
+ LocaleList.forLanguageTags("en-AU,en-GB,en-US,en,en-IN");
+ final ArrayList<Locale> availableLocales = new ArrayList<>();
+ availableLocales.add(Locale.forLanguageTag("fr-CA"));
+ availableLocales.add(Locale.forLanguageTag("en"));
+ final ArrayList<Locale> dest = new ArrayList<>();
+ LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+ assertEquals(1, dest.size());
+ assertEquals(availableLocales.get(1), dest.get(0)); // "en"
+ }
+ {
+ final LocaleList preferredLocales =
+ LocaleList.forLanguageTags("en-AU,en-GB,en-US,en,en-IN");
+ final ArrayList<Locale> availableLocales = new ArrayList<>();
+ availableLocales.add(Locale.forLanguageTag("fr-CA"));
+ availableLocales.add(Locale.forLanguageTag("en-CA"));
+ availableLocales.add(Locale.forLanguageTag("en-IN"));
+ final ArrayList<Locale> dest = new ArrayList<>();
+ LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+ assertEquals(1, dest.size());
+ assertEquals(availableLocales.get(2), dest.get(0)); // "en-IN"
+ }
+ {
+ final LocaleList preferredLocales =
+ LocaleList.forLanguageTags("en-AU,en-GB,en-US,en-IN");
+ final ArrayList<Locale> availableLocales = new ArrayList<>();
+ availableLocales.add(Locale.forLanguageTag("fr-CA"));
+ availableLocales.add(Locale.forLanguageTag("en-CA"));
+ availableLocales.add(Locale.forLanguageTag("en-NZ"));
+ availableLocales.add(Locale.forLanguageTag("en-BZ"));
+ final ArrayList<Locale> dest = new ArrayList<>();
+ LocaleUtils.filterByLanguage(availableLocales, sIdentityMapper, preferredLocales, dest);
+ assertEquals(1, dest.size());
+ assertEquals(availableLocales.get(1), dest.get(0)); // "en-CA"
+ }
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java
new file mode 100644
index 0000000..1c3cd38
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java
@@ -0,0 +1,745 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+
+import android.os.BatteryStats;
+import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import com.android.internal.os.BatteryStatsImpl;
+
+/**
+ * Provides test cases for android.os.BatteryStats.
+ */
+public class BatteryStatsServTest extends TestCase {
+ private static final String TAG = "BatteryStatsServTest";
+
+ public static class TestServ extends BatteryStatsImpl.Uid.Pkg.Serv {
+ TestServ(MockBatteryStatsImpl bsi) {
+ super(bsi);
+ }
+
+ void populate() {
+ mStartTime = 1010;
+ mRunningSince = 2021;
+ mRunning = true;
+ mStarts = 4042;
+ mLaunchedTime = 5053;
+ mLaunchedSince = 6064;
+ mLaunched = true;
+ mLaunches = 8085;
+ mLoadedStartTime = 9096;
+ mLoadedStarts = 10017;
+ mLoadedLaunches = 11118;
+ mLastStartTime = 12219;
+ mLastStarts = 13310;
+ mLastLaunches = 14411;
+ mUnpluggedStartTime = 15512;
+ mUnpluggedStarts = 16613;
+ mUnpluggedLaunches = 17714;
+ }
+
+ long getStartTime() {
+ return mStartTime;
+ }
+
+ long getRunningSince() {
+ return mRunningSince;
+ }
+
+ void setRunning(boolean val) {
+ mRunning = val;
+ }
+
+ boolean getRunning() {
+ return mRunning;
+ }
+
+ int getStarts() {
+ return mStarts;
+ }
+
+ long getLaunchedTime() {
+ return mLaunchedTime;
+ }
+
+ long getLaunchedSince() {
+ return mLaunchedSince;
+ }
+
+ void setLaunched(boolean val) {
+ mLaunched = val;
+ }
+
+ boolean getLaunched() {
+ return mLaunched;
+ }
+
+ int getLaunches() {
+ return mLaunches;
+ }
+
+ long getLoadedStartTime() {
+ return mLoadedStartTime;
+ }
+
+ int getLoadedStarts() {
+ return mLoadedStarts;
+ }
+
+ int getLoadedLaunches() {
+ return mLoadedLaunches;
+ }
+
+ long getLastStartTime() {
+ return mLastStartTime;
+ }
+
+ int getLastStarts() {
+ return mLastStarts;
+ }
+
+ int getLastLaunches() {
+ return mLastLaunches;
+ }
+
+ long getUnpluggedStartTime() {
+ return mUnpluggedStartTime;
+ }
+
+ int getUnpluggedStarts() {
+ return mUnpluggedStarts;
+ }
+
+ int getUnpluggedLaunches() {
+ return mUnpluggedLaunches;
+ }
+ }
+
+ /**
+ * Test that the constructor and detach methods touch the time bast observer list.
+ */
+ @SmallTest
+ public void testConstructAndDetach() throws Exception {
+ MockBatteryStatsImpl bsi = new MockBatteryStatsImpl();
+
+ TestServ serv = new TestServ(bsi);
+ Assert.assertTrue(bsi.getOnBatteryTimeBase().hasObserver(serv));
+
+ serv.detach();
+ Assert.assertFalse(bsi.getOnBatteryTimeBase().hasObserver(serv));
+ }
+
+ /**
+ * Test OnTimeStarted
+ */
+ @SmallTest
+ public void testOnTimeStarted() throws Exception {
+ MockBatteryStatsImpl bsi = new MockBatteryStatsImpl();
+ TestServ serv = new TestServ(bsi);
+
+ serv.populate();
+ serv.setRunning(true);
+ serv.onTimeStarted(111111, 20000, 222222);
+ Assert.assertEquals(18989, serv.getUnpluggedStartTime());
+ Assert.assertEquals(4042, serv.getUnpluggedStarts());
+ Assert.assertEquals(8085, serv.getUnpluggedLaunches());
+
+ serv.populate();
+ serv.setRunning(false);
+ serv.onTimeStarted(111111, 20000, 222222);
+ Assert.assertEquals(1010, serv.getUnpluggedStartTime());
+ Assert.assertEquals(4042, serv.getUnpluggedStarts());
+ Assert.assertEquals(8085, serv.getUnpluggedLaunches());
+ }
+
+ /**
+ * Test parceling and unparceling.
+ */
+ @SmallTest
+ public void testParceling() throws Exception {
+ MockBatteryStatsImpl bsi = new MockBatteryStatsImpl();
+ TestServ orig = new TestServ(bsi);
+ orig.populate();
+
+ Parcel parcel = Parcel.obtain();
+ orig.writeToParcelLocked(parcel);
+
+ parcel.setDataPosition(0);
+
+ TestServ serv = new TestServ(bsi);
+ serv.readFromParcelLocked(parcel);
+
+ Assert.assertEquals(1010, serv.getStartTime());
+ Assert.assertEquals(2021, serv.getRunningSince());
+ Assert.assertTrue(serv.getRunning());
+ Assert.assertEquals(4042, serv.getStarts());
+ Assert.assertEquals(5053, serv.getLaunchedTime());
+ Assert.assertEquals(6064, serv.getLaunchedSince());
+ Assert.assertTrue(serv.getLaunched());
+ Assert.assertEquals(8085, serv.getLaunches());
+ Assert.assertEquals(9096, serv.getLoadedStartTime());
+ Assert.assertEquals(10017, serv.getLoadedStarts());
+ Assert.assertEquals(11118, serv.getLoadedLaunches());
+ Assert.assertEquals(0, serv.getLastStartTime());
+ Assert.assertEquals(0, serv.getLastStarts());
+ Assert.assertEquals(0, serv.getLastLaunches());
+ Assert.assertEquals(15512, serv.getUnpluggedStartTime());
+ Assert.assertEquals(16613, serv.getUnpluggedStarts());
+ Assert.assertEquals(17714, serv.getUnpluggedLaunches());
+ }
+
+ /**
+ * Test getLaunchTimeToNow()
+ */
+ @SmallTest
+ public void testLaunchTimeToNow() throws Exception {
+ MockBatteryStatsImpl bsi = new MockBatteryStatsImpl();
+ TestServ serv = new TestServ(bsi);
+
+ serv.populate();
+ serv.setLaunched(true);
+ Assert.assertEquals(8989, serv.getLaunchTimeToNowLocked(10000));
+
+ serv.populate();
+ serv.setLaunched(false);
+ Assert.assertEquals(5053, serv.getLaunchTimeToNowLocked(10000));
+
+ }
+
+ /**
+ * Test getStartTimeToNow()
+ */
+ @SmallTest
+ public void testStartTimeToNow() throws Exception {
+ MockBatteryStatsImpl bsi = new MockBatteryStatsImpl();
+ TestServ serv = new TestServ(bsi);
+
+ serv.populate();
+ serv.setRunning(true);
+ Assert.assertEquals(18989, serv.getStartTimeToNowLocked(20000));
+
+ serv.populate();
+ serv.setRunning(false);
+ Assert.assertEquals(1010, serv.getStartTimeToNowLocked(20000));
+ }
+
+ /**
+ * Test startLaunchedLocked while not previously launched
+ */
+ @SmallTest
+ public void testStartLaunchedLockedWhileLaunched() throws Exception {
+ MockBatteryStatsImpl bsi = new MockBatteryStatsImpl() {
+ @Override
+ public long getBatteryUptimeLocked() {
+ return 777777L;
+ }
+ };
+
+ TestServ serv = new TestServ(bsi);
+
+ serv.populate();
+ serv.setLaunched(true);
+ serv.startLaunchedLocked();
+
+ // No changes
+ Assert.assertEquals(1010, serv.getStartTime());
+ Assert.assertEquals(2021, serv.getRunningSince());
+ Assert.assertTrue(serv.getRunning());
+ Assert.assertEquals(4042, serv.getStarts());
+ Assert.assertEquals(5053, serv.getLaunchedTime());
+ Assert.assertEquals(6064, serv.getLaunchedSince());
+ Assert.assertTrue(serv.getLaunched());
+ Assert.assertEquals(8085, serv.getLaunches());
+ Assert.assertEquals(9096, serv.getLoadedStartTime());
+ Assert.assertEquals(10017, serv.getLoadedStarts());
+ Assert.assertEquals(11118, serv.getLoadedLaunches());
+ Assert.assertEquals(12219, serv.getLastStartTime());
+ Assert.assertEquals(13310, serv.getLastStarts());
+ Assert.assertEquals(14411, serv.getLastLaunches());
+ Assert.assertEquals(15512, serv.getUnpluggedStartTime());
+ Assert.assertEquals(16613, serv.getUnpluggedStarts());
+ Assert.assertEquals(17714, serv.getUnpluggedLaunches());
+ }
+
+ /**
+ * Test startLaunchedLocked while previously launched
+ */
+ @SmallTest
+ public void testStartLaunchedLockedWhileNotLaunched() throws Exception {
+ MockBatteryStatsImpl bsi = new MockBatteryStatsImpl() {
+ @Override
+ public long getBatteryUptimeLocked() {
+ return 777777L;
+ }
+ };
+
+ TestServ serv = new TestServ(bsi);
+
+ serv.populate();
+ serv.setLaunched(false);
+ serv.startLaunchedLocked();
+ Assert.assertEquals(1010, serv.getStartTime());
+ Assert.assertEquals(2021, serv.getRunningSince());
+ Assert.assertTrue(serv.getRunning());
+ Assert.assertEquals(4042, serv.getStarts());
+ Assert.assertEquals(5053, serv.getLaunchedTime());
+ Assert.assertEquals(777777L, serv.getLaunchedSince()); // <-- changed
+ Assert.assertTrue(serv.getLaunched()); // <-- changed
+ Assert.assertEquals(8086, serv.getLaunches()); // <-- changed
+ Assert.assertEquals(9096, serv.getLoadedStartTime());
+ Assert.assertEquals(10017, serv.getLoadedStarts());
+ Assert.assertEquals(11118, serv.getLoadedLaunches());
+ Assert.assertEquals(12219, serv.getLastStartTime());
+ Assert.assertEquals(13310, serv.getLastStarts());
+ Assert.assertEquals(14411, serv.getLastLaunches());
+ Assert.assertEquals(15512, serv.getUnpluggedStartTime());
+ Assert.assertEquals(16613, serv.getUnpluggedStarts());
+ Assert.assertEquals(17714, serv.getUnpluggedLaunches());
+ }
+
+ /**
+ * Test stopLaunchedLocked when not previously launched.
+ */
+ @SmallTest
+ public void testStopLaunchedLockedWhileNotLaunched() throws Exception {
+ MockBatteryStatsImpl bsi = new MockBatteryStatsImpl() {
+ @Override
+ public long getBatteryUptimeLocked() {
+ return 777777L;
+ }
+ };
+ TestServ serv = new TestServ(bsi);
+
+ serv.populate();
+ serv.setLaunched(false);
+
+ serv.stopLaunchedLocked();
+
+ // No changes
+ Assert.assertEquals(1010, serv.getStartTime());
+ Assert.assertEquals(2021, serv.getRunningSince());
+ Assert.assertTrue(serv.getRunning());
+ Assert.assertEquals(4042, serv.getStarts());
+ Assert.assertEquals(5053, serv.getLaunchedTime());
+ Assert.assertEquals(6064, serv.getLaunchedSince());
+ Assert.assertFalse(serv.getLaunched());
+ Assert.assertEquals(8085, serv.getLaunches());
+ Assert.assertEquals(9096, serv.getLoadedStartTime());
+ Assert.assertEquals(10017, serv.getLoadedStarts());
+ Assert.assertEquals(11118, serv.getLoadedLaunches());
+ Assert.assertEquals(12219, serv.getLastStartTime());
+ Assert.assertEquals(13310, serv.getLastStarts());
+ Assert.assertEquals(14411, serv.getLastLaunches());
+ Assert.assertEquals(15512, serv.getUnpluggedStartTime());
+ Assert.assertEquals(16613, serv.getUnpluggedStarts());
+ Assert.assertEquals(17714, serv.getUnpluggedLaunches());
+ }
+
+ /**
+ * Test stopLaunchedLocked when previously launched, with measurable time between
+ * start and stop.
+ */
+ @SmallTest
+ public void testStopLaunchedLockedWhileLaunchedNormal() throws Exception {
+ MockBatteryStatsImpl bsi = new MockBatteryStatsImpl() {
+ @Override
+ public long getBatteryUptimeLocked() {
+ return 777777L;
+ }
+ };
+ TestServ serv = new TestServ(bsi);
+
+ serv.populate();
+ serv.setLaunched(true);
+
+ serv.stopLaunchedLocked();
+
+ Assert.assertEquals(1010, serv.getStartTime());
+ Assert.assertEquals(2021, serv.getRunningSince());
+ Assert.assertTrue(serv.getRunning());
+ Assert.assertEquals(4042, serv.getStarts());
+ Assert.assertEquals(777777L-6064+5053, serv.getLaunchedTime()); // <-- changed
+ Assert.assertEquals(6064, serv.getLaunchedSince());
+ Assert.assertFalse(serv.getLaunched());
+ Assert.assertEquals(8085, serv.getLaunches());
+ Assert.assertEquals(9096, serv.getLoadedStartTime());
+ Assert.assertEquals(10017, serv.getLoadedStarts());
+ Assert.assertEquals(11118, serv.getLoadedLaunches());
+ Assert.assertEquals(12219, serv.getLastStartTime());
+ Assert.assertEquals(13310, serv.getLastStarts());
+ Assert.assertEquals(14411, serv.getLastLaunches());
+ Assert.assertEquals(15512, serv.getUnpluggedStartTime());
+ Assert.assertEquals(16613, serv.getUnpluggedStarts());
+ Assert.assertEquals(17714, serv.getUnpluggedLaunches());
+ }
+
+ /**
+ * Test stopLaunchedLocked when previously launched, with no measurable time between
+ * start and stop.
+ */
+ @SmallTest
+ public void testStopLaunchedLockedWhileLaunchedTooQuick() throws Exception {
+ MockBatteryStatsImpl bsi = new MockBatteryStatsImpl() {
+ @Override
+ public long getBatteryUptimeLocked() {
+ return 6064L;
+ }
+ };
+ TestServ serv = new TestServ(bsi);
+
+ serv.populate();
+ serv.setLaunched(true);
+
+ serv.stopLaunchedLocked();
+
+ Assert.assertEquals(1010, serv.getStartTime());
+ Assert.assertEquals(2021, serv.getRunningSince());
+ Assert.assertTrue(serv.getRunning());
+ Assert.assertEquals(4042, serv.getStarts());
+ Assert.assertEquals(5053, serv.getLaunchedTime());
+ Assert.assertEquals(6064, serv.getLaunchedSince());
+ Assert.assertFalse(serv.getLaunched());
+ Assert.assertEquals(8085-1, serv.getLaunches()); // <-- changed
+ Assert.assertEquals(9096, serv.getLoadedStartTime());
+ Assert.assertEquals(10017, serv.getLoadedStarts());
+ Assert.assertEquals(11118, serv.getLoadedLaunches());
+ Assert.assertEquals(12219, serv.getLastStartTime());
+ Assert.assertEquals(13310, serv.getLastStarts());
+ Assert.assertEquals(14411, serv.getLastLaunches());
+ Assert.assertEquals(15512, serv.getUnpluggedStartTime());
+ Assert.assertEquals(16613, serv.getUnpluggedStarts());
+ Assert.assertEquals(17714, serv.getUnpluggedLaunches());
+ }
+
+ /**
+ * Test startRunningLocked while previously running
+ */
+ @SmallTest
+ public void testStartRunningLockedWhileRunning() throws Exception {
+ MockBatteryStatsImpl bsi = new MockBatteryStatsImpl() {
+ @Override
+ public long getBatteryUptimeLocked() {
+ return 777777L;
+ }
+ };
+ TestServ serv = new TestServ(bsi);
+
+ serv.populate();
+ serv.setRunning(true);
+
+ serv.startRunningLocked();
+
+ // no change
+ Assert.assertEquals(1010, serv.getStartTime());
+ Assert.assertEquals(2021, serv.getRunningSince());
+ Assert.assertTrue(serv.getRunning());
+ Assert.assertEquals(4042, serv.getStarts());
+ Assert.assertEquals(5053, serv.getLaunchedTime());
+ Assert.assertEquals(6064, serv.getLaunchedSince());
+ Assert.assertTrue(serv.getLaunched());
+ Assert.assertEquals(8085, serv.getLaunches());
+ Assert.assertEquals(9096, serv.getLoadedStartTime());
+ Assert.assertEquals(10017, serv.getLoadedStarts());
+ Assert.assertEquals(11118, serv.getLoadedLaunches());
+ Assert.assertEquals(12219, serv.getLastStartTime());
+ Assert.assertEquals(13310, serv.getLastStarts());
+ Assert.assertEquals(14411, serv.getLastLaunches());
+ Assert.assertEquals(15512, serv.getUnpluggedStartTime());
+ Assert.assertEquals(16613, serv.getUnpluggedStarts());
+ Assert.assertEquals(17714, serv.getUnpluggedLaunches());
+ }
+
+ /**
+ * Test startRunningLocked while not previously launched
+ */
+ @SmallTest
+ public void testStartRunningLockedWhileNotRunning() throws Exception {
+ MockBatteryStatsImpl bsi = new MockBatteryStatsImpl() {
+ @Override
+ public long getBatteryUptimeLocked() {
+ return 777777L;
+ }
+ };
+ TestServ serv = new TestServ(bsi);
+
+ serv.populate();
+ serv.setRunning(false);
+
+ serv.startRunningLocked();
+
+ Assert.assertEquals(1010, serv.getStartTime());
+ Assert.assertEquals(777777L, serv.getRunningSince());
+ Assert.assertTrue(serv.getRunning());
+ Assert.assertEquals(4042+1, serv.getStarts());
+ Assert.assertEquals(5053, serv.getLaunchedTime());
+ Assert.assertEquals(6064, serv.getLaunchedSince());
+ Assert.assertTrue(serv.getLaunched());
+ Assert.assertEquals(8085, serv.getLaunches());
+ Assert.assertEquals(9096, serv.getLoadedStartTime());
+ Assert.assertEquals(10017, serv.getLoadedStarts());
+ Assert.assertEquals(11118, serv.getLoadedLaunches());
+ Assert.assertEquals(12219, serv.getLastStartTime());
+ Assert.assertEquals(13310, serv.getLastStarts());
+ Assert.assertEquals(14411, serv.getLastLaunches());
+ Assert.assertEquals(15512, serv.getUnpluggedStartTime());
+ Assert.assertEquals(16613, serv.getUnpluggedStarts());
+ Assert.assertEquals(17714, serv.getUnpluggedLaunches());
+ }
+
+ /**
+ * Test stopRunningLocked when previously launched, with measurable time between
+ * start and stop.
+ */
+ @SmallTest
+ public void testStopRunningLockedWhileRunningNormal() throws Exception {
+ MockBatteryStatsImpl bsi = new MockBatteryStatsImpl() {
+ @Override
+ public long getBatteryUptimeLocked() {
+ return 777777L;
+ }
+ };
+ TestServ serv = new TestServ(bsi);
+
+ serv.populate();
+ serv.setRunning(true);
+
+ serv.stopRunningLocked();
+
+ Assert.assertEquals(777777L-2021+1010, serv.getStartTime()); // <-- changed
+ Assert.assertEquals(2021, serv.getRunningSince());
+ Assert.assertFalse(serv.getRunning()); // <-- changed
+ Assert.assertEquals(4042, serv.getStarts());
+ Assert.assertEquals(5053, serv.getLaunchedTime());
+ Assert.assertEquals(6064, serv.getLaunchedSince());
+ Assert.assertTrue(serv.getLaunched());
+ Assert.assertEquals(8085, serv.getLaunches());
+ Assert.assertEquals(9096, serv.getLoadedStartTime());
+ Assert.assertEquals(10017, serv.getLoadedStarts());
+ Assert.assertEquals(11118, serv.getLoadedLaunches());
+ Assert.assertEquals(12219, serv.getLastStartTime());
+ Assert.assertEquals(13310, serv.getLastStarts());
+ Assert.assertEquals(14411, serv.getLastLaunches());
+ Assert.assertEquals(15512, serv.getUnpluggedStartTime());
+ Assert.assertEquals(16613, serv.getUnpluggedStarts());
+ Assert.assertEquals(17714, serv.getUnpluggedLaunches());
+ }
+
+ /**
+ * Test stopRunningLocked when previously launched, with measurable time between
+ * start and stop.
+ */
+ @SmallTest
+ public void testStopRunningLockedWhileRunningTooQuick() throws Exception {
+ MockBatteryStatsImpl bsi = new MockBatteryStatsImpl() {
+ @Override
+ public long getBatteryUptimeLocked() {
+ return 2021;
+ }
+ };
+ TestServ serv = new TestServ(bsi);
+
+ serv.populate();
+ serv.setRunning(true);
+
+ serv.stopRunningLocked();
+
+ Assert.assertEquals(1010, serv.getStartTime());
+ Assert.assertEquals(2021, serv.getRunningSince());
+ Assert.assertFalse(serv.getRunning()); // <-- changed
+ Assert.assertEquals(4042-1, serv.getStarts()); // <-- changed
+ Assert.assertEquals(5053, serv.getLaunchedTime());
+ Assert.assertEquals(6064, serv.getLaunchedSince());
+ Assert.assertTrue(serv.getLaunched());
+ Assert.assertEquals(8085, serv.getLaunches());
+ Assert.assertEquals(9096, serv.getLoadedStartTime());
+ Assert.assertEquals(10017, serv.getLoadedStarts());
+ Assert.assertEquals(11118, serv.getLoadedLaunches());
+ Assert.assertEquals(12219, serv.getLastStartTime());
+ Assert.assertEquals(13310, serv.getLastStarts());
+ Assert.assertEquals(14411, serv.getLastLaunches());
+ Assert.assertEquals(15512, serv.getUnpluggedStartTime());
+ Assert.assertEquals(16613, serv.getUnpluggedStarts());
+ Assert.assertEquals(17714, serv.getUnpluggedLaunches());
+ }
+
+ /**
+ * Test that getBatteryStats returns the BatteryStatsImpl passed in to the contstructor.
+ */
+ @SmallTest
+ public void testGetBatteryStats() throws Exception {
+ MockBatteryStatsImpl bsi = new MockBatteryStatsImpl();
+ TestServ serv = new TestServ(bsi);
+
+ Assert.assertEquals(bsi, serv.getBatteryStats());
+ }
+
+ /**
+ * Test getLaunches
+ */
+ @SmallTest
+ public void testGetLaunches() throws Exception {
+ MockBatteryStatsImpl bsi = new MockBatteryStatsImpl();
+ TestServ serv = new TestServ(bsi);
+ serv.populate();
+
+ Assert.assertEquals(8085, serv.getLaunches(BatteryStats.STATS_SINCE_CHARGED));
+ Assert.assertEquals(8085-11118, serv.getLaunches(BatteryStats.STATS_CURRENT));
+ Assert.assertEquals(8085-17714, serv.getLaunches(BatteryStats.STATS_SINCE_UNPLUGGED));
+
+ // No change to fields
+ Assert.assertEquals(1010, serv.getStartTime());
+ Assert.assertEquals(2021, serv.getRunningSince());
+ Assert.assertTrue(serv.getRunning());
+ Assert.assertEquals(4042, serv.getStarts());
+ Assert.assertEquals(5053, serv.getLaunchedTime());
+ Assert.assertEquals(6064, serv.getLaunchedSince());
+ Assert.assertTrue(serv.getLaunched());
+ Assert.assertEquals(8085, serv.getLaunches());
+ Assert.assertEquals(9096, serv.getLoadedStartTime());
+ Assert.assertEquals(10017, serv.getLoadedStarts());
+ Assert.assertEquals(11118, serv.getLoadedLaunches());
+ Assert.assertEquals(12219, serv.getLastStartTime());
+ Assert.assertEquals(13310, serv.getLastStarts());
+ Assert.assertEquals(14411, serv.getLastLaunches());
+ Assert.assertEquals(15512, serv.getUnpluggedStartTime());
+ Assert.assertEquals(16613, serv.getUnpluggedStarts());
+ Assert.assertEquals(17714, serv.getUnpluggedLaunches());
+ }
+
+ /**
+ * Test getStartTime while running
+ */
+ @SmallTest
+ public void testGetStartTimeRunning() throws Exception {
+ MockBatteryStatsImpl bsi = new MockBatteryStatsImpl();
+ TestServ serv = new TestServ(bsi);
+ serv.populate();
+ serv.setRunning(true);
+
+ final long startTimeToNow = 1010 + 20000 - 2021;
+
+ Assert.assertEquals(startTimeToNow,
+ serv.getStartTime(20000, BatteryStats.STATS_SINCE_CHARGED));
+ Assert.assertEquals(startTimeToNow-9096,
+ serv.getStartTime(20000, BatteryStats.STATS_CURRENT));
+ Assert.assertEquals(startTimeToNow-15512,
+ serv.getStartTime(20000, BatteryStats.STATS_SINCE_UNPLUGGED));
+
+ // No change to fields
+ Assert.assertEquals(1010, serv.getStartTime());
+ Assert.assertEquals(2021, serv.getRunningSince());
+ Assert.assertTrue(serv.getRunning());
+ Assert.assertEquals(4042, serv.getStarts());
+ Assert.assertEquals(5053, serv.getLaunchedTime());
+ Assert.assertEquals(6064, serv.getLaunchedSince());
+ Assert.assertTrue(serv.getLaunched());
+ Assert.assertEquals(8085, serv.getLaunches());
+ Assert.assertEquals(9096, serv.getLoadedStartTime());
+ Assert.assertEquals(10017, serv.getLoadedStarts());
+ Assert.assertEquals(11118, serv.getLoadedLaunches());
+ Assert.assertEquals(12219, serv.getLastStartTime());
+ Assert.assertEquals(13310, serv.getLastStarts());
+ Assert.assertEquals(14411, serv.getLastLaunches());
+ Assert.assertEquals(15512, serv.getUnpluggedStartTime());
+ Assert.assertEquals(16613, serv.getUnpluggedStarts());
+ Assert.assertEquals(17714, serv.getUnpluggedLaunches());
+ }
+
+ /**
+ * Test getStartTime while not running
+ */
+ @SmallTest
+ public void testGetStartTimeNotRunning() throws Exception {
+ MockBatteryStatsImpl bsi = new MockBatteryStatsImpl();
+ TestServ serv = new TestServ(bsi);
+ serv.populate();
+ serv.setRunning(false);
+
+ final long startTimeToNow = 1010;
+
+ Assert.assertEquals(startTimeToNow,
+ serv.getStartTime(20000, BatteryStats.STATS_SINCE_CHARGED));
+ Assert.assertEquals(startTimeToNow-9096,
+ serv.getStartTime(20000, BatteryStats.STATS_CURRENT));
+ Assert.assertEquals(startTimeToNow-15512,
+ serv.getStartTime(20000, BatteryStats.STATS_SINCE_UNPLUGGED));
+
+ // No change to fields
+ Assert.assertEquals(1010, serv.getStartTime());
+ Assert.assertEquals(2021, serv.getRunningSince());
+ Assert.assertFalse(serv.getRunning());
+ Assert.assertEquals(4042, serv.getStarts());
+ Assert.assertEquals(5053, serv.getLaunchedTime());
+ Assert.assertEquals(6064, serv.getLaunchedSince());
+ Assert.assertTrue(serv.getLaunched());
+ Assert.assertEquals(8085, serv.getLaunches());
+ Assert.assertEquals(9096, serv.getLoadedStartTime());
+ Assert.assertEquals(10017, serv.getLoadedStarts());
+ Assert.assertEquals(11118, serv.getLoadedLaunches());
+ Assert.assertEquals(12219, serv.getLastStartTime());
+ Assert.assertEquals(13310, serv.getLastStarts());
+ Assert.assertEquals(14411, serv.getLastLaunches());
+ Assert.assertEquals(15512, serv.getUnpluggedStartTime());
+ Assert.assertEquals(16613, serv.getUnpluggedStarts());
+ Assert.assertEquals(17714, serv.getUnpluggedLaunches());
+ }
+
+
+ /**
+ * Test getStarts
+ */
+ @SmallTest
+ public void testGetStarts() throws Exception {
+ MockBatteryStatsImpl bsi = new MockBatteryStatsImpl();
+ TestServ serv = new TestServ(bsi);
+ serv.populate();
+
+ Assert.assertEquals(4042, serv.getStarts(BatteryStats.STATS_SINCE_CHARGED));
+ Assert.assertEquals(4042-10017, serv.getStarts(BatteryStats.STATS_CURRENT));
+ Assert.assertEquals(4042-16613, serv.getStarts(BatteryStats.STATS_SINCE_UNPLUGGED));
+
+ // No change to fields
+ Assert.assertEquals(1010, serv.getStartTime());
+ Assert.assertEquals(2021, serv.getRunningSince());
+ Assert.assertTrue(serv.getRunning());
+ Assert.assertEquals(4042, serv.getStarts());
+ Assert.assertEquals(5053, serv.getLaunchedTime());
+ Assert.assertEquals(6064, serv.getLaunchedSince());
+ Assert.assertTrue(serv.getLaunched());
+ Assert.assertEquals(8085, serv.getLaunches());
+ Assert.assertEquals(9096, serv.getLoadedStartTime());
+ Assert.assertEquals(10017, serv.getLoadedStarts());
+ Assert.assertEquals(11118, serv.getLoadedLaunches());
+ Assert.assertEquals(12219, serv.getLastStartTime());
+ Assert.assertEquals(13310, serv.getLastStarts());
+ Assert.assertEquals(14411, serv.getLastLaunches());
+ Assert.assertEquals(15512, serv.getUnpluggedStartTime());
+ Assert.assertEquals(16613, serv.getUnpluggedStarts());
+ Assert.assertEquals(17714, serv.getUnpluggedLaunches());
+ }
+
+}
+
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
new file mode 100644
index 0000000..05aa53c
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
@@ -0,0 +1,15 @@
+package com.android.internal.os;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ BatteryStatsServTest.class,
+ BatteryStatsTimeBaseTest.class,
+ BatteryStatsTimerTest.class,
+ BatteryStatsUidTest.class,
+ })
+public class BatteryStatsTests {
+}
+
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java
new file mode 100644
index 0000000..ab92f15
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+
+import android.os.BatteryStats;
+import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.mockito.Mockito;
+
+/**
+ * Provides test cases for android.os.BatteryStats.
+ */
+public class BatteryStatsTimeBaseTest extends TestCase {
+ private static final String TAG = "BatteryStatsTimeBaseTest";
+
+ static class TestTimeBase extends BatteryStatsImpl.TimeBase {
+
+ public void populate(long uptime, long realtime, boolean running, long pastUptime,
+ long uptimeStart, long pastRealtime, long realtimeStart,
+ long unpluggedUptime, long unpluggedRealtime) {
+ mUptime = uptime;
+ mRealtime = realtime;
+ mRunning = running;
+ mPastUptime = pastUptime;
+ mUptimeStart = uptimeStart;
+ mPastRealtime = pastRealtime;
+ mRealtimeStart = realtimeStart;
+ mUnpluggedUptime = unpluggedUptime;
+ mUnpluggedRealtime = unpluggedRealtime;
+ }
+
+ public void verify(long uptime, long realtime, boolean running, long pastUptime,
+ long uptimeStart, long pastRealtime, long realtimeStart,
+ long unpluggedUptime, long unpluggedRealtime) {
+ Assert.assertEquals(uptime, mUptime);
+ Assert.assertEquals(realtime, mRealtime);
+ Assert.assertEquals(running, mRunning);
+ Assert.assertEquals(pastUptime, mPastUptime);
+ Assert.assertEquals(uptimeStart, mUptimeStart);
+ Assert.assertEquals(pastRealtime, mPastRealtime);
+ Assert.assertEquals(realtimeStart, mRealtimeStart);
+ Assert.assertEquals(unpluggedUptime, mUnpluggedUptime);
+ Assert.assertEquals(unpluggedRealtime, mUnpluggedRealtime);
+ }
+ }
+
+ /**
+ * Test the observers and the setRunning call.
+ */
+ @SmallTest
+ public void testRunning() throws Exception {
+ TestTimeBase tb = new TestTimeBase();
+
+ // Toggle running once, to accumulate past uptime and past realtime
+ // so the test values aren't 0.
+ tb.setRunning(true, 100, 10000);
+ tb.setRunning(false, 200, 11000);
+ Assert.assertEquals(100, tb.getUptimeStart());
+ Assert.assertEquals(10000, tb.getRealtimeStart());
+
+ // Create some observers
+ BatteryStatsImpl.TimeBaseObs observer1 = Mockito.mock(BatteryStatsImpl.TimeBaseObs.class);
+ BatteryStatsImpl.TimeBaseObs observer2 = Mockito.mock(BatteryStatsImpl.TimeBaseObs.class);
+ BatteryStatsImpl.TimeBaseObs observer3 = Mockito.mock(BatteryStatsImpl.TimeBaseObs.class);
+
+ // Add them
+ tb.add(observer1);
+ tb.add(observer2);
+ tb.add(observer3);
+ Assert.assertTrue(tb.hasObserver(observer1));
+ Assert.assertTrue(tb.hasObserver(observer2));
+ Assert.assertTrue(tb.hasObserver(observer3));
+
+ // Remove one
+ tb.remove(observer3);
+ Assert.assertTrue(tb.hasObserver(observer1));
+ Assert.assertTrue(tb.hasObserver(observer2));
+ Assert.assertFalse(tb.hasObserver(observer3));
+
+ // Start running, make sure we get a started call on the two active observers
+ // and not the third.
+ tb.setRunning(true, 250, 14000);
+
+ Assert.assertTrue(tb.isRunning());
+
+ if (false) {
+ Log.d(TAG, "mUptimeStart=" + tb.getUptimeStart()
+ + " mRealtimeStart=" + tb.getRealtimeStart()
+ + " mUptime=" + tb.getUptime(250)
+ + " mRealtime=" + tb.getRealtime(14000)
+ + " isRunning=" + tb.isRunning());
+ }
+
+ Assert.assertEquals(250, tb.getUptimeStart());
+ Assert.assertEquals(14000, tb.getRealtimeStart());
+ Assert.assertEquals(100, tb.getUptime(250));
+ Assert.assertEquals(1000, tb.getRealtime(14000));
+
+ Mockito.verify(observer1).onTimeStarted(14000, 100, 1000);
+ Mockito.verify(observer1, Mockito.never()).onTimeStopped(-1, -1, -1);
+ Mockito.verifyNoMoreInteractions(observer1);
+ Mockito.verify(observer2).onTimeStarted(14000, 100, 1000);
+ Mockito.verify(observer2, Mockito.never()).onTimeStopped(-1, -1, -1);
+ Mockito.verifyNoMoreInteractions(observer2);
+
+ Mockito.reset(observer1);
+ Mockito.reset(observer2);
+ Mockito.reset(observer3);
+
+ // Advance the "timer" and make sure the getters account for the current time passed in
+ Assert.assertEquals(400, tb.getUptime(550));
+ Assert.assertEquals(1555, tb.getRealtime(14555));
+
+ // Stop running, make sure we get a stopped call on the two active observers
+ // and not the third.
+ tb.setRunning(false, 402, 14002);
+
+ Assert.assertFalse(tb.isRunning());
+
+ if (false) {
+ Log.d(TAG, "mUptimeStart=" + tb.getUptimeStart()
+ + " mRealtimeStart=" + tb.getRealtimeStart()
+ + " mUptime=" + tb.getUptime(250)
+ + " mRealtime=" + tb.getRealtime(14000)
+ + " isRunning=" + tb.isRunning());
+ }
+
+ Assert.assertEquals(252, tb.getUptime(402));
+ Assert.assertEquals(1002, tb.getRealtime(14002));
+
+ Mockito.verify(observer1).onTimeStopped(14002, 252, 1002);
+ Mockito.verify(observer1, Mockito.never()).onTimeStopped(-1, -1, -1);
+ Mockito.verifyNoMoreInteractions(observer1);
+ Mockito.verify(observer2).onTimeStopped(14002, 252, 1002);
+ Mockito.verify(observer2, Mockito.never()).onTimeStopped(-1, -1, -1);
+ Mockito.verifyNoMoreInteractions(observer2);
+
+ // Advance the "timer" and make sure the getters account for the current time passed in
+ // is the same as the time when running went to false.
+ Assert.assertEquals(252, tb.getUptime(600));
+ Assert.assertEquals(1002, tb.getRealtime(17000));
+ }
+
+ /**
+ * Test that reset while running updates the plugged and unplugged times
+ */
+ @SmallTest
+ public void testResetWhileRunning() throws Exception {
+ TestTimeBase tb = new TestTimeBase();
+ tb.populate(100, 200, true, 300, 400, 500, 600, 700, 800);
+
+ tb.reset(666, 6666);
+
+ // Not sure if this is a bug: reset while running does not
+ // reset mPastUptime, but while it is running it does.
+ tb.verify(100, 200, true, 300, 666, 500, 6666, 300, 500);
+ }
+
+ /**
+ * Test that reset while running updates the plugged and unplugged times
+ */
+ @SmallTest
+ public void testResetWhileNotRunning() throws Exception {
+ TestTimeBase tb = new TestTimeBase();
+ tb.populate(100, 200, false, 300, 400, 500, 600, 700, 800);
+
+ tb.reset(666, 6666);
+
+ tb.verify(100, 200, false, 0, 400, 0, 600, 700, 800);
+ }
+
+ /**
+ * Test init
+ */
+ @SmallTest
+ public void testInit() throws Exception {
+ TestTimeBase tb = new TestTimeBase();
+ tb.populate(100, 200, false, 300, 400, 500, 600, 700, 800);
+
+ tb.init(666, 6666);
+
+ tb.verify(0, 0, false, 0, 666, 0, 6666, 0, 0);
+ }
+
+ /**
+ * Test writeToParcel and readFromParcel
+ */
+ @SmallTest
+ public void testParcellingWhileRunning() throws Exception {
+ TestTimeBase tb1 = new TestTimeBase();
+
+ tb1.populate(100, 200, true, 300, 400, 500, 600, 700, 800);
+
+ Parcel parcel = Parcel.obtain();
+ tb1.writeToParcel(parcel, 666, 6666);
+
+ parcel.setDataPosition(0);
+
+ TestTimeBase tb2 = new TestTimeBase();
+ tb2.readFromParcel(parcel);
+
+ // Running is not preserved across parceling
+ tb2.verify(100, 200, false, 300+666-400, 400, 500+6666-600, 600, 700, 800);
+ }
+
+ /**
+ * Test writeToParcel and readFromParcel
+ */
+ @SmallTest
+ public void testParcellingWhileNotRunning() throws Exception {
+ TestTimeBase tb1 = new TestTimeBase();
+
+ tb1.populate(100, 200, false, 300, 400, 500, 600, 700, 800);
+
+ Parcel parcel = Parcel.obtain();
+ tb1.writeToParcel(parcel, 666, 6666);
+
+ parcel.setDataPosition(0);
+
+ TestTimeBase tb2 = new TestTimeBase();
+ tb2.readFromParcel(parcel);
+
+ tb2.verify(100, 200, false, 300, 400, 500, 600, 700, 800);
+ }
+
+ /**
+ * Test writeSummaryToParcel and readSummaryFromParcel
+ */
+ @SmallTest
+ public void testSummary() throws Exception {
+ TestTimeBase tb1 = new TestTimeBase();
+
+ tb1.populate(100, 200, true, 300, 400, 500, 600, 700, 800);
+
+ Parcel parcel = Parcel.obtain();
+ tb1.writeSummaryToParcel(parcel, 666, 6666);
+
+ parcel.setDataPosition(0);
+
+ TestTimeBase tb2 = new TestTimeBase();
+
+ // readSummaryFromParcel doesn't affect the other fields.
+ // Not sure if this is deliberate
+ tb2.populate(1, 2, true, 3, 4, 5, 6, 7, 8);
+
+ tb2.readSummaryFromParcel(parcel);
+
+ tb2.verify(666, 6766, true, 3, 4, 5, 6, 7, 8);
+ }
+
+ /**
+ * Test computeUptime
+ */
+ @SmallTest
+ public void testComputeUptime() throws Exception {
+ TestTimeBase tb = new TestTimeBase();
+
+ tb.populate(100, 200, true, 300, 400, 500, 600, 50, 60);
+
+ Assert.assertEquals(100+300+666-400,
+ tb.computeUptime(666, BatteryStats.STATS_SINCE_CHARGED));
+ Assert.assertEquals(300+666-400,
+ tb.computeUptime(666, BatteryStats.STATS_CURRENT));
+ Assert.assertEquals(300+666-400-50,
+ tb.computeUptime(666, BatteryStats.STATS_SINCE_UNPLUGGED));
+
+ Assert.assertEquals(0, tb.computeUptime(666, 6000));
+ }
+
+ /**
+ * Test computeUptime
+ */
+ @SmallTest
+ public void testComputeRealtime() throws Exception {
+ TestTimeBase tb = new TestTimeBase();
+
+ tb.populate(100, 200, true, 300, 400, 500, 600, 50, 60);
+
+ Assert.assertEquals(200+500+6666-600,
+ tb.computeRealtime(6666, BatteryStats.STATS_SINCE_CHARGED));
+ Assert.assertEquals(500+6666-600,
+ tb.computeRealtime(6666, BatteryStats.STATS_CURRENT));
+ Assert.assertEquals(500+6666-600-60,
+ tb.computeRealtime(6666, BatteryStats.STATS_SINCE_UNPLUGGED));
+
+ Assert.assertEquals(0, tb.computeUptime(666, 6000));
+ }
+
+ /**
+ * Test dump
+ */
+ @SmallTest
+ public void testDump() throws Exception {
+ TestTimeBase tb = new TestTimeBase();
+
+ tb.populate(100, 200, true, 300, 400, 500, 600, 50, 60);
+
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+
+ tb.dump(pw, "+++++ ");
+
+ pw.close();
+
+ // note the spaces at the ends of the lines which come from formatTimeMs.
+ final String CORRECT = "+++++ mRunning=true\n"
+ + "+++++ mUptime=0ms \n"
+ + "+++++ mRealtime=0ms \n"
+ + "+++++ mPastUptime=0ms mUptimeStart=0ms mUnpluggedUptime=0ms \n"
+ + "+++++ mPastRealtime=0ms mRealtimeStart=0ms mUnpluggedRealtime=0ms \n";
+
+ Assert.assertEquals(CORRECT, sw.toString());
+ }
+
+}
+
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java
new file mode 100644
index 0000000..3e17fcb
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java
@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import android.os.BatteryStats;
+import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+import android.util.StringBuilderPrinter;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import com.android.internal.os.BatteryStatsImpl.Clocks;
+import com.android.internal.os.BatteryStatsImpl.TimeBase;
+import com.android.internal.os.BatteryStatsImpl.Timer;
+
+/**
+ * Provides test cases for android.os.BatteryStats.
+ */
+public class BatteryStatsTimerTest extends TestCase {
+ private static final String TAG = "BatteryStatsTest";
+
+ class TestTimer extends Timer {
+ long nextComputeRunTime;
+ long lastComputeRunTimeRealtime;
+
+ int nextComputeCurrentCount;
+
+ TestTimer(Clocks clocks, int type, TimeBase timeBase, Parcel in) {
+ super(clocks, type, timeBase, in);
+ }
+
+ TestTimer(Clocks clocks, int type, TimeBase timeBase) {
+ super(clocks, type, timeBase);
+ }
+
+ protected long computeRunTimeLocked(long curBatteryRealtime) {
+ lastComputeRunTimeRealtime = curBatteryRealtime;
+ return nextComputeRunTime;
+ }
+
+ protected int computeCurrentCountLocked() {
+ return nextComputeCurrentCount;
+ }
+
+ public int getCount() {
+ return mCount;
+ }
+
+ public void setCount(int val) {
+ mCount = val;
+ }
+
+ public int getLoadedCount() {
+ return mLoadedCount;
+ }
+
+ public void setLoadedCount(int val) {
+ mLoadedCount = val;
+ }
+
+ public int getLastCount() {
+ return mLastCount;
+ }
+
+ public void setLastCount(int val) {
+ mLastCount = val;
+ }
+
+ public int getUnpluggedCount() {
+ return mUnpluggedCount;
+ }
+
+ public void setUnpluggedCount(int val) {
+ mUnpluggedCount = val;
+ }
+
+ public long getTotalTime() {
+ return mTotalTime;
+ }
+
+ public void setTotalTime(long val) {
+ mTotalTime = val;
+ }
+
+ public long getLoadedTime() {
+ return mLoadedTime;
+ }
+
+ public void setLoadedTime(long val) {
+ mLoadedTime = val;
+ }
+
+ public long getLastTime() {
+ return mLastTime;
+ }
+
+ public void setLastTime(long val) {
+ mLastTime = val;
+ }
+
+ public long getUnpluggedTime() {
+ return mUnpluggedTime;
+ }
+
+ public void setUnpluggedTime(long val) {
+ mUnpluggedTime = val;
+ }
+
+ public long getTimeBeforeMark() {
+ return mTimeBeforeMark;
+ }
+
+ public void setTimeBeforeMark(long val) {
+ mTimeBeforeMark = val;
+ }
+ }
+
+ /**
+ * Tests that the flow through TimeBase.setRunning propagates through
+ * to the timer.
+ */
+ @SmallTest
+ public void testRunning() throws Exception {
+ TimeBase timeBase = new TimeBase();
+ MockClocks clocks = new MockClocks();
+
+ TestTimer timer = new TestTimer(clocks, 0, timeBase);
+ timer.nextComputeCurrentCount = 3000;
+
+ // Test that starting the timer counts the unplugged time and counters
+ timer.nextComputeRunTime = 4;
+ timer.onTimeStarted(10, 20, 50);
+ Assert.assertEquals(50, timer.lastComputeRunTimeRealtime);
+ Assert.assertEquals(4, timer.getUnpluggedTime());
+ Assert.assertEquals(0, timer.getUnpluggedCount());
+
+ // Test that stopping the timer updates mTotalTime and mCount
+ timer.nextComputeRunTime = 17;
+ timer.onTimeStopped(100, 130, 170);
+ Assert.assertEquals(17, timer.getTotalTime());
+ Assert.assertEquals(3000, timer.getCount());
+ }
+
+ /**
+ * Tests that the parcel can be parceled and unparceled without losing anything.
+ */
+ @SmallTest
+ public void testParceling() throws Exception {
+ TimeBase timeBase = new TimeBase();
+ MockClocks clocks = new MockClocks();
+
+ // Test write then read
+ TestTimer timer1 = new TestTimer(clocks, 0, timeBase);
+ timer1.setCount(1);
+ timer1.setLoadedCount(2);
+ timer1.setLastCount(3);
+ timer1.setUnpluggedCount(4);
+ timer1.setTotalTime(9223372036854775807L);
+ timer1.setLoadedTime(9223372036854775806L);
+ timer1.setLastTime(9223372036854775805L);
+ timer1.setUnpluggedTime(9223372036854775804L);
+ timer1.setTimeBeforeMark(9223372036854775803L);
+ timer1.nextComputeRunTime = 201;
+
+ Parcel parcel = Parcel.obtain();
+ Timer.writeTimerToParcel(parcel, timer1, 77);
+
+ parcel.setDataPosition(0);
+ Assert.assertTrue("parcel null object", parcel.readInt() != 0);
+
+ TestTimer timer2 = new TestTimer(clocks, 0, timeBase, parcel);
+ Assert.assertEquals(1, timer2.getCount());
+ Assert.assertEquals(2, timer2.getLoadedCount());
+ Assert.assertEquals(0, timer2.getLastCount()); // NOT saved
+ Assert.assertEquals(4, timer2.getUnpluggedCount());
+ Assert.assertEquals(201, timer2.getTotalTime()); // from computeRunTimeLocked()
+ Assert.assertEquals(9223372036854775806L, timer2.getLoadedTime());
+ Assert.assertEquals(0, timer2.getLastTime()); // NOT saved
+ Assert.assertEquals(9223372036854775804L, timer2.getUnpluggedTime());
+ Assert.assertEquals(9223372036854775803L, timer2.getTimeBeforeMark());
+
+ parcel.recycle();
+ }
+
+ /**
+ * Tests that the parcel can be parceled and unparceled without losing anything.
+ */
+ @SmallTest
+ public void testParcelingNull() throws Exception {
+ // Test writing null
+ Parcel parcel = Parcel.obtain();
+ Timer.writeTimerToParcel(parcel, null, 88);
+
+ parcel.setDataPosition(0);
+ Assert.assertEquals(0, parcel.readInt());
+
+ parcel.recycle();
+ }
+
+ /**
+ * Tests that reset() clears the correct times.
+ */
+ @SmallTest
+ public void testResetNoDetach() throws Exception {
+ TimeBase timeBase = new TimeBase();
+ MockClocks clocks = new MockClocks();
+
+ TestTimer timer = new TestTimer(clocks, 0, timeBase);
+ timer.setCount(1);
+ timer.setLoadedCount(2);
+ timer.setLastCount(3);
+ timer.setUnpluggedCount(4);
+ timer.setTotalTime(9223372036854775807L);
+ timer.setLoadedTime(9223372036854775806L);
+ timer.setLastTime(9223372036854775805L);
+ timer.setUnpluggedTime(9223372036854775804L);
+ timer.setTimeBeforeMark(9223372036854775803L);
+
+ timer.reset(false);
+
+ Assert.assertEquals(0, timer.getCount());
+ Assert.assertEquals(0, timer.getLoadedCount());
+ Assert.assertEquals(0, timer.getLastCount());
+ Assert.assertEquals(4, timer.getUnpluggedCount());
+ Assert.assertEquals(0, timer.getTotalTime());
+ Assert.assertEquals(0, timer.getLoadedTime());
+ Assert.assertEquals(0, timer.getLastTime());
+ Assert.assertEquals(9223372036854775804L, timer.getUnpluggedTime());
+ Assert.assertEquals(0, timer.getTimeBeforeMark());
+
+ // reset(false) shouldn't remove it from the list
+ Assert.assertEquals(true, timeBase.hasObserver(timer));
+ }
+
+ /**
+ * Tests that reset() clears the correct times.
+ */
+ @SmallTest
+ public void testResetDetach() throws Exception {
+ TimeBase timeBase = new TimeBase();
+ MockClocks clocks = new MockClocks();
+
+ TestTimer timer = new TestTimer(clocks, 0, timeBase);
+ timer.setCount(1);
+ timer.setLoadedCount(2);
+ timer.setLastCount(3);
+ timer.setUnpluggedCount(4);
+ timer.setTotalTime(9223372036854775807L);
+ timer.setLoadedTime(9223372036854775806L);
+ timer.setLastTime(9223372036854775805L);
+ timer.setUnpluggedTime(9223372036854775804L);
+ timer.setTimeBeforeMark(9223372036854775803L);
+
+ timer.reset(true);
+
+ Assert.assertEquals(0, timer.getCount());
+ Assert.assertEquals(0, timer.getLoadedCount());
+ Assert.assertEquals(0, timer.getLastCount());
+ Assert.assertEquals(4, timer.getUnpluggedCount());
+ Assert.assertEquals(0, timer.getTotalTime());
+ Assert.assertEquals(0, timer.getLoadedTime());
+ Assert.assertEquals(0, timer.getLastTime());
+ Assert.assertEquals(9223372036854775804L, timer.getUnpluggedTime());
+ Assert.assertEquals(0, timer.getTimeBeforeMark());
+
+ // reset(true) should remove it from the list
+ Assert.assertEquals(false, timeBase.hasObserver(timer));
+ }
+
+ /**
+ * Tests reading and writing the summary to a parcel
+ */
+ @SmallTest
+ public void testSummaryParceling() throws Exception {
+ TimeBase timeBase = new TimeBase();
+ timeBase.setRunning(true, 10, 20);
+ timeBase.setRunning(false, 45, 60);
+ Assert.assertEquals(40, timeBase.getRealtime(200));
+ // the past uptime is 35 and the past runtime is 40
+
+ MockClocks clocks = new MockClocks();
+
+ TestTimer timer1 = new TestTimer(clocks, 0, timeBase);
+ timer1.setCount(1);
+ timer1.setLoadedCount(2);
+ timer1.setLastCount(3);
+ timer1.setUnpluggedCount(4);
+ timer1.setTotalTime(9223372036854775807L);
+ timer1.setLoadedTime(9223372036854775806L);
+ timer1.setLastTime(9223372036854775805L);
+ timer1.setUnpluggedTime(9223372036854775804L);
+ timer1.setTimeBeforeMark(9223372036854775803L);
+
+ Parcel parcel = Parcel.obtain();
+ timer1.nextComputeRunTime = 9223372036854775800L;
+ timer1.writeSummaryFromParcelLocked(parcel, 201);
+ Assert.assertEquals(40, timer1.lastComputeRunTimeRealtime);
+
+ TestTimer timer2 = new TestTimer(clocks, 0, timeBase);
+
+ // Make sure that all the values get touched
+ timer2.setCount(666);
+ timer2.setLoadedCount(666);
+ timer2.setLastCount(666);
+ timer2.setUnpluggedCount(666);
+ timer2.setTotalTime(666);
+ timer2.setLoadedTime(666);
+ timer2.setLastTime(666);
+ timer2.setUnpluggedTime(666);
+ timer2.setTimeBeforeMark(666);
+
+ parcel.setDataPosition(0);
+
+ parcel.setDataPosition(0);
+ timer2.readSummaryFromParcelLocked(parcel);
+
+ Assert.assertEquals(1, timer2.getCount());
+ Assert.assertEquals(1, timer2.getLoadedCount());
+ Assert.assertEquals(0, timer2.getLastCount());
+ Assert.assertEquals(1, timer2.getUnpluggedCount());
+ Assert.assertEquals(9223372036854775800L, timer2.getTotalTime());
+ Assert.assertEquals(9223372036854775800L, timer2.getLoadedTime());
+ Assert.assertEquals(0, timer2.getLastTime());
+ Assert.assertEquals(9223372036854775800L, timer2.getUnpluggedTime());
+ Assert.assertEquals(9223372036854775800L, timer2.getTimeBeforeMark());
+
+ parcel.recycle();
+ }
+
+ /**
+ * Tests getTotalTimeLocked
+ */
+ @SmallTest
+ public void testGetTotalTimeLocked() throws Exception {
+ TimeBase timeBase = new TimeBase();
+ timeBase.setRunning(true, 10, 20);
+ timeBase.setRunning(false, 45, 60);
+ Assert.assertEquals(40, timeBase.getRealtime(200));
+
+ MockClocks clocks = new MockClocks();
+
+ TestTimer timer = new TestTimer(clocks, 0, timeBase);
+ timer.setCount(1);
+ timer.setLoadedCount(2);
+ timer.setLastCount(3);
+ timer.setUnpluggedCount(4);
+ timer.setTotalTime(100);
+ timer.setLoadedTime(200);
+ timer.setLastTime(300);
+ timer.setUnpluggedTime(400);
+ timer.setTimeBeforeMark(500);
+
+ timer.nextComputeRunTime = 10000;
+
+ // Timer.getTotalTimeLocked(STATS_SINCE_CHARGED)
+ timer.lastComputeRunTimeRealtime = -1;
+ Assert.assertEquals(10000,
+ timer.getTotalTimeLocked(66, BatteryStats.STATS_SINCE_CHARGED));
+ Assert.assertEquals(40, timer.lastComputeRunTimeRealtime);
+
+ // Timer.getTotalTimeLocked(STATS_CURRENT)
+ timer.lastComputeRunTimeRealtime = -1;
+ Assert.assertEquals(9800, timer.getTotalTimeLocked(66, BatteryStats.STATS_CURRENT));
+ Assert.assertEquals(40, timer.lastComputeRunTimeRealtime);
+
+ // Timer.getTotalTimeLocked(STATS_SINCE_UNPLUGGED)
+ timer.lastComputeRunTimeRealtime = -1;
+ Assert.assertEquals(9600, timer.getTotalTimeLocked(66, BatteryStats.STATS_SINCE_UNPLUGGED));
+ Assert.assertEquals(40, timer.lastComputeRunTimeRealtime);
+ }
+
+ /**
+ * Tests getCountLocked
+ */
+ @SmallTest
+ public void testGetCountLocked() throws Exception {
+ TimeBase timeBase = new TimeBase();
+ timeBase.setRunning(true, 10, 20);
+ timeBase.setRunning(false, 45, 60);
+ Assert.assertEquals(40, timeBase.getRealtime(200));
+
+ MockClocks clocks = new MockClocks();
+
+ TestTimer timer = new TestTimer(clocks, 0, timeBase);
+ timer.setCount(1);
+ timer.setLoadedCount(2);
+ timer.setLastCount(3);
+ timer.setUnpluggedCount(4);
+ timer.setTotalTime(100);
+ timer.setLoadedTime(200);
+ timer.setLastTime(300);
+ timer.setUnpluggedTime(400);
+ timer.setTimeBeforeMark(500);
+
+ // Timer.getCountLocked(STATS_SINCE_CHARGED)
+ timer.nextComputeCurrentCount = 10000;
+ Assert.assertEquals(10000, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+
+ // Timer.getCountLocked(STATS_CURRENT)
+ timer.nextComputeCurrentCount = 10000;
+ Assert.assertEquals(9998, timer.getCountLocked(BatteryStats.STATS_CURRENT));
+
+ // Timer.getCountLocked(STATS_SINCE_UNPLUGGED)
+ timer.nextComputeCurrentCount = 10000;
+ Assert.assertEquals(9996, timer.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
+ }
+
+ /**
+ * Tests getTimeSinceMarkLocked
+ */
+ @SmallTest
+ public void testGetTimeSinceMarked() throws Exception {
+ TimeBase timeBase = new TimeBase();
+ timeBase.setRunning(true, 10, 20);
+ timeBase.setRunning(false, 45, 60);
+ Assert.assertEquals(40, timeBase.getRealtime(200));
+
+ MockClocks clocks = new MockClocks();
+
+ TestTimer timer = new TestTimer(clocks, 0, timeBase);
+ timer.setCount(1);
+ timer.setLoadedCount(2);
+ timer.setLastCount(3);
+ timer.setUnpluggedCount(4);
+ timer.setTotalTime(100);
+ timer.setLoadedTime(200);
+ timer.setLastTime(300);
+ timer.setUnpluggedTime(400);
+ timer.setTimeBeforeMark(500);
+
+ timer.nextComputeRunTime = 10000;
+ Assert.assertEquals(9500, timer.getTimeSinceMarkLocked(666));
+ }
+
+ /**
+ * Tests logState
+ */
+ @SmallTest
+ public void testLogState() throws Exception {
+ TimeBase timeBase = new TimeBase();
+ MockClocks clocks = new MockClocks();
+
+ TestTimer timer = new TestTimer(clocks, 0, timeBase);
+ timer.setTotalTime(100);
+ timer.setLoadedTime(200);
+ timer.setLastTime(300);
+ timer.setUnpluggedTime(400);
+ timer.setTimeBeforeMark(500);
+ timer.setCount(1);
+ timer.setLoadedCount(2);
+ timer.setLastCount(3);
+ timer.setUnpluggedCount(4);
+ timer.setTotalTime(9223372036854775807L);
+ timer.setLoadedTime(9223372036854775806L);
+ timer.setLastTime(9223372036854775805L);
+ timer.setUnpluggedTime(9223372036854775804L);
+ timer.setTimeBeforeMark(9223372036854775803L);
+
+ StringBuilder sb = new StringBuilder();
+ StringBuilderPrinter pw = new StringBuilderPrinter(sb);
+
+ timer.logState(pw, " ");
+
+ Assert.assertEquals(
+ " mCount=1 mLoadedCount=2 mLastCount=3 mUnpluggedCount=4\n"
+ + " mTotalTime=9223372036854775807 mLoadedTime=9223372036854775806\n"
+ + " mLastTime=9223372036854775805 mUnpluggedTime=9223372036854775804\n",
+ sb.toString());
+ }
+}
+
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsUidTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsUidTest.java
new file mode 100644
index 0000000..a7e75a2
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsUidTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+
+import android.os.BatteryStats;
+import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import com.android.internal.os.BatteryStatsImpl;
+
+import org.mockito.Mockito;
+
+/**
+ * Provides test cases for android.os.BatteryStats.
+ */
+public class BatteryStatsUidTest extends TestCase {
+ private static final String TAG = "BatteryStatsTimeBaseTest";
+
+ static class TestBsi extends BatteryStatsImpl {
+ TestBsi(MockClocks clocks) {
+ super(clocks);
+ }
+ }
+
+ /**
+ * Test the observers and the setRunning call.
+ */
+ @SmallTest
+ public void testParceling() throws Exception {
+ }
+}
+
diff --git a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
new file mode 100644
index 0000000..3924489
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+
+import android.os.BatteryStats;
+import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import com.android.internal.os.BatteryStatsImpl;
+
+import org.mockito.Mockito;
+
+/**
+ * Mocks a BatteryStatsImpl object.
+ */
+public class MockBatteryStatsImpl extends BatteryStatsImpl {
+ public BatteryStatsImpl.Clocks clocks;
+
+ MockBatteryStatsImpl() {
+ super(new MockClocks());
+ this.clocks = mClocks;
+ }
+
+ public TimeBase getOnBatteryTimeBase() {
+ return mOnBatteryTimeBase;
+ }
+
+}
+
diff --git a/core/java/android/hardware/ICameraServiceListener.aidl b/core/tests/coretests/src/com/android/internal/os/MockClocks.java
similarity index 61%
copy from core/java/android/hardware/ICameraServiceListener.aidl
copy to core/tests/coretests/src/com/android/internal/os/MockClocks.java
index 49278b6..f750c37 100644
--- a/core/java/android/hardware/ICameraServiceListener.aidl
+++ b/core/tests/coretests/src/com/android/internal/os/MockClocks.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,15 +14,19 @@
* limitations under the License.
*/
-package android.hardware;
+package com.android.internal.os;
-/** @hide */
-interface ICameraServiceListener
-{
- /**
- * Keep up-to-date with frameworks/av/include/camera/ICameraServiceListener.h
- */
- void onStatusChanged(int status, int cameraId);
+public class MockClocks implements BatteryStatsImpl.Clocks {
+ public long realtime;
+ public long uptime;
- void onTorchStatusChanged(int status, String cameraId);
+ @Override
+ public long elapsedRealtime() {
+ return realtime;
+ }
+
+ @Override
+ public long uptimeMillis() {
+ return uptime;
+ }
}
diff --git a/core/tests/coretests/src/com/android/internal/util/AsyncChannelTest.java b/core/tests/coretests/src/com/android/internal/util/AsyncChannelTest.java
deleted file mode 100644
index 7088650..0000000
--- a/core/tests/coretests/src/com/android/internal/util/AsyncChannelTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.util;
-
-import android.os.Debug;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-
-import junit.framework.TestCase;
-
-/**
- * Test for AsyncChannel.
- */
-public class AsyncChannelTest extends TestCase {
- private static final boolean DBG = true;
- private static final boolean WAIT_FOR_DEBUGGER = false;
- private static final String TAG = "AsyncChannelTest";
-
- @SmallTest
- public void test1() throws Exception {
- if (DBG) log("test1");
- if (WAIT_FOR_DEBUGGER) Debug.waitForDebugger();
- assertTrue(1 == 1);
- }
-
- protected void log(String s) {
- Log.d(TAG, s);
- }
-}
diff --git a/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.mk b/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.mk
index ff5a535..994131a 100644
--- a/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.mk
+++ b/core/tests/hosttests/test-apps/SharedUid/32/jni/Android.mk
@@ -32,6 +32,8 @@
# All of the shard libraries we link against.
LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_CFLAGS += -Wall -Wextra -Werror
+
# Also need the JNI headers.
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE)
diff --git a/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp b/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp
index 67b12d7..99cf587 100644
--- a/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp
+++ b/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp
@@ -22,7 +22,7 @@
#include "jni.h"
static jint
-add(JNIEnv *env, jobject thiz, jint a, jint b) {
+add(JNIEnv */* env */, jobject /* thiz */, jint a, jint b) {
int result = a + b;
ALOGI("%d + %d = %d", a, b, result);
return result;
@@ -82,7 +82,7 @@
void* venv;
} UnionJNIEnvToVoid;
-jint JNI_OnLoad(JavaVM* vm, void* reserved)
+jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
{
UnionJNIEnvToVoid uenv;
uenv.venv = NULL;
diff --git a/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.mk b/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.mk
index abb1d9f..6c2679b 100644
--- a/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.mk
+++ b/core/tests/hosttests/test-apps/SharedUid/64/jni/Android.mk
@@ -34,6 +34,8 @@
LOCAL_SHARED_LIBRARIES := \
libutils liblog
+LOCAL_CFLAGS += -Wall -Wextra -Werror
+
# Also need the JNI headers.
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE)
diff --git a/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp b/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp
index 342b3bc..0b6d750 100644
--- a/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp
+++ b/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp
@@ -22,7 +22,7 @@
#include "jni.h"
static jint
-add(JNIEnv *env, jobject thiz, jint a, jint b) {
+add(JNIEnv */* env */, jobject /* thiz */, jint a, jint b) {
int result = a + b;
ALOGI("%d + %d = %d", a, b, result);
return result;
@@ -82,7 +82,7 @@
void* venv;
} UnionJNIEnvToVoid;
-jint JNI_OnLoad(JavaVM* vm, void* reserved)
+jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
{
UnionJNIEnvToVoid uenv;
uenv.venv = NULL;
diff --git a/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.mk b/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.mk
index ae8e636..d668f29 100644
--- a/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.mk
+++ b/core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.mk
@@ -33,6 +33,8 @@
LOCAL_LDLIBS = -llog
LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_CFLAGS += -Wall -Wextra -Werror
+
# Also need the JNI headers.
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE)
diff --git a/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp b/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp
index 9b38e3e..3947e21 100644
--- a/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp
+++ b/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp
@@ -22,7 +22,7 @@
#include "jni.h"
static jint
-add(JNIEnv *env, jobject thiz, jint a, jint b) {
+add(JNIEnv */* env */, jobject /* thiz */, jint a, jint b) {
int result = a + b;
ALOGI("%d + %d = %d", a, b, result);
return result;
@@ -82,7 +82,7 @@
void* venv;
} UnionJNIEnvToVoid;
-jint JNI_OnLoad(JavaVM* vm, void* reserved)
+jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
{
UnionJNIEnvToVoid uenv;
uenv.venv = NULL;
diff --git a/core/tests/utiltests/Android.mk b/core/tests/utiltests/Android.mk
new file mode 100644
index 0000000..3c6c32e
--- /dev/null
+++ b/core/tests/utiltests/Android.mk
@@ -0,0 +1,24 @@
+#########################################################################
+# Build FrameworksUtilTests package
+#########################################################################
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+
+# Include all test java files.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ android-support-test \
+ mockito-target
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_PACKAGE_NAME := FrameworksUtilTests
+
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
diff --git a/core/tests/utiltests/AndroidManifest.xml b/core/tests/utiltests/AndroidManifest.xml
new file mode 100644
index 0000000..fecaf8e
--- /dev/null
+++ b/core/tests/utiltests/AndroidManifest.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.frameworks.utiltests">
+
+ <uses-permission android:name="android.permission.READ_LOGS" />
+ <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+ <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.BROADCAST_STICKY" />
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+ <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" />
+ <uses-permission android:name="android.permission.MANAGE_APP_TOKENS" />
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
+
+ <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
+ <uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />
+ <uses-permission android:name="android.permission.MODIFY_NETWORK_ACCOUNTING" />
+ <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+ <uses-permission android:name="android.permission.MANAGE_USERS" />
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+ <uses-permission android:name="android.permission.MANAGE_DEVICE_ADMINS" />
+ <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.PACKET_KEEPALIVE_OFFLOAD" />
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.frameworks.utiltests"
+ android:label="Frameworks Utility Tests" />
+
+</manifest>
diff --git a/core/tests/coretests/src/com/android/internal/util/ArrayUtilsTest.java b/core/tests/utiltests/src/com/android/internal/util/ArrayUtilsTest.java
similarity index 100%
rename from core/tests/coretests/src/com/android/internal/util/ArrayUtilsTest.java
rename to core/tests/utiltests/src/com/android/internal/util/ArrayUtilsTest.java
diff --git a/core/tests/coretests/src/com/android/internal/util/BitwiseStreamsTest.java b/core/tests/utiltests/src/com/android/internal/util/BitwiseStreamsTest.java
similarity index 100%
rename from core/tests/coretests/src/com/android/internal/util/BitwiseStreamsTest.java
rename to core/tests/utiltests/src/com/android/internal/util/BitwiseStreamsTest.java
diff --git a/core/tests/coretests/src/com/android/internal/util/CallbackRegistryTest.java b/core/tests/utiltests/src/com/android/internal/util/CallbackRegistryTest.java
similarity index 100%
rename from core/tests/coretests/src/com/android/internal/util/CallbackRegistryTest.java
rename to core/tests/utiltests/src/com/android/internal/util/CallbackRegistryTest.java
diff --git a/core/tests/coretests/src/com/android/internal/util/CharSequencesTest.java b/core/tests/utiltests/src/com/android/internal/util/CharSequencesTest.java
similarity index 100%
rename from core/tests/coretests/src/com/android/internal/util/CharSequencesTest.java
rename to core/tests/utiltests/src/com/android/internal/util/CharSequencesTest.java
diff --git a/core/tests/coretests/src/com/android/internal/util/FastXmlSerializerTest.java b/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java
similarity index 94%
rename from core/tests/coretests/src/com/android/internal/util/FastXmlSerializerTest.java
rename to core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java
index be7116d..5f36c2d 100644
--- a/core/tests/coretests/src/com/android/internal/util/FastXmlSerializerTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java
@@ -42,6 +42,6 @@
out.endDocument();
assertEquals("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
- + "<string name=\"meow\"></string>", stream.toString());
+ + "<string name=\"meow\"></string>\n", stream.toString());
}
}
diff --git a/core/tests/coretests/src/com/android/internal/util/FileRotatorTest.java b/core/tests/utiltests/src/com/android/internal/util/FileRotatorTest.java
similarity index 100%
rename from core/tests/coretests/src/com/android/internal/util/FileRotatorTest.java
rename to core/tests/utiltests/src/com/android/internal/util/FileRotatorTest.java
diff --git a/core/tests/coretests/src/com/android/internal/util/IndentingPrintWriterTest.java b/core/tests/utiltests/src/com/android/internal/util/IndentingPrintWriterTest.java
similarity index 100%
rename from core/tests/coretests/src/com/android/internal/util/IndentingPrintWriterTest.java
rename to core/tests/utiltests/src/com/android/internal/util/IndentingPrintWriterTest.java
diff --git a/core/tests/utiltests/src/com/android/internal/util/MessageUtilsTest.java b/core/tests/utiltests/src/com/android/internal/util/MessageUtilsTest.java
new file mode 100644
index 0000000..32b969a
--- /dev/null
+++ b/core/tests/utiltests/src/com/android/internal/util/MessageUtilsTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import static org.junit.Assert.*;
+
+import com.android.internal.util.MessageUtils;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.SparseArray;
+
+import org.junit.Test;
+
+
+class A {
+ // Should not see these.
+ private int mMember;
+ public final int CMD_NOT_STATIC = 7;
+ private static final String CMD_NOT_INT = "not an integer";
+ public static int CMD_NOT_FINAL = 34;
+ public static final int kWrongPrefix = 99;
+
+ // Should see these.
+ private static final int CMD_DO_SOMETHING = 12;
+ public static final int EVENT_SOMETHING_HAPPENED = 45;
+}
+
+class B {
+ public static final int CMD_FOO = 56;
+ public static final int EVENT_BAR = 55;
+ public static final int NOTIFICATION_BAZ = 12;
+}
+
+/**
+ * Unit tests for {@link com.android.util.MessageUtils}.
+ */
+@SmallTest
+public class MessageUtilsTest {
+
+ private static final Class[] CLASSES = { A.class, B.class };
+
+ private SparseArray<String> makeSparseArray(int[] keys, String[] values) throws Exception {
+ assertEquals("Must specify same number of keys and values", keys.length, values.length);
+ SparseArray<String> out = new SparseArray<>();
+ for (int i = 0; i < keys.length; i++) {
+ out.put(keys[i], values[i]);
+ }
+ return out;
+ }
+
+ private void assertSparseArrayEquals(
+ SparseArray<String> a1, SparseArray<String> a2) throws Exception {
+ String msg = String.format("%s != %s", a1.toString(), a2.toString());
+ assertEquals(msg, a1.size(), a2.size());
+ int size = a1.size();
+ for (int i = 0; i < size; i++) {
+ assertEquals(msg, a1.keyAt(i), a2.keyAt(i));
+ assertEquals(msg, a1.valueAt(i), a2.valueAt(i));
+ }
+ }
+
+ @Test
+ public void basicOperation() throws Exception {
+ SparseArray<String> expected = makeSparseArray(
+ new int[]{12, 45, 55, 56},
+ new String[]{"CMD_DO_SOMETHING", "EVENT_SOMETHING_HAPPENED", "EVENT_BAR", "CMD_FOO"});
+ assertSparseArrayEquals(expected, MessageUtils.findMessageNames(CLASSES));
+ }
+
+ @Test
+ public void withPrefixes() throws Exception {
+ SparseArray<String> expected = makeSparseArray(
+ new int[]{45, 55},
+ new String[]{"EVENT_SOMETHING_HAPPENED", "EVENT_BAR"});
+ assertSparseArrayEquals(expected, MessageUtils.findMessageNames(CLASSES,
+ new String[]{"EVENT_"}));
+ }
+
+ @Test(expected=MessageUtils.DuplicateConstantError.class)
+ public void duplicateConstants() {
+ MessageUtils.findMessageNames(CLASSES, new String[]{"CMD_", "NOTIFICATION_"});
+ }
+
+}
diff --git a/core/tests/coretests/src/com/android/internal/util/PredicatesTest.java b/core/tests/utiltests/src/com/android/internal/util/PredicatesTest.java
similarity index 100%
rename from core/tests/coretests/src/com/android/internal/util/PredicatesTest.java
rename to core/tests/utiltests/src/com/android/internal/util/PredicatesTest.java
diff --git a/core/tests/coretests/src/com/android/internal/util/ProcFileReaderTest.java b/core/tests/utiltests/src/com/android/internal/util/ProcFileReaderTest.java
similarity index 100%
rename from core/tests/coretests/src/com/android/internal/util/ProcFileReaderTest.java
rename to core/tests/utiltests/src/com/android/internal/util/ProcFileReaderTest.java
diff --git a/core/tests/coretests/src/com/android/internal/util/StateMachineTest.java b/core/tests/utiltests/src/com/android/internal/util/StateMachineTest.java
similarity index 100%
rename from core/tests/coretests/src/com/android/internal/util/StateMachineTest.java
rename to core/tests/utiltests/src/com/android/internal/util/StateMachineTest.java
diff --git a/core/tests/utiltests/src/com/android/internal/util/WakeupMessageTest.java b/core/tests/utiltests/src/com/android/internal/util/WakeupMessageTest.java
new file mode 100644
index 0000000..da8bc1d
--- /dev/null
+++ b/core/tests/utiltests/src/com/android/internal/util/WakeupMessageTest.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+import android.app.AlarmManager;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+/**
+ * Unit tests for {@link com.android.internal.util.WakeupMessage}.
+ */
+@SmallTest
+public class WakeupMessageTest {
+ private static final String TEST_CMD_NAME = "TEST cmd Name";
+ private static final int TEST_CMD = 18;
+ private static final int TEST_ARG1 = 33;
+ private static final int TEST_ARG2 = 182;
+
+ @Mock AlarmManager mAlarmManager;
+ WakeupMessage mMessage;
+ // Make a spy so that we can verify calls to it
+ @Spy MessageCapturingHandler mHandler = new MessageCapturingHandler();
+
+ ArgumentCaptor<AlarmManager.OnAlarmListener> mListenerCaptor =
+ ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
+
+ /**
+ * A Handler that will capture the most recent message sent to it.
+ *
+ * This handler is setup on the main Looper
+ */
+ public static class MessageCapturingHandler extends Handler {
+ private Message mLastMessage;
+
+ public MessageCapturingHandler() {
+ super(Looper.getMainLooper(), /* Nothing is actually dispatched on this Looper */
+ null, false);
+ }
+
+ @Override
+ public void handleMessage(Message m) {
+ // need to copy since it will be recycled after this method returns
+ mLastMessage = Message.obtain(m);
+ }
+
+ public Message getLastMessage() {
+ return mLastMessage;
+ }
+ }
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ Context context = mock(Context.class);
+ when(context.getSystemService(Context.ALARM_SERVICE)).thenReturn(mAlarmManager);
+ // capture the listener for each AlarmManager.setExact call
+ doNothing().when(mAlarmManager).setExact(anyInt(), anyLong(), any(String.class),
+ mListenerCaptor.capture(), any(Handler.class));
+
+ mMessage = new WakeupMessage(context, mHandler, TEST_CMD_NAME, TEST_CMD, TEST_ARG1,
+ TEST_ARG2);
+ }
+
+ /**
+ * Ensure the test is cleaned up and ready for the next test.
+ */
+ @After
+ public void cleanup() {
+ validateMockitoUsage();
+ }
+
+ private void scheduleAndVerifyAlarm(long when) {
+ mMessage.schedule(when);
+ verify(mAlarmManager).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), eq(when),
+ eq(TEST_CMD_NAME), any(AlarmManager.OnAlarmListener.class), eq(mHandler));
+ }
+
+ private void verifyMessageDispatchedOnce() {
+ verify(mHandler, times(1)).handleMessage(any(Message.class));
+ assertEquals("what", TEST_CMD, mHandler.getLastMessage().what);
+ assertEquals("arg1", TEST_ARG1, mHandler.getLastMessage().arg1);
+ assertEquals("arg2", TEST_ARG2, mHandler.getLastMessage().arg2);
+ }
+
+ /**
+ * Schedule and deliver a single message
+ */
+ @Test
+ public void scheduleAndDeliverMessage() {
+ final long when = 1001;
+ scheduleAndVerifyAlarm(when);
+ verify(mHandler, never()).handleMessage(any(Message.class));
+ mListenerCaptor.getValue().onAlarm();
+ verifyMessageDispatchedOnce();
+ }
+
+ /**
+ * Check that the message is not delivered if cancel is called it after its alarm fires but
+ * before onAlarm is called.
+ *
+ * This ensures that if cancel is called on the handler thread, any previously-scheduled message
+ * is guaranteed not to be delivered.
+ */
+ @Test
+ public void scheduleAndCancelMessage() {
+ final long when = 1010;
+ scheduleAndVerifyAlarm(when);
+ mMessage.cancel();
+ mListenerCaptor.getValue().onAlarm();
+ verify(mHandler, never()).handleMessage(any(Message.class));
+ }
+
+ /**
+ * Verify nothing happens when cancel is called without a schedule
+ */
+ @Test
+ public void cancelWithoutSchedule() {
+ mMessage.cancel();
+ }
+
+ /**
+ * Verify that the message is silently rescheduled if schedule is called twice without the
+ * message being dispatched first.
+ */
+ @Test
+ public void scheduleTwiceWithoutMessageDispatched() {
+ final long when1 = 1011;
+ final long when2 = 1012;
+ scheduleAndVerifyAlarm(when1);
+ scheduleAndVerifyAlarm(when2);
+ mListenerCaptor.getValue().onAlarm();
+ verifyMessageDispatchedOnce();
+ }
+
+}
diff --git a/core/tests/coretests/src/com/android/internal/util/XmlUtilsTest.java b/core/tests/utiltests/src/com/android/internal/util/XmlUtilsTest.java
similarity index 100%
rename from core/tests/coretests/src/com/android/internal/util/XmlUtilsTest.java
rename to core/tests/utiltests/src/com/android/internal/util/XmlUtilsTest.java
diff --git a/data/keyboards/qwerty2.kcm b/data/keyboards/qwerty2.kcm
index d96914f..b981d83 100644
--- a/data/keyboards/qwerty2.kcm
+++ b/data/keyboards/qwerty2.kcm
@@ -23,8 +23,8 @@
number: '2'
base: 'a'
shift, capslock: 'A'
- alt: 'a'
- shift+alt, capslock+alt: 'A'
+ alt: '\u00e1'
+ shift+alt, capslock+alt: '\u00c1'
}
key B {
@@ -41,8 +41,8 @@
number: '2'
base: 'c'
shift, capslock: 'C'
- alt: '\u00e7'
- shift+alt, capslock+alt: '\u00e7'
+ alt: '\u00a9'
+ shift+alt, capslock+alt: '\u00a2'
}
key D {
@@ -50,8 +50,8 @@
number: '3'
base: 'd'
shift, capslock: 'D'
- alt: '\''
- shift+alt, capslock+alt: '\''
+ alt: '\u00f0'
+ shift+alt, capslock+alt: '\u00d0'
}
key E {
@@ -59,8 +59,8 @@
number: '3'
base: 'e'
shift, capslock: 'E'
- alt: '"'
- shift+alt, capslock+alt: '\u0301'
+ alt: '\u00e9'
+ shift+alt, capslock+alt: '\u00c9'
}
key F {
@@ -95,8 +95,8 @@
number: '4'
base: 'i'
shift, capslock: 'I'
- alt: '-'
- shift+alt, capslock+alt: '\u0302'
+ alt: '\u00ed'
+ shift+alt, capslock+alt: '\u00cd'
}
key J {
@@ -122,8 +122,8 @@
number: '5'
base: 'l'
shift, capslock: 'L'
- alt: ':'
- shift+alt, capslock+alt: '`'
+ alt: '\u00f8'
+ shift+alt, capslock+alt: '\u00d8'
}
key M {
@@ -131,7 +131,7 @@
number: '6'
base: 'm'
shift, capslock: 'M'
- alt: '%'
+ alt: '\u00b5'
shift+alt, capslock+alt: none
}
@@ -140,8 +140,8 @@
number: '6'
base: 'n'
shift, capslock: 'N'
- alt: none
- shift+alt, capslock+alt: '\u0303'
+ alt: '\u00f1'
+ shift+alt, capslock+alt: '\u00d1'
}
key O {
@@ -149,8 +149,8 @@
number: '6'
base: 'o'
shift, capslock: 'O'
- alt: '+'
- shift+alt, capslock+alt: '+'
+ alt: '\u00f3'
+ shift+alt, capslock+alt: '\u00d3'
}
key P {
@@ -158,8 +158,8 @@
number: '7'
base: 'p'
shift, capslock: 'P'
- alt: '='
- shift+alt, capslock+alt: '\u00a5'
+ alt: '\u00f6'
+ shift+alt, capslock+alt: '\u00d6'
}
key Q {
@@ -167,8 +167,8 @@
number: '7'
base: 'q'
shift, capslock: 'Q'
- alt: '|'
- shift+alt, capslock+alt: '\u0300'
+ alt: '\u00e4'
+ shift+alt, capslock+alt: '\u00c4'
}
key R {
@@ -176,8 +176,8 @@
number: '7'
base: 'r'
shift, capslock: 'R'
- alt: '`'
- shift+alt, capslock+alt: '\u20ac'
+ alt: '\u00ae'
+ shift+alt, capslock+alt: 'R'
}
key S {
@@ -185,8 +185,8 @@
number: '7'
base: 's'
shift, capslock: 'S'
- alt: '\\'
- shift+alt, capslock+alt: '\u00df'
+ alt: '\u00df'
+ shift+alt, capslock+alt: '\u00a7'
}
key T {
@@ -194,8 +194,8 @@
number: '8'
base: 't'
shift, capslock: 'T'
- alt: '{'
- shift+alt, capslock+alt: '\u00a3'
+ alt: '\u00fe'
+ shift+alt, capslock+alt: '\u00de'
}
key U {
@@ -203,8 +203,8 @@
number: '8'
base: 'u'
shift, capslock: 'U'
- alt: '_'
- shift+alt, capslock+alt: '\u0308'
+ alt: '\u00fa'
+ shift+alt, capslock+alt: '\u00da'
}
key V {
@@ -221,8 +221,8 @@
number: '9'
base: 'w'
shift, capslock: 'W'
- alt: '~'
- shift+alt, capslock+alt: '~'
+ alt: '\u00e5'
+ shift+alt, capslock+alt: '\u00c5'
}
key X {
@@ -239,8 +239,8 @@
number: '9'
base: 'y'
shift, capslock: 'Y'
- alt: '}'
- shift+alt, capslock+alt: '\u00a1'
+ alt: '\u00fc'
+ shift+alt, capslock+alt: '\u00dc'
}
key Z {
@@ -248,8 +248,8 @@
number: '9'
base: 'z'
shift, capslock: 'Z'
- alt: 'z'
- shift+alt, capslock+alt: 'Z'
+ alt: '\u00e6'
+ shift+alt, capslock+alt: '\u00c6'
}
key COMMA {
@@ -257,8 +257,8 @@
number: ','
base: ','
shift: '<'
- alt: ','
- shift+alt: ','
+ alt: '\u00e7'
+ shift+alt: '\u00c7'
}
key PERIOD {
@@ -284,7 +284,7 @@
number: '/'
base: '/'
shift: '?'
- alt: '?'
+ alt: '\u00bf'
shift+alt: '?'
}
@@ -320,7 +320,7 @@
number: '0'
base: '0'
shift: ')'
- alt: ')'
+ alt: '\u02bc'
shift+alt: ')'
}
@@ -329,8 +329,8 @@
number: '1'
base: '1'
shift: '!'
- alt: '!'
- shift+alt: '!'
+ alt: '\u00a1'
+ shift+alt: '\u00b9'
}
key 2 {
@@ -338,7 +338,7 @@
number: '2'
base: '2'
shift: '@'
- alt: '@'
+ alt: '\u00b2'
shift+alt: '@'
}
@@ -347,7 +347,7 @@
number: '3'
base: '3'
shift: '#'
- alt: '#'
+ alt: '\u00b3'
shift+alt: '#'
}
@@ -356,8 +356,8 @@
number: '4'
base: '4'
shift: '$'
- alt: '$'
- shift+alt: '$'
+ alt: '\u00a4'
+ shift+alt: '\u00a3'
}
key 5 {
@@ -365,7 +365,7 @@
number: '5'
base: '5'
shift: '%'
- alt: '%'
+ alt: '\u20ac'
shift+alt: '%'
}
@@ -374,8 +374,8 @@
number: '6'
base: '6'
shift: '^'
- alt: '^'
- shift+alt: '^'
+ alt: '\u00bc'
+ shift+alt: '\u0302'
}
key 7 {
@@ -383,7 +383,7 @@
number: '7'
base: '7'
shift: '&'
- alt: '&'
+ alt: '\u00bd'
shift+alt: '&'
}
@@ -392,7 +392,7 @@
number: '8'
base: '8'
shift: '*'
- alt: '*'
+ alt: '\u00be'
shift+alt: '*'
}
@@ -401,7 +401,7 @@
number: '9'
base: '9'
shift: '('
- alt: '('
+ alt: '\u02bb'
shift+alt: '('
}
@@ -410,8 +410,8 @@
number: '`'
base: '`'
shift: '~'
- alt: '`'
- shift+alt: '~'
+ alt: '\u0300'
+ shift+alt: '\u0303'
}
key MINUS {
@@ -419,7 +419,7 @@
number: '-'
base: '-'
shift: '_'
- alt: '-'
+ alt: '\u00a5'
shift+alt: '_'
}
@@ -428,8 +428,8 @@
number: '='
base: '='
shift: '+'
- alt: '='
- shift+alt: '+'
+ alt: '\u00d7'
+ shift+alt: '\u00f7'
}
key LEFT_BRACKET {
@@ -437,7 +437,7 @@
number: '['
base: '['
shift: '{'
- alt: '['
+ alt: '\u00ab'
shift+alt: '{'
}
@@ -446,7 +446,7 @@
number: ']'
base: ']'
shift: '}'
- alt: ']'
+ alt: '\u00bb'
shift+alt: '}'
}
@@ -455,8 +455,8 @@
number: '\\'
base: '\\'
shift: '|'
- alt: '\\'
- shift+alt: '|'
+ alt: '\u00ac'
+ shift+alt: '\u00a6'
}
key SEMICOLON {
@@ -464,8 +464,8 @@
number: ';'
base: ';'
shift: ':'
- alt: ';'
- shift+alt: ':'
+ alt: '\u00b6'
+ shift+alt: '\u00b0'
}
key APOSTROPHE {
@@ -473,8 +473,8 @@
number: '\''
base: '\''
shift: '"'
- alt: '\''
- shift+alt: '"'
+ alt: '\u0301'
+ shift+alt: '\u0308'
}
key STAR {
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index f3f2e5e..e99c15a 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -631,6 +631,16 @@
</ul>
</li>
+ <li class="nav-section">
+ <div class="nav-section-header"><a href="<?cs var:toroot ?>guide/topics/security/index.html">
+ <span class="en">Security</span>
+ </a></div>
+ <ul>
+ <li><a href="<?cs var:toroot ?>guide/topics/security/security-config.html">
+ <span class="en">Network Security Config</span>
+ </a></li>
+ </ul>
+ </li>
</ul>
diff --git a/docs/html/guide/topics/security/index.jd b/docs/html/guide/topics/security/index.jd
new file mode 100644
index 0000000..22fb775
--- /dev/null
+++ b/docs/html/guide/topics/security/index.jd
@@ -0,0 +1,7 @@
+page.title=Security
+page.landing=true
+page.landing.intro=Configure the security of your application.
+
+@jd:body
+<div class="landing-docs">
+</div>
diff --git a/docs/html/guide/topics/security/security-config.jd b/docs/html/guide/topics/security/security-config.jd
new file mode 100644
index 0000000..4cee253
--- /dev/null
+++ b/docs/html/guide/topics/security/security-config.jd
@@ -0,0 +1,539 @@
+page.title=Network Security Config
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>In this document</h2>
+<ol>
+<li><a href="#SupportedFeatures">Features</a></li>
+<li><a href="#Examples">Examples</a>
+ <ol>
+ <li><a href="#TrustingCustomCas">Trusting Custom CAs</a>
+ <ol>
+ <li><a href="#TrustingACustomCa">Trusting a Custom CA</a></li>
+ <li><a href="#LimitingCas">Limiting the Set of Trusted CAs</a></li>
+ <li><a href="#TrustingAdditionalCas">Trusting Additional CAs</a></li>
+ </ol>
+ </li>
+ <li><a href="#TrustingDebugCa">Debugging-only CAs</a></li>
+ <li><a href="#UsesCleartextTraffic">Cleartext Traffic Opt-Out</a></li>
+ <li><a href="#CertificatePinning">Certificate Pinning</a></li>
+ <li><a href="#ConfigInheritance">Configuration Inheritance</a></li>
+ </ol>
+</li>
+<li><a href="#FileFormat">Configuration File Format</a></li>
+</ol>
+</div>
+</div>
+
+<p>The Android Network Security Config lets apps customize their network security settings
+in a safe, declarative configuration file without modifying application code.
+These settings can be configured for specific domains and app-wide.</p>
+
+<h2 id="SupportedFeatures">Features</h2>
+<ul>
+<li><b>Custom trust anchors.</b> Lets an application customize which Certificate Authorities (CA) are trusted
+for its secure connections. For example, trusting particular self-signed certificates or restricting the set of public
+CAs that the app trusts.
+</li>
+<li><b>Debug-only overrides.</b> Lets an application developer safely debug secure connections of their
+application without added risk to the installed base.
+</li>
+<li><b>Cleartext traffic opt-out.</b> Lets an application protect itself from accidental usage of cleartext traffic.</li>
+<li><b>Certificate pinning.</b> An advanced feature that lets an application restrict pin its secure connection
+to particular certificates.</li>
+</ul>
+
+<h2 id="Examples">Examples</h2>
+<h3 id="TrustingCustomCas">Trusting Custom CAs</h3>
+<p>An application may want to trust a custom set of CAs instead of the platform
+default. The most common reasons of this are:
+<ul>
+<li>Connecting to a host with a custom certificate authority(self-signed, issued by an internal corporate CA, etc).</li>
+<li>Limiting the set of CAs to only the CAs you trust instead of every preinstalled CA.</li>
+<li>Trusting additional CAs not included in the system.</li>
+</ul>
+</p>
+<p>By default secure (e.g. TLS, HTTPS) connections from all applications trust the pre-installed system CAs, and
+applications targeting API level 23 (Android M) and below also trust the user-added CA store by default.
+An application can customize its own connections using {@code base-config} (for app-wide customization) or
+{@code domain-config} (for per-domain customization).</p>
+
+<h4 id="TrustingACustomCa">Trusting a Custom CA</h4>
+<p>Assume you want to connect to your host which uses a self-signed SSL certificate or to
+a host whose SSL certificate is issued by a non-public CA which you trust, e.g., your company's internal
+CA.</p>
+<p>
+<code>res/xml/network_security_config.xml</code>:
+<pre>
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+ <domain-config>
+ <domain includeSubdomains="true">example.com</domain>
+ <trust-anchors>
+ <certificates src="@raw/my_ca"/>
+ </trust-anchors>
+ </domain-config>
+</network-security-config>
+</pre>
+</p>
+<p>Add the self-signed or non-public CA certificate, in PEM or DER format, to {@code res/raw/my_ca}.</p>
+<p>
+In <code>AndroidManifest.xml</code> reference the above config
+<pre>
+<?xml version="1.0" encoding="utf-8"?>
+...
+<application ...>
+ <meta-data android:name="android.security.net.config"
+ android:resource="@xml/network_security_config" />
+ ...
+</pre>
+</p>
+<h4 id="LimitingCas">Limiting the Set of Trusted CAs</h4>
+<p>An application that does not want to trust all CAs trusted by system can instead specify its own
+reduced set of CAs to trust. This protects the application from fradulent certificates issued by any
+of the other CAs.</p>
+
+<p>The config to limit the set of trusted CAs is similar to <a href="#TrustingACustomCa">trusting a custom CA</a>
+for a specific domain except that multiple CAs are provided in the resource.</p>
+
+<p>
+<code>res/xml/network_security_config.xml</code>:
+<pre>
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+ <domain-config>
+ <domain includeSubdomains="true">secure.example.com</domain>
+ <domain includeSubdomains="true">cdn.example.com</domain>
+ <trust-anchors>
+ <certificates src="@raw/trusted_roots"/>
+ </trust-anchors>
+ </domain-config>
+</network-security-config>
+</pre>
+</p>
+<p>Add the trusted CAs, in PEM or DER format, to {@code res/raw/trusted_roots}.
+Note that if using PEM format the file must contain <em>only</em> PEM data and no extra text.
+You can also provide multiple <a href="certificates"><code><certificates></code></a> elements instead
+of one.</p>
+<p>
+In <code>AndroidManifest.xml</code> reference the above config
+<pre>
+<?xml version="1.0" encoding="utf-8"?>
+...
+<application ...>
+ <meta-data android:name="android.security.net.config"
+ android:resource="@xml/network_security_config" />
+ ...
+</pre>
+</p>
+
+<h4 id="TrustingAdditionalCas">Trusting Additional CAs</h4>
+<p>An application may want to trust additional CAs not trusted by the system, this could be due to
+the system not yet including the CA or a CA that does not meet the requirements for inclusion into
+the Android system. An application can do this by specifying multiple certificate sources for a configuration.
+</p>
+<p>
+<code>res/xml/network_security_config.xml</code>:
+<pre>
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+ <base-config>
+ <trust-anchors>
+ <certificates src="@raw/extracas"/>
+ <certificates src="system"/>
+ </trust-anchors>
+ </base-config>
+</network-security-config>
+</pre>
+</p>
+<p>
+In <code>AndroidManifest.xml</code> reference the above config
+<pre>
+<?xml version="1.0" encoding="utf-8"?>
+...
+<application ...>
+ <meta-data android:name="android.security.net.config"
+ android:resource="@xml/network_security_config" />
+ ...
+</pre>
+</p>
+
+<h3 id="TrustingDebugCa">Debugging-only CAs</h3>
+<p>When debugging an application that connects over HTTPS you may want to connect to a local development
+server, which does not have the SSL certificate for your production server. In order to support this
+without any modification to your application's code you can specify debug-only CAs that are
+<i>only</i> trusted when <a href="{@docRoot}guide/topics/manifest/application-element.html#debug">android:debuggable</a>
+is {@code true} by using {@code debug-overrides}. Normally IDEs and build tools set this flag automatically for non-release builds.</p>
+<p>This is safer than the usual conditional code because, as a security precaution, application stores
+do not accept applications which are marked debuggable.</p>
+
+<p>
+<code>res/xml/network_security_config.xml</code>:
+<pre>
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+ <debug-overrides>
+ <trust-anchors>
+ <certificates src="@raw/debug_cas"/>
+ </trust-anchors>
+ </debug-overrides>
+</network-security-config>
+</pre>
+</p>
+<p>
+In <code>AndroidManifest.xml</code> reference the above config
+<pre>
+<?xml version="1.0" encoding="utf-8"?>
+...
+<application ...>
+ <meta-data android:name="android.security.net.config"
+ android:resource="@xml/network_security_config" />
+ ...
+</pre>
+</p>
+
+<h3 id="UsesCleartextTraffic">Cleartext Traffic Opt-Out</h3>
+<p>Applications which intend to connect to destinations using only secure connections can opt-out
+of supporting cleartext (i.e. plain HTTP instead of HTTPS) to those destinations. This helps prevent
+accidental regressions in applications due to changes in URLs provided by external sources such as
+backend servers.</p>
+<p>See {a href="{@docRoot}reference/android/security/NetworkSecurityPolicy.html#isCleartextTrafficPermitted()} for more details.</p>
+
+<p>For example, an application may want to ensure that all connections to {@code secure.example.com} are always
+done over HTTPS to protect sensitive traffic from hostile networks.</p>
+
+<p>
+<code>res/xml/network_security_config.xml</code>:
+<pre>
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+ <domain-config usesCleartextTraffic="false">
+ <domain includeSubdomains="true">secure.example.com</domain>
+ </domain-config>
+</network-security-config>
+</pre>
+</p>
+<p>
+In <code>AndroidManifest.xml</code> reference the above config
+<pre>
+<?xml version="1.0" encoding="utf-8"?>
+...
+<application ...>
+ <meta-data android:name="android.security.net.config"
+ android:resource="@xml/network_security_config" />
+ ...
+</pre>
+</p>
+
+<h3 id="CertificatePinning">Certificate Pinning</h3>
+<p>Normally an application trusts all preinstalled CAs. If any of these CAs were to issue a fradulent certificate
+the application would be at risk from a MiTM attack. Some applications choose to limit the set of
+certificates they accept by either limiting the set of CAs they trust or by certificate pinning.</p>
+
+<p>Certificate pinning is done by providing a set of certificates by hash of the public key (SubjectPublicKeyInfo
+of the X.509 certificate). A certificate chain is then only valid if the certificate chain contains at least
+one of the pinned public keys.</p>
+
+<p>Note that when using certificate pinning you should always include a backup key so that if you
+are forced to switch to new keys, or change CAs (when pinning to a CA certificate or an intermediate of that CA),
+your application's connectivity is unaffected. Otherwise you will have to push out an update to the
+application to restore connectivity.</p>
+
+<p>Additionally it is possible to set an expiration time for pins after which pinning will not be
+performed. This helps prevent connectivity issues in applications which have not been updated.
+However, setting an expiration time on pins may enable pinning bypass.
+</p>
+
+<p>
+<code>res/xml/network_security_config.xml</code>:
+<pre>
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+ <domain-config>
+ <domain includeSubdomains="true">example.com</domain>
+ <pin-set expiration="2018-01-01">
+ <pin digest="SHA-256">7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=</pin>
+ <!-- backup pin -->
+ <pin digest="SHA-256">fwza0LRMXouZHRC8Ei+4PyuldPDcf3UKgO/04cDM1oE=</pin>
+ </domain-config>
+</network-security-config>
+</pre>
+</p>
+<p>
+In <code>AndroidManifest.xml</code> reference the above config
+<pre>
+<?xml version="1.0" encoding="utf-8"?>
+...
+<application ...>
+ <meta-data android:name="android.security.net.config"
+ android:resource="@xml/network_security_config" />
+ ...
+</pre>
+</p>
+
+<h3 id="ConfigInheritance">Configuration Inheritance</h3>
+<p>Values not set in a specific config will be inherited.
+This allows more complex configurations while keeping the configuration file readable.</p>
+
+<p>If a value is not set in a specific entry then value from the next more general entry will be used.
+Values not set in a {@code domain-config} will be taken from the parent {@code domain-config}, if nested, or
+from the {@code base-config} if not. Values not set in the {@code base-config} will use
+the platform default values.
+
+<p>For example consider, where all connections to subdomains of {@code example.com}
+must use a custom set of CAs. Additonally cleartext traffic to these domains is permitted
+<em>except</em> when connecting to {@code secure.example.com}. By nesting the configuration
+for {@code secure.example.com} inside the configuration for {@code example.com} the
+{@code trust-anchors} does not need to be duplicated.</p>
+
+<p>
+<code>res/xml/network_security_config.xml</code>:
+<pre>
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+ <domain-config>
+ <domain includeSubdomains="true">example.com</domain>
+ <trust-anchors>
+ <certificates src="@raw/my_ca"/>
+ </trust-anchors>
+ <domain-config cleartextTrafficPermitted="false">
+ <domain includeSubdomains="true">secure.example.com</domain>
+ </domain-config>
+ </domain-config>
+</network-security-config>
+</pre>
+</p>
+<p>
+In <code>AndroidManifest.xml</code> reference the above config
+<pre>
+<?xml version="1.0" encoding="utf-8"?>
+...
+<application ...>
+ <meta-data android:name="android.security.net.config"
+ android:resource="@xml/network_security_config" />
+ ...
+</pre>
+</p>
+
+<h2 id="FileFormat">Configuration File Format</h2>
+<p>The configuration file is XML. Here is what it can contain:</p>
+</p>
+<pre>
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+ <base-config>
+ <trust-anchors>
+ <certificates src="..."/>
+ ...
+ </trust-anchors>
+ </base-config>
+
+ <domain-config>
+ <domain>android.com</domain>
+ ...
+ <trust-anchors>
+ <certificates src="..."/>
+ ...
+ </trust-anchors>
+ <pin-set>
+ <pin digest="...">...</pin>
+ ...
+ </pin-set>
+ </domain-config>
+ ...
+ <debug-overrides>
+ <trust-anchors>
+ <certificates src="..."/>
+ ...
+ </trust-anchors>
+ </debug-overrides>
+</network-security-config>
+</pre>
+
+<h3 id="network-security-config"><network-security-config></h3>
+<dl class="xml">
+<dt>can contain:</dt>
+<dd>0 or 1 <code><a href="#base-config"><base-config></a></code>
+<br/>Any number of <code><a href="#domain-config"><domain-config></a></code>
+<br/>0 or 1<code><a href="#debug-overrides"><debug-overrides></a></code>
+</dd>
+</dl>
+
+
+<h3 id="base-config"><base-config></h3>
+<dl class="xml">
+<dt>syntax:</dt>
+<dd><pre class="stx"><base-config <a href="#usesCleartextTraffic">usesCleartextTraffic</a>=["true" | "false"]>
+ ...
+</base-config></pre></dd>
+<dt>can contain:</dt>
+<dd><code><a href="#trust-anchors"><trust-anchors></a></code></dd>
+<dt>descrption:</dt>
+<dd>
+The default configuration used by all connections whose destination is not covered by a
+<a href="#domain-config"><code>domain-config</code></a>.
+
+<p>Any values that are not set will use the platform default values.
+The default configuration for applications targeting above API level 24 and above:
+<pre>
+<base-config usesCleartextTraffic="true">
+ <trust-anchors>
+ <certificates src="system" />
+ </trust-anchors>
+</base-config>
+</pre>
+The default configuration for applications targeting API level 23 and below is:
+<pre>
+<base-config usesCleartextTraffic="true">
+ <trust-anchors>
+ <certificates src="system" />
+ <certificates src="user" />
+ </trust-anchors>
+</base-config>
+</pre>
+</p>
+</dd>
+</dl>
+
+<h3 id="domain-config"><domain-config></h3>
+<dl class="xml">
+<dt>syntax:</dt>
+<dd><pre class="stx"><domain-config <a href="#usesCleartextTraffic">usesCleartextTraffic</a>=["true" | "false"]>
+ ...
+</domain-config></pre></dd>
+<dt>Can Contain:</dt>
+
+<dd>
+1 or more <code><a href="#domain"><domain></a></code>
+<br/>0 or 1 <code><a href="#trust-anchors"><trust-anchors></a></code>
+<br/>0 or 1 <code><a href="#pin-set"><pin-set></code></a>
+<br/>Any number of nested <code><domain-config></code></dd>
+
+<dt>Descrption</dt>
+<dd>Configuration used for connections to specific destinations as the defined by {@code domain} elements.
+
+<p>Note that if multiple {@code domain-config} elements cover a destination the config with the most specific (longest)
+matching domain rule will be used.</p></dd>
+</dl>
+
+<h3 id="domain"><domain></h3>
+<dl class="xml">
+<dt>syntax:</dt>
+<dd><pre class="stx"><domain includeSubdomains=["true" | "false"]>example.com</domain></pre></dd>
+<dt>Attributes:</dt>
+<dd><dl class="attr">
+<dt>{@code includeSubdomains}</dt>
+<dd>If {@code "true"} then this domain rule will match the domain and all subdomains, including
+subdomains of subdomains, otherwise the rule only applies to exact matches.</dd>
+</dl>
+</dd>
+
+<dt>Descrption:</dt>
+</dl>
+
+<h3 id="debug-overrides"><debug-overrides></h3>
+<dl class="xml">
+<dt>syntax:</dt>
+<dd><pre class="stx"><debug-overrides>
+ ...
+</debug-overrides></pre></dd>
+<dt>Can Contain:</dt>
+<dd>0 or 1 <code><a href="#trust-anchors"><trust-anchors></a></code></dd>
+<dt>Description:</dt>
+<dd>Overrides to be applied when
+<a href="{@docRoot}guide/topics/manifest/application-element.html#debug">android:debuggable</a> is
+{@code "true"} which is normally the case for non-release builds generated by IDEs and build tools.
+Trust anchors specified in {@code debug-overrides} are added to all other configurations and certificate
+pinning is not performed when the server's certificate chain uses one of these debug-only trust anchors.
+If <a href="{@docRoot}guide/topics/manifest/application-element.html#debug">android:debuggable</a> is
+{@code "false"} then this section is completely ignored.
+</dd>
+</dl>
+
+<h3 id="trust-anchors"><trust-anchors></h3>
+<dl class="xml">
+<dt>syntax:</dt>
+<dd>
+<pre class="stx"><trust-anchors>
+...
+</trust-anchors>
+</pre></dd>
+<dt>Can Contain:</dt>
+<dd>Any number of <code><a href="#certificates"><certificates></a></code></dd>
+<dt>Description:</dt>
+<dd>Set of trust anchors for secure connections.</dd>
+</dl>
+
+
+<h3 id="certificates"><certificates></h3>
+<dl class="xml">
+<dt>syntax:</dt>
+<dd><pre class="stx"><certificates src=["system" | "user" | "<i>raw resource</i>"]
+ overridePins=["true" | "false"] />
+</pre></dd>
+<dt>description:</dt>
+<dd>Set of X.509 certificates for {@code trust-anchors} elements.</dd>
+
+<dt>attributes:</dt>
+<dd><dl class="attr">
+<dt>{@code src}</dt>
+<dd>
+The source of CA certificates, can be one of
+<ul>
+ <li>a raw resource id pointing to a file containing X.509 certificates. Certificates must be encoded in DER or PEM format.
+ In the case of PEM certificates the file <em>must not</em> contain extra non-PEM data such as comments.</li>
+ <li>{@code "system"} for the pre-installed system CA certificates</li>
+ <li>{@code "user"} for user-added CA certificates</li>
+</ul>
+</dd>
+
+<dt>{@code overridePins}</dt>
+<dd>
+Specifies if the CAs from this source bypass certificate pinning. If {@code "true"} then certificate chains which
+chain through one of the CAs from this source then pinning will not be performed. This can be useful
+for debug CAs or to support letting the user MiTM your app's secure traffic.
+<p>
+Default is {@code "false"} unless specified in a {@code debug-overrides} element, in which case the default is {@code "true"}.
+</p>
+</dd>
+</dl>
+</dd>
+
+<h3 id="pin-set"><pin-set></h3>
+<dl class="xml">
+<dt>syntax:</dt>
+<dd>
+<pre class="stx"><pin-set expiration="date">
+...
+</pin-set>
+</pre></dd>
+<dt>Can Contain:</dt>
+<dd>Any number of <code><a href="#pin"><pin></a></code></dd>
+<dt>Description:</dt>
+<dd>A set of public key pins. For a secure connection to be trusted, one of the public keys in the chain of trust must
+be in the set of pins. See <code><a href="#pin"><pin></a></code> for the format of pins.</dd>
+<dt>Attributes:</dt>
+<dd><dl class="attr">
+<dt>{@code expiration}</dt>
+<dd>The date, in {@code yyyy-MM-dd} format, at and after which the pins expire, thus disabling pinning.
+If the attribute is not set then the pins do not expire.
+<p>Expiration helps prevent connectivity issues in applications which do not get updates to their
+pin set, for example because the user disabled application updates.</p>
+</dd>
+</dl>
+</dd>
+
+<h3 id="pin"><pin></h3>
+<dl class="xml">
+<dt>syntax:</dt>
+<dd>
+<pre class="stx"><pin digest=["SHA-256"]>base64 encoded digest of X.509 SubjectPublicKeyInfo (SPKI)</pin></pre></dd>
+<dt>Attributes:</dt>
+<dd><dl class="attr">
+<dt>{@code digest}</dt>
+<dd>The digest algorithm used to generate the pin. Currently only {@code "SHA-256"} is supported.</dd>
+</dl>
+</dd>
+</dl>
diff --git a/docs/html/guide/topics/sensors/sensors_overview.jd b/docs/html/guide/topics/sensors/sensors_overview.jd
index 0b3cb2b..53faca0 100644
--- a/docs/html/guide/topics/sensors/sensors_overview.jd
+++ b/docs/html/guide/topics/sensors/sensors_overview.jd
@@ -465,6 +465,7 @@
...
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
+mSensor = null;
if (mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null){
List<Sensor> gravSensors = mSensorManager.getSensorList(Sensor.TYPE_GRAVITY);
@@ -476,7 +477,7 @@
}
}
}
-else{
+if (mSensor == null){
// Use the accelerometer.
if (mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null){
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
diff --git a/docs/html/preview/behavior-changes.jd b/docs/html/preview/behavior-changes.jd
index cab4163..264e741 100644
--- a/docs/html/preview/behavior-changes.jd
+++ b/docs/html/preview/behavior-changes.jd
@@ -393,7 +393,7 @@
only affects notifications generated by applications in the managed profile.</li>
</ul>
</li>
- <li>The {@link android.app.admin.DevicePolicyManager#createAndInitializeUser(android.content.ComponentName, java.lang.String, java.lang.String, android.content.ComponentName, android.os.Bundle) createAndInitializeUser()} and {@link android.app.admin.DevicePolicyManager#createUser(android.content.ComponentName, java.lang.String) createUser()} methods have been deprecated.</li>
+ <li>The {@link android.app.admin.DevicePolicyManager#createAndManageUser(android.content.ComponentName, java.lang.String, android.content.ComponentName, android.os.PersistableBundle, int) createAndManageUser()} method replaces createAndInitializeUser(), which has been removed.</li>
<li>The {@link android.app.admin.DevicePolicyManager#setScreenCaptureDisabled(android.content.ComponentName, boolean) setScreenCaptureDisabled()}
method now also blocks the assist structure when an app of the given user is in the foreground. </li>
<li>{@link android.app.admin.DevicePolicyManager#EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM}
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index d4f745d..af99f79 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -91,8 +91,11 @@
// a Canvas object.
private static final long NATIVE_ALLOCATION_SIZE = 525;
- private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
- getNativeFinalizer(), NATIVE_ALLOCATION_SIZE);
+ // Use a Holder to allow static initialization of Canvas in the boot image.
+ private static class NoImagePreloadHolder {
+ public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
+ getNativeFinalizer(), NATIVE_ALLOCATION_SIZE);
+ }
// This field is used to finalize the native Canvas properly
private Runnable mFinalizer;
@@ -107,7 +110,8 @@
if (!isHardwareAccelerated()) {
// 0 means no native bitmap
mNativeCanvasWrapper = initRaster(null);
- mFinalizer = sRegistry.registerNativeAllocation(this, mNativeCanvasWrapper);
+ mFinalizer = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
+ this, mNativeCanvasWrapper);
} else {
mFinalizer = null;
}
@@ -128,7 +132,8 @@
}
throwIfCannotDraw(bitmap);
mNativeCanvasWrapper = initRaster(bitmap);
- mFinalizer = sRegistry.registerNativeAllocation(this, mNativeCanvasWrapper);
+ mFinalizer = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
+ this, mNativeCanvasWrapper);
mBitmap = bitmap;
mDensity = bitmap.mDensity;
}
@@ -139,7 +144,8 @@
throw new IllegalStateException();
}
mNativeCanvasWrapper = nativeCanvas;
- mFinalizer = sRegistry.registerNativeAllocation(this, mNativeCanvasWrapper);
+ mFinalizer = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
+ this, mNativeCanvasWrapper);
mDensity = Bitmap.getDefaultDensity();
}
diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java
index aa40408..99fa9fe 100644
--- a/graphics/java/android/graphics/Outline.java
+++ b/graphics/java/android/graphics/Outline.java
@@ -18,6 +18,7 @@
import android.annotation.FloatRange;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.graphics.drawable.Drawable;
/**
@@ -176,6 +177,34 @@
}
/**
+ * Populates {@code outBounds} with the outline bounds, if set, and returns
+ * {@code true}. If no outline bounds are set, or if a path has been set
+ * via {@link #setConvexPath(Path)}, returns {@code false}.
+ *
+ * @param outRect the rect to populate with the outline bounds, if set
+ * @return {@code true} if {@code outBounds} was populated with outline
+ * bounds, or {@code false} if no outline bounds are set
+ */
+ public boolean getRect(@NonNull Rect outRect) {
+ if (mRect == null) {
+ return false;
+ }
+ outRect.set(mRect);
+ return true;
+ }
+
+ /**
+ * Returns the rounded rect radius, if set, or {@code -1} if a path has
+ * been set via {@link #setConvexPath(Path)}. A return value of {@code 0}
+ * indicates a non-rounded rect.
+ *
+ * @return the rounded rect radius or {@code -1}
+ */
+ public float getRadius() {
+ return mRadius;
+ }
+
+ /**
* Sets the outline to the oval defined by input rect.
*/
public void setOval(int left, int top, int right, int bottom) {
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 534121a..291fdc4 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -44,8 +44,11 @@
// The approximate size of a native paint object.
private static final long NATIVE_PAINT_SIZE = 98;
- private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
- nGetNativeFinalizer(), NATIVE_PAINT_SIZE);
+ // Use a Holder to allow static initialization of Paint in the boot image.
+ private static class NoImagePreloadHolder {
+ public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
+ nGetNativeFinalizer(), NATIVE_PAINT_SIZE);
+ }
/**
* @hide
@@ -452,7 +455,7 @@
*/
public Paint(int flags) {
mNativePaint = nInit();
- sRegistry.registerNativeAllocation(this, mNativePaint);
+ NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativePaint);
setFlags(flags | HIDDEN_DEFAULT_PAINT_FLAGS);
// TODO: Turning off hinting has undesirable side effects, we need to
// revisit hinting once we add support for subpixel positioning
@@ -471,7 +474,7 @@
*/
public Paint(Paint paint) {
mNativePaint = nInitWithPaint(paint.getNativeInstance());
- sRegistry.registerNativeAllocation(this, mNativePaint);
+ NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativePaint);
setClassVariablesFrom(paint);
}
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index af8ccf5..ca214ab 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -40,6 +40,7 @@
import android.os.Build;
import android.util.ArrayMap;
import android.util.AttributeSet;
+import android.util.IntArray;
import android.util.Log;
import android.util.LongArray;
import android.util.PathParser;
@@ -154,7 +155,7 @@
private static final boolean DBG_ANIMATION_VECTOR_DRAWABLE = false;
/** Local, mutable animator set. */
- private final VectorDrawableAnimator mAnimatorSet = new VectorDrawableAnimator();
+ private VectorDrawableAnimator mAnimatorSet = new VectorDrawableAnimatorRT(this);
/**
* The resources against which this drawable was created. Used to attempt
@@ -164,8 +165,8 @@
private AnimatedVectorDrawableState mAnimatedVectorState;
- /** Whether the animator set has been prepared. */
- private boolean mHasAnimatorSet;
+ /** The animator set that is parsed from the xml. */
+ private AnimatorSet mAnimatorSetFromXml = null;
private boolean mMutated;
@@ -234,13 +235,8 @@
@Override
public void draw(Canvas canvas) {
- if (canvas.isHardwareAccelerated()) {
- mAnimatorSet.recordLastSeenTarget((DisplayListCanvas) canvas);
- }
+ mAnimatorSet.onDraw(canvas);
mAnimatedVectorState.mVectorDrawable.draw(canvas);
- if (isStarted()) {
- invalidateSelf();
- }
}
@Override
@@ -395,6 +391,24 @@
mRes = state.mPendingAnims == null ? null : res;
}
+ /**
+ * Force to animate on UI thread.
+ * @hide
+ */
+ public void forceAnimationOnUI() {
+ if (mAnimatorSet instanceof VectorDrawableAnimatorRT) {
+ VectorDrawableAnimatorRT animator = (VectorDrawableAnimatorRT) mAnimatorSet;
+ if (animator.isRunning()) {
+ throw new UnsupportedOperationException("Cannot force Animated Vector Drawable to" +
+ " run on UI thread when the animation has started on RenderThread.");
+ }
+ mAnimatorSet = new VectorDrawableAnimatorUI(this);
+ if (mAnimatorSetFromXml != null) {
+ mAnimatorSet.init(mAnimatorSetFromXml);
+ }
+ }
+ }
+
@Override
public boolean canApplyTheme() {
return (mAnimatedVectorState != null && mAnimatedVectorState.canApplyTheme())
@@ -611,46 +625,52 @@
return mAnimatorSet.isRunning();
}
- private boolean isStarted() {
- return mAnimatorSet.isStarted();
- }
-
/**
* Resets the AnimatedVectorDrawable to the start state as specified in the animators.
*/
public void reset() {
+ ensureAnimatorSet();
+ if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+ Log.w(LOGTAG, "calling reset on AVD: " +
+ ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState)
+ getConstantState()).mVectorDrawable.getConstantState()).mRootName
+ + ", at: " + this);
+ }
mAnimatorSet.reset();
- invalidateSelf();
}
@Override
public void start() {
ensureAnimatorSet();
-
- // If any one of the animator has not ended, do nothing.
- if (isStarted()) {
- return;
+ if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+ Log.w(LOGTAG, "calling start on AVD: " +
+ ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState)
+ getConstantState()).mVectorDrawable.getConstantState()).mRootName
+ + ", at: " + this);
}
-
mAnimatorSet.start();
- invalidateSelf();
}
@NonNull
private void ensureAnimatorSet() {
- if (!mHasAnimatorSet) {
+ if (mAnimatorSetFromXml == null) {
// TODO: Skip the AnimatorSet creation and init the VectorDrawableAnimator directly
// with a list of LocalAnimators.
- AnimatorSet set = new AnimatorSet();
- mAnimatedVectorState.prepareLocalAnimators(set, mRes);
- mHasAnimatorSet = true;
- mAnimatorSet.initWithAnimatorSet(set);
+ mAnimatorSetFromXml = new AnimatorSet();
+ mAnimatedVectorState.prepareLocalAnimators(mAnimatorSetFromXml, mRes);
+ mAnimatorSet.init(mAnimatorSetFromXml);
mRes = null;
}
}
@Override
public void stop() {
+ if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+ Log.w(LOGTAG, "calling stop on AVD: " +
+ ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState)
+ getConstantState()).mVectorDrawable.getConstantState())
+ .mRootName + ", at: " + this);
+ }
mAnimatorSet.end();
}
@@ -671,7 +691,6 @@
}
mAnimatorSet.reverse();
- invalidateSelf();
}
/**
@@ -740,7 +759,7 @@
// A helper function to clean up the animator listener in the mAnimatorSet.
private void removeAnimatorSetListener() {
if (mAnimatorListener != null) {
- mAnimatorSet.removeListener();
+ mAnimatorSet.removeListener(mAnimatorListener);
mAnimatorListener = null;
}
}
@@ -770,10 +789,104 @@
mAnimationCallbacks.clear();
}
+ private interface VectorDrawableAnimator {
+ void init(AnimatorSet set);
+ void start();
+ void end();
+ void reset();
+ void reverse();
+ boolean canReverse();
+ void setListener(AnimatorListener listener);
+ void removeListener(AnimatorListener listener);
+ void onDraw(Canvas canvas);
+ boolean isStarted();
+ boolean isRunning();
+ }
+
+ private static class VectorDrawableAnimatorUI implements VectorDrawableAnimator {
+ private AnimatorSet mSet = new AnimatorSet();
+ private final Drawable mDrawable;
+
+ VectorDrawableAnimatorUI(AnimatedVectorDrawable drawable) {
+ mDrawable = drawable;
+ }
+
+ @Override
+ public void init(AnimatorSet set) {
+ mSet = set;
+ }
+
+ @Override
+ public void start() {
+ if (mSet.isStarted()) {
+ return;
+ }
+ mSet.start();
+ invalidateOwningView();
+ }
+
+ @Override
+ public void end() {
+ mSet.end();
+ }
+
+ @Override
+ public void reset() {
+ start();
+ mSet.cancel();
+ }
+
+ @Override
+ public void reverse() {
+ mSet.reverse();
+ invalidateOwningView();
+ }
+
+ @Override
+ public boolean canReverse() {
+ return mSet.canReverse();
+ }
+
+ @Override
+ public void setListener(AnimatorListener listener) {
+ mSet.addListener(listener);
+ }
+
+ @Override
+ public void removeListener(AnimatorListener listener) {
+ mSet.removeListener(listener);
+ }
+
+ @Override
+ public void onDraw(Canvas canvas) {
+ if (mSet.isStarted()) {
+ invalidateOwningView();
+ }
+ }
+
+ @Override
+ public boolean isStarted() {
+ return mSet.isStarted();
+ }
+
+ @Override
+ public boolean isRunning() {
+ return mSet.isRunning();
+ }
+
+ private void invalidateOwningView() {
+ mDrawable.invalidateSelf();
+ }
+ }
+
/**
* @hide
*/
- public static class VectorDrawableAnimator {
+ public static class VectorDrawableAnimatorRT implements VectorDrawableAnimator {
+ private static final int START_ANIMATION = 1;
+ private static final int REVERSE_ANIMATION = 2;
+ private static final int RESET_ANIMATION = 3;
+ private static final int END_ANIMATION = 4;
private AnimatorListener mListener = null;
private final LongArray mStartDelays = new LongArray();
private PropertyValuesHolder.PropertyValues mTmpValues =
@@ -782,24 +895,26 @@
private boolean mContainsSequentialAnimators = false;
private boolean mStarted = false;
private boolean mInitialized = false;
- private boolean mAnimationPending = false;
private boolean mIsReversible = false;
// This needs to be set before parsing starts.
private boolean mShouldIgnoreInvalidAnim;
// TODO: Consider using NativeAllocationRegistery to track native allocation
private final VirtualRefBasePtr mSetRefBasePtr;
- private WeakReference<RenderNode> mTarget = null;
private WeakReference<RenderNode> mLastSeenTarget = null;
+ private int mLastListenerId = 0;
+ private final IntArray mPendingAnimationActions = new IntArray();
+ private final Drawable mDrawable;
-
- VectorDrawableAnimator() {
+ VectorDrawableAnimatorRT(AnimatedVectorDrawable drawable) {
+ mDrawable = drawable;
mSetPtr = nCreateAnimatorSet();
// Increment ref count on native AnimatorSet, so it doesn't get released before Java
// side is done using it.
mSetRefBasePtr = new VirtualRefBasePtr(mSetPtr);
}
- private void initWithAnimatorSet(AnimatorSet set) {
+ @Override
+ public void init(AnimatorSet set) {
if (mInitialized) {
// Already initialized
throw new UnsupportedOperationException("VectorDrawableAnimator cannot be " +
@@ -810,6 +925,7 @@
mInitialized = true;
// Check reversible.
+ mIsReversible = true;
if (mContainsSequentialAnimators) {
mIsReversible = false;
} else {
@@ -821,14 +937,13 @@
}
}
}
- mIsReversible = true;
}
private void parseAnimatorSet(AnimatorSet set, long startTime) {
ArrayList<Animator> animators = set.getChildAnimations();
boolean playTogether = set.shouldPlayTogether();
- // Convert AnimatorSet to VectorDrawableAnimator
+ // Convert AnimatorSet to VectorDrawableAnimatorRT
for (int i = 0; i < animators.size(); i++) {
Animator animator = animators.get(i);
// Here we only support ObjectAnimator
@@ -1042,133 +1157,213 @@
* to the last seen RenderNode target and start right away.
*/
protected void recordLastSeenTarget(DisplayListCanvas canvas) {
- if (mAnimationPending) {
- mLastSeenTarget = new WeakReference<RenderNode>(
- RenderNodeAnimatorSetHelper.getTarget(canvas));
+ mLastSeenTarget = new WeakReference<RenderNode>(
+ RenderNodeAnimatorSetHelper.getTarget(canvas));
+ if (mPendingAnimationActions.size() > 0 && useLastSeenTarget()) {
if (DBG_ANIMATION_VECTOR_DRAWABLE) {
Log.d(LOGTAG, "Target is set in the next frame");
}
- mAnimationPending = false;
- start();
- } else {
- mLastSeenTarget = new WeakReference<RenderNode>(
- RenderNodeAnimatorSetHelper.getTarget(canvas));
+ for (int i = 0; i < mPendingAnimationActions.size(); i++) {
+ handlePendingAction(mPendingAnimationActions.get(i));
+ }
+ mPendingAnimationActions.clear();
}
-
}
- private boolean setTarget(RenderNode node) {
- if (mTarget != null && mTarget.get() != null) {
- // TODO: Maybe we want to support target change.
- throw new IllegalStateException("Target already set!");
+ private void handlePendingAction(int pendingAnimationAction) {
+ if (pendingAnimationAction == START_ANIMATION) {
+ startAnimation();
+ } else if (pendingAnimationAction == REVERSE_ANIMATION) {
+ reverseAnimation();
+ } else if (pendingAnimationAction == RESET_ANIMATION) {
+ resetAnimation();
+ } else if (pendingAnimationAction == END_ANIMATION) {
+ endAnimation();
+ } else {
+ throw new UnsupportedOperationException("Animation action " +
+ pendingAnimationAction + "is not supported");
}
-
- node.addAnimator(this);
- mTarget = new WeakReference<RenderNode>(node);
- return true;
}
private boolean useLastSeenTarget() {
- if (mLastSeenTarget != null && mLastSeenTarget.get() != null) {
- setTarget(mLastSeenTarget.get());
- return true;
+ if (mLastSeenTarget != null) {
+ final RenderNode target = mLastSeenTarget.get();
+ if (target != null && target.isAttached()) {
+ target.addAnimator(this);
+ return true;
+ }
}
return false;
}
+ private void invalidateOwningView() {
+ mDrawable.invalidateSelf();
+ }
+
+ private void addPendingAction(int pendingAnimationAction) {
+ invalidateOwningView();
+ mPendingAnimationActions.add(pendingAnimationAction);
+ }
+
+ @Override
public void start() {
if (!mInitialized) {
return;
}
- if (mStarted) {
- return;
+ if (useLastSeenTarget()) {
+ if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+ Log.d(LOGTAG, "Target is set. Starting VDAnimatorSet from java");
+ }
+ startAnimation();
+ } else {
+ addPendingAction(START_ANIMATION);
}
- if (!useLastSeenTarget()) {
- mAnimationPending = true;
- return;
- }
-
- if (DBG_ANIMATION_VECTOR_DRAWABLE) {
- Log.d(LOGTAG, "Target is set. Starting VDAnimatorSet from java");
- }
-
- nStart(mSetPtr, this);
- if (mListener != null) {
- mListener.onAnimationStart(null);
- }
- mStarted = true;
}
+ @Override
public void end() {
- if (mInitialized && mStarted) {
- nEnd(mSetPtr);
- onAnimationEnd();
- }
- }
-
- void reset() {
if (!mInitialized) {
return;
}
- // TODO: Need to implement reset.
- Log.w(LOGTAG, "Reset is yet to be implemented");
- nReset(mSetPtr);
+
+ if (useLastSeenTarget()) {
+ endAnimation();
+ } else {
+ addPendingAction(END_ANIMATION);
+ }
+ }
+
+ @Override
+ public void reset() {
+ if (!mInitialized) {
+ return;
+ }
+
+ if (useLastSeenTarget()) {
+ resetAnimation();
+ } else {
+ addPendingAction(RESET_ANIMATION);
+ }
}
// Current (imperfect) Java AnimatorSet cannot be reversed when the set contains sequential
// animators or when the animator set has a start delay
- void reverse() {
- if (!mIsReversible) {
+ @Override
+ public void reverse() {
+ if (!mIsReversible || !mInitialized) {
return;
}
- // TODO: Need to support reverse (non-public API)
- Log.w(LOGTAG, "Reverse is yet to be implemented");
- nReverse(mSetPtr, this);
+ if (useLastSeenTarget()) {
+ if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+ Log.d(LOGTAG, "Target is set. Reversing VDAnimatorSet from java");
+ }
+ reverseAnimation();
+ } else {
+ addPendingAction(REVERSE_ANIMATION);
+ }
+ }
+
+ // This should only be called after animator has been added to the RenderNode target.
+ private void startAnimation() {
+ if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+ Log.w(LOGTAG, "starting animation on VD: " +
+ ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState)
+ mDrawable.getConstantState()).mVectorDrawable.getConstantState())
+ .mRootName);
+ }
+ mStarted = true;
+ nStart(mSetPtr, this, ++mLastListenerId);
+ invalidateOwningView();
+ if (mListener != null) {
+ mListener.onAnimationStart(null);
+ }
+ }
+
+ // This should only be called after animator has been added to the RenderNode target.
+ private void endAnimation() {
+ if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+ Log.w(LOGTAG, "ending animation on VD: " +
+ ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState)
+ mDrawable.getConstantState()).mVectorDrawable.getConstantState())
+ .mRootName);
+ }
+ nEnd(mSetPtr);
+ invalidateOwningView();
+ }
+
+ // This should only be called after animator has been added to the RenderNode target.
+ private void resetAnimation() {
+ nReset(mSetPtr);
+ invalidateOwningView();
+ }
+
+ // This should only be called after animator has been added to the RenderNode target.
+ private void reverseAnimation() {
+ mStarted = true;
+ nReverse(mSetPtr, this, ++mLastListenerId);
+ invalidateOwningView();
+ if (mListener != null) {
+ mListener.onAnimationStart(null);
+ }
}
public long getAnimatorNativePtr() {
return mSetPtr;
}
- boolean canReverse() {
+ @Override
+ public boolean canReverse() {
return mIsReversible;
}
- boolean isStarted() {
+ @Override
+ public boolean isStarted() {
return mStarted;
}
- boolean isRunning() {
+ @Override
+ public boolean isRunning() {
if (!mInitialized) {
return false;
}
return mStarted;
}
- void setListener(AnimatorListener listener) {
+ @Override
+ public void setListener(AnimatorListener listener) {
mListener = listener;
}
- void removeListener() {
+ @Override
+ public void removeListener(AnimatorListener listener) {
mListener = null;
}
- private void onAnimationEnd() {
+ @Override
+ public void onDraw(Canvas canvas) {
+ if (canvas.isHardwareAccelerated()) {
+ recordLastSeenTarget((DisplayListCanvas) canvas);
+ }
+ }
+
+ private void onAnimationEnd(int listenerId) {
+ if (listenerId != mLastListenerId) {
+ return;
+ }
+ if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+ Log.d(LOGTAG, "on finished called from native");
+ }
mStarted = false;
if (mListener != null) {
mListener.onAnimationEnd(null);
}
- mTarget = null;
}
// onFinished: should be called from native
- private static void callOnFinished(VectorDrawableAnimator set) {
- if (DBG_ANIMATION_VECTOR_DRAWABLE) {
- Log.d(LOGTAG, "on finished called from native");
- }
- set.onAnimationEnd();
+ private static void callOnFinished(VectorDrawableAnimatorRT set, int id) {
+ set.onAnimationEnd(id);
}
}
@@ -1188,8 +1383,8 @@
private static native long nCreateRootAlphaPropertyHolder(long nativePtr, float startValue,
float endValue);
private static native void nSetPropertyHolderData(long nativePtr, float[] data, int length);
- private static native void nStart(long animatorSetPtr, VectorDrawableAnimator set);
- private static native void nReverse(long animatorSetPtr, VectorDrawableAnimator set);
+ private static native void nStart(long animatorSetPtr, VectorDrawableAnimatorRT set, int id);
+ private static native void nReverse(long animatorSetPtr, VectorDrawableAnimatorRT set, int id);
private static native void nEnd(long animatorSetPtr);
private static native void nReset(long animatorSetPtr);
}
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index d05c66a..3b0e7e8 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -898,19 +898,19 @@
* @param res the resources used to inflate density-dependent values
*/
final void updateDensity(Resources res) {
- if (mSourceRes != null) {
+ if (res != null) {
mSourceRes = res;
- }
- // The density may have changed since the last update (if any). Any
- // dimension-type attributes will need their default values scaled.
- final int targetDensity = Drawable.resolveDensity(res, mDensity);
- final int sourceDensity = mDensity;
- mDensity = targetDensity;
+ // The density may have changed since the last update (if any). Any
+ // dimension-type attributes will need their default values scaled.
+ final int targetDensity = Drawable.resolveDensity(res, mDensity);
+ final int sourceDensity = mDensity;
+ mDensity = targetDensity;
- if (sourceDensity != targetDensity) {
- mCheckedConstantSize = false;
- mCheckedPadding = false;
+ if (sourceDensity != targetDensity) {
+ mCheckedConstantSize = false;
+ mCheckedPadding = false;
+ }
}
}
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index bfbdfa5..6816539 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -66,11 +66,16 @@
public class NinePatchDrawable extends Drawable {
// dithering helps a lot, and is pretty cheap, so default is true
private static final boolean DEFAULT_DITHER = false;
+
+ /** Temporary rect used for density scaling. */
+ private Rect mTempRect;
+
private NinePatchState mNinePatchState;
- private NinePatch mNinePatch;
private PorterDuffColorFilter mTintFilter;
private Rect mPadding;
private Insets mOpticalInsets = Insets.NONE;
+ private Rect mOutlineInsets;
+ private float mOutlineRadius;
private Paint mPaint;
private boolean mMutated;
@@ -86,8 +91,9 @@
/**
* Create drawable from raw nine-patch data, not dealing with density.
+ *
* @deprecated Use {@link #NinePatchDrawable(Resources, Bitmap, byte[], Rect, String)}
- * to ensure that the drawable has correctly set its target density.
+ * to ensure that the drawable has correctly set its target density.
*/
@Deprecated
public NinePatchDrawable(Bitmap bitmap, byte[] chunk, Rect padding, String srcName) {
@@ -101,7 +107,6 @@
public NinePatchDrawable(Resources res, Bitmap bitmap, byte[] chunk,
Rect padding, String srcName) {
this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding), res);
- mNinePatchState.mTargetDensity = mTargetDensity;
}
/**
@@ -114,16 +119,17 @@
Rect padding, Rect opticalInsets, String srcName) {
this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding, opticalInsets),
res);
- mNinePatchState.mTargetDensity = mTargetDensity;
}
/**
* Create drawable from existing nine-patch, not dealing with density.
+ *
* @deprecated Use {@link #NinePatchDrawable(Resources, NinePatch)}
- * to ensure that the drawable has correctly set its target density.
+ * to ensure that the drawable has correctly set its target
+ * density.
*/
@Deprecated
- public NinePatchDrawable(NinePatch patch) {
+ public NinePatchDrawable(@NonNull NinePatch patch) {
this(new NinePatchState(patch, new Rect()), null);
}
@@ -131,9 +137,8 @@
* Create drawable from existing nine-patch, setting initial target density
* based on the display metrics of the resources.
*/
- public NinePatchDrawable(Resources res, NinePatch patch) {
+ public NinePatchDrawable(@Nullable Resources res, @NonNull NinePatch patch) {
this(new NinePatchState(patch, new Rect()), res);
- mNinePatchState.mTargetDensity = mTargetDensity;
}
/**
@@ -146,7 +151,7 @@
* @see android.graphics.Bitmap#setDensity(int)
* @see android.graphics.Bitmap#getDensity()
*/
- public void setTargetDensity(Canvas canvas) {
+ public void setTargetDensity(@NonNull Canvas canvas) {
setTargetDensity(canvas.getDensity());
}
@@ -158,7 +163,7 @@
* @see android.graphics.Bitmap#setDensity(int)
* @see android.graphics.Bitmap#getDensity()
*/
- public void setTargetDensity(DisplayMetrics metrics) {
+ public void setTargetDensity(@NonNull DisplayMetrics metrics) {
setTargetDensity(metrics.densityDpi);
}
@@ -171,78 +176,24 @@
* @see android.graphics.Bitmap#getDensity()
*/
public void setTargetDensity(int density) {
- if (density != mTargetDensity) {
- mTargetDensity = density == 0 ? DisplayMetrics.DENSITY_DEFAULT : density;
- if (mNinePatch != null) {
- computeBitmapSize();
- }
+ if (density == 0) {
+ density = DisplayMetrics.DENSITY_DEFAULT;
+ }
+
+ if (mTargetDensity != density) {
+ mTargetDensity = density;
+
+ computeBitmapSize();
invalidateSelf();
}
}
- private static Insets scaleFromDensity(Insets insets, int sdensity, int tdensity) {
- int left = Drawable.scaleFromDensity(insets.left, sdensity, tdensity, true);
- int top = Drawable.scaleFromDensity(insets.top, sdensity, tdensity, true);
- int right = Drawable.scaleFromDensity(insets.right, sdensity, tdensity, true);
- int bottom = Drawable.scaleFromDensity(insets.bottom, sdensity, tdensity, true);
- return Insets.of(left, top, right, bottom);
- }
-
- private void computeBitmapSize() {
- final int sdensity = mNinePatch.getDensity();
- final int tdensity = mTargetDensity;
- if (sdensity == tdensity) {
- mBitmapWidth = mNinePatch.getWidth();
- mBitmapHeight = mNinePatch.getHeight();
- mOpticalInsets = mNinePatchState.mOpticalInsets;
- } else {
- mBitmapWidth = Drawable.scaleFromDensity(
- mNinePatch.getWidth(), sdensity, tdensity, true);
- mBitmapHeight = Drawable.scaleFromDensity(
- mNinePatch.getHeight(), sdensity, tdensity, true);
- if (mNinePatchState.mPadding != null && mPadding != null) {
- Rect dest = mPadding;
- Rect src = mNinePatchState.mPadding;
- if (dest == src) {
- mPadding = dest = new Rect(src);
- }
- dest.left = Drawable.scaleFromDensity(src.left, sdensity, tdensity, true);
- dest.top = Drawable.scaleFromDensity(src.top, sdensity, tdensity, true);
- dest.right = Drawable.scaleFromDensity(src.right, sdensity, tdensity, true);
- dest.bottom = Drawable.scaleFromDensity(src.bottom, sdensity, tdensity, true);
- }
- mOpticalInsets = scaleFromDensity(mNinePatchState.mOpticalInsets, sdensity, tdensity);
- }
- }
-
- /**
- * Sets the nine patch used by this drawable.
- *
- * @param ninePatch the nine patch for this drawable
- */
- public void setNinePatch(NinePatch ninePatch) {
- if (mNinePatch != ninePatch) {
- mNinePatch = ninePatch;
- if (ninePatch != null) {
- computeBitmapSize();
- } else {
- mBitmapWidth = mBitmapHeight = -1;
- mOpticalInsets = Insets.NONE;
- }
- invalidateSelf();
- }
- }
-
- /**
- * @return the nine patch used by this drawable
- */
- public NinePatch getNinePatch() {
- return mNinePatch;
- }
-
@Override
public void draw(Canvas canvas) {
- final Rect bounds = getBounds();
+ final NinePatchState state = mNinePatchState;
+
+ Rect bounds = getBounds();
+ int restoreToCount = -1;
final boolean clearColorFilter;
if (mTintFilter != null && getPaint().getColorFilter() == null) {
@@ -252,22 +203,52 @@
clearColorFilter = false;
}
- final boolean needsMirroring = needsMirroring();
- if (needsMirroring) {
- // Mirror the 9patch
- canvas.translate(bounds.right - bounds.left, 0);
- canvas.scale(-1.0f, 1.0f);
- }
-
final int restoreAlpha;
- if (mNinePatchState.mBaseAlpha != 1.0f) {
- restoreAlpha = mPaint.getAlpha();
- mPaint.setAlpha((int) (restoreAlpha * mNinePatchState.mBaseAlpha + 0.5f));
+ if (state.mBaseAlpha != 1.0f) {
+ restoreAlpha = getPaint().getAlpha();
+ mPaint.setAlpha((int) (restoreAlpha * state.mBaseAlpha + 0.5f));
} else {
restoreAlpha = -1;
}
- mNinePatch.draw(canvas, bounds, mPaint);
+ final boolean needsDensityScaling = canvas.getDensity() == 0;
+ if (needsDensityScaling) {
+ restoreToCount = restoreToCount >= 0 ? restoreToCount : canvas.save();
+
+ // Apply density scaling.
+ final float scale = mTargetDensity / (float) state.mNinePatch.getDensity();
+ final float px = bounds.left;
+ final float py = bounds.top;
+ canvas.scale(scale, scale, px, py);
+
+ if (mTempRect == null) {
+ mTempRect = new Rect();
+ }
+
+ // Scale the bounds to match.
+ final Rect scaledBounds = mTempRect;
+ scaledBounds.left = bounds.left;
+ scaledBounds.top = bounds.top;
+ scaledBounds.right = bounds.left + Math.round(bounds.width() / scale);
+ scaledBounds.bottom = bounds.top + Math.round(bounds.height() / scale);
+ bounds = scaledBounds;
+ }
+
+ final boolean needsMirroring = needsMirroring();
+ if (needsMirroring) {
+ restoreToCount = restoreToCount >= 0 ? restoreToCount : canvas.save();
+
+ // Mirror the 9patch.
+ final float cx = (bounds.left + bounds.right) / 2.0f;
+ final float cy = (bounds.top + bounds.bottom) / 2.0f;
+ canvas.scale(-1.0f, 1.0f, cx, cy);
+ }
+
+ state.mNinePatch.draw(canvas, bounds, mPaint);
+
+ if (restoreToCount >= 0) {
+ canvas.restoreToCount(restoreToCount);
+ }
if (clearColorFilter) {
mPaint.setColorFilter(null);
@@ -284,38 +265,36 @@
}
@Override
- public boolean getPadding(Rect padding) {
- final Rect scaledPadding = mPadding;
- if (scaledPadding != null) {
- if (needsMirroring()) {
- padding.set(scaledPadding.right, scaledPadding.top,
- scaledPadding.left, scaledPadding.bottom);
- } else {
- padding.set(scaledPadding);
- }
+ public boolean getPadding(@NonNull Rect padding) {
+ if (mPadding != null) {
+ padding.set(mPadding);
return (padding.left | padding.top | padding.right | padding.bottom) != 0;
+ } else {
+ return super.getPadding(padding);
}
- return false;
}
@Override
public void getOutline(@NonNull Outline outline) {
final Rect bounds = getBounds();
- if (bounds.isEmpty()) return;
+ if (bounds.isEmpty()) {
+ return;
+ }
- if (mNinePatchState != null) {
- NinePatch.InsetStruct insets = mNinePatchState.mNinePatch.getBitmap().getNinePatchInsets();
+ if (mNinePatchState != null && mOutlineInsets != null) {
+ final NinePatch.InsetStruct insets =
+ mNinePatchState.mNinePatch.getBitmap().getNinePatchInsets();
if (insets != null) {
- final Rect outlineInsets = insets.outlineRect;
- outline.setRoundRect(bounds.left + outlineInsets.left,
- bounds.top + outlineInsets.top,
- bounds.right - outlineInsets.right,
- bounds.bottom - outlineInsets.bottom,
- insets.outlineRadius);
+ outline.setRoundRect(bounds.left + mOutlineInsets.left,
+ bounds.top + mOutlineInsets.top,
+ bounds.right - mOutlineInsets.right,
+ bounds.bottom - mOutlineInsets.bottom,
+ mOutlineRadius);
outline.setAlpha(insets.outlineAlpha * (getAlpha() / 255.0f));
return;
}
}
+
super.getOutline(outline);
}
@@ -324,11 +303,12 @@
*/
@Override
public Insets getOpticalInsets() {
+ final Insets opticalInsets = mOpticalInsets;
if (needsMirroring()) {
- return Insets.of(mOpticalInsets.right, mOpticalInsets.top,
- mOpticalInsets.left, mOpticalInsets.bottom);
+ return Insets.of(opticalInsets.right, opticalInsets.top,
+ opticalInsets.left, opticalInsets.bottom);
} else {
- return mOpticalInsets;
+ return opticalInsets;
}
}
@@ -352,7 +332,7 @@
}
@Override
- public void setColorFilter(ColorFilter colorFilter) {
+ public void setColorFilter(@Nullable ColorFilter colorFilter) {
if (mPaint == null && colorFilter == null) {
// Fast common case -- leave at no color filter.
return;
@@ -362,14 +342,14 @@
}
@Override
- public void setTintList(ColorStateList tint) {
+ public void setTintList(@Nullable ColorStateList tint) {
mNinePatchState.mTint = tint;
mTintFilter = updateTintFilter(mTintFilter, tint, mNinePatchState.mTintMode);
invalidateSelf();
}
@Override
- public void setTintMode(PorterDuff.Mode tintMode) {
+ public void setTintMode(@Nullable PorterDuff.Mode tintMode) {
mNinePatchState.mTintMode = tintMode;
mTintFilter = updateTintFilter(mTintFilter, mNinePatchState.mTint, tintMode);
invalidateSelf();
@@ -409,10 +389,7 @@
@Override
public boolean isFilterBitmap() {
- if (mPaint == null) {
- return false;
- }
- return getPaint().isFilterBitmap();
+ return mPaint != null && getPaint().isFilterBitmap();
}
@Override
@@ -430,7 +407,7 @@
/**
* Updates the constant state from the values in the typed array.
*/
- private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException {
+ private void updateStateFromTypedArray(@NonNull TypedArray a) throws XmlPullParserException {
final Resources r = a.getResources();
final NinePatchState state = mNinePatchState;
@@ -491,12 +468,10 @@
if (tint != null) {
state.mTint = tint;
}
-
- state.mTargetDensity = Drawable.resolveDensity(r, state.mTargetDensity);
}
@Override
- public void applyTheme(Theme t) {
+ public void applyTheme(@NonNull Theme t) {
super.applyTheme(t);
final NinePatchState state = mNinePatchState;
@@ -528,6 +503,7 @@
return mNinePatchState != null && mNinePatchState.canApplyTheme();
}
+ @NonNull
public Paint getPaint() {
if (mPaint == null) {
mPaint = new Paint();
@@ -536,45 +512,26 @@
return mPaint;
}
- /**
- * Retrieves the width of the source .png file (before resizing).
- */
@Override
public int getIntrinsicWidth() {
return mBitmapWidth;
}
- /**
- * Retrieves the height of the source .png file (before resizing).
- */
@Override
public int getIntrinsicHeight() {
return mBitmapHeight;
}
@Override
- public int getMinimumWidth() {
- return mBitmapWidth;
- }
-
- @Override
- public int getMinimumHeight() {
- return mBitmapHeight;
- }
-
- /**
- * Returns a {@link android.graphics.PixelFormat graphics.PixelFormat}
- * value of OPAQUE or TRANSLUCENT.
- */
- @Override
public int getOpacity() {
- return mNinePatch.hasAlpha() || (mPaint != null && mPaint.getAlpha() < 255) ?
- PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
+ return mNinePatchState.mNinePatch.hasAlpha()
+ || (mPaint != null && mPaint.getAlpha() < 255) ?
+ PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
}
@Override
public Region getTransparentRegion() {
- return mNinePatch.getTransparentRegion(getBounds());
+ return mNinePatchState.mNinePatch.getTransparentRegion(getBounds());
}
@Override
@@ -587,7 +544,6 @@
public Drawable mutate() {
if (!mMutated && super.mutate() == this) {
mNinePatchState = new NinePatchState(mNinePatchState);
- mNinePatch = mNinePatchState.mNinePatch;
mMutated = true;
}
return this;
@@ -619,8 +575,9 @@
}
final static class NinePatchState extends ConstantState {
+ int mChangingConfigurations;
+
// Values loaded during inflation.
- int[] mThemeAttrs = null;
NinePatch mNinePatch = null;
ColorStateList mTint = null;
Mode mTintMode = DEFAULT_TINT_MODE;
@@ -628,10 +585,9 @@
Insets mOpticalInsets = Insets.NONE;
float mBaseAlpha = 1.0f;
boolean mDither = DEFAULT_DITHER;
- int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
boolean mAutoMirrored = false;
- int mChangingConfigurations;
+ int[] mThemeAttrs;
NinePatchState() {
// Empty constructor.
@@ -655,27 +611,24 @@
mAutoMirrored = autoMirror;
}
- // Copy constructor
-
- NinePatchState(@NonNull NinePatchState state) {
- // We don't deep-copy any fields because they are all immutable.
- mNinePatch = state.mNinePatch;
- mTint = state.mTint;
- mTintMode = state.mTintMode;
- mThemeAttrs = state.mThemeAttrs;
- mPadding = state.mPadding;
- mOpticalInsets = state.mOpticalInsets;
- mBaseAlpha = state.mBaseAlpha;
- mDither = state.mDither;
- mChangingConfigurations = state.mChangingConfigurations;
- mTargetDensity = state.mTargetDensity;
- mAutoMirrored = state.mAutoMirrored;
+ NinePatchState(@NonNull NinePatchState orig) {
+ mChangingConfigurations = orig.mChangingConfigurations;
+ mNinePatch = orig.mNinePatch;
+ mTint = orig.mTint;
+ mTintMode = orig.mTintMode;
+ mPadding = orig.mPadding;
+ mOpticalInsets = orig.mOpticalInsets;
+ mBaseAlpha = orig.mBaseAlpha;
+ mDither = orig.mDither;
+ mAutoMirrored = orig.mAutoMirrored;
+ mThemeAttrs = orig.mThemeAttrs;
}
@Override
public boolean canApplyTheme() {
return mThemeAttrs != null
- || (mTint != null && mTint.canApplyTheme());
+ || (mTint != null && mTint.canApplyTheme())
+ || super.canApplyTheme();
}
@Override
@@ -704,44 +657,98 @@
}
}
+ private void computeBitmapSize() {
+ final NinePatch ninePatch = mNinePatchState.mNinePatch;
+ if (ninePatch == null) {
+ return;
+ }
+
+ final int sourceDensity = ninePatch.getDensity();
+ final int targetDensity = mTargetDensity;
+
+ final Insets sourceOpticalInsets = mNinePatchState.mOpticalInsets;
+ if (sourceOpticalInsets != Insets.NONE) {
+ final int left = Drawable.scaleFromDensity(
+ sourceOpticalInsets.left, sourceDensity, targetDensity, true);
+ final int top = Drawable.scaleFromDensity(
+ sourceOpticalInsets.top, sourceDensity, targetDensity, true);
+ final int right = Drawable.scaleFromDensity(
+ sourceOpticalInsets.right, sourceDensity, targetDensity, true);
+ final int bottom = Drawable.scaleFromDensity(
+ sourceOpticalInsets.bottom, sourceDensity, targetDensity, true);
+ mOpticalInsets = Insets.of(left, top, right, bottom);
+ } else {
+ mOpticalInsets = Insets.NONE;
+ }
+
+ final Rect sourcePadding = mNinePatchState.mPadding;
+ if (sourcePadding != null) {
+ if (mPadding == null) {
+ mPadding = new Rect();
+ }
+ mPadding.left = Drawable.scaleFromDensity(
+ sourcePadding.left, sourceDensity, targetDensity, false);
+ mPadding.top = Drawable.scaleFromDensity(
+ sourcePadding.top, sourceDensity, targetDensity, false);
+ mPadding.right = Drawable.scaleFromDensity(
+ sourcePadding.right, sourceDensity, targetDensity, false);
+ mPadding.bottom = Drawable.scaleFromDensity(
+ sourcePadding.bottom, sourceDensity, targetDensity, false);
+ } else {
+ mPadding = null;
+ }
+
+ mBitmapHeight = Drawable.scaleFromDensity(
+ ninePatch.getHeight(), sourceDensity, targetDensity, true);
+ mBitmapWidth = Drawable.scaleFromDensity(
+ ninePatch.getWidth(), sourceDensity, targetDensity, true);
+
+ final NinePatch.InsetStruct insets = ninePatch.getBitmap().getNinePatchInsets();
+ if (insets != null) {
+ if (mOutlineInsets == null) {
+ mOutlineInsets = new Rect();
+ }
+ final Rect outlineInsets = insets.outlineRect;
+ mOutlineInsets.left = Drawable.scaleFromDensity(
+ outlineInsets.left, sourceDensity, targetDensity, false);
+ mOutlineInsets.top = Drawable.scaleFromDensity(
+ outlineInsets.top, sourceDensity, targetDensity, false);
+ mOutlineInsets.right = Drawable.scaleFromDensity(
+ outlineInsets.right, sourceDensity, targetDensity, false);
+ mOutlineInsets.bottom = Drawable.scaleFromDensity(
+ outlineInsets.bottom, sourceDensity, targetDensity, false);
+ mOutlineRadius = Drawable.scaleFromDensity(
+ insets.outlineRadius, sourceDensity, targetDensity);
+ } else {
+ mOutlineInsets = null;
+ }
+ }
+
/**
* The one constructor to rule them all. This is called by all public
* constructors to set the state and initialize local properties.
+ *
+ * @param state constant state to assign to the new drawable
*/
- private NinePatchDrawable(NinePatchState state, Resources res) {
+ private NinePatchDrawable(@NonNull NinePatchState state, @Nullable Resources res) {
mNinePatchState = state;
updateLocalState(res);
-
- // Push density applied by setNinePatchState into state.
- mNinePatchState.mTargetDensity = mTargetDensity;
}
/**
* Initializes local dynamic properties from state.
*/
- private void updateLocalState(Resources res) {
+ private void updateLocalState(@Nullable Resources res) {
final NinePatchState state = mNinePatchState;
- if (res != null) {
- final int densityDpi = res.getDisplayMetrics().densityDpi;
- mTargetDensity = densityDpi == 0 ? DisplayMetrics.DENSITY_DEFAULT : densityDpi;
- } else {
- mTargetDensity = state.mTargetDensity;
- }
-
-
// If we can, avoid calling any methods that initialize Paint.
if (state.mDither != DEFAULT_DITHER) {
setDither(state.mDither);
}
- // Make a local copy of the padding.
- if (state.mPadding != null) {
- mPadding = new Rect(state.mPadding);
- }
-
+ mTargetDensity = Drawable.resolveDensity(res, mTargetDensity);
mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
- setNinePatch(state.mNinePatch);
+ computeBitmapSize();
}
}
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index d8801b8..f23fceb 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -1151,9 +1151,13 @@
uint32_t screenConfig2;
};
- // If true, it means that the script of the locale was explicitly provided.
- // If false, it means that the script was automatically computed.
- bool localeScriptWasProvided;
+ // If false and localeScript is set, it means that the script of the locale
+ // was explicitly provided.
+ //
+ // If true, it means that localeScript was automatically computed.
+ // localeScript may still not be set in this case, which means that we
+ // tried but could not compute a script.
+ bool localeScriptWasComputed;
void copyFromDeviceNoSwap(const ResTable_config& o);
@@ -1233,7 +1237,7 @@
inline void clearLocale() {
locale = 0;
- localeScriptWasProvided = false;
+ localeScriptWasComputed = false;
memset(localeScript, 0, sizeof(localeScript));
memset(localeVariant, 0, sizeof(localeVariant));
}
@@ -1896,6 +1900,13 @@
mutable Mutex mLock;
+ // Mutex that controls access to the list of pre-filtered configurations
+ // to check when looking up entries.
+ // When iterating over a bag, the mLock mutex is locked. While mLock is locked,
+ // we do resource lookups.
+ // Mutex is not reentrant, so we must use a different lock than mLock.
+ mutable Mutex mFilteredConfigLock;
+
status_t mError;
ResTable_config mParams;
diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index 302b0bd..6830a74 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -217,42 +217,42 @@
}
/**
- * Delete all types (private key, certificate, CA certificate) for a
+ * Delete all types (private key, user certificate, CA certificate) for a
* particular {@code alias}. All three can exist for any given alias.
- * Returns {@code true} if there was at least one of those types.
+ * Returns {@code true} if the alias no longer contains any types.
*/
public static boolean deleteAllTypesForAlias(KeyStore keystore, String alias) {
return deleteAllTypesForAlias(keystore, alias, KeyStore.UID_SELF);
}
/**
- * Delete all types (private key, certificate, CA certificate) for a
+ * Delete all types (private key, user certificate, CA certificate) for a
* particular {@code alias}. All three can exist for any given alias.
- * Returns {@code true} if there was at least one of those types.
+ * Returns {@code true} if the alias no longer contains any types.
*/
public static boolean deleteAllTypesForAlias(KeyStore keystore, String alias, int uid) {
/*
* Make sure every type is deleted. There can be all three types, so
* don't use a conditional here.
*/
- return keystore.delete(Credentials.USER_PRIVATE_KEY + alias, uid)
- | keystore.delete(Credentials.USER_SECRET_KEY + alias, uid)
- | deleteCertificateTypesForAlias(keystore, alias, uid);
+ return deletePrivateKeyTypeForAlias(keystore, alias, uid)
+ & deleteSecretKeyTypeForAlias(keystore, alias, uid)
+ & deleteCertificateTypesForAlias(keystore, alias, uid);
}
/**
- * Delete all types (private key, certificate, CA certificate) for a
- * particular {@code alias}. All three can exist for any given alias.
- * Returns {@code true} if there was at least one of those types.
+ * Delete certificate types (user certificate, CA certificate) for a
+ * particular {@code alias}. Both can exist for any given alias.
+ * Returns {@code true} if the alias no longer contains either type.
*/
public static boolean deleteCertificateTypesForAlias(KeyStore keystore, String alias) {
return deleteCertificateTypesForAlias(keystore, alias, KeyStore.UID_SELF);
}
/**
- * Delete all types (private key, certificate, CA certificate) for a
- * particular {@code alias}. All three can exist for any given alias.
- * Returns {@code true} if there was at least one of those types.
+ * Delete certificate types (user certificate, CA certificate) for a
+ * particular {@code alias}. Both can exist for any given alias.
+ * Returns {@code true} if the alias no longer contains either type.
*/
public static boolean deleteCertificateTypesForAlias(KeyStore keystore, String alias, int uid) {
/*
@@ -260,12 +260,12 @@
* so don't use a conditional here.
*/
return keystore.delete(Credentials.USER_CERTIFICATE + alias, uid)
- | keystore.delete(Credentials.CA_CERTIFICATE + alias, uid);
+ & keystore.delete(Credentials.CA_CERTIFICATE + alias, uid);
}
/**
* Delete private key for a particular {@code alias}.
- * Returns {@code true} if an entry was was deleted.
+ * Returns {@code true} if the entry no longer exists.
*/
static boolean deletePrivateKeyTypeForAlias(KeyStore keystore, String alias) {
return deletePrivateKeyTypeForAlias(keystore, alias, KeyStore.UID_SELF);
@@ -273,7 +273,7 @@
/**
* Delete private key for a particular {@code alias}.
- * Returns {@code true} if an entry was was deleted.
+ * Returns {@code true} if the entry no longer exists.
*/
static boolean deletePrivateKeyTypeForAlias(KeyStore keystore, String alias, int uid) {
return keystore.delete(Credentials.USER_PRIVATE_KEY + alias, uid);
@@ -281,7 +281,7 @@
/**
* Delete secret key for a particular {@code alias}.
- * Returns {@code true} if an entry was was deleted.
+ * Returns {@code true} if the entry no longer exists.
*/
public static boolean deleteSecretKeyTypeForAlias(KeyStore keystore, String alias) {
return deleteSecretKeyTypeForAlias(keystore, alias, KeyStore.UID_SELF);
@@ -289,7 +289,7 @@
/**
* Delete secret key for a particular {@code alias}.
- * Returns {@code true} if an entry was was deleted.
+ * Returns {@code true} if the entry no longer exists.
*/
public static boolean deleteSecretKeyTypeForAlias(KeyStore keystore, String alias, int uid) {
return keystore.delete(Credentials.USER_SECRET_KEY + alias, uid);
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 7adad8a..0886487 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -547,11 +547,8 @@
Intent intent = new Intent(IKeyChainService.class.getName());
ComponentName comp = intent.resolveSystemService(context.getPackageManager(), 0);
intent.setComponent(comp);
- boolean isBound = context.bindServiceAsUser(intent,
- keyChainServiceConnection,
- Context.BIND_AUTO_CREATE,
- user);
- if (!isBound) {
+ if (comp == null || !context.bindServiceAsUser(
+ intent, keyChainServiceConnection, Context.BIND_AUTO_CREATE, user)) {
throw new AssertionError("could not bind to KeyChainService");
}
return new KeyChainConnection(context, keyChainServiceConnection, q.take());
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 3090ac1..70e4b6f 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -183,7 +183,8 @@
public boolean delete(String key, int uid) {
try {
- return mBinder.del(key, uid) == NO_ERROR;
+ int ret = mBinder.del(key, uid);
+ return (ret == NO_ERROR || ret == KEY_NOT_FOUND);
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return false;
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
index 1321a83..b234d0f 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
@@ -234,7 +234,8 @@
KeymasterUtils.addUserAuthArgs(new KeymasterArguments(),
spec.isUserAuthenticationRequired(),
spec.getUserAuthenticationValidityDurationSeconds(),
- spec.isUserAuthenticationValidWhileOnBody());
+ spec.isUserAuthenticationValidWhileOnBody(),
+ spec.isInvalidatedByBiometricEnrollment());
} catch (IllegalStateException | IllegalArgumentException e) {
throw new InvalidAlgorithmParameterException(e);
}
@@ -273,7 +274,8 @@
KeymasterUtils.addUserAuthArgs(args,
spec.isUserAuthenticationRequired(),
spec.getUserAuthenticationValidityDurationSeconds(),
- spec.isUserAuthenticationValidWhileOnBody());
+ spec.isUserAuthenticationValidWhileOnBody(),
+ spec.isInvalidatedByBiometricEnrollment());
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
args,
mKeymasterAlgorithm,
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
index 830402a..1818f52 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -345,7 +345,8 @@
KeymasterUtils.addUserAuthArgs(new KeymasterArguments(),
mSpec.isUserAuthenticationRequired(),
mSpec.getUserAuthenticationValidityDurationSeconds(),
- mSpec.isUserAuthenticationValidWhileOnBody());
+ mSpec.isUserAuthenticationValidWhileOnBody(),
+ mSpec.isInvalidatedByBiometricEnrollment());
} catch (IllegalArgumentException | IllegalStateException e) {
throw new InvalidAlgorithmParameterException(e);
}
@@ -531,7 +532,8 @@
KeymasterUtils.addUserAuthArgs(args,
mSpec.isUserAuthenticationRequired(),
mSpec.getUserAuthenticationValidityDurationSeconds(),
- mSpec.isUserAuthenticationValidWhileOnBody());
+ mSpec.isUserAuthenticationValidWhileOnBody(),
+ mSpec.isInvalidatedByBiometricEnrollment());
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, mSpec.getKeyValidityStart());
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
mSpec.getKeyValidityForOriginationEnd());
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
index 5f5f2c2..0379863 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
@@ -17,10 +17,12 @@
package android.security.keystore;
import android.security.Credentials;
+import android.security.GateKeeper;
import android.security.KeyStore;
import android.security.keymaster.KeyCharacteristics;
import android.security.keymaster.KeymasterDefs;
+import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.ProviderException;
import java.security.spec.InvalidKeySpecException;
@@ -91,6 +93,7 @@
@KeyProperties.BlockModeEnum String[] blockModes;
int keymasterSwEnforcedUserAuthenticators;
int keymasterHwEnforcedUserAuthenticators;
+ List<BigInteger> keymasterSecureUserIds;
try {
if (keyCharacteristics.hwEnforced.containsTag(KeymasterDefs.KM_TAG_ORIGIN)) {
insideSecureHardware = true;
@@ -147,6 +150,8 @@
keyCharacteristics.swEnforced.getEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0);
keymasterHwEnforcedUserAuthenticators =
keyCharacteristics.hwEnforced.getEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0);
+ keymasterSecureUserIds =
+ keyCharacteristics.getUnsignedLongs(KeymasterDefs.KM_TAG_USER_SECURE_ID);
} catch (IllegalArgumentException e) {
throw new ProviderException("Unsupported key characteristic", e);
}
@@ -170,6 +175,15 @@
boolean userAuthenticationValidWhileOnBody =
keyCharacteristics.hwEnforced.getBoolean(KeymasterDefs.KM_TAG_ALLOW_WHILE_ON_BODY);
+ boolean invalidatedByBiometricEnrollment = false;
+ if (keymasterSwEnforcedUserAuthenticators == KeymasterDefs.HW_AUTH_FINGERPRINT
+ || keymasterHwEnforcedUserAuthenticators == KeymasterDefs.HW_AUTH_FINGERPRINT) {
+ // Fingerprint-only key; will be invalidated if the root SID isn't in the SID list.
+ invalidatedByBiometricEnrollment = keymasterSecureUserIds != null
+ && !keymasterSecureUserIds.isEmpty()
+ && !keymasterSecureUserIds.contains(getGateKeeperSecureUserId());
+ }
+
return new KeyInfo(entryAlias,
insideSecureHardware,
origin,
@@ -185,7 +199,16 @@
userAuthenticationRequired,
(int) userAuthenticationValidityDurationSeconds,
userAuthenticationRequirementEnforcedBySecureHardware,
- userAuthenticationValidWhileOnBody);
+ userAuthenticationValidWhileOnBody,
+ invalidatedByBiometricEnrollment);
+ }
+
+ private static BigInteger getGateKeeperSecureUserId() throws ProviderException {
+ try {
+ return BigInteger.valueOf(GateKeeper.getSecureUserId());
+ } catch (IllegalStateException e) {
+ throw new ProviderException("Failed to get GateKeeper secure user ID", e);
+ }
}
@Override
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index d660020..fcbb553 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -499,7 +499,8 @@
KeymasterUtils.addUserAuthArgs(importArgs,
spec.isUserAuthenticationRequired(),
spec.getUserAuthenticationValidityDurationSeconds(),
- spec.isUserAuthenticationValidWhileOnBody());
+ spec.isUserAuthenticationValidWhileOnBody(),
+ spec.isInvalidatedByBiometricEnrollment());
importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
spec.getKeyValidityStart());
importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
@@ -694,7 +695,8 @@
KeymasterUtils.addUserAuthArgs(args,
params.isUserAuthenticationRequired(),
params.getUserAuthenticationValidityDurationSeconds(),
- params.isUserAuthenticationValidWhileOnBody());
+ params.isUserAuthenticationValidWhileOnBody(),
+ params.isInvalidatedByBiometricEnrollment());
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
args,
keymasterAlgorithm,
@@ -763,11 +765,6 @@
@Override
public void engineDeleteEntry(String alias) throws KeyStoreException {
- if (!engineContainsAlias(alias)) {
- return;
- }
- // At least one entry corresponding to this alias exists in keystore
-
if (!Credentials.deleteAllTypesForAlias(mKeyStore, alias, mUid)) {
throw new KeyStoreException("Failed to delete entry: " + alias);
}
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index a84e7f34..127d756 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -253,6 +253,7 @@
private final byte[] mAttestationChallenge;
private final boolean mUniqueIdIncluded;
private final boolean mUserAuthenticationValidWhileOnBody;
+ private final boolean mInvalidatedByBiometricEnrollment;
/**
* @hide should be built with Builder
@@ -279,7 +280,8 @@
int userAuthenticationValidityDurationSeconds,
byte[] attestationChallenge,
boolean uniqueIdIncluded,
- boolean userAuthenticationValidWhileOnBody) {
+ boolean userAuthenticationValidWhileOnBody,
+ boolean invalidatedByBiometricEnrollment) {
if (TextUtils.isEmpty(keyStoreAlias)) {
throw new IllegalArgumentException("keyStoreAlias must not be empty");
}
@@ -324,6 +326,7 @@
mAttestationChallenge = Utils.cloneIfNotNull(attestationChallenge);
mUniqueIdIncluded = uniqueIdIncluded;
mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
+ mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
}
/**
@@ -607,6 +610,19 @@
}
/**
+ * Returns {@code true} if the key is irreversibly invalidated when a new fingerprint is
+ * enrolled or all enrolled fingerprints are removed. This has effect only for keys that
+ * require fingerprint user authentication for every use.
+ *
+ * @see #isUserAuthenticationRequired()
+ * @see #getUserAuthenticationValidityDurationSeconds()
+ * @see Builder#setInvalidatedByBiometricEnrollment(boolean)
+ */
+ public boolean isInvalidatedByBiometricEnrollment() {
+ return mInvalidatedByBiometricEnrollment;
+ }
+
+ /**
* Builder of {@link KeyGenParameterSpec} instances.
*/
public final static class Builder {
@@ -633,6 +649,7 @@
private byte[] mAttestationChallenge = null;
private boolean mUniqueIdIncluded = false;
private boolean mUserAuthenticationValidWhileOnBody;
+ private boolean mInvalidatedByBiometricEnrollment = true;
/**
* Creates a new instance of the {@code Builder}.
@@ -966,8 +983,10 @@
* or when the secure lock screen is forcibly reset (e.g., by a Device Administrator).
* Additionally, if the key requires that user authentication takes place for every use of
* the key, it is also irreversibly invalidated once a new fingerprint is enrolled or once\
- * no more fingerprints are enrolled. Attempts to initialize cryptographic operations using
- * such keys will throw {@link KeyPermanentlyInvalidatedException}.</li>
+ * no more fingerprints are enrolled, unless {@link
+ * #setInvalidatedByBiometricEnrollment(boolean)} is used to allow validity after
+ * enrollment. Attempts to initialize cryptographic operations using such keys will throw
+ * {@link KeyPermanentlyInvalidatedException}.</li>
* </ul>
*
* <p>This authorization applies only to secret key and private key operations. Public key
@@ -1110,6 +1129,30 @@
}
/**
+ * Sets whether this key should be invalidated on fingerprint enrollment. This
+ * applies only to keys which require user authentication (see {@link
+ * #setUserAuthenticationRequired(boolean)}) and if no positive validity duration has been
+ * set (see {@link #setUserAuthenticationValidityDurationSeconds(int)}, meaning the key is
+ * valid for fingerprint authentication only.
+ *
+ * <p>By default, {@code invalidateKey} is {@code true}, so keys that are valid for
+ * fingerprint authentication only are <em>irreversibly invalidated</em> when a new
+ * fingerprint is enrolled, or when all existing fingerprints are deleted. That may be
+ * changed by calling this method with {@code invalidateKey} set to {@code false}.
+ *
+ * <p>Invalidating keys on enrollment of a new finger or unenrollment of all fingers
+ * improves security by ensuring that an unauthorized person who obtains the password can't
+ * gain the use of fingerprint-authenticated keys by enrolling their own finger. However,
+ * invalidating keys makes key-dependent operations impossible, requiring some fallback
+ * procedure to authenticate the user and set up a new key.
+ */
+ @NonNull
+ public Builder setInvalidatedByBiometricEnrollment(boolean invalidateKey) {
+ mInvalidatedByBiometricEnrollment = invalidateKey;
+ return this;
+ }
+
+ /**
* Builds an instance of {@code KeyGenParameterSpec}.
*/
@NonNull
@@ -1136,7 +1179,8 @@
mUserAuthenticationValidityDurationSeconds,
mAttestationChallenge,
mUniqueIdIncluded,
- mUserAuthenticationValidWhileOnBody);
+ mUserAuthenticationValidWhileOnBody,
+ mInvalidatedByBiometricEnrollment);
}
}
}
diff --git a/keystore/java/android/security/keystore/KeyInfo.java b/keystore/java/android/security/keystore/KeyInfo.java
index f77b5ba..fa6d8b3 100644
--- a/keystore/java/android/security/keystore/KeyInfo.java
+++ b/keystore/java/android/security/keystore/KeyInfo.java
@@ -80,6 +80,7 @@
private final int mUserAuthenticationValidityDurationSeconds;
private final boolean mUserAuthenticationRequirementEnforcedBySecureHardware;
private final boolean mUserAuthenticationValidWhileOnBody;
+ private final boolean mInvalidatedByBiometricEnrollment;
/**
* @hide
@@ -99,7 +100,8 @@
boolean userAuthenticationRequired,
int userAuthenticationValidityDurationSeconds,
boolean userAuthenticationRequirementEnforcedBySecureHardware,
- boolean userAuthenticationValidWhileOnBody) {
+ boolean userAuthenticationValidWhileOnBody,
+ boolean invalidatedByBiometricEnrollment) {
mKeystoreAlias = keystoreKeyAlias;
mInsideSecureHardware = insideSecureHardware;
mOrigin = origin;
@@ -119,6 +121,7 @@
mUserAuthenticationRequirementEnforcedBySecureHardware =
userAuthenticationRequirementEnforcedBySecureHardware;
mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
+ mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
}
/**
@@ -290,4 +293,12 @@
public boolean isUserAuthenticationValidWhileOnBody() {
return mUserAuthenticationValidWhileOnBody;
}
+
+ /**
+ * Returns {@code true} if the key will be invalidated by enrollment of a new fingerprint or
+ * removal of all fingerprints.
+ */
+ public boolean isInvalidatedByBiometricEnrollment() {
+ return mInvalidatedByBiometricEnrollment;
+ }
}
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index 4700b68..fa57bdb 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -215,6 +215,7 @@
private final boolean mUserAuthenticationRequired;
private final int mUserAuthenticationValidityDurationSeconds;
private final boolean mUserAuthenticationValidWhileOnBody;
+ private final boolean mInvalidatedByBiometricEnrollment;
private KeyProtection(
Date keyValidityStart,
@@ -228,7 +229,8 @@
boolean randomizedEncryptionRequired,
boolean userAuthenticationRequired,
int userAuthenticationValidityDurationSeconds,
- boolean userAuthenticationValidWhileOnBody) {
+ boolean userAuthenticationValidWhileOnBody,
+ boolean invalidatedByBiometricEnrollment) {
mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart);
mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd);
mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd);
@@ -243,6 +245,7 @@
mUserAuthenticationRequired = userAuthenticationRequired;
mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
+ mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
}
/**
@@ -412,6 +415,19 @@
}
/**
+ * Returns {@code true} if the key is irreversibly invalidated when a new fingerprint is
+ * enrolled or all enrolled fingerprints are removed. This has effect only for keys that
+ * require fingerprint user authentication for every use.
+ *
+ * @see #isUserAuthenticationRequired()
+ * @see #getUserAuthenticationValidityDurationSeconds()
+ * @see Builder#setInvalidatedByBiometricEnrollment(boolean)
+ */
+ public boolean isInvalidatedByBiometricEnrollment() {
+ return mInvalidatedByBiometricEnrollment;
+ }
+
+ /**
* Builder of {@link KeyProtection} instances.
*/
public final static class Builder {
@@ -428,6 +444,7 @@
private boolean mUserAuthenticationRequired;
private int mUserAuthenticationValidityDurationSeconds = -1;
private boolean mUserAuthenticationValidWhileOnBody;
+ private boolean mInvalidatedByBiometricEnrollment = true;
/**
* Creates a new instance of the {@code Builder}.
@@ -638,9 +655,10 @@
* or when the secure lock screen is forcibly reset (e.g., by a Device Administrator).
* Additionally, if the key requires that user authentication takes place for every use of
* the key, it is also irreversibly invalidated once a new fingerprint is enrolled or once\
- * no more fingerprints are enrolled. Attempts to initialize cryptographic operations using
- * such keys will throw {@link KeyPermanentlyInvalidatedException}.</li>
- * </ul>
+ * no more fingerprints are enrolled, unless {@link
+ * #setInvalidatedByBiometricEnrollment(boolean)} is used to allow validity after
+ * enrollment. Attempts to initialize cryptographic operations using such keys will throw
+ * {@link KeyPermanentlyInvalidatedException}.</li> </ul>
*
* <p>This authorization applies only to secret key and private key operations. Public key
* operations are not restricted.
@@ -729,6 +747,30 @@
}
/**
+ * Sets whether this key should be invalidated on fingerprint enrollment. This
+ * applies only to keys which require user authentication (see {@link
+ * #setUserAuthenticationRequired(boolean)}) and if no positive validity duration has been
+ * set (see {@link #setUserAuthenticationValidityDurationSeconds(int)}, meaning the key is
+ * valid for fingerprint authentication only.
+ *
+ * <p>By default, {@code invalidateKey} is {@code true}, so keys that are valid for
+ * fingerprint authentication only are <em>irreversibly invalidated</em> when a new
+ * fingerprint is enrolled, or when all existing fingerprints are deleted. That may be
+ * changed by calling this method with {@code invalidateKey} set to {@code false}.
+ *
+ * <p>Invalidating keys on enrollment of a new finger or unenrollment of all fingers
+ * improves security by ensuring that an unauthorized person who obtains the password can't
+ * gain the use of fingerprint-authenticated keys by enrolling their own finger. However,
+ * invalidating keys makes key-dependent operations impossible, requiring some fallback
+ * procedure to authenticate the user and set up a new key.
+ */
+ @NonNull
+ public Builder setInvalidatedByBiometricEnrollment(boolean invalidateKey) {
+ mInvalidatedByBiometricEnrollment = invalidateKey;
+ return this;
+ }
+
+ /**
* Builds an instance of {@link KeyProtection}.
*
* @throws IllegalArgumentException if a required field is missing
@@ -747,7 +789,8 @@
mRandomizedEncryptionRequired,
mUserAuthenticationRequired,
mUserAuthenticationValidityDurationSeconds,
- mUserAuthenticationValidWhileOnBody);
+ mUserAuthenticationValidWhileOnBody,
+ mInvalidatedByBiometricEnrollment);
}
}
}
diff --git a/keystore/java/android/security/keystore/KeymasterUtils.java b/keystore/java/android/security/keystore/KeymasterUtils.java
index 3a008bc..f5272aa 100644
--- a/keystore/java/android/security/keystore/KeymasterUtils.java
+++ b/keystore/java/android/security/keystore/KeymasterUtils.java
@@ -97,7 +97,8 @@
public static void addUserAuthArgs(KeymasterArguments args,
boolean userAuthenticationRequired,
int userAuthenticationValidityDurationSeconds,
- boolean userAuthenticationValidWhileOnBody) {
+ boolean userAuthenticationValidWhileOnBody,
+ boolean invalidatedByBiometricEnrollment) {
if (!userAuthenticationRequired) {
args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
return;
@@ -117,8 +118,20 @@
"At least one fingerprint must be enrolled to create keys requiring user"
+ " authentication for every use");
}
- args.addUnsignedLong(KeymasterDefs.KM_TAG_USER_SECURE_ID,
- KeymasterArguments.toUint64(fingerprintOnlySid));
+
+ long sid;
+ if (invalidatedByBiometricEnrollment) {
+ // The fingerprint-only SID will change on fingerprint enrollment or removal of all,
+ // enrolled fingerprints, invalidating the key.
+ sid = fingerprintOnlySid;
+ } else {
+ // The root SID will *not* change on fingerprint enrollment, or removal of all
+ // enrolled fingerprints, allowing the key to remain valid.
+ sid = getRootSid();
+ }
+
+ args.addUnsignedLong(
+ KeymasterDefs.KM_TAG_USER_SECURE_ID, KeymasterArguments.toUint64(sid));
args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, KeymasterDefs.HW_AUTH_FINGERPRINT);
if (userAuthenticationValidWhileOnBody) {
throw new ProviderException("Key validity extension while device is on-body is not "
@@ -127,11 +140,7 @@
} else {
// The key is authorized for use for the specified amount of time after the user has
// authenticated. Whatever unlocks the secure lock screen should authorize this key.
- long rootSid = GateKeeper.getSecureUserId();
- if (rootSid == 0) {
- throw new IllegalStateException("Secure lock screen must be enabled"
- + " to create keys requiring user authentication");
- }
+ long rootSid = getRootSid();
args.addUnsignedLong(KeymasterDefs.KM_TAG_USER_SECURE_ID,
KeymasterArguments.toUint64(rootSid));
args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE,
@@ -184,4 +193,13 @@
break;
}
}
+
+ private static long getRootSid() {
+ long rootSid = GateKeeper.getSecureUserId();
+ if (rootSid == 0) {
+ throw new IllegalStateException("Secure lock screen must be enabled"
+ + " to create keys requiring user authentication");
+ }
+ return rootSid;
+ }
}
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 3277c36..49b3a51 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -25,6 +25,7 @@
#include <string.h>
#include <limits>
+#include <memory>
#include <type_traits>
#include <androidfw/ByteBucketArray.h>
@@ -1869,8 +1870,8 @@
// The language & region are equal, so compare the scripts and variants.
const char emptyScript[sizeof(l.localeScript)] = {'\0', '\0', '\0', '\0'};
- const char *lScript = l.localeScriptWasProvided ? l.localeScript : emptyScript;
- const char *rScript = r.localeScriptWasProvided ? r.localeScript : emptyScript;
+ const char *lScript = l.localeScriptWasComputed ? emptyScript : l.localeScript;
+ const char *rScript = r.localeScriptWasComputed ? emptyScript : r.localeScript;
int script = memcmp(lScript, rScript, sizeof(l.localeScript));
if (script) {
return script;
@@ -2015,11 +2016,11 @@
// scripts since it seems more useful to do so. We will consider
// "en-US-POSIX" to be more specific than "en-Latn-US".
- const int score = (localeScriptWasProvided ? 1 : 0) +
- ((localeVariant[0] != 0) ? 2 : 0);
+ const int score = ((localeScript[0] != '\0' && !localeScriptWasComputed) ? 1 : 0) +
+ ((localeVariant[0] != '\0') ? 2 : 0);
- const int oScore = (o.localeScriptWasProvided ? 1 : 0) +
- ((o.localeVariant[0] != 0) ? 2 : 0);
+ const int oScore = (o.localeScript[0] != '\0' && !o.localeScriptWasComputed ? 1 : 0) +
+ ((o.localeVariant[0] != '\0') ? 2 : 0);
return score - oScore;
@@ -2534,7 +2535,8 @@
if (settings.localeScript[0] == '\0') { // could not determine the request's script
countriesMustMatch = true;
} else {
- if (localeScript[0] == '\0') { // script was not provided, so we try to compute it
+ if (localeScript[0] == '\0' && !localeScriptWasComputed) {
+ // script was not provided or computed, so we try to compute it
localeDataComputeScript(computed_script, language, country);
if (computed_script[0] == '\0') { // we could not compute the script
countriesMustMatch = true;
@@ -2683,8 +2685,8 @@
if (!language[0]) {
return;
}
-
- if (!localeScriptWasProvided && !localeVariant[0]) {
+ const bool scriptWasProvided = localeScript[0] != '\0' && !localeScriptWasComputed;
+ if (!scriptWasProvided && !localeVariant[0]) {
// Legacy format.
if (out.size() > 0) {
out.append("-");
@@ -2714,7 +2716,7 @@
size_t len = unpackLanguage(buf);
out.append(buf, len);
- if (localeScriptWasProvided) {
+ if (scriptWasProvided) {
out.append("+");
out.append(localeScript, sizeof(localeScript));
}
@@ -2745,7 +2747,7 @@
charsWritten += unpackLanguage(str);
}
- if (localeScriptWasProvided) {
+ if (localeScript[0] && !localeScriptWasComputed) {
if (charsWritten) {
str[charsWritten++] = '-';
}
@@ -2786,7 +2788,6 @@
for (size_t i = 1; i < 4; ++i) {
config->localeScript[i] = tolower(start[i]);
}
- config->localeScriptWasProvided = true;
break;
}
case 5:
@@ -2806,7 +2807,6 @@
void ResTable_config::setBcp47Locale(const char* in) {
locale = 0;
- localeScriptWasProvided = false;
memset(localeScript, 0, sizeof(localeScript));
memset(localeVariant, 0, sizeof(localeVariant));
@@ -2823,9 +2823,10 @@
const size_t size = in + strlen(in) - start;
assignLocaleComponent(this, start, size);
- if (localeScript[0] == '\0') {
+ localeScriptWasComputed = (localeScript[0] == '\0');
+ if (localeScriptWasComputed) {
computeScript();
- };
+ }
}
String8 ResTable_config::toString() const {
@@ -3146,6 +3147,9 @@
StringPoolRef keyStr;
};
+template <typename T>
+using SharedVector = std::shared_ptr<Vector<T>>;
+
struct ResTable::Type
{
Type(const Header* _header, const Package* _package, size_t count)
@@ -3158,6 +3162,10 @@
const uint32_t* typeSpecFlags;
IdmapEntries idmapEntries;
Vector<const ResTable_type*> configs;
+
+ // The set of configurations that match the current parameters.
+ // This will be swapped with a new set when the parameters change.
+ SharedVector<const ResTable_type*> filteredConfigs;
};
struct ResTable::Package
@@ -4430,18 +4438,44 @@
void ResTable::setParameters(const ResTable_config* params)
{
- mLock.lock();
+ AutoMutex _lock(mLock);
+ AutoMutex _lock2(mFilteredConfigLock);
+
if (kDebugTableGetEntry) {
ALOGI("Setting parameters: %s\n", params->toString().string());
}
mParams = *params;
- for (size_t i=0; i<mPackageGroups.size(); i++) {
+ for (size_t p = 0; p < mPackageGroups.size(); p++) {
+ PackageGroup* packageGroup = mPackageGroups.editItemAt(p);
if (kDebugTableNoisy) {
- ALOGI("CLEARING BAGS FOR GROUP %zu!", i);
+ ALOGI("CLEARING BAGS FOR GROUP %zu!", p);
}
- mPackageGroups[i]->clearBagCache();
+ packageGroup->clearBagCache();
+
+ for (size_t t = 0; t < packageGroup->types.size(); t++) {
+ TypeList& typeList = packageGroup->types.editItemAt(t);
+ for (size_t ts = 0; ts < typeList.size(); ts++) {
+ Type* type = typeList.editItemAt(ts);
+
+ SharedVector<const ResTable_type*> newFilteredConfigs =
+ std::make_shared<Vector<const ResTable_type*>>();
+ for (size_t ti = 0; ti < type->configs.size(); ti++) {
+ ResTable_config config;
+ config.copyFromDtoH(type->configs[ti]->config);
+
+ if (config.match(mParams)) {
+ newFilteredConfigs->add(type->configs[ti]);
+ }
+ }
+
+ if (kDebugTableNoisy) {
+ ALOGD("Updating pkg=%zu type=%zu with %zu filtered configs",
+ p, t, newFilteredConfigs->size());
+ }
+ type->filteredConfigs = newFilteredConfigs;
+ }
+ }
}
- mLock.unlock();
}
void ResTable::getParameters(ResTable_config* params) const
@@ -5974,9 +6008,29 @@
specFlags = -1;
}
- const size_t numConfigs = typeSpec->configs.size();
+ const Vector<const ResTable_type*>* candidateConfigs = &typeSpec->configs;
+
+ SharedVector<const ResTable_type*> filteredConfigs;
+ if (config && memcmp(&mParams, config, sizeof(mParams)) == 0) {
+ // Grab the lock first so we can safely get the current filtered list.
+ AutoMutex _lock(mFilteredConfigLock);
+
+ // This configuration is equal to the one we have previously cached for,
+ // so use the filtered configs.
+
+ if (typeSpec->filteredConfigs) {
+ // Grab a reference to the shared_ptr so it doesn't get destroyed while
+ // going through this list.
+ filteredConfigs = typeSpec->filteredConfigs;
+
+ // Use this filtered list.
+ candidateConfigs = filteredConfigs.get();
+ }
+ }
+
+ const size_t numConfigs = candidateConfigs->size();
for (size_t c = 0; c < numConfigs; c++) {
- const ResTable_type* const thisType = typeSpec->configs[c];
+ const ResTable_type* const thisType = candidateConfigs->itemAt(c);
if (thisType == NULL) {
continue;
}
diff --git a/libs/androidfw/tests/ConfigLocale_test.cpp b/libs/androidfw/tests/ConfigLocale_test.cpp
index 4b8d65c..2bf9b12 100644
--- a/libs/androidfw/tests/ConfigLocale_test.cpp
+++ b/libs/androidfw/tests/ConfigLocale_test.cpp
@@ -125,10 +125,10 @@
if (script != NULL) {
memcpy(out->localeScript, script, 4);
- out->localeScriptWasProvided = true;
+ out->localeScriptWasComputed = false;
} else {
out->computeScript();
- out->localeScriptWasProvided = false;
+ out->localeScriptWasComputed = true;
}
if (variant != NULL) {
@@ -182,7 +182,7 @@
EXPECT_EQ('n', test.language[1]);
EXPECT_EQ('U', test.country[0]);
EXPECT_EQ('S', test.country[1]);
- EXPECT_FALSE(test.localeScriptWasProvided);
+ EXPECT_TRUE(test.localeScriptWasComputed);
EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4));
EXPECT_EQ(0, test.localeVariant[0]);
@@ -203,7 +203,7 @@
EXPECT_EQ('e', test.language[0]);
EXPECT_EQ('n', test.language[1]);
EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4));
- EXPECT_TRUE(test.localeScriptWasProvided);
+ EXPECT_FALSE(test.localeScriptWasComputed);
memset(out, 1, 4);
test.unpackRegion(out);
EXPECT_EQ('4', out[0]);
@@ -216,7 +216,7 @@
EXPECT_EQ('d', out[0]);
EXPECT_EQ('e', out[1]);
EXPECT_EQ('\0', out[2]);
- EXPECT_FALSE(test.localeScriptWasProvided);
+ EXPECT_TRUE(test.localeScriptWasComputed);
EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4));
memset(out, 1, 4);
test.unpackRegion(out);
@@ -229,7 +229,7 @@
EXPECT_EQ('d', out[0]);
EXPECT_EQ('e', out[1]);
EXPECT_EQ('\0', out[2]);
- EXPECT_TRUE(test.localeScriptWasProvided);
+ EXPECT_FALSE(test.localeScriptWasComputed);
EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4));
memset(out, 1, 4);
test.unpackRegion(out);
@@ -270,11 +270,11 @@
fillIn("en", NULL, "Latn", NULL, &config);
char out[RESTABLE_MAX_LOCALE_LEN];
- config.localeScriptWasProvided = true;
+ config.localeScriptWasComputed = false;
config.getBcp47Locale(out);
EXPECT_EQ(0, strcmp("en-Latn", out));
- config.localeScriptWasProvided = false;
+ config.localeScriptWasComputed = true;
config.getBcp47Locale(out);
EXPECT_EQ(0, strcmp("en", out));
}
@@ -379,7 +379,7 @@
// emulate packages built with older AAPT
memset(supported.localeScript, '\0', 4);
- supported.localeScriptWasProvided = false;
+ supported.localeScriptWasComputed = false;
EXPECT_TRUE(supported.match(requested));
}
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 6257122..70995ac 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -7,7 +7,7 @@
# Enables fine-grained GLES error checking
# If set to true, every GLES call is wrapped & error checked
# Has moderate overhead
-HWUI_ENABLE_OPENGL_VALIDATION := false
+HWUI_ENABLE_OPENGL_VALIDATION := true
hwui_src_files := \
font/CacheTexture.cpp \
@@ -119,6 +119,7 @@
BakedOpState.cpp \
FrameBuilder.cpp \
LayerBuilder.cpp \
+ OpDumper.cpp \
RecordingCanvas.cpp
hwui_cflags += -DHWUI_NEW_OPS
@@ -241,6 +242,7 @@
tests/unit/GpuMemoryTrackerTests.cpp \
tests/unit/LayerUpdateQueueTests.cpp \
tests/unit/LinearAllocatorTests.cpp \
+ tests/unit/MatrixTests.cpp \
tests/unit/OffscreenBufferPoolTests.cpp \
tests/unit/SkiaBehaviorTests.cpp \
tests/unit/StringUtilsTests.cpp \
@@ -253,6 +255,7 @@
tests/unit/BakedOpStateTests.cpp \
tests/unit/FrameBuilderTests.cpp \
tests/unit/LeakCheckTests.cpp \
+ tests/unit/OpDumperTests.cpp \
tests/unit/RecordingCanvasTests.cpp
endif
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index 7bd2b24..bd71e0d 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -33,6 +33,7 @@
BaseRenderNodeAnimator::BaseRenderNodeAnimator(float finalValue)
: mTarget(nullptr)
+ , mStagingTarget(nullptr)
, mFinalValue(finalValue)
, mDeltaValue(0)
, mFromValue(0)
@@ -42,7 +43,8 @@
, mStartTime(0)
, mDuration(300)
, mStartDelay(0)
- , mMayRunAsync(true) {
+ , mMayRunAsync(true)
+ , mPlayTime(0) {
}
BaseRenderNodeAnimator::~BaseRenderNodeAnimator() {
@@ -81,26 +83,133 @@
}
void BaseRenderNodeAnimator::attach(RenderNode* target) {
- mTarget = target;
+ mStagingTarget = target;
onAttached();
}
+void BaseRenderNodeAnimator::start() {
+ mStagingPlayState = PlayState::Running;
+ mStagingRequests.push_back(Request::Start);
+ onStagingPlayStateChanged();
+}
+
+void BaseRenderNodeAnimator::cancel() {
+ mStagingPlayState = PlayState::Finished;
+ mStagingRequests.push_back(Request::Cancel);
+ onStagingPlayStateChanged();
+}
+
+void BaseRenderNodeAnimator::reset() {
+ mStagingPlayState = PlayState::Finished;
+ mStagingRequests.push_back(Request::Reset);
+ onStagingPlayStateChanged();
+}
+
+void BaseRenderNodeAnimator::reverse() {
+ mStagingPlayState = PlayState::Reversing;
+ mStagingRequests.push_back(Request::Reverse);
+ onStagingPlayStateChanged();
+}
+
+void BaseRenderNodeAnimator::end() {
+ mStagingPlayState = PlayState::Finished;
+ mStagingRequests.push_back(Request::End);
+ onStagingPlayStateChanged();
+}
+
+void BaseRenderNodeAnimator::resolveStagingRequest(Request request) {
+ switch (request) {
+ case Request::Start:
+ mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) ?
+ mPlayTime : 0;
+ mPlayState = PlayState::Running;
+ break;
+ case Request::Reverse:
+ mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) ?
+ mPlayTime : mDuration;
+ mPlayState = PlayState::Reversing;
+ break;
+ case Request::Reset:
+ mPlayTime = 0;
+ mPlayState = PlayState::Finished;
+ break;
+ case Request::Cancel:
+ mPlayState = PlayState::Finished;
+ break;
+ case Request::End:
+ mPlayTime = mPlayState == PlayState::Reversing ? 0 : mDuration;
+ mPlayState = PlayState::Finished;
+ break;
+ default:
+ LOG_ALWAYS_FATAL("Invalid staging request: %d", static_cast<int>(request));
+ };
+}
+
void BaseRenderNodeAnimator::pushStaging(AnimationContext& context) {
+ if (mStagingTarget) {
+ RenderNode* oldTarget = mTarget;
+ mTarget = mStagingTarget;
+ mStagingTarget = nullptr;
+ if (oldTarget && oldTarget != mTarget) {
+ oldTarget->onAnimatorTargetChanged(this);
+ }
+ }
+
if (!mHasStartValue) {
doSetStartValue(getValue(mTarget));
}
- if (mStagingPlayState > mPlayState) {
- if (mStagingPlayState == PlayState::Restarted) {
- mStagingPlayState = PlayState::Running;
+
+ if (!mStagingRequests.empty()) {
+ // No interpolator was set, use the default
+ if (mPlayState == PlayState::NotStarted && !mInterpolator) {
+ mInterpolator.reset(Interpolator::createDefaultInterpolator());
}
- mPlayState = mStagingPlayState;
- // Oh boy, we're starting! Man the battle stations!
- if (mPlayState == PlayState::Running) {
- transitionToRunning(context);
- } else if (mPlayState == PlayState::Finished) {
+ // Keep track of the play state and play time before they are changed when
+ // staging requests are resolved.
+ nsecs_t currentPlayTime = mPlayTime;
+ PlayState prevFramePlayState = mPlayState;
+
+ // Resolve staging requests one by one.
+ for (Request request : mStagingRequests) {
+ resolveStagingRequest(request);
+ }
+ mStagingRequests.clear();
+
+ if (mStagingPlayState == PlayState::Finished) {
+ // Set the staging play time and end the animation
+ updatePlayTime(mPlayTime);
callOnFinishedListener(context);
+ } else if (mStagingPlayState == PlayState::Running
+ || mStagingPlayState == PlayState::Reversing) {
+ bool changed = currentPlayTime != mPlayTime || prevFramePlayState != mStagingPlayState;
+ if (prevFramePlayState != mStagingPlayState) {
+ transitionToRunning(context);
+ }
+ if (changed) {
+ // Now we need to seek to the stagingPlayTime (i.e. the animation progress that was
+ // requested from UI thread). It is achieved by modifying mStartTime, such that
+ // current time - mStartTime = stagingPlayTime (or mDuration -stagingPlayTime in the
+ // case of reversing)
+ nsecs_t currentFrameTime = context.frameTimeMs();
+ if (mPlayState == PlayState::Reversing) {
+ // Reverse is not supported for animations with a start delay, so here we
+ // assume no start delay.
+ mStartTime = currentFrameTime - (mDuration - mPlayTime);
+ } else {
+ // Animation should play forward
+ if (mPlayTime == 0) {
+ // If the request is to start from the beginning, include start delay.
+ mStartTime = currentFrameTime + mStartDelay;
+ } else {
+ // If the request is to seek to a non-zero play time, then we skip start
+ // delay.
+ mStartTime = currentFrameTime - mPlayTime;
+ }
+ }
+ }
}
}
+ onPushStaging();
}
void BaseRenderNodeAnimator::transitionToRunning(AnimationContext& context) {
@@ -117,10 +226,6 @@
// Set to 0 so that the animate() basically instantly finishes
mStartTime = 0;
}
- // No interpolator was set, use the default
- if (!mInterpolator) {
- mInterpolator.reset(Interpolator::createDefaultInterpolator());
- }
if (mDuration < 0 || mDuration > 50000) {
ALOGW("Your duration is strange and confusing: %" PRId64, mDuration);
}
@@ -136,37 +241,37 @@
// This should be set before setValue() so animators can query this time when setValue
// is called.
- nsecs_t currentFrameTime = context.frameTimeMs();
- onPlayTimeChanged(currentFrameTime - mStartTime);
+ nsecs_t currentPlayTime = context.frameTimeMs() - mStartTime;
+ bool finished = updatePlayTime(currentPlayTime);
+ if (finished && mPlayState != PlayState::Finished) {
+ mPlayState = PlayState::Finished;
+ callOnFinishedListener(context);
+ }
+ return finished;
+}
+bool BaseRenderNodeAnimator::updatePlayTime(nsecs_t playTime) {
+ mPlayTime = mPlayState == PlayState::Reversing ? mDuration - playTime : playTime;
+ onPlayTimeChanged(mPlayTime);
// If BaseRenderNodeAnimator is handling the delay (not typical), then
// because the staging properties reflect the final value, we always need
// to call setValue even if the animation isn't yet running or is still
// being delayed as we need to override the staging value
- if (mStartTime > context.frameTimeMs()) {
+ if (playTime < 0) {
setValue(mTarget, mFromValue);
return false;
}
float fraction = 1.0f;
-
- if (mPlayState == PlayState::Running && mDuration > 0) {
- fraction = (float)(currentFrameTime - mStartTime) / mDuration;
+ if ((mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) && mDuration > 0) {
+ fraction = mPlayTime / (float) mDuration;
}
- if (fraction >= 1.0f) {
- fraction = 1.0f;
- mPlayState = PlayState::Finished;
- }
+ fraction = MathUtils::clamp(fraction, 0.0f, 1.0f);
fraction = mInterpolator->interpolate(fraction);
setValue(mTarget, mFromValue + (mDeltaValue * fraction));
- if (mPlayState == PlayState::Finished) {
- callOnFinishedListener(context);
- return true;
- }
-
- return false;
+ return playTime >= mDuration;
}
void BaseRenderNodeAnimator::forceEndNow(AnimationContext& context) {
@@ -215,18 +320,36 @@
void RenderPropertyAnimator::onAttached() {
if (!mHasStartValue
- && mTarget->isPropertyFieldDirty(mPropertyAccess->dirtyMask)) {
- setStartValue((mTarget->stagingProperties().*mPropertyAccess->getter)());
+ && mStagingTarget->isPropertyFieldDirty(mPropertyAccess->dirtyMask)) {
+ setStartValue((mStagingTarget->stagingProperties().*mPropertyAccess->getter)());
}
}
void RenderPropertyAnimator::onStagingPlayStateChanged() {
if (mStagingPlayState == PlayState::Running) {
- (mTarget->mutateStagingProperties().*mPropertyAccess->setter)(finalValue());
+ if (mStagingTarget) {
+ (mStagingTarget->mutateStagingProperties().*mPropertyAccess->setter)(finalValue());
+ } else {
+ // In the case of start delay where stagingTarget has been sync'ed over and null'ed
+ // we delay the properties update to push staging.
+ mShouldUpdateStagingProperties = true;
+ }
} else if (mStagingPlayState == PlayState::Finished) {
// We're being canceled, so make sure that whatever values the UI thread
// is observing for us is pushed over
+ mShouldSyncPropertyFields = true;
+ }
+}
+
+void RenderPropertyAnimator::onPushStaging() {
+ if (mShouldUpdateStagingProperties) {
+ (mTarget->mutateStagingProperties().*mPropertyAccess->setter)(finalValue());
+ mShouldUpdateStagingProperties = false;
+ }
+
+ if (mShouldSyncPropertyFields) {
mTarget->setPropertyFieldsDirty(dirtyMask());
+ mShouldSyncPropertyFields = false;
}
}
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index 2c9c9c3..fdae0f3 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -24,6 +24,8 @@
#include "utils/Macros.h"
+#include <vector>
+
namespace android {
namespace uirenderer {
@@ -59,14 +61,14 @@
mMayRunAsync = mayRunAsync;
}
bool mayRunAsync() { return mMayRunAsync; }
- ANDROID_API void start() {
- if (mStagingPlayState == PlayState::NotStarted) {
- mStagingPlayState = PlayState::Running;
- } else {
- mStagingPlayState = PlayState::Restarted;
- }
- onStagingPlayStateChanged(); }
- ANDROID_API void end() { mStagingPlayState = PlayState::Finished; onStagingPlayStateChanged(); }
+ ANDROID_API void start();
+ ANDROID_API void reset();
+ ANDROID_API void reverse();
+ // Terminates the animation at its current progress.
+ ANDROID_API void cancel();
+
+ // Terminates the animation and skip to the end of the animation.
+ ANDROID_API void end();
void attach(RenderNode* target);
virtual void onAttached() {}
@@ -74,36 +76,42 @@
void pushStaging(AnimationContext& context);
bool animate(AnimationContext& context);
- bool isRunning() { return mPlayState == PlayState::Running; }
+ bool isRunning() { return mPlayState == PlayState::Running
+ || mPlayState == PlayState::Reversing; }
bool isFinished() { return mPlayState == PlayState::Finished; }
float finalValue() { return mFinalValue; }
ANDROID_API virtual uint32_t dirtyMask() = 0;
void forceEndNow(AnimationContext& context);
+ RenderNode* target() { return mTarget; }
+ RenderNode* stagingTarget() { return mStagingTarget; }
protected:
// PlayState is used by mStagingPlayState and mPlayState to track the state initiated from UI
// thread and Render Thread animation state, respectively.
// From the UI thread, mStagingPlayState transition looks like
- // NotStarted -> Running -> Finished
- // ^ |
- // | |
- // Restarted <------
+ // NotStarted -> Running/Reversing -> Finished
+ // ^ |
+ // | |
+ // ----------------------
// Note: For mStagingState, the Finished state (optional) is only set when the animation is
// terminated by user.
//
// On Render Thread, mPlayState transition:
- // NotStart -> Running -> Finished
- // ^ |
- // | |
- // -------------
+ // NotStart -> Running/Reversing-> Finished
+ // ^ |
+ // | |
+ // ------------------
+ // Note that if the animation is in Running/Reversing state, calling start or reverse again
+ // would do nothing if the animation has the same play direction as the request; otherwise,
+ // the animation would start from where it is and change direction (i.e. Reversing <-> Running)
enum class PlayState {
NotStarted,
Running,
+ Reversing,
Finished,
- Restarted,
};
BaseRenderNodeAnimator(float finalValue);
@@ -111,14 +119,15 @@
virtual float getValue(RenderNode* target) const = 0;
virtual void setValue(RenderNode* target, float value) = 0;
- RenderNode* target() { return mTarget; }
void callOnFinishedListener(AnimationContext& context);
virtual void onStagingPlayStateChanged() {}
virtual void onPlayTimeChanged(nsecs_t playTime) {}
+ virtual void onPushStaging() {}
RenderNode* mTarget;
+ RenderNode* mStagingTarget;
float mFinalValue;
float mDeltaValue;
@@ -132,13 +141,28 @@
nsecs_t mDuration;
nsecs_t mStartDelay;
bool mMayRunAsync;
+ // Play Time tracks the progress of animation, it should always be [0, mDuration], 0 being
+ // the beginning of the animation, will reach mDuration at the end of an animation.
+ nsecs_t mPlayTime;
sp<AnimationListener> mListener;
private:
+ enum class Request {
+ Start,
+ Reverse,
+ Reset,
+ Cancel,
+ End
+ };
inline void checkMutable();
virtual void transitionToRunning(AnimationContext& context);
void doSetStartValue(float value);
+ bool updatePlayTime(nsecs_t playTime);
+ void resolveStagingRequest(Request request);
+
+ std::vector<Request> mStagingRequests;
+
};
class RenderPropertyAnimator : public BaseRenderNodeAnimator {
@@ -167,6 +191,7 @@
virtual void setValue(RenderNode* target, float value) override;
virtual void onAttached() override;
virtual void onStagingPlayStateChanged() override;
+ virtual void onPushStaging() override;
private:
typedef bool (RenderProperties::*SetFloatProperty)(float value);
@@ -176,6 +201,8 @@
const PropertyAccessors* mPropertyAccess;
static const PropertyAccessors PROPERTY_ACCESSOR_LUT[];
+ bool mShouldSyncPropertyFields = false;
+ bool mShouldUpdateStagingProperties = false;
};
class CanvasPropertyPrimitiveAnimator : public BaseRenderNodeAnimator {
diff --git a/libs/hwui/AnimatorManager.cpp b/libs/hwui/AnimatorManager.cpp
index cd30b18..f170e9c 100644
--- a/libs/hwui/AnimatorManager.cpp
+++ b/libs/hwui/AnimatorManager.cpp
@@ -27,9 +27,8 @@
using namespace std;
-static void unref(BaseRenderNodeAnimator* animator) {
+static void detach(sp<BaseRenderNodeAnimator>& animator) {
animator->detach();
- animator->decStrong(nullptr);
}
AnimatorManager::AnimatorManager(RenderNode& parent)
@@ -38,14 +37,28 @@
}
AnimatorManager::~AnimatorManager() {
- for_each(mNewAnimators.begin(), mNewAnimators.end(), unref);
- for_each(mAnimators.begin(), mAnimators.end(), unref);
+ for_each(mNewAnimators.begin(), mNewAnimators.end(), detach);
+ for_each(mAnimators.begin(), mAnimators.end(), detach);
}
void AnimatorManager::addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
- animator->incStrong(nullptr);
+ RenderNode* stagingTarget = animator->stagingTarget();
+ if (stagingTarget == &mParent) {
+ return;
+ }
+ mNewAnimators.emplace_back(animator.get());
+ // If the animator is already attached to other RenderNode, remove it from that RenderNode's
+ // new animator list. This ensures one animator only ends up in one newAnimatorList during one
+ // frame, even when it's added multiple times to multiple targets.
+ if (stagingTarget) {
+ stagingTarget->removeAnimator(animator);
+ }
animator->attach(&mParent);
- mNewAnimators.push_back(animator.get());
+}
+
+void AnimatorManager::removeAnimator(const sp<BaseRenderNodeAnimator>& animator) {
+ mNewAnimators.erase(std::remove(mNewAnimators.begin(), mNewAnimators.end(), animator),
+ mNewAnimators.end());
}
void AnimatorManager::setAnimationHandle(AnimationHandle* handle) {
@@ -56,38 +69,40 @@
&mParent, mParent.getName());
}
-template<typename T>
-static void move_all(T& source, T& dest) {
- dest.reserve(source.size() + dest.size());
- for (typename T::iterator it = source.begin(); it != source.end(); it++) {
- dest.push_back(*it);
- }
- source.clear();
-}
-
void AnimatorManager::pushStaging() {
if (mNewAnimators.size()) {
LOG_ALWAYS_FATAL_IF(!mAnimationHandle,
"Trying to start new animators on %p (%s) without an animation handle!",
&mParent, mParent.getName());
- // Since this is a straight move, we don't need to inc/dec the ref count
- move_all(mNewAnimators, mAnimators);
+
+ // Only add new animators that are not already in the mAnimators list
+ for (auto& anim : mNewAnimators) {
+ if (anim->target() != &mParent) {
+ mAnimators.push_back(std::move(anim));
+ }
+ }
+ mNewAnimators.clear();
}
- for (vector<BaseRenderNodeAnimator*>::iterator it = mAnimators.begin(); it != mAnimators.end(); it++) {
- (*it)->pushStaging(mAnimationHandle->context());
+ for (auto& animator : mAnimators) {
+ animator->pushStaging(mAnimationHandle->context());
}
}
+void AnimatorManager::onAnimatorTargetChanged(BaseRenderNodeAnimator* animator) {
+ LOG_ALWAYS_FATAL_IF(animator->target() == &mParent, "Target has not been changed");
+ mAnimators.erase(std::remove(mAnimators.begin(), mAnimators.end(), animator), mAnimators.end());
+}
+
class AnimateFunctor {
public:
- AnimateFunctor(TreeInfo& info, AnimationContext& context)
- : dirtyMask(0), mInfo(info), mContext(context) {}
+ AnimateFunctor(TreeInfo& info, AnimationContext& context, uint32_t* outDirtyMask)
+ : mInfo(info), mContext(context), mDirtyMask(outDirtyMask) {}
- bool operator() (BaseRenderNodeAnimator* animator) {
- dirtyMask |= animator->dirtyMask();
+ bool operator() (sp<BaseRenderNodeAnimator>& animator) {
+ *mDirtyMask |= animator->dirtyMask();
bool remove = animator->animate(mContext);
if (remove) {
- animator->decStrong(nullptr);
+ animator->detach();
} else {
if (animator->isRunning()) {
mInfo.out.hasAnimations = true;
@@ -99,11 +114,10 @@
return remove;
}
- uint32_t dirtyMask;
-
private:
TreeInfo& mInfo;
AnimationContext& mContext;
+ uint32_t* mDirtyMask;
};
uint32_t AnimatorManager::animate(TreeInfo& info) {
@@ -128,21 +142,20 @@
}
uint32_t AnimatorManager::animateCommon(TreeInfo& info) {
- AnimateFunctor functor(info, mAnimationHandle->context());
- std::vector< BaseRenderNodeAnimator* >::iterator newEnd;
- newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
+ uint32_t dirtyMask;
+ AnimateFunctor functor(info, mAnimationHandle->context(), &dirtyMask);
+ auto newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
mAnimators.erase(newEnd, mAnimators.end());
mAnimationHandle->notifyAnimationsRan();
mParent.mProperties.updateMatrix();
- return functor.dirtyMask;
+ return dirtyMask;
}
-static void endStagingAnimator(BaseRenderNodeAnimator* animator) {
- animator->end();
+static void endStagingAnimator(sp<BaseRenderNodeAnimator>& animator) {
+ animator->cancel();
if (animator->listener()) {
- animator->listener()->onAnimationFinished(animator);
+ animator->listener()->onAnimationFinished(animator.get());
}
- animator->decStrong(nullptr);
}
void AnimatorManager::endAllStagingAnimators() {
@@ -157,9 +170,8 @@
public:
EndActiveAnimatorsFunctor(AnimationContext& context) : mContext(context) {}
- void operator() (BaseRenderNodeAnimator* animator) {
+ void operator() (sp<BaseRenderNodeAnimator>& animator) {
animator->forceEndNow(mContext);
- animator->decStrong(nullptr);
}
private:
diff --git a/libs/hwui/AnimatorManager.h b/libs/hwui/AnimatorManager.h
index fb75eb8..61f6179 100644
--- a/libs/hwui/AnimatorManager.h
+++ b/libs/hwui/AnimatorManager.h
@@ -39,11 +39,13 @@
~AnimatorManager();
void addAnimator(const sp<BaseRenderNodeAnimator>& animator);
+ void removeAnimator(const sp<BaseRenderNodeAnimator>& animator);
void setAnimationHandle(AnimationHandle* handle);
bool hasAnimationHandle() { return mAnimationHandle; }
void pushStaging();
+ void onAnimatorTargetChanged(BaseRenderNodeAnimator* animator);
// Returns the combined dirty mask of all animators run
uint32_t animate(TreeInfo& info);
@@ -66,9 +68,8 @@
AnimationHandle* mAnimationHandle;
// To improve the efficiency of resizing & removing from the vector
- // use manual ref counting instead of sp<>.
- std::vector<BaseRenderNodeAnimator*> mNewAnimators;
- std::vector<BaseRenderNodeAnimator*> mAnimators;
+ std::vector< sp<BaseRenderNodeAnimator> > mNewAnimators;
+ std::vector< sp<BaseRenderNodeAnimator> > mAnimators;
};
} /* namespace uirenderer */
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp
index f83e1fa..06b712e 100644
--- a/libs/hwui/BakedOpDispatcher.cpp
+++ b/libs/hwui/BakedOpDispatcher.cpp
@@ -30,6 +30,7 @@
#include <algorithm>
#include <math.h>
#include <SkPaintDefaults.h>
+#include <SkPathOps.h>
namespace android {
namespace uirenderer {
@@ -60,7 +61,10 @@
for (size_t i = 0; i < opList.count; i++) {
const BakedOpState& state = *(opList.states[i]);
TextureVertex* rectVerts = &vertices[i * 4];
- Rect opBounds = state.computedState.clippedBounds;
+
+ // calculate unclipped bounds, since they'll determine texture coordinates
+ Rect opBounds = state.op->unmappedBounds;
+ state.computedState.transform.mapRect(opBounds);
if (CC_LIKELY(state.computedState.transform.isPureTranslate())) {
// pure translate, so snap (same behavior as onBitmapOp)
opBounds.snapToPixelBoundaries();
@@ -334,15 +338,15 @@
}
static void renderPathTexture(BakedOpRenderer& renderer, const BakedOpState& state,
- PathTexture& texture, const RecordedOp& op) {
+ float xOffset, float yOffset, PathTexture& texture, const SkPaint& paint) {
Rect dest(texture.width(), texture.height());
- dest.translate(texture.left - texture.offset,
- texture.top - texture.offset);
+ dest.translate(xOffset + texture.left - texture.offset,
+ yOffset + texture.top - texture.offset);
Glop glop;
GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
.setRoundRectClipState(state.roundRectClipState)
.setMeshTexturedUnitQuad(nullptr)
- .setFillPathTexturePaint(texture, *(op.paint), state.alpha)
+ .setFillPathTexturePaint(texture, paint, state.alpha)
.setTransform(state.computedState.transform, TransformFlags::None)
.setModelViewMapUnitToRect(dest)
.build();
@@ -368,7 +372,8 @@
op.startAngle, op.sweepAngle, op.useCenter, op.paint);
const AutoTexture holder(texture);
if (CC_LIKELY(holder.texture)) {
- renderPathTexture(renderer, state, *texture, op);
+ renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.top,
+ *texture, *(op.paint));
}
} else {
SkRect rect = getBoundsOfFill(op);
@@ -519,12 +524,19 @@
op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.paint);
const AutoTexture holder(texture);
if (CC_LIKELY(holder.texture)) {
- renderPathTexture(renderer, state, *texture, op);
+ renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.right,
+ *texture, *(op.paint));
}
} else {
SkPath path;
SkRect rect = getBoundsOfFill(op);
path.addOval(rect);
+
+ if (state.computedState.localProjectionPathMask != nullptr) {
+ // Mask the ripple path by the local space projection mask in local space.
+ // Note that this can create CCW paths.
+ Op(path, *state.computedState.localProjectionPathMask, kIntersect_SkPathOp, &path);
+ }
renderConvexPath(renderer, state, path, *(op.paint));
}
}
@@ -562,7 +574,9 @@
PathTexture* texture = renderer.caches().pathCache.get(op.path, op.paint);
const AutoTexture holder(texture);
if (CC_LIKELY(holder.texture)) {
- renderPathTexture(renderer, state, *texture, op);
+ // Unlike other callers to renderPathTexture, no offsets are used because PathOp doesn't
+ // have any translate built in, other than what's in the SkPath itself
+ renderPathTexture(renderer, state, 0, 0, *texture, *(op.paint));
}
}
@@ -588,7 +602,8 @@
op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.paint);
const AutoTexture holder(texture);
if (CC_LIKELY(holder.texture)) {
- renderPathTexture(renderer, state, *texture, op);
+ renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.top,
+ *texture, *(op.paint));
}
} else {
SkPath path;
@@ -622,7 +637,8 @@
op.rx, op.ry, op.paint);
const AutoTexture holder(texture);
if (CC_LIKELY(holder.texture)) {
- renderPathTexture(renderer, state, *texture, op);
+ renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.top,
+ *texture, *(op.paint));
}
} else {
const VertexBuffer* buffer = renderer.caches().tessellationCache.getRoundRect(
diff --git a/libs/hwui/BakedOpRenderer.cpp b/libs/hwui/BakedOpRenderer.cpp
index 35c8f6b..98493d7 100644
--- a/libs/hwui/BakedOpRenderer.cpp
+++ b/libs/hwui/BakedOpRenderer.cpp
@@ -135,17 +135,7 @@
mRenderState.stencil().disable();
}
- mCaches.clearGarbage();
- mCaches.pathCache.trim();
- mCaches.tessellationCache.trim();
-
-#if DEBUG_MEMORY_USAGE
- mCaches.dumpMemoryUsage();
-#else
- if (Properties::debugLevel & kDebugMemory) {
- mCaches.dumpMemoryUsage();
- }
-#endif
+ // Note: we leave FBO 0 renderable here, for post-frame-content decoration
}
void BakedOpRenderer::setViewport(uint32_t width, uint32_t height) {
@@ -179,6 +169,38 @@
return texture;
}
+void BakedOpRenderer::drawRects(const float* rects, int count, const SkPaint* paint) {
+ std::vector<Vertex> vertices;
+ vertices.reserve(count);
+ Vertex* vertex = vertices.data();
+
+ for (int index = 0; index < count; index += 4) {
+ float l = rects[index + 0];
+ float t = rects[index + 1];
+ float r = rects[index + 2];
+ float b = rects[index + 3];
+
+ Vertex::set(vertex++, l, t);
+ Vertex::set(vertex++, r, t);
+ Vertex::set(vertex++, l, b);
+ Vertex::set(vertex++, r, b);
+ }
+
+ LOG_ALWAYS_FATAL_IF(mRenderTarget.frameBufferId != 0, "decoration only supported for FBO 0");
+ // TODO: Currently assume full FBO damage, due to FrameInfoVisualizer::unionDirty.
+ // Should should scissor safely.
+ mRenderState.scissor().setEnabled(false);
+ Glop glop;
+ GlopBuilder(mRenderState, mCaches, &glop)
+ .setRoundRectClipState(nullptr)
+ .setMeshIndexedQuads(vertices.data(), count / 4)
+ .setFillPaint(*paint, 1.0f)
+ .setTransform(Matrix4::identity(), TransformFlags::None)
+ .setModelViewIdentityEmptyBounds()
+ .build();
+ mRenderState.render(glop, mRenderTarget.orthoMatrix);
+}
+
// clears and re-fills stencil with provided rendertarget space quads,
// and then put stencil into test mode
void BakedOpRenderer::setupStencilQuads(std::vector<Vertex>& quadVertices,
@@ -296,12 +318,9 @@
}
}
- // dirty offscreenbuffer
- if (dirtyBounds && mRenderTarget.offscreenBuffer) {
- // register layer damage to draw-back region
- android::Rect dirty(dirtyBounds->left, dirtyBounds->top,
- dirtyBounds->right, dirtyBounds->bottom);
- mRenderTarget.offscreenBuffer->region.orSelf(dirty);
+ if (dirtyBounds) {
+ // dirty offscreenbuffer if present
+ dirtyRenderTarget(*dirtyBounds);
}
}
@@ -329,29 +348,9 @@
mRenderState.invokeFunctor(op.functor, DrawGlInfo::kModeDraw, &info);
}
-#define VALIDATE_RECT_ARG(rect, arg) \
- ((isnanf(rect.arg) || rect.arg < -10000 || rect.arg > 10000) ? (\
- ALOGW("suspicious " #rect "." #arg "! %f", rect.arg),\
- false) : true)
-
-#define VALIDATE_RECT(rect) \
- VALIDATE_RECT_ARG(rect, bottom) & \
- VALIDATE_RECT_ARG(rect, left) & \
- VALIDATE_RECT_ARG(rect, top) & \
- VALIDATE_RECT_ARG(rect, right)
-
void BakedOpRenderer::dirtyRenderTarget(const Rect& uiDirty) {
if (mRenderTarget.offscreenBuffer) {
- bool valid = VALIDATE_RECT(uiDirty);
- android::Rect dirty;
- if (valid) {
- dirty = android::Rect(uiDirty.left, uiDirty.top, uiDirty.right, uiDirty.bottom);
- } else {
- dirty = android::Rect(0, 0,
- mRenderTarget.offscreenBuffer->viewportWidth,
- mRenderTarget.offscreenBuffer->viewportHeight);
- }
- mRenderTarget.offscreenBuffer->region.orSelf(dirty);
+ mRenderTarget.offscreenBuffer->dirty(uiDirty);
}
}
diff --git a/libs/hwui/BakedOpRenderer.h b/libs/hwui/BakedOpRenderer.h
index 55ea935..4b65255 100644
--- a/libs/hwui/BakedOpRenderer.h
+++ b/libs/hwui/BakedOpRenderer.h
@@ -85,6 +85,16 @@
bool offscreenRenderTarget() { return mRenderTarget.offscreenBuffer != nullptr; }
void dirtyRenderTarget(const Rect& dirtyRect);
bool didDraw() const { return mHasDrawn; }
+
+ uint32_t getViewportWidth() const { return mRenderTarget.viewportWidth; }
+ uint32_t getViewportHeight() const { return mRenderTarget.viewportHeight; }
+
+ // simple draw methods, to be used for end frame decoration
+ void drawRect(float left, float top, float right, float bottom, const SkPaint* paint) {
+ float ltrb[4] = { left, top, right, bottom };
+ drawRects(ltrb, 4, paint);
+ }
+ void drawRects(const float* rects, int count, const SkPaint* paint);
private:
void setViewport(uint32_t width, uint32_t height);
void clearColorBuffer(const Rect& clearRect);
diff --git a/libs/hwui/BakedOpState.cpp b/libs/hwui/BakedOpState.cpp
index a542c26..26653f7 100644
--- a/libs/hwui/BakedOpState.cpp
+++ b/libs/hwui/BakedOpState.cpp
@@ -21,6 +21,15 @@
namespace android {
namespace uirenderer {
+static int computeClipSideFlags(const Rect& clip, const Rect& bounds) {
+ int clipSideFlags = 0;
+ if (clip.left > bounds.left) clipSideFlags |= OpClipSideFlags::Left;
+ if (clip.top > bounds.top) clipSideFlags |= OpClipSideFlags::Top;
+ if (clip.right < bounds.right) clipSideFlags |= OpClipSideFlags::Right;
+ if (clip.bottom < bounds.bottom) clipSideFlags |= OpClipSideFlags::Bottom;
+ return clipSideFlags;
+}
+
ResolvedRenderState::ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot,
const RecordedOp& recordedOp, bool expandForStroke) {
// resolvedMatrix = parentMatrix * localMatrix
@@ -54,12 +63,22 @@
clipState = nullptr;
clippedBounds.setEmpty();
} else {
- // Not rejected! compute true clippedBounds and clipSideFlags
- if (clipRect.left > clippedBounds.left) clipSideFlags |= OpClipSideFlags::Left;
- if (clipRect.top > clippedBounds.top) clipSideFlags |= OpClipSideFlags::Top;
- if (clipRect.right < clippedBounds.right) clipSideFlags |= OpClipSideFlags::Right;
- if (clipRect.bottom < clippedBounds.bottom) clipSideFlags |= OpClipSideFlags::Bottom;
+ // Not rejected! compute true clippedBounds, clipSideFlags, and path mask
+ clipSideFlags = computeClipSideFlags(clipRect, clippedBounds);
clippedBounds.doIntersect(clipRect);
+
+ if (CC_UNLIKELY(snapshot.projectionPathMask)) {
+ // map projection path mask from render target space into op space,
+ // so intersection with op geometry is possible
+ Matrix4 inverseTransform;
+ inverseTransform.loadInverse(transform);
+ SkMatrix skInverseTransform;
+ inverseTransform.copyTo(skInverseTransform);
+
+ auto localMask = allocator.create<SkPath>();
+ snapshot.projectionPathMask->transform(skInverseTransform, localMask);
+ localProjectionPathMask = localMask;
+ }
}
}
@@ -67,13 +86,17 @@
: transform(*snapshot.transform)
, clipState(snapshot.mutateClipArea().serializeClip(allocator))
, clippedBounds(clipState->rect)
- , clipSideFlags(OpClipSideFlags::Full) {}
+ , clipSideFlags(OpClipSideFlags::Full)
+ , localProjectionPathMask(nullptr) {}
-ResolvedRenderState::ResolvedRenderState(const ClipRect* viewportRect, const Rect& dstRect)
+ResolvedRenderState::ResolvedRenderState(const ClipRect* clipRect, const Rect& dstRect)
: transform(Matrix4::identity())
- , clipState(viewportRect)
+ , clipState(clipRect)
, clippedBounds(dstRect)
- , clipSideFlags(OpClipSideFlags::None) {}
+ , clipSideFlags(computeClipSideFlags(clipRect->rect, dstRect))
+ , localProjectionPathMask(nullptr) {
+ clippedBounds.doIntersect(clipRect->rect);
+}
} // namespace uirenderer
} // namespace android
diff --git a/libs/hwui/BakedOpState.h b/libs/hwui/BakedOpState.h
index 5a5845a..ffe2901 100644
--- a/libs/hwui/BakedOpState.h
+++ b/libs/hwui/BakedOpState.h
@@ -88,6 +88,7 @@
const ClipBase* clipState = nullptr;
Rect clippedBounds;
int clipSideFlags = 0;
+ const SkPath* localProjectionPathMask = nullptr;
};
/**
@@ -154,7 +155,6 @@
// simple state (straight pointer/value storage):
const float alpha;
const RoundRectClipState* roundRectClipState;
- const ProjectionPathMask* projectionPathMask;
const RecordedOp* op;
private:
@@ -165,21 +165,18 @@
: computedState(allocator, snapshot, recordedOp, expandForStroke)
, alpha(snapshot.alpha)
, roundRectClipState(snapshot.roundRectClipState)
- , projectionPathMask(snapshot.projectionPathMask)
, op(&recordedOp) {}
BakedOpState(LinearAllocator& allocator, Snapshot& snapshot, const ShadowOp* shadowOpPtr)
: computedState(allocator, snapshot)
, alpha(snapshot.alpha)
, roundRectClipState(snapshot.roundRectClipState)
- , projectionPathMask(snapshot.projectionPathMask)
, op(shadowOpPtr) {}
- BakedOpState(const ClipRect* viewportRect, const Rect& dstRect, const RecordedOp& recordedOp)
- : computedState(viewportRect, dstRect)
+ BakedOpState(const ClipRect* clipRect, const Rect& dstRect, const RecordedOp& recordedOp)
+ : computedState(clipRect, dstRect)
, alpha(1.0f)
, roundRectClipState(nullptr)
- , projectionPathMask(nullptr)
, op(&recordedOp) {}
};
diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp
index e368537..afe9807 100644
--- a/libs/hwui/ClipArea.cpp
+++ b/libs/hwui/ClipArea.cpp
@@ -375,15 +375,13 @@
serialization->rect.set(mClipRegion.getBounds());
break;
}
+ // TODO: this is only done for draw time, should eventually avoid for record time
+ serialization->rect.snapToPixelBoundaries();
mLastSerialization = serialization;
}
return mLastSerialization;
}
-inline static const Rect& getRect(const ClipBase* scb) {
- return reinterpret_cast<const ClipRect*>(scb)->rect;
-}
-
inline static const RectangleList& getRectList(const ClipBase* scb) {
return reinterpret_cast<const ClipRectList*>(scb)->rectList;
}
@@ -404,11 +402,17 @@
return currentRectCount + recordedRectCount > RectangleList::kMaxTransformedRectangles;
}
+static const ClipRect sEmptyClipRect(Rect(0, 0));
+
const ClipBase* ClipArea::serializeIntersectedClip(LinearAllocator& allocator,
const ClipBase* recordedClip, const Matrix4& recordedClipTransform) {
+
// if no recordedClip passed, just serialize current state
if (!recordedClip) return serializeClip(allocator);
+ // if either is empty, clip is empty
+ if (CC_UNLIKELY(recordedClip->rect.isEmpty())|| mClipRect.isEmpty()) return &sEmptyClipRect;
+
if (!mLastResolutionResult
|| recordedClip != mLastResolutionClip
|| recordedClipTransform != mLastResolutionTransform) {
@@ -419,9 +423,10 @@
&& recordedClip->mode == ClipMode::Rectangle
&& recordedClipTransform.rectToRect())) {
// common case - result is a single rectangle
- auto rectClip = allocator.create<ClipRect>(getRect(recordedClip));
+ auto rectClip = allocator.create<ClipRect>(recordedClip->rect);
recordedClipTransform.mapRect(rectClip->rect);
rectClip->rect.doIntersect(mClipRect);
+ rectClip->rect.snapToPixelBoundaries();
mLastResolutionResult = rectClip;
} else if (CC_UNLIKELY(mMode == ClipMode::Region
|| recordedClip->mode == ClipMode::Region
@@ -432,11 +437,11 @@
case ClipMode::Rectangle:
if (CC_LIKELY(recordedClipTransform.rectToRect())) {
// simple transform, skip creating SkPath
- Rect resultClip(getRect(recordedClip));
+ Rect resultClip(recordedClip->rect);
recordedClipTransform.mapRect(resultClip);
other.setRect(resultClip.toSkIRect());
} else {
- SkPath transformedRect = pathFromTransformedRectangle(getRect(recordedClip),
+ SkPath transformedRect = pathFromTransformedRectangle(recordedClip->rect,
recordedClipTransform);
other.setPath(transformedRect, createViewportRegion());
}
@@ -468,6 +473,7 @@
regionClip->region.op(mClipRegion, other, SkRegion::kIntersect_Op);
break;
}
+ // Don't need to snap, since region's in int bounds
regionClip->rect.set(regionClip->region.getBounds());
mLastResolutionResult = regionClip;
} else {
@@ -478,7 +484,7 @@
}
if (recordedClip->mode == ClipMode::Rectangle) {
- rectList.intersectWith(getRect(recordedClip), recordedClipTransform);
+ rectList.intersectWith(recordedClip->rect, recordedClipTransform);
} else {
const RectangleList& other = getRectList(recordedClip);
for (int i = 0; i < other.getTransformedRectanglesCount(); i++) {
@@ -489,6 +495,7 @@
}
}
rectListClip->rect = rectList.calculateBounds();
+ rectListClip->rect.snapToPixelBoundaries();
mLastResolutionResult = rectListClip;
}
}
@@ -499,7 +506,7 @@
if (!clip) return; // nothing to do
if (CC_LIKELY(clip->mode == ClipMode::Rectangle)) {
- clipRectWithTransform(getRect(clip), &transform, SkRegion::kIntersect_Op);
+ clipRectWithTransform(clip->rect, &transform, SkRegion::kIntersect_Op);
} else if (CC_LIKELY(clip->mode == ClipMode::RectangleList)) {
auto&& rectList = getRectList(clip);
for (int i = 0; i < rectList.getTransformedRectanglesCount(); i++) {
diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp
index 00560d7..a14bdc4 100644
--- a/libs/hwui/DisplayListCanvas.cpp
+++ b/libs/hwui/DisplayListCanvas.cpp
@@ -415,12 +415,7 @@
void DisplayListCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
mDisplayList->ref(tree);
- const SkBitmap& bitmap = tree->getBitmapUpdateIfDirty();
- SkPaint* paint = tree->getPaint();
- const SkRect bounds = tree->getBounds();
- addDrawOp(new (alloc()) DrawBitmapRectOp(refBitmap(bitmap),
- 0, 0, bitmap.width(), bitmap.height(),
- bounds.left(), bounds.top(), bounds.right(), bounds.bottom(), refPaint(paint)));
+ addDrawOp(new (alloc()) DrawVectorDrawableOp(tree));
}
void DisplayListCanvas::drawTextOnPath(const uint16_t* glyphs, int count,
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 98315d0..516e619 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -28,6 +28,7 @@
#include "UvMapper.h"
#include "utils/LinearAllocator.h"
#include "utils/PaintUtils.h"
+#include "VectorDrawable.h"
#include <algorithm>
@@ -1107,6 +1108,30 @@
float* mRadius;
};
+class DrawVectorDrawableOp : public DrawOp {
+public:
+ DrawVectorDrawableOp(VectorDrawableRoot* tree)
+ : DrawOp(nullptr), mTree(tree) {}
+
+ virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
+ const SkBitmap& bitmap = mTree->getBitmapUpdateIfDirty();
+ SkPaint* paint = mTree->getPaint();
+ const SkRect bounds = mTree->getBounds();
+ renderer.drawBitmap(&bitmap, Rect(0, 0, bitmap.width(), bitmap.height()),
+ bounds, paint);
+ }
+
+ virtual void output(int level, uint32_t logFlags) const override {
+ OP_LOG("Draw Vector Drawable %p", mTree);
+ }
+
+ virtual const char* name() override { return "DrawVectorDrawable"; }
+
+private:
+ VectorDrawableRoot* mTree;
+
+};
+
class DrawOvalOp : public DrawStrokableOp {
public:
DrawOvalOp(float left, float top, float right, float bottom, const SkPaint* paint)
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index 4f51036..5642170 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -389,34 +389,38 @@
}
void FrameBuilder::deferProjectedChildren(const RenderNode& renderNode) {
- const SkPath* projectionReceiverOutline = renderNode.properties().getOutline().getPath();
int count = mCanvasState.save(SaveFlags::MatrixClip);
+ const SkPath* projectionReceiverOutline = renderNode.properties().getOutline().getPath();
- // can't be null, since DL=null node rejection happens before deferNodePropsAndOps
- const DisplayList& displayList = *(renderNode.getDisplayList());
-
- const RecordedOp* op = (displayList.getOps()[displayList.projectionReceiveIndex]);
- const RenderNodeOp* backgroundOp = static_cast<const RenderNodeOp*>(op);
- const RenderProperties& backgroundProps = backgroundOp->renderNode->properties();
-
- // Transform renderer to match background we're projecting onto
- // (by offsetting canvas by translationX/Y of background rendernode, since only those are set)
- mCanvasState.translate(backgroundProps.getTranslationX(), backgroundProps.getTranslationY());
-
- // If the projection receiver has an outline, we mask projected content to it
- // (which we know, apriori, are all tessellated paths)
- mCanvasState.setProjectionPathMask(mAllocator, projectionReceiverOutline);
-
- // draw projected nodes
- for (size_t i = 0; i < renderNode.mProjectedNodes.size(); i++) {
- RenderNodeOp* childOp = renderNode.mProjectedNodes[i];
-
- int restoreTo = mCanvasState.save(SaveFlags::Matrix);
- mCanvasState.concatMatrix(childOp->transformFromCompositingAncestor);
- deferRenderNodeOpImpl(*childOp);
- mCanvasState.restoreToCount(restoreTo);
+ SkPath transformedMaskPath; // on stack, since BakedOpState makes a deep copy
+ if (projectionReceiverOutline) {
+ // transform the mask for this projector into render target space
+ // TODO: consider combining both transforms by stashing transform instead of applying
+ SkMatrix skCurrentTransform;
+ mCanvasState.currentTransform()->copyTo(skCurrentTransform);
+ projectionReceiverOutline->transform(
+ skCurrentTransform,
+ &transformedMaskPath);
+ mCanvasState.setProjectionPathMask(mAllocator, &transformedMaskPath);
}
+ for (size_t i = 0; i < renderNode.mProjectedNodes.size(); i++) {
+ RenderNodeOp* childOp = renderNode.mProjectedNodes[i];
+ RenderNode& childNode = *childOp->renderNode;
+
+ // Draw child if it has content, but ignore state in childOp - matrix already applied to
+ // transformFromCompositingAncestor, and record-time clip is ignored when projecting
+ if (!childNode.nothingToDraw()) {
+ int restoreTo = mCanvasState.save(SaveFlags::MatrixClip);
+
+ // Apply transform between ancestor and projected descendant
+ mCanvasState.concatMatrix(childOp->transformFromCompositingAncestor);
+
+ deferNodePropsAndOps(childNode);
+
+ mCanvasState.restoreToCount(restoreTo);
+ }
+ }
mCanvasState.restoreToCount(count);
}
@@ -513,10 +517,6 @@
BakedOpState* bakedState = tryBakeOpState(op);
if (!bakedState) return; // quick rejected
- currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Bitmap);
-
- // TODO: Fix this ( b/26569206 )
-/*
// Don't merge non-simply transformed or neg scale ops, SET_TEXTURE doesn't handle rotation
// Don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in
// MergingDrawBatch::canMergeWith()
@@ -531,7 +531,6 @@
} else {
currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Bitmap);
}
-*/
}
void FrameBuilder::deferBitmapMeshOp(const BitmapMeshOp& op) {
@@ -782,39 +781,46 @@
boundsTransform.mapRect(dstRect);
dstRect.doIntersect(mCanvasState.currentSnapshot()->getRenderTargetClip());
- // Allocate a holding position for the layer object (copyTo will produce, copyFrom will consume)
- OffscreenBuffer** layerHandle = mAllocator.create<OffscreenBuffer*>(nullptr);
+ if (dstRect.isEmpty()) {
+ // Unclipped layer rejected - push a null op, so next EndUnclippedLayerOp is ignored
+ currentLayer().activeUnclippedSaveLayers.push_back(nullptr);
+ } else {
+ // Allocate a holding position for the layer object (copyTo will produce, copyFrom will consume)
+ OffscreenBuffer** layerHandle = mAllocator.create<OffscreenBuffer*>(nullptr);
- /**
- * First, defer an operation to copy out the content from the rendertarget into a layer.
- */
- auto copyToOp = mAllocator.create_trivial<CopyToLayerOp>(op, layerHandle);
- BakedOpState* bakedState = BakedOpState::directConstruct(mAllocator,
- &(currentLayer().viewportClip), dstRect, *copyToOp);
- currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::CopyToLayer);
+ /**
+ * First, defer an operation to copy out the content from the rendertarget into a layer.
+ */
+ auto copyToOp = mAllocator.create_trivial<CopyToLayerOp>(op, layerHandle);
+ BakedOpState* bakedState = BakedOpState::directConstruct(mAllocator,
+ &(currentLayer().repaintClip), dstRect, *copyToOp);
+ currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::CopyToLayer);
- /**
- * Defer a clear rect, so that clears from multiple unclipped layers can be drawn
- * both 1) simultaneously, and 2) as long after the copyToLayer executes as possible
- */
- currentLayer().deferLayerClear(dstRect);
+ /**
+ * Defer a clear rect, so that clears from multiple unclipped layers can be drawn
+ * both 1) simultaneously, and 2) as long after the copyToLayer executes as possible
+ */
+ currentLayer().deferLayerClear(dstRect);
- /**
- * And stash an operation to copy that layer back under the rendertarget until
- * a balanced EndUnclippedLayerOp is seen
- */
- auto copyFromOp = mAllocator.create_trivial<CopyFromLayerOp>(op, layerHandle);
- bakedState = BakedOpState::directConstruct(mAllocator,
- &(currentLayer().viewportClip), dstRect, *copyFromOp);
- currentLayer().activeUnclippedSaveLayers.push_back(bakedState);
+ /**
+ * And stash an operation to copy that layer back under the rendertarget until
+ * a balanced EndUnclippedLayerOp is seen
+ */
+ auto copyFromOp = mAllocator.create_trivial<CopyFromLayerOp>(op, layerHandle);
+ bakedState = BakedOpState::directConstruct(mAllocator,
+ &(currentLayer().repaintClip), dstRect, *copyFromOp);
+ currentLayer().activeUnclippedSaveLayers.push_back(bakedState);
+ }
}
void FrameBuilder::deferEndUnclippedLayerOp(const EndUnclippedLayerOp& /* ignored */) {
LOG_ALWAYS_FATAL_IF(currentLayer().activeUnclippedSaveLayers.empty(), "no layer to end!");
BakedOpState* copyFromLayerOp = currentLayer().activeUnclippedSaveLayers.back();
- currentLayer().deferUnmergeableOp(mAllocator, copyFromLayerOp, OpBatchType::CopyFromLayer);
currentLayer().activeUnclippedSaveLayers.pop_back();
+ if (copyFromLayerOp) {
+ currentLayer().deferUnmergeableOp(mAllocator, copyFromLayerOp, OpBatchType::CopyFromLayer);
+ }
}
} // namespace uirenderer
diff --git a/libs/hwui/FrameInfoVisualizer.cpp b/libs/hwui/FrameInfoVisualizer.cpp
index b7dd3b7..adadd32 100644
--- a/libs/hwui/FrameInfoVisualizer.cpp
+++ b/libs/hwui/FrameInfoVisualizer.cpp
@@ -15,7 +15,11 @@
*/
#include "FrameInfoVisualizer.h"
+#if HWUI_NEW_OPS
+#include "BakedOpRenderer.h"
+#else
#include "OpenGLRenderer.h"
+#endif
#include "utils/Color.h"
#include <cutils/compiler.h>
@@ -88,7 +92,7 @@
}
}
-void FrameInfoVisualizer::draw(OpenGLRenderer* canvas) {
+void FrameInfoVisualizer::draw(ContentRenderer* renderer) {
RETURN_IF_DISABLED();
if (mShowDirtyRegions) {
@@ -96,7 +100,7 @@
if (mFlashToggle) {
SkPaint paint;
paint.setColor(0x7fff0000);
- canvas->drawRect(mDirtyRegion.fLeft, mDirtyRegion.fTop,
+ renderer->drawRect(mDirtyRegion.fLeft, mDirtyRegion.fTop,
mDirtyRegion.fRight, mDirtyRegion.fBottom, &paint);
}
}
@@ -111,9 +115,9 @@
info.markSwapBuffers();
info.markFrameCompleted();
- initializeRects(canvas->getViewportHeight(), canvas->getViewportWidth());
- drawGraph(canvas);
- drawThreshold(canvas);
+ initializeRects(renderer->getViewportHeight(), renderer->getViewportWidth());
+ drawGraph(renderer);
+ drawThreshold(renderer);
}
}
@@ -194,27 +198,26 @@
}
}
-void FrameInfoVisualizer::drawGraph(OpenGLRenderer* canvas) {
+void FrameInfoVisualizer::drawGraph(ContentRenderer* renderer) {
SkPaint paint;
for (size_t i = 0; i < Bar.size(); i++) {
nextBarSegment(Bar[i].start, Bar[i].end);
paint.setColor(Bar[i].color & BAR_FAST_MASK);
- canvas->drawRects(mFastRects.get(), mNumFastRects * 4, &paint);
+ renderer->drawRects(mFastRects.get(), mNumFastRects * 4, &paint);
paint.setColor(Bar[i].color & BAR_JANKY_MASK);
- canvas->drawRects(mJankyRects.get(), mNumJankyRects * 4, &paint);
+ renderer->drawRects(mJankyRects.get(), mNumJankyRects * 4, &paint);
}
}
-void FrameInfoVisualizer::drawThreshold(OpenGLRenderer* canvas) {
+void FrameInfoVisualizer::drawThreshold(ContentRenderer* renderer) {
SkPaint paint;
paint.setColor(THRESHOLD_COLOR);
- paint.setStrokeWidth(mThresholdStroke);
-
- float pts[4];
- pts[0] = 0.0f;
- pts[1] = pts[3] = canvas->getViewportHeight() - (FRAME_THRESHOLD * mVerticalUnit);
- pts[2] = canvas->getViewportWidth();
- canvas->drawLines(pts, 4, &paint);
+ float yLocation = renderer->getViewportHeight() - (FRAME_THRESHOLD * mVerticalUnit);
+ renderer->drawRect(0.0f,
+ yLocation - mThresholdStroke/2,
+ renderer->getViewportWidth(),
+ yLocation + mThresholdStroke/2,
+ &paint);
}
bool FrameInfoVisualizer::consumeProperties() {
diff --git a/libs/hwui/FrameInfoVisualizer.h b/libs/hwui/FrameInfoVisualizer.h
index cf877c4..83adf19 100644
--- a/libs/hwui/FrameInfoVisualizer.h
+++ b/libs/hwui/FrameInfoVisualizer.h
@@ -28,7 +28,13 @@
namespace android {
namespace uirenderer {
+#if HWUI_NEW_OPS
+class BakedOpRenderer;
+typedef BakedOpRenderer ContentRenderer;
+#else
class OpenGLRenderer;
+typedef OpenGLRenderer ContentRenderer;
+#endif
// TODO: This is a bit awkward as it needs to match the thing in CanvasContext
// A better abstraction here would be nice but iterators are painful
@@ -46,7 +52,7 @@
void setDensity(float density);
void unionDirty(SkRect* dirty);
- void draw(OpenGLRenderer* canvas);
+ void draw(ContentRenderer* renderer);
void dumpData(int fd);
@@ -56,8 +62,8 @@
void initializeRects(const int baseline, const int width);
void nextBarSegment(FrameInfoIndex start, FrameInfoIndex end);
- void drawGraph(OpenGLRenderer* canvas);
- void drawThreshold(OpenGLRenderer* canvas);
+ void drawGraph(ContentRenderer* renderer);
+ void drawThreshold(ContentRenderer* renderer);
inline float durationMS(size_t index, FrameInfoIndex start, FrameInfoIndex end) {
float duration = mFrameSource[index].duration(start, end) * 0.000001f;
diff --git a/libs/hwui/LayerBuilder.cpp b/libs/hwui/LayerBuilder.cpp
index 1ba3bf2..c5af279 100644
--- a/libs/hwui/LayerBuilder.cpp
+++ b/libs/hwui/LayerBuilder.cpp
@@ -140,7 +140,10 @@
// Identical round rect clip state means both ops will clip in the same way, or not at all.
// As the state objects are const, we can compare their pointers to determine mergeability
if (lhs->roundRectClipState != rhs->roundRectClipState) return false;
- if (lhs->projectionPathMask != rhs->projectionPathMask) return false;
+
+ // Local masks prevent merge, since they're potentially in different coordinate spaces
+ if (lhs->computedState.localProjectionPathMask
+ || rhs->computedState.localProjectionPathMask) return false;
/* Clipping compatibility check
*
@@ -199,10 +202,10 @@
: width(width)
, height(height)
, repaintRect(repaintRect)
+ , repaintClip(repaintRect)
, offscreenBuffer(renderNode ? renderNode->getLayer() : nullptr)
, beginLayerOp(beginLayerOp)
- , renderNode(renderNode)
- , viewportClip(Rect(width, height)) {}
+ , renderNode(renderNode) {}
// iterate back toward target to see if anything drawn since should overlap the new op
// if no target, merging ops still iterate to find similar batch to insert after
@@ -239,7 +242,7 @@
// put the verts in the frame allocator, since
// 1) SimpleRectsOps needs verts, not rects
// 2) even if mClearRects stored verts, std::vectors will move their contents
- Vertex* const verts = (Vertex*) allocator.alloc<Vertex>(vertCount * sizeof(Vertex));
+ Vertex* const verts = (Vertex*) allocator.create_trivial_array<Vertex>(vertCount);
Vertex* currentVert = verts;
Rect bounds = mClearRects[0];
@@ -260,7 +263,7 @@
Matrix4::identity(), nullptr, paint,
verts, vertCount);
BakedOpState* bakedState = BakedOpState::directConstruct(allocator,
- &viewportClip, bounds, *op);
+ &repaintClip, bounds, *op);
deferUnmergeableOp(allocator, bakedState, OpBatchType::Vertices);
}
}
diff --git a/libs/hwui/LayerBuilder.h b/libs/hwui/LayerBuilder.h
index 99968e1..4a7ca2d 100644
--- a/libs/hwui/LayerBuilder.h
+++ b/libs/hwui/LayerBuilder.h
@@ -109,10 +109,10 @@
const uint32_t width;
const uint32_t height;
const Rect repaintRect;
+ const ClipRect repaintClip;
OffscreenBuffer* offscreenBuffer;
const BeginLayerOp* beginLayerOp;
const RenderNode* renderNode;
- const ClipRect viewportClip;
// list of deferred CopyFromLayer ops, to be deferred upon encountering EndUnclippedLayerOps
std::vector<BakedOpState*> activeUnclippedSaveLayers;
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index e04b9a2..5bce8ac 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -353,7 +353,7 @@
bool LayerRenderer::copyLayer(RenderState& renderState, Layer* layer, SkBitmap* bitmap) {
Caches& caches = Caches::getInstance();
- if (layer
+ if (layer && layer->getRenderTarget() != GL_NONE
&& bitmap->width() <= caches.maxTextureSize
&& bitmap->height() <= caches.maxTextureSize) {
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index 73ebd1304..deab956 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -438,7 +438,7 @@
}
void Matrix4::mapRect(Rect& r) const {
- if (isIdentity()) return;
+ if (isIdentity() || r.isEmpty()) return;
if (isSimple()) {
MUL_ADD_STORE(r.left, data[kScaleX], data[kTranslateX]);
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index 1c25f26..36007cd 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -14,15 +14,15 @@
* limitations under the License.
*/
-#ifndef ANDROID_HWUI_MATRIX_H
-#define ANDROID_HWUI_MATRIX_H
-
-#include <SkMatrix.h>
-
-#include <cutils/compiler.h>
+#pragma once
#include "Rect.h"
+#include <cutils/compiler.h>
+#include <iomanip>
+#include <ostream>
+#include <SkMatrix.h>
+
namespace android {
namespace uirenderer {
@@ -218,6 +218,22 @@
void dump(const char* label = nullptr) const;
+ friend std::ostream& operator<<(std::ostream& os, const Matrix4& matrix) {
+ if (matrix.isSimple()) {
+ os << "offset " << matrix.getTranslateX() << "x" << matrix.getTranslateY();
+ if (!matrix.isPureTranslate()) {
+ os << ", scale " << matrix[kScaleX] << "x" << matrix[kScaleY];
+ }
+ } else {
+ os << "[" << matrix[0];
+ for (int i = 1; i < 16; i++) {
+ os << ", " << matrix[i];
+ }
+ os << "]";
+ }
+ return os;
+ }
+
static const Matrix4& identity();
private:
@@ -244,4 +260,3 @@
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_HWUI_MATRIX_H
diff --git a/libs/hwui/OpDumper.cpp b/libs/hwui/OpDumper.cpp
new file mode 100644
index 0000000..c34cfbe
--- /dev/null
+++ b/libs/hwui/OpDumper.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "OpDumper.h"
+
+#include "RecordedOp.h"
+
+namespace android {
+namespace uirenderer {
+
+#define STRINGIFY(n) #n,
+static const char* sOpNameLut[] = BUILD_FULL_OP_LUT(STRINGIFY);
+
+void OpDumper::dump(const RecordedOp& op, std::ostream& output, int level) {
+ for (int i = 0; i < level; i++) {
+ output << " ";
+ }
+
+ Rect localBounds(op.unmappedBounds);
+ op.localMatrix.mapRect(localBounds);
+ output << sOpNameLut[op.opId] << " " << localBounds;
+
+ if (op.localClip && !op.localClip->rect.contains(localBounds)) {
+ output << std::fixed << std::setprecision(0)
+ << " clip=" << op.localClip->rect
+ << " mode=" << (int)op.localClip->mode;
+ }
+}
+
+} // namespace uirenderer
+} // namespace android
diff --git a/media/mca/effect/java/android/media/effect/package-info.java b/libs/hwui/OpDumper.h
similarity index 64%
copy from media/mca/effect/java/android/media/effect/package-info.java
copy to libs/hwui/OpDumper.h
index b2c14ff..c99b517 100644
--- a/media/mca/effect/java/android/media/effect/package-info.java
+++ b/libs/hwui/OpDumper.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,15 +14,19 @@
* limitations under the License.
*/
+#pragma once
-package android.media.effect;
+#include <ostream>
-/**
- * <h1>Effect Framework</h1>
- *
- * This package includes a collection of high-performance visual effects that make use of the
- * mobile filter framework subsystem.
- *
- * TODO: More Documentation
- *
- */
+namespace android {
+namespace uirenderer {
+
+struct RecordedOp;
+
+class OpDumper {
+public:
+ static void dump(const RecordedOp& op, std::ostream& output, int level = 0);
+};
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index b7a5923..7693fdc 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1148,7 +1148,9 @@
// always store/restore, since these are just pointers
state.mRoundRectClipState = currentSnapshot()->roundRectClipState;
+#if !HWUI_NEW_OPS
state.mProjectionPathMask = currentSnapshot()->projectionPathMask;
+#endif
return false;
}
@@ -1156,7 +1158,9 @@
setGlobalMatrix(state.mMatrix);
writableSnapshot()->alpha = state.mAlpha;
writableSnapshot()->roundRectClipState = state.mRoundRectClipState;
+#if !HWUI_NEW_OPS
writableSnapshot()->projectionPathMask = state.mProjectionPathMask;
+#endif
if (state.mClipValid && !skipClipRestore) {
writableSnapshot()->setClip(state.mClip.left, state.mClip.top,
@@ -1833,6 +1837,7 @@
path.addCircle(x, y, radius);
}
+#if !HWUI_NEW_OPS
if (CC_UNLIKELY(currentSnapshot()->projectionPathMask != nullptr)) {
// mask ripples with projection mask
SkPath maskPath = *(currentSnapshot()->projectionPathMask->projectionMask);
@@ -1852,6 +1857,7 @@
// in local space. Note that this can create CCW paths.
Op(path, maskPath, kIntersect_SkPathOp, &path);
}
+#endif
drawConvexPath(path, p);
}
diff --git a/libs/hwui/PixelBuffer.cpp b/libs/hwui/PixelBuffer.cpp
index 6df994c..165c7db 100644
--- a/libs/hwui/PixelBuffer.cpp
+++ b/libs/hwui/PixelBuffer.cpp
@@ -36,12 +36,14 @@
CpuPixelBuffer(GLenum format, uint32_t width, uint32_t height);
uint8_t* map(AccessMode mode = kAccessMode_ReadWrite) override;
- void unmap() override;
uint8_t* getMappedPointer() const override;
void upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) override;
+protected:
+ void unmap() override;
+
private:
std::unique_ptr<uint8_t[]> mBuffer;
};
@@ -81,12 +83,14 @@
~GpuPixelBuffer();
uint8_t* map(AccessMode mode = kAccessMode_ReadWrite) override;
- void unmap() override;
uint8_t* getMappedPointer() const override;
void upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) override;
+protected:
+ void unmap() override;
+
private:
GLuint mBuffer;
uint8_t* mMappedPointer;
@@ -118,6 +122,7 @@
LOG_ALWAYS_FATAL("Failed to map PBO");
}
mAccessMode = mode;
+ mCaches.pixelBufferState().unbind();
}
return mMappedPointer;
@@ -147,6 +152,7 @@
unmap();
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, mFormat,
GL_UNSIGNED_BYTE, reinterpret_cast<void*>(offset));
+ mCaches.pixelBufferState().unbind();
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/PixelBuffer.h b/libs/hwui/PixelBuffer.h
index aac5ec4..bbef36b 100644
--- a/libs/hwui/PixelBuffer.h
+++ b/libs/hwui/PixelBuffer.h
@@ -91,14 +91,6 @@
virtual uint8_t* map(AccessMode mode = kAccessMode_ReadWrite) = 0;
/**
- * Unmaps this buffer, if needed. After the buffer is unmapped,
- * the pointer previously returned by map() becomes invalid and
- * should not be used. After calling this method, getMappedPointer()
- * will always return NULL.
- */
- virtual void unmap() = 0;
-
- /**
* Returns the current access mode for this buffer. If the buffer
* is not mapped, this method returns kAccessMode_None.
*/
@@ -204,6 +196,14 @@
mFormat(format), mWidth(width), mHeight(height), mAccessMode(kAccessMode_None) {
}
+ /**
+ * Unmaps this buffer, if needed. After the buffer is unmapped,
+ * the pointer previously returned by map() becomes invalid and
+ * should not be used. After calling this method, getMappedPointer()
+ * will always return NULL.
+ */
+ virtual void unmap() = 0;
+
GLenum mFormat;
uint32_t mWidth;
diff --git a/libs/hwui/PropertyValuesAnimatorSet.cpp b/libs/hwui/PropertyValuesAnimatorSet.cpp
index eca1afcc..b29f91f 100644
--- a/libs/hwui/PropertyValuesAnimatorSet.cpp
+++ b/libs/hwui/PropertyValuesAnimatorSet.cpp
@@ -17,6 +17,8 @@
#include "PropertyValuesAnimatorSet.h"
#include "RenderNode.h"
+#include <algorithm>
+
namespace android {
namespace uirenderer {
@@ -53,16 +55,26 @@
}
void PropertyValuesAnimatorSet::onPlayTimeChanged(nsecs_t playTime) {
- for (size_t i = 0; i < mAnimators.size(); i++) {
- mAnimators[i]->setCurrentPlayTime(playTime);
+ if (playTime == 0 && mDuration > 0) {
+ // Reset all the animators
+ for (auto it = mAnimators.rbegin(); it != mAnimators.rend(); it++) {
+ // Note that this set may containing animators modifying the same property, so when we
+ // reset the animators, we need to make sure the animators that end the first will
+ // have the final say on what the property value should be.
+ (*it)->setFraction(0);
+ }
+ } else if (playTime >= mDuration) {
+ // Skip all the animators to end
+ for (auto& anim : mAnimators) {
+ anim->setFraction(1);
+ }
+ } else {
+ for (auto& anim : mAnimators) {
+ anim->setCurrentPlayTime(playTime);
+ }
}
}
-void PropertyValuesAnimatorSet::reset() {
- // TODO: implement reset through adding a play state because we need to support reset() even
- // during an animation run.
-}
-
void PropertyValuesAnimatorSet::start(AnimationListener* listener) {
init();
mOneShotListener = listener;
@@ -70,20 +82,23 @@
}
void PropertyValuesAnimatorSet::reverse(AnimationListener* listener) {
-// TODO: implement reverse
+ init();
+ mOneShotListener = listener;
+ BaseRenderNodeAnimator::reverse();
}
void PropertyValuesAnimatorSet::init() {
if (mInitialized) {
return;
}
- nsecs_t maxDuration = 0;
- for (size_t i = 0; i < mAnimators.size(); i++) {
- if (maxDuration < mAnimators[i]->getTotalDuration()) {
- maxDuration = mAnimators[i]->getTotalDuration();
- }
- }
- mDuration = maxDuration;
+
+ // Sort the animators by their total duration. Note that all the animators in the set start at
+ // the same time, so the ones with longer total duration (which includes start delay) will
+ // be the ones that end later.
+ std::sort(mAnimators.begin(), mAnimators.end(), [](auto& a, auto&b) {
+ return a->getTotalDuration() < b->getTotalDuration();
+ });
+ mDuration = mAnimators[mAnimators.size() - 1]->getTotalDuration();
mInitialized = true;
}
@@ -106,18 +121,19 @@
void PropertyAnimator::setCurrentPlayTime(nsecs_t playTime) {
if (playTime >= mStartDelay && playTime < mTotalDuration) {
nsecs_t currentIterationPlayTime = (playTime - mStartDelay) % mDuration;
- mLatestFraction = currentIterationPlayTime / (float) mDuration;
+ float fraction = currentIterationPlayTime / (float) mDuration;
+ setFraction(fraction);
} else if (mLatestFraction < 1.0f && playTime >= mTotalDuration) {
- mLatestFraction = 1.0f;
- } else {
- return;
+ // This makes sure we only set the fraction = 1 once. It is needed because there might
+ // be another animator modifying the same property after this animator finishes, we need
+ // to make sure we don't set conflicting values on the same property within one frame.
+ setFraction(1.0f);
}
-
- setFraction(mLatestFraction);
}
void PropertyAnimator::setFraction(float fraction) {
- float interpolatedFraction = mInterpolator->interpolate(mLatestFraction);
+ mLatestFraction = fraction;
+ float interpolatedFraction = mInterpolator->interpolate(fraction);
mPropertyValuesHolder->setFraction(interpolatedFraction);
}
diff --git a/libs/hwui/PropertyValuesAnimatorSet.h b/libs/hwui/PropertyValuesAnimatorSet.h
index 4c7ce52..c7ae7c0 100644
--- a/libs/hwui/PropertyValuesAnimatorSet.h
+++ b/libs/hwui/PropertyValuesAnimatorSet.h
@@ -50,7 +50,6 @@
void start(AnimationListener* listener);
void reverse(AnimationListener* listener);
- void reset();
void addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder,
Interpolator* interpolators, int64_t startDelays,
diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h
index bb26e2e..c37458d 100644
--- a/libs/hwui/RecordedOp.h
+++ b/libs/hwui/RecordedOp.h
@@ -119,6 +119,9 @@
#define BUILD_RENDERABLE_OP_LUT(OP_FN) \
{ MAP_OPS_BASED_ON_TYPE(NULLPTR_OP_FN, OP_FN, OP_FN, OP_FN) }
+#define BUILD_FULL_OP_LUT(OP_FN) \
+ { MAP_OPS_BASED_ON_TYPE(OP_FN, OP_FN, OP_FN, OP_FN) }
+
/**
* Op mapping functions, which skip unsupported ops.
*
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 269e590..ddf0528 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -24,6 +24,14 @@
namespace android {
namespace uirenderer {
+
+static Rect sUnreasonablyLargeBounds(-10000, -10000, 10000, 10000);
+
+static const Rect& getConservativeOpBounds(const ClipBase* clip) {
+ // if op is clipped, that rect can be used, but otherwise just use a conservatively large rect
+ return clip ? clip->rect : sUnreasonablyLargeBounds;
+}
+
RecordingCanvas::RecordingCanvas(size_t width, size_t height)
: mState(*this)
, mResourceCache(ResourceCache::getInstance()) {
@@ -241,10 +249,11 @@
}
void RecordingCanvas::drawPaint(const SkPaint& paint) {
+ const ClipBase* clip = getRecordedClip();
addOp(alloc().create_trivial<RectOp>(
- mState.getRenderTargetClipBounds(), // OK, since we've not passed transform
+ getConservativeOpBounds(clip),
Matrix4::identity(),
- getRecordedClip(),
+ clip,
refPaint(&paint)));
}
@@ -290,7 +299,7 @@
void RecordingCanvas::drawSimpleRects(const float* rects, int vertexCount, const SkPaint* paint) {
if (rects == nullptr) return;
- Vertex* rectData = (Vertex*) mDisplayList->allocator.alloc<Vertex>(vertexCount * sizeof(Vertex));
+ Vertex* rectData = (Vertex*) mDisplayList->allocator.create_trivial_array<Vertex>(vertexCount);
Vertex* vertex = rectData;
float left = FLT_MAX;
@@ -406,12 +415,16 @@
void RecordingCanvas::drawArc(float left, float top, float right, float bottom,
float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) {
- addOp(alloc().create_trivial<ArcOp>(
- Rect(left, top, right, bottom),
- *(mState.currentSnapshot()->transform),
- getRecordedClip(),
- refPaint(&paint),
- startAngle, sweepAngle, useCenter));
+ if (fabs(sweepAngle) >= 360.0f) {
+ drawOval(left, top, right, bottom, paint);
+ } else {
+ addOp(alloc().create_trivial<ArcOp>(
+ Rect(left, top, right, bottom),
+ *(mState.currentSnapshot()->transform),
+ getRecordedClip(),
+ refPaint(&paint),
+ startAngle, sweepAngle, useCenter));
+ }
}
void RecordingCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
@@ -527,10 +540,11 @@
float hOffset, float vOffset, const SkPaint& paint) {
if (!glyphs || glyphCount <= 0 || PaintUtils::paintWillNotDrawText(paint)) return;
glyphs = refBuffer<glyph_t>(glyphs, glyphCount);
+ auto clip = getRecordedClip();
addOp(alloc().create_trivial<TextOnPathOp>(
- mState.getLocalClipBounds(), // TODO: explicitly define bounds
+ getConservativeOpBounds(clip), // TODO: explicitly define bounds
*(mState.currentSnapshot()->transform),
- getRecordedClip(),
+ clip,
refPaint(&paint), glyphs, glyphCount, refPath(&path), hOffset, vOffset));
}
@@ -579,15 +593,23 @@
void RecordingCanvas::callDrawGLFunction(Functor* functor) {
mDisplayList->functors.push_back(functor);
+ auto clip = getRecordedClip();
addOp(alloc().create_trivial<FunctorOp>(
- mState.getLocalClipBounds(), // TODO: explicitly define bounds
+ getConservativeOpBounds(clip), // TODO: explicitly define bounds
*(mState.currentSnapshot()->transform),
- getRecordedClip(),
+ clip,
functor));
}
size_t RecordingCanvas::addOp(RecordedOp* op) {
- // TODO: validate if "addDrawOp" quickrejection logic is useful before adding
+ // skip op with empty clip
+ if (op->localClip && op->localClip->rect.isEmpty()) {
+ // NOTE: this rejection happens after op construction/content ref-ing, so content ref'd
+ // and held by renderthread isn't affected by clip rejection.
+ // Could rewind alloc here if desired, but callers would have to not touch op afterwards.
+ return -1;
+ }
+
int insertIndex = mDisplayList->ops.size();
mDisplayList->ops.push_back(op);
if (mDeferredBarrierType != DeferredBarrierType::None) {
diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h
index 30c925c..d9fce9b 100644
--- a/libs/hwui/Rect.h
+++ b/libs/hwui/Rect.h
@@ -14,16 +14,17 @@
* limitations under the License.
*/
-#ifndef ANDROID_HWUI_RECT_H
-#define ANDROID_HWUI_RECT_H
+#pragma once
-#include <cmath>
-#include <algorithm>
-#include <SkRect.h>
+#include "Vertex.h"
#include <utils/Log.h>
-#include "Vertex.h"
+#include <algorithm>
+#include <cmath>
+#include <iomanip>
+#include <ostream>
+#include <SkRect.h>
namespace android {
namespace uirenderer {
@@ -282,9 +283,23 @@
void dump(const char* label = nullptr) const {
ALOGD("%s[l=%.2f t=%.2f r=%.2f b=%.2f]", label ? label : "Rect", left, top, right, bottom);
}
+
+ friend std::ostream& operator<<(std::ostream& os, const Rect& rect) {
+ if (rect.isEmpty()) {
+ return os << "empty";
+ }
+
+ if (rect.left == 0 && rect.top == 0) {
+ return os << "[" << rect.right << " x " << rect.bottom << "]";
+ }
+
+ return os << "[" << rect.left
+ << " " << rect.top
+ << " " << rect.right
+ << " " << rect.bottom << "]";
+ }
}; // class Rect
}; // namespace uirenderer
}; // namespace android
-#endif // ANDROID_HWUI_RECT_H
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index bade216..61441ce 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -19,8 +19,9 @@
#include "DamageAccumulator.h"
#include "Debug.h"
#if HWUI_NEW_OPS
-#include "RecordedOp.h"
#include "BakedOpRenderer.h"
+#include "RecordedOp.h"
+#include "OpDumper.h"
#endif
#include "DisplayListOp.h"
#include "LayerRenderer.h"
@@ -95,6 +96,34 @@
* This function is a simplified version of replay(), where we simply retrieve and log the
* display list. This function should remain in sync with the replay() function.
*/
+#if HWUI_NEW_OPS
+void RenderNode::output(uint32_t level, const char* label) {
+ ALOGD("%s (%s %p%s%s%s%s%s)",
+ label,
+ getName(),
+ this,
+ (MathUtils::isZero(properties().getAlpha()) ? ", zero alpha" : ""),
+ (properties().hasShadow() ? ", casting shadow" : ""),
+ (isRenderable() ? "" : ", empty"),
+ (properties().getProjectBackwards() ? ", projected" : ""),
+ (mLayer != nullptr ? ", on HW Layer" : ""));
+ properties().debugOutputProperties(level + 1);
+
+ if (mDisplayList) {
+ for (auto&& op : mDisplayList->getOps()) {
+ std::stringstream strout;
+ OpDumper::dump(*op, strout, level + 1);
+ if (op->opId == RecordedOpId::RenderNodeOp) {
+ auto rnOp = reinterpret_cast<const RenderNodeOp*>(op);
+ rnOp->renderNode->output(level + 1, strout.str().c_str());
+ } else {
+ ALOGD("%s", strout.str().c_str());
+ }
+ }
+ }
+ ALOGD("%*s/RenderNode(%s %p)", level * 2, "", getName(), this);
+}
+#else
void RenderNode::output(uint32_t level) {
ALOGD("%*sStart display list (%p, %s%s%s%s%s%s)", (level - 1) * 2, "", this,
getName(),
@@ -104,22 +133,16 @@
(properties().getProjectBackwards() ? ", projected" : ""),
(mLayer != nullptr ? ", on HW Layer" : ""));
ALOGD("%*s%s %d", level * 2, "", "Save", SaveFlags::MatrixClip);
-
properties().debugOutputProperties(level);
-
if (mDisplayList) {
-#if HWUI_NEW_OPS
- LOG_ALWAYS_FATAL("op dumping unsupported");
-#else
// TODO: consider printing the chunk boundaries here
for (auto&& op : mDisplayList->getOps()) {
op->output(level, DisplayListOp::kOpLogFlag_Recurse);
}
-#endif
}
-
ALOGD("%*sDone (%p, %s)", (level - 1) * 2, "", this, getName());
-}
+ }
+#endif
void RenderNode::copyTo(proto::RenderNode *pnode) {
pnode->set_id(static_cast<uint64_t>(
@@ -218,6 +241,10 @@
mAnimatorManager.addAnimator(animator);
}
+void RenderNode::removeAnimator(const sp<BaseRenderNodeAnimator>& animator) {
+ mAnimatorManager.removeAnimator(animator);
+}
+
void RenderNode::damageSelf(TreeInfo& info) {
if (isRenderable()) {
if (properties().getClipDamageToBounds()) {
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index f248de54..8381925 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -123,7 +123,11 @@
void defer(DeferStateStruct& deferStruct, const int level);
void replay(ReplayStateStruct& replayStruct, const int level);
+#if HWUI_NEW_OPS
+ ANDROID_API void output(uint32_t level = 0, const char* label = "Root");
+#else
ANDROID_API void output(uint32_t level = 1);
+#endif
ANDROID_API int getDebugSize();
void copyTo(proto::RenderNode* node);
@@ -187,6 +191,12 @@
// UI thread only!
ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator);
+ void removeAnimator(const sp<BaseRenderNodeAnimator>& animator);
+
+ // This can only happen during pushStaging()
+ void onAnimatorTargetChanged(BaseRenderNodeAnimator* animator) {
+ mAnimatorManager.onAnimatorTargetChanged(animator);
+ }
AnimatorManager& animators() { return mAnimatorManager; }
diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp
index b848af4..0b0f0fa 100644
--- a/libs/hwui/RenderProperties.cpp
+++ b/libs/hwui/RenderProperties.cpp
@@ -102,22 +102,23 @@
void RenderProperties::debugOutputProperties(const int level) const {
if (mPrimitiveFields.mLeft != 0 || mPrimitiveFields.mTop != 0) {
- ALOGD("%*sTranslate (left, top) %d, %d", level * 2, "", mPrimitiveFields.mLeft, mPrimitiveFields.mTop);
+ ALOGD("%*s(Translate (left, top) %d, %d)", level * 2, "",
+ mPrimitiveFields.mLeft, mPrimitiveFields.mTop);
}
if (mStaticMatrix) {
- ALOGD("%*sConcatMatrix (static) %p: " SK_MATRIX_STRING,
+ ALOGD("%*s(ConcatMatrix (static) %p: " SK_MATRIX_STRING ")",
level * 2, "", mStaticMatrix, SK_MATRIX_ARGS(mStaticMatrix));
}
if (mAnimationMatrix) {
- ALOGD("%*sConcatMatrix (animation) %p: " SK_MATRIX_STRING,
+ ALOGD("%*s(ConcatMatrix (animation) %p: " SK_MATRIX_STRING ")",
level * 2, "", mAnimationMatrix, SK_MATRIX_ARGS(mAnimationMatrix));
}
if (hasTransformMatrix()) {
if (isTransformTranslateOnly()) {
- ALOGD("%*sTranslate %.2f, %.2f, %.2f",
+ ALOGD("%*s(Translate %.2f, %.2f, %.2f)",
level * 2, "", getTranslationX(), getTranslationY(), getZ());
} else {
- ALOGD("%*sConcatMatrix %p: " SK_MATRIX_STRING,
+ ALOGD("%*s(ConcatMatrix %p: " SK_MATRIX_STRING ")",
level * 2, "", mComputedFields.mTransformMatrix, SK_MATRIX_ARGS(mComputedFields.mTransformMatrix));
}
}
@@ -132,7 +133,7 @@
if (CC_LIKELY(isLayer || !getHasOverlappingRendering())) {
// simply scale rendering content's alpha
- ALOGD("%*sScaleAlpha %.2f", level * 2, "", mPrimitiveFields.mAlpha);
+ ALOGD("%*s(ScaleAlpha %.2f)", level * 2, "", mPrimitiveFields.mAlpha);
} else {
// savelayeralpha to create an offscreen buffer to apply alpha
Rect layerBounds(0, 0, getWidth(), getHeight());
@@ -140,19 +141,18 @@
getClippingRectForFlags(clipFlags, &layerBounds);
clipFlags = 0; // all clipping done by savelayer
}
- ALOGD("%*sSaveLayerAlpha %d, %d, %d, %d, %d, 0x%x", level * 2, "",
+ ALOGD("%*s(SaveLayerAlpha %d, %d, %d, %d, %d, 0x%x)", level * 2, "",
(int)layerBounds.left, (int)layerBounds.top,
(int)layerBounds.right, (int)layerBounds.bottom,
(int)(mPrimitiveFields.mAlpha * 255),
SaveFlags::HasAlphaLayer | SaveFlags::ClipToLayer);
}
-
-
}
+
if (clipFlags) {
Rect clipRect;
getClippingRectForFlags(clipFlags, &clipRect);
- ALOGD("%*sClipRect %d, %d, %d, %d", level * 2, "",
+ ALOGD("%*s(ClipRect %d, %d, %d, %d)", level * 2, "",
(int)clipRect.left, (int)clipRect.top, (int)clipRect.right, (int)clipRect.bottom);
}
}
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index 27fea1f..cf5e69a 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -146,6 +146,9 @@
}
void Snapshot::buildScreenSpaceTransform(Matrix4* outTransform) const {
+#if HWUI_NEW_OPS
+ LOG_ALWAYS_FATAL("not supported - not needed by new ops");
+#else
// build (reverse ordered) list of the stack of snapshots, terminated with a NULL
Vector<const Snapshot*> snapshotList;
snapshotList.push(nullptr);
@@ -171,6 +174,7 @@
outTransform->multiply(*(current->transform));
}
}
+#endif
}
///////////////////////////////////////////////////////////////////////////////
@@ -223,15 +227,19 @@
}
void Snapshot::setProjectionPathMask(LinearAllocator& allocator, const SkPath* path) {
+#if HWUI_NEW_OPS
+ // TODO: remove allocator param for HWUI_NEW_OPS
+ projectionPathMask = path;
+#else
if (path) {
ProjectionPathMask* mask = new (allocator) ProjectionPathMask;
mask->projectionMask = path;
buildScreenSpaceTransform(&(mask->projectionMaskTransform));
-
projectionPathMask = mask;
} else {
projectionPathMask = nullptr;
}
+#endif
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index 0ac2f14..3a01d04 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -44,7 +44,7 @@
*/
class RoundRectClipState {
public:
- /** static void* operator new(size_t size); PURPOSELY OMITTED, allocator only **/
+ static void* operator new(size_t size) = delete;
static void* operator new(size_t size, LinearAllocator& allocator) {
return allocator.alloc<RoundRectClipState>(size);
}
@@ -63,9 +63,10 @@
float radius;
};
+// TODO: remove for HWUI_NEW_OPS
class ProjectionPathMask {
public:
- /** static void* operator new(size_t size); PURPOSELY OMITTED, allocator only **/
+ static void* operator new(size_t size) = delete;
static void* operator new(size_t size, LinearAllocator& allocator) {
return allocator.alloc<ProjectionPathMask>(size);
}
@@ -219,6 +220,7 @@
* Fills outTransform with the current, total transform to screen space,
* across layer boundaries.
*/
+ // TODO: remove for HWUI_NEW_OPS
void buildScreenSpaceTransform(Matrix4* outTransform) const;
/**
@@ -294,9 +296,13 @@
const RoundRectClipState* roundRectClipState;
/**
- * Current projection masking path - used exclusively to mask tessellated circles.
+ * Current projection masking path - used exclusively to mask projected, tessellated circles.
*/
+#if HWUI_NEW_OPS
+ const SkPath* projectionPathMask;
+#else
const ProjectionPathMask* projectionPathMask;
+#endif
void dump() const;
diff --git a/libs/hwui/renderstate/MeshState.cpp b/libs/hwui/renderstate/MeshState.cpp
index 03cb5ce..b575c69 100644
--- a/libs/hwui/renderstate/MeshState.cpp
+++ b/libs/hwui/renderstate/MeshState.cpp
@@ -34,7 +34,6 @@
glGenBuffers(1, &mUnitQuadBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mUnitQuadBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(kUnitQuadVertices), kUnitQuadVertices, GL_STATIC_DRAW);
-
mCurrentBuffer = mUnitQuadBuffer;
uint16_t regionIndices[kMaxNumberOfQuads * 6];
@@ -78,26 +77,18 @@
// Buffer Objects
///////////////////////////////////////////////////////////////////////////////
-bool MeshState::bindMeshBuffer() {
- return bindMeshBuffer(mUnitQuadBuffer);
-}
-
-bool MeshState::bindMeshBuffer(GLuint buffer) {
- if (!buffer) buffer = mUnitQuadBuffer;
- return bindMeshBufferInternal(buffer);
-}
-
-bool MeshState::unbindMeshBuffer() {
- return bindMeshBufferInternal(0);
-}
-
-bool MeshState::bindMeshBufferInternal(GLuint buffer) {
+void MeshState::bindMeshBuffer(GLuint buffer) {
if (mCurrentBuffer != buffer) {
glBindBuffer(GL_ARRAY_BUFFER, buffer);
mCurrentBuffer = buffer;
- return true;
+
+ // buffer has changed, so invalidate cached vertex pos/texcoord pointers
+ resetVertexPointers();
}
- return false;
+}
+
+void MeshState::unbindMeshBuffer() {
+ return bindMeshBuffer(0);
}
void MeshState::genOrUpdateMeshBuffer(GLuint* buffer, GLsizeiptr size,
@@ -122,16 +113,22 @@
// Vertices
///////////////////////////////////////////////////////////////////////////////
-void MeshState::bindPositionVertexPointer(bool force, const GLvoid* vertices, GLsizei stride) {
- if (force || vertices != mCurrentPositionPointer || stride != mCurrentPositionStride) {
+void MeshState::bindPositionVertexPointer(const GLvoid* vertices, GLsizei stride) {
+ // update pos coords if !current vbo, since vertices may point into mutable memory (e.g. stack)
+ if (mCurrentBuffer == 0
+ || vertices != mCurrentPositionPointer
+ || stride != mCurrentPositionStride) {
glVertexAttribPointer(Program::kBindingPosition, 2, GL_FLOAT, GL_FALSE, stride, vertices);
mCurrentPositionPointer = vertices;
mCurrentPositionStride = stride;
}
}
-void MeshState::bindTexCoordsVertexPointer(bool force, const GLvoid* vertices, GLsizei stride) {
- if (force || vertices != mCurrentTexCoordsPointer || stride != mCurrentTexCoordsStride) {
+void MeshState::bindTexCoordsVertexPointer(const GLvoid* vertices, GLsizei stride) {
+ // update tex coords if !current vbo, since vertices may point into mutable memory (e.g. stack)
+ if (mCurrentBuffer == 0
+ || vertices != mCurrentTexCoordsPointer
+ || stride != mCurrentTexCoordsStride) {
glVertexAttribPointer(Program::kBindingTexCoords, 2, GL_FLOAT, GL_FALSE, stride, vertices);
mCurrentTexCoordsPointer = vertices;
mCurrentTexCoordsStride = stride;
@@ -143,10 +140,6 @@
mCurrentTexCoordsPointer = this;
}
-void MeshState::resetTexCoordsVertexPointer() {
- mCurrentTexCoordsPointer = this;
-}
-
void MeshState::enableTexCoordsVertexArray() {
if (!mTexCoordsArrayEnabled) {
glEnableVertexAttribArray(Program::kBindingTexCoords);
@@ -166,26 +159,18 @@
// Indices
///////////////////////////////////////////////////////////////////////////////
-bool MeshState::bindIndicesBufferInternal(const GLuint buffer) {
+void MeshState::bindIndicesBuffer(const GLuint buffer) {
if (mCurrentIndicesBuffer != buffer) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
mCurrentIndicesBuffer = buffer;
- return true;
}
- return false;
}
-bool MeshState::bindQuadIndicesBuffer() {
- return bindIndicesBufferInternal(mQuadListIndices);
-}
-
-bool MeshState::unbindIndicesBuffer() {
+void MeshState::unbindIndicesBuffer() {
if (mCurrentIndicesBuffer) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
mCurrentIndicesBuffer = 0;
- return true;
}
- return false;
}
} /* namespace uirenderer */
diff --git a/libs/hwui/renderstate/MeshState.h b/libs/hwui/renderstate/MeshState.h
index 6c0fb78..dd68468 100644
--- a/libs/hwui/renderstate/MeshState.h
+++ b/libs/hwui/renderstate/MeshState.h
@@ -60,20 +60,16 @@
///////////////////////////////////////////////////////////////////////////////
// Buffer objects
///////////////////////////////////////////////////////////////////////////////
- /**
- * Binds the VBO used to render simple textured quads.
- */
- bool bindMeshBuffer();
/**
* Binds the specified VBO if needed. If buffer == 0, binds default simple textured quad.
*/
- bool bindMeshBuffer(GLuint buffer);
+ void bindMeshBuffer(GLuint buffer);
/**
- * Unbinds the VBO used to render simple textured quads.
+ * Unbinds the current VBO if active.
*/
- bool unbindMeshBuffer();
+ void unbindMeshBuffer();
void genOrUpdateMeshBuffer(GLuint* buffer, GLsizeiptr size, const void* data, GLenum usage);
void deleteMeshBuffer(GLuint);
@@ -85,21 +81,20 @@
* Binds an attrib to the specified float vertex pointer.
* Assumes a stride of gTextureVertexStride and a size of 2.
*/
- void bindPositionVertexPointer(bool force, const GLvoid* vertices,
+ void bindPositionVertexPointer(const GLvoid* vertices,
GLsizei stride = kTextureVertexStride);
/**
* Binds an attrib to the specified float vertex pointer.
* Assumes a stride of gTextureVertexStride and a size of 2.
*/
- void bindTexCoordsVertexPointer(bool force, const GLvoid* vertices,
+ void bindTexCoordsVertexPointer(const GLvoid* vertices,
GLsizei stride = kTextureVertexStride);
/**
* Resets the vertex pointers.
*/
void resetVertexPointers();
- void resetTexCoordsVertexPointer();
void enableTexCoordsVertexArray();
void disableTexCoordsVertexArray();
@@ -107,12 +102,8 @@
///////////////////////////////////////////////////////////////////////////////
// Indices
///////////////////////////////////////////////////////////////////////////////
- /**
- * Binds a global indices buffer that can draw up to
- * gMaxNumberOfQuads quads.
- */
- bool bindQuadIndicesBuffer();
- bool unbindIndicesBuffer();
+ void bindIndicesBuffer(const GLuint buffer);
+ void unbindIndicesBuffer();
///////////////////////////////////////////////////////////////////////////////
// Getters - for use in Glop building
@@ -121,8 +112,6 @@
GLuint getQuadListIBO() { return mQuadListIndices; }
private:
MeshState();
- bool bindMeshBufferInternal(const GLuint buffer);
- bool bindIndicesBufferInternal(const GLuint buffer);
GLuint mUnitQuadBuffer;
diff --git a/libs/hwui/renderstate/OffscreenBufferPool.cpp b/libs/hwui/renderstate/OffscreenBufferPool.cpp
index 54f38e8..5f984b5 100644
--- a/libs/hwui/renderstate/OffscreenBufferPool.cpp
+++ b/libs/hwui/renderstate/OffscreenBufferPool.cpp
@@ -54,6 +54,14 @@
return Rect(0, viewportHeight * texY, viewportWidth * texX, 0);
}
+void OffscreenBuffer::dirty(Rect dirtyArea) {
+ dirtyArea.doIntersect(0, 0, viewportWidth, viewportHeight);
+ if (!dirtyArea.isEmpty()) {
+ region.orSelf(android::Rect(dirtyArea.left, dirtyArea.top,
+ dirtyArea.right, dirtyArea.bottom));
+ }
+}
+
void OffscreenBuffer::updateMeshFromRegion() {
// avoid T-junctions as they cause artifacts in between the resultant
// geometry when complex transforms occur.
diff --git a/libs/hwui/renderstate/OffscreenBufferPool.h b/libs/hwui/renderstate/OffscreenBufferPool.h
index 94155ef..089f131 100644
--- a/libs/hwui/renderstate/OffscreenBufferPool.h
+++ b/libs/hwui/renderstate/OffscreenBufferPool.h
@@ -48,6 +48,8 @@
Rect getTextureCoordinates();
+ void dirty(Rect dirtyArea);
+
// must be called prior to rendering, to construct/update vertex buffer
void updateMeshFromRegion();
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index e535f2f..ea4391b 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -292,28 +292,27 @@
// ---------- Mesh setup ----------
// --------------------------------
// vertices
- const bool force = meshState().bindMeshBufferInternal(vertices.bufferObject)
- || (vertices.position != nullptr);
- meshState().bindPositionVertexPointer(force, vertices.position, vertices.stride);
+ meshState().bindMeshBuffer(vertices.bufferObject);
+ meshState().bindPositionVertexPointer(vertices.position, vertices.stride);
// indices
- meshState().bindIndicesBufferInternal(indices.bufferObject);
+ meshState().bindIndicesBuffer(indices.bufferObject);
if (vertices.attribFlags & VertexAttribFlags::TextureCoord) {
const Glop::Fill::TextureData& texture = fill.texture;
// texture always takes slot 0, shader samplers increment from there
mCaches->textureState().activateTexture(0);
+ mCaches->textureState().bindTexture(texture.target, texture.texture->id());
if (texture.clamp != GL_INVALID_ENUM) {
- texture.texture->setWrap(texture.clamp, true, false, texture.target);
+ texture.texture->setWrap(texture.clamp, false, false, texture.target);
}
if (texture.filter != GL_INVALID_ENUM) {
- texture.texture->setFilter(texture.filter, true, false, texture.target);
+ texture.texture->setFilter(texture.filter, false, false, texture.target);
}
- mCaches->textureState().bindTexture(texture.target, texture.texture->id());
meshState().enableTexCoordsVertexArray();
- meshState().bindTexCoordsVertexPointer(force, vertices.texCoord, vertices.stride);
+ meshState().bindTexCoordsVertexPointer(vertices.texCoord, vertices.stride);
if (texture.textureTransform) {
glUniformMatrix4fv(fill.program->getUniform("mainTextureTransform"), 1,
@@ -361,11 +360,9 @@
const GLbyte* vertexData = static_cast<const GLbyte*>(vertices.position);
while (elementsCount > 0) {
GLsizei drawCount = std::min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6);
-
- // rebind pointers without forcing, since initial bind handled above
- meshState().bindPositionVertexPointer(false, vertexData, vertices.stride);
+ meshState().bindPositionVertexPointer(vertexData, vertices.stride);
if (vertices.attribFlags & VertexAttribFlags::TextureCoord) {
- meshState().bindTexCoordsVertexPointer(false,
+ meshState().bindTexCoordsVertexPointer(
vertexData + kMeshTextureOffset, vertices.stride);
}
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 4f528b1..a496b49 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -348,12 +348,26 @@
FrameBuilder frameBuilder(mLayerUpdateQueue, dirty, frame.width(), frame.height(),
mRenderNodes, mLightGeometry, mContentDrawBounds, &Caches::getInstance());
mLayerUpdateQueue.clear();
- BakedOpRenderer renderer(Caches::getInstance(), mRenderThread.renderState(),
+ auto&& caches = Caches::getInstance();
+ BakedOpRenderer renderer(caches, mRenderThread.renderState(),
mOpaque, mLightInfo);
- // TODO: profiler().draw(mCanvas);
frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
+ profiler().draw(&renderer);
bool drew = renderer.didDraw();
+ // post frame cleanup
+ caches.clearGarbage();
+ caches.pathCache.trim();
+ caches.tessellationCache.trim();
+
+#if DEBUG_MEMORY_USAGE
+ mCaches.dumpMemoryUsage();
+#else
+ if (CC_UNLIKELY(Properties::debugLevel & kDebugMemory)) {
+ caches.dumpMemoryUsage();
+ }
+#endif
+
#else
mCanvas->prepareDirty(frame.width(), frame.height(),
dirty.fLeft, dirty.fTop, dirty.fRight, dirty.fBottom, mOpaque);
@@ -476,7 +490,7 @@
// metrics the frame was swapped at this point
mCurrentFrameInfo->markSwapBuffers();
- if (drew) {
+ if (drew || mEglManager.damageRequiresSwap()) {
if (CC_UNLIKELY(!mEglManager.swapBuffers(frame, screenDirty))) {
setSurface(nullptr);
}
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 364d4dd..8def7ad 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -270,6 +270,12 @@
// Ensure we always have a valid surface & context
surface = mPBufferSurface;
}
+ // TODO: Temporary to help diagnose b/27286867
+ if (mCurrentSurface == mPBufferSurface || surface == mPBufferSurface) {
+ ALOGD("Switching from surface %p%s to %p%s", mCurrentSurface,
+ mCurrentSurface == mPBufferSurface ? " (pbuffer)" : "",
+ surface, surface == mPBufferSurface ? " (pbuffer)" : "");
+ }
if (!eglMakeCurrent(mEglDisplay, surface, surface, mEglContext)) {
if (errOut) {
*errOut = eglGetError();
@@ -324,6 +330,10 @@
#endif
}
+bool EglManager::damageRequiresSwap() {
+ return EglExtensions.setDamage && mSwapBehavior == SwapBehavior::BufferAge;
+}
+
bool EglManager::swapBuffers(const Frame& frame, const SkRect& screenDirty) {
if (CC_UNLIKELY(Properties::waitForGpuCompletion)) {
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index 62b5b99..459baed 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -70,6 +70,10 @@
bool makeCurrent(EGLSurface surface, EGLint* errOut = nullptr);
Frame beginFrame(EGLSurface surface);
void damageFrame(const Frame& frame, const SkRect& dirty);
+ // If this returns true it is mandatory that swapBuffers is called
+ // if damageFrame is called without subsequent calls to damageFrame().
+ // See EGL_KHR_partial_update for more information
+ bool damageRequiresSwap();
bool swapBuffers(const Frame& frame, const SkRect& screenDirty);
// Returns true iff the surface is now preserving buffers.
diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp
index 3440d03..9595a85 100644
--- a/libs/hwui/tests/common/TestUtils.cpp
+++ b/libs/hwui/tests/common/TestUtils.cpp
@@ -162,6 +162,7 @@
renderState.onGLContextCreated();
rtCallback(renderthread::RenderThread::getInstance());
+ renderState.flush(Caches::FlushMode::Full);
renderState.onGLContextDestroyed();
// Restore the previous signal handler
diff --git a/libs/hwui/tests/unit/ClipAreaTests.cpp b/libs/hwui/tests/unit/ClipAreaTests.cpp
index 679569e..822d04f 100644
--- a/libs/hwui/tests/unit/ClipAreaTests.cpp
+++ b/libs/hwui/tests/unit/ClipAreaTests.cpp
@@ -27,7 +27,7 @@
namespace android {
namespace uirenderer {
-static Rect kViewportBounds(0, 0, 2048, 2048);
+static Rect kViewportBounds(2048, 2048);
static ClipArea createClipArea() {
ClipArea area;
@@ -140,17 +140,15 @@
// rect list
Matrix4 rotate;
- rotate.loadRotate(2.0f);
- area.clipRectWithTransform(Rect(200, 200), &rotate, SkRegion::kIntersect_Op);
+ rotate.loadRotate(5.0f);
+ area.clipRectWithTransform(Rect(50, 50, 150, 150), &rotate, SkRegion::kIntersect_Op);
{
auto serializedClip = area.serializeClip(allocator);
ASSERT_NE(nullptr, serializedClip);
ASSERT_EQ(ClipMode::RectangleList, serializedClip->mode);
auto clipRectList = reinterpret_cast<const ClipRectList*>(serializedClip);
EXPECT_EQ(2, clipRectList->rectList.getTransformedRectanglesCount());
- EXPECT_FALSE(clipRectList->rect.isEmpty());
- EXPECT_FLOAT_EQ(199.87817f, clipRectList->rect.right)
- << "Right side should be clipped by rotated rect";
+ EXPECT_EQ(Rect(37, 54, 145, 163), clipRectList->rect);
EXPECT_EQ(serializedClip, area.serializeClip(allocator))
<< "Requery of clip on unmodified ClipArea must return same pointer.";
}
@@ -228,6 +226,7 @@
ClipRegion recordedClip;
recordedClip.region.setPath(ovalPath, SkRegion(SkIRect::MakeWH(200, 200)));
+ recordedClip.rect = Rect(200, 200);
Matrix4 translate10x20;
translate10x20.loadTranslate(10, 20, 0);
@@ -240,5 +239,28 @@
}
}
+TEST(ClipArea, serializeIntersectedClip_snap) {
+ ClipArea area(createClipArea());
+ area.setClip(100.2, 100.4, 500.6, 500.8);
+ LinearAllocator allocator;
+
+ {
+ // no recorded clip case
+ auto resolvedClip = area.serializeIntersectedClip(allocator, nullptr, Matrix4::identity());
+ EXPECT_EQ(Rect(100, 100, 501, 501), resolvedClip->rect);
+ }
+ {
+ // recorded clip case
+ ClipRect recordedClip(Rect(100.12, 100.74));
+ Matrix4 translateScale;
+ translateScale.loadTranslate(100, 100, 0);
+ translateScale.scale(2, 3, 1); // recorded clip will have non-int coords, even after transform
+ auto resolvedClip = area.serializeIntersectedClip(allocator, &recordedClip, translateScale);
+ ASSERT_NE(nullptr, resolvedClip);
+ EXPECT_EQ(ClipMode::Rectangle, resolvedClip->mode);
+ EXPECT_EQ(Rect(100, 100, 300, 402), resolvedClip->rect);
+ }
+}
+
} // namespace uirenderer
} // namespace android
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index f49dd3f..4c56a22 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -216,8 +216,7 @@
<< "Expect number of ops = 2 * loop count";
}
-// TODO: Disabled due to b/26793764
-TEST(FrameBuilder, DISABLED_clippedMerging) {
+TEST(FrameBuilder, clippedMerging) {
class ClippedMergingTestRenderer : public TestRendererBase {
public:
void onMergedBitmapOps(const MergedBakedOpList& opList) override {
@@ -651,6 +650,62 @@
<< "Expect 4 copyTos, 4 copyFroms, 1 clear SimpleRects, and 1 rect.";
}
+TEST(FrameBuilder, saveLayerUnclipped_clearClip) {
+ class SaveLayerUnclippedClearClipTestRenderer : public TestRendererBase {
+ public:
+ void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(0, mIndex++);
+ }
+ void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(1, mIndex++);
+ ASSERT_NE(nullptr, op.paint);
+ EXPECT_EQ(SkXfermode::kClear_Mode, PaintUtils::getXfermodeDirect(op.paint));
+ EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds)
+ << "Expect dirty rect as clip";
+ ASSERT_NE(nullptr, state.computedState.clipState);
+ EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clipState->rect);
+ EXPECT_EQ(ClipMode::Rectangle, state.computedState.clipState->mode);
+ }
+ void onRectOp(const RectOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(2, mIndex++);
+ }
+ void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(3, mIndex++);
+ }
+ };
+
+ auto node = TestUtils::createNode(0, 0, 200, 200,
+ [](RenderProperties& props, RecordingCanvas& canvas) {
+ // save smaller than clip, so we get unclipped behavior
+ canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0));
+ canvas.drawRect(0, 0, 200, 200, SkPaint());
+ canvas.restore();
+ });
+
+ // draw with partial screen dirty, and assert we see that rect later
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeLTRB(50, 50, 150, 150), 200, 200,
+ TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
+ SaveLayerUnclippedClearClipTestRenderer renderer;
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+ EXPECT_EQ(4, renderer.getIndex());
+}
+
+TEST(FrameBuilder, saveLayerUnclipped_reject) {
+ auto node = TestUtils::createNode(0, 0, 200, 200,
+ [](RenderProperties& props, RecordingCanvas& canvas) {
+ // unclipped savelayer + rect both in area that won't intersect with dirty
+ canvas.saveLayerAlpha(100, 100, 200, 200, 128, (SaveFlags::Flags)(0));
+ canvas.drawRect(100, 100, 200, 200, SkPaint());
+ canvas.restore();
+ });
+
+ // draw with partial screen dirty that doesn't intersect with savelayer
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 200, 200,
+ TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
+ FailRenderer renderer;
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+}
+
/* saveLayerUnclipped { saveLayer { saveLayerUnclipped { rect } } } will play back as:
* - startTemporaryLayer, onCopyToLayer, onSimpleRects, onRect, onCopyFromLayer, endLayer
* - startFrame, onCopyToLayer, onSimpleRects, drawLayer, onCopyFromLayer, endframe
@@ -934,21 +989,26 @@
EXPECT_EQ(Rect(100, 100), op.unmappedBounds);
EXPECT_EQ(SK_ColorWHITE, op.paint->getColor());
expectedMatrix.loadIdentity();
+ EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask);
break;
case 1:
EXPECT_EQ(Rect(-10, -10, 60, 60), op.unmappedBounds);
EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor());
- expectedMatrix.loadTranslate(50, 50, 0); // TODO: should scroll be respected here?
+ expectedMatrix.loadTranslate(50 - scrollX, 50 - scrollY, 0);
+ ASSERT_NE(nullptr, state.computedState.localProjectionPathMask);
+ EXPECT_EQ(Rect(-35, -30, 45, 50),
+ Rect(state.computedState.localProjectionPathMask->getBounds()));
break;
case 2:
EXPECT_EQ(Rect(100, 50), op.unmappedBounds);
EXPECT_EQ(SK_ColorBLUE, op.paint->getColor());
expectedMatrix.loadTranslate(-scrollX, 50 - scrollY, 0);
+ EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask);
break;
default:
ADD_FAILURE();
}
- EXPECT_MATRIX_APPROX_EQ(expectedMatrix, state.computedState.transform);
+ EXPECT_EQ(expectedMatrix, state.computedState.transform);
}
};
@@ -989,6 +1049,9 @@
});
auto parent = TestUtils::createNode(0, 0, 100, 100,
[&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) {
+ // Set a rect outline for the projecting ripple to be masked against.
+ properties.mutableOutline().setRoundRect(10, 10, 90, 90, 5, 1.0f);
+
canvas.save(SaveFlags::MatrixClip);
canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally)
canvas.drawRenderNode(receiverBackground.get());
@@ -1003,6 +1066,145 @@
EXPECT_EQ(3, renderer.getIndex());
}
+RENDERTHREAD_TEST(FrameBuilder, projectionHwLayer) {
+ static const int scrollX = 5;
+ static const int scrollY = 10;
+ class ProjectionHwLayerTestRenderer : public TestRendererBase {
+ public:
+ void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override {
+ EXPECT_EQ(0, mIndex++);
+ }
+ void onArcOp(const ArcOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(1, mIndex++);
+ ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask);
+ }
+ void endLayer() override {
+ EXPECT_EQ(2, mIndex++);
+ }
+ void onRectOp(const RectOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(3, mIndex++);
+ ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask);
+ }
+ void onOvalOp(const OvalOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(4, mIndex++);
+ ASSERT_NE(nullptr, state.computedState.localProjectionPathMask);
+ Matrix4 expected;
+ expected.loadTranslate(100 - scrollX, 100 - scrollY, 0);
+ EXPECT_EQ(expected, state.computedState.transform);
+ EXPECT_EQ(Rect(-85, -80, 295, 300),
+ Rect(state.computedState.localProjectionPathMask->getBounds()));
+ }
+ void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(5, mIndex++);
+ ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask);
+ }
+ };
+ auto receiverBackground = TestUtils::createNode(0, 0, 400, 400,
+ [](RenderProperties& properties, RecordingCanvas& canvas) {
+ properties.setProjectionReceiver(true);
+ // scroll doesn't apply to background, so undone via translationX/Y
+ // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver!
+ properties.setTranslationX(scrollX);
+ properties.setTranslationY(scrollY);
+
+ canvas.drawRect(0, 0, 400, 400, SkPaint());
+ });
+ auto projectingRipple = TestUtils::createNode(0, 0, 200, 200,
+ [](RenderProperties& properties, RecordingCanvas& canvas) {
+ properties.setProjectBackwards(true);
+ properties.setClipToBounds(false);
+ canvas.drawOval(100, 100, 300, 300, SkPaint()); // drawn mostly out of layer bounds
+ });
+ auto child = TestUtils::createNode(100, 100, 300, 300,
+ [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) {
+ properties.mutateLayerProperties().setType(LayerType::RenderLayer);
+ canvas.drawRenderNode(projectingRipple.get());
+ canvas.drawArc(0, 0, 200, 200, 0.0f, 280.0f, true, SkPaint());
+ });
+ auto parent = TestUtils::createNode(0, 0, 400, 400,
+ [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) {
+ // Set a rect outline for the projecting ripple to be masked against.
+ properties.mutableOutline().setRoundRect(10, 10, 390, 390, 0, 1.0f);
+ canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally)
+ canvas.drawRenderNode(receiverBackground.get());
+ canvas.drawRenderNode(child.get());
+ });
+
+ OffscreenBuffer** layerHandle = child->getLayerHandle();
+
+ // create RenderNode's layer here in same way prepareTree would, setting windowTransform
+ OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 200, 200);
+ Matrix4 windowTransform;
+ windowTransform.loadTranslate(100, 100, 0); // total transform of layer's origin
+ layer.setWindowTransform(windowTransform);
+ *layerHandle = &layer;
+
+ auto syncedList = TestUtils::createSyncedNodeList(parent);
+ LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
+ layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(200, 200));
+ FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400,
+ syncedList, sLightGeometry, nullptr);
+ ProjectionHwLayerTestRenderer renderer;
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+ EXPECT_EQ(6, renderer.getIndex());
+
+ // clean up layer pointer, so we can safely destruct RenderNode
+ *layerHandle = nullptr;
+}
+
+RENDERTHREAD_TEST(FrameBuilder, projectionChildScroll) {
+ static const int scrollX = 500000;
+ static const int scrollY = 0;
+ class ProjectionChildScrollTestRenderer : public TestRendererBase {
+ public:
+ void onRectOp(const RectOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(0, mIndex++);
+ EXPECT_TRUE(state.computedState.transform.isIdentity());
+ }
+ void onOvalOp(const OvalOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(1, mIndex++);
+ ASSERT_NE(nullptr, state.computedState.clipState);
+ ASSERT_EQ(ClipMode::Rectangle, state.computedState.clipState->mode);
+ ASSERT_EQ(Rect(400, 400), state.computedState.clipState->rect);
+ EXPECT_TRUE(state.computedState.transform.isIdentity());
+ }
+ };
+ auto receiverBackground = TestUtils::createNode(0, 0, 400, 400,
+ [](RenderProperties& properties, RecordingCanvas& canvas) {
+ properties.setProjectionReceiver(true);
+ canvas.drawRect(0, 0, 400, 400, SkPaint());
+ });
+ auto projectingRipple = TestUtils::createNode(0, 0, 200, 200,
+ [](RenderProperties& properties, RecordingCanvas& canvas) {
+ // scroll doesn't apply to background, so undone via translationX/Y
+ // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver!
+ properties.setTranslationX(scrollX);
+ properties.setTranslationY(scrollY);
+ properties.setProjectBackwards(true);
+ properties.setClipToBounds(false);
+ canvas.drawOval(0, 0, 200, 200, SkPaint());
+ });
+ auto child = TestUtils::createNode(0, 0, 400, 400,
+ [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) {
+ // Record time clip will be ignored by projectee
+ canvas.clipRect(100, 100, 300, 300, SkRegion::kIntersect_Op);
+
+ canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally)
+ canvas.drawRenderNode(projectingRipple.get());
+ });
+ auto parent = TestUtils::createNode(0, 0, 400, 400,
+ [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) {
+ canvas.drawRenderNode(receiverBackground.get());
+ canvas.drawRenderNode(child.get());
+ });
+
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400,
+ TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr);
+ ProjectionChildScrollTestRenderer renderer;
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+ EXPECT_EQ(2, renderer.getIndex());
+}
+
// creates a 100x100 shadow casting node with provided translationZ
static sp<RenderNode> createWhiteRectShadowCaster(float translationZ) {
return TestUtils::createNode(0, 0, 100, 100,
diff --git a/libs/hwui/tests/unit/MatrixTests.cpp b/libs/hwui/tests/unit/MatrixTests.cpp
new file mode 100644
index 0000000..da22637
--- /dev/null
+++ b/libs/hwui/tests/unit/MatrixTests.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "Matrix.h"
+#include "Rect.h"
+
+using namespace android::uirenderer;
+
+TEST(Matrix, mapRect) {
+ // Skew, so we don't hit identity/translate/simple fast paths
+ Matrix4 matrix;
+ matrix.skew(0.1f, 0.1f);
+
+ // non-zero empty rect, so sorting x/y would make rect non-empty
+ Rect empty(100, 100, -100, -100);
+ ASSERT_TRUE(empty.isEmpty());
+ matrix.mapRect(empty);
+ EXPECT_TRUE(empty.isEmpty())
+ << "Empty rect should always remain empty, regardless of mapping.";
+}
diff --git a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
index 2fd8795..0c6eb57 100644
--- a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
+++ b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
@@ -55,6 +55,14 @@
});
}
+TEST(OffscreenBuffer, dirty) {
+ TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
+ OffscreenBuffer buffer(thread.renderState(), Caches::getInstance(), 256u, 256u);
+ buffer.dirty(Rect(-100, -100, 100, 100));
+ EXPECT_EQ(android::Rect(100, 100), buffer.region.getBounds());
+ });
+}
+
TEST(OffscreenBufferPool, construct) {
TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
OffscreenBufferPool pool;
diff --git a/libs/hwui/tests/unit/OpDumperTests.cpp b/libs/hwui/tests/unit/OpDumperTests.cpp
new file mode 100644
index 0000000..01840d7
--- /dev/null
+++ b/libs/hwui/tests/unit/OpDumperTests.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "tests/common/TestUtils.h"
+#include "OpDumper.h"
+
+using namespace android;
+using namespace android::uirenderer;
+
+TEST(OpDumper, dump) {
+ SkPaint paint;
+ RectOp op(uirenderer::Rect(100, 100), Matrix4::identity(), nullptr, &paint);
+
+ std::stringstream stream;
+ OpDumper::dump(op, stream);
+ EXPECT_STREQ("RectOp [100 x 100]", stream.str().c_str());
+
+ stream.str("");
+ OpDumper::dump(op, stream, 2);
+ EXPECT_STREQ(" RectOp [100 x 100]", stream.str().c_str());
+
+ ClipRect clipRect(uirenderer::Rect(50, 50));
+ op.localClip = &clipRect;
+
+ stream.str("");
+ OpDumper::dump(op, stream, 2);
+ EXPECT_STREQ(" RectOp [100 x 100] clip=[50 x 50] mode=0", stream.str().c_str());
+}
diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
index 20d2f1f..d35b1f9 100644
--- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -19,6 +19,7 @@
#include <RecordedOp.h>
#include <RecordingCanvas.h>
#include <tests/common/TestUtils.h>
+#include <utils/Color.h>
namespace android {
namespace uirenderer {
@@ -57,6 +58,33 @@
<< "Clip should be serialized once";
}
+TEST(RecordingCanvas, emptyClipRect) {
+ auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
+ canvas.save(SaveFlags::MatrixClip);
+ canvas.clipRect(0, 0, 100, 100, SkRegion::kIntersect_Op);
+ canvas.clipRect(100, 100, 200, 200, SkRegion::kIntersect_Op);
+ canvas.drawRect(0, 0, 50, 50, SkPaint()); // rejected at record time
+ canvas.restore();
+ });
+ ASSERT_EQ(0u, dl->getOps().size()) << "Must be zero ops. Rect should be rejected.";
+}
+
+TEST(RecordingCanvas, drawArc) {
+ auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
+ canvas.drawArc(0, 0, 200, 200, 0, 180, true, SkPaint());
+ canvas.drawArc(0, 0, 100, 100, 0, 360, true, SkPaint());
+ });
+
+ auto&& ops = dl->getOps();
+ ASSERT_EQ(2u, ops.size()) << "Must be exactly two ops";
+ EXPECT_EQ(RecordedOpId::ArcOp, ops[0]->opId);
+ EXPECT_EQ(Rect(200, 200), ops[0]->unmappedBounds);
+
+ EXPECT_EQ(RecordedOpId::OvalOp, ops[1]->opId)
+ << "Circular arcs should be converted to ovals";
+ EXPECT_EQ(Rect(100, 100), ops[1]->unmappedBounds);
+}
+
TEST(RecordingCanvas, drawLines) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
SkPaint paint;
@@ -169,6 +197,19 @@
ASSERT_EQ(3, count);
}
+TEST(RecordingCanvas, drawColor) {
+ auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
+ canvas.drawColor(Color::Black, SkXfermode::kSrcOver_Mode);
+ });
+
+ ASSERT_EQ(1u, dl->getOps().size()) << "Must be exactly one op";
+ auto op = *(dl->getOps()[0]);
+ EXPECT_EQ(RecordedOpId::RectOp, op.opId);
+ EXPECT_EQ(nullptr, op.localClip);
+ EXPECT_TRUE(op.unmappedBounds.contains(Rect(-1000, -1000, 1000, 1000)))
+ << "no clip, unmappedBounds should resolve to be much larger than DL bounds";
+}
+
TEST(RecordingCanvas, backgroundAndImage) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
SkBitmap bitmap;
@@ -401,9 +442,7 @@
// since the same clip will be computed at draw time. If such a change is made, this
// check could be done at record time by querying the clip, or the clip could be altered
// slightly so that it is serialized.
- EXPECT_RECT_APPROX_EQ(Rect(58.57864, 58.57864, 341.42136, 341.42136),
- (reinterpret_cast<const ClipRect*>(op.localClip))->rect);
-
+ EXPECT_EQ(Rect(59, 59, 341, 341), op.localClip->rect);
EXPECT_EQ(Rect(400, 400), op.unmappedBounds);
expectedMatrix.loadIdentity();
EXPECT_MATRIX_APPROX_EQ(expectedMatrix, op.localMatrix);
diff --git a/libs/hwui/utils/LinearAllocator.h b/libs/hwui/utils/LinearAllocator.h
index 0a0e185..34c8c6b 100644
--- a/libs/hwui/utils/LinearAllocator.h
+++ b/libs/hwui/utils/LinearAllocator.h
@@ -84,6 +84,13 @@
return new (allocImpl(sizeof(T))) T(std::forward<Params>(params)...);
}
+ template<class T>
+ T* create_trivial_array(int count) {
+ static_assert(std::is_trivially_destructible<T>::value,
+ "Error, called create_trivial_array on a non-trivial type");
+ return reinterpret_cast<T*>(allocImpl(sizeof(T) * count));
+ }
+
/**
* Attempt to deallocate the given buffer, with the LinearAllocator attempting to rewind its
* state if possible.
diff --git a/libs/hwui/utils/StringUtils.h b/libs/hwui/utils/StringUtils.h
index 05a3d59..5add957 100644
--- a/libs/hwui/utils/StringUtils.h
+++ b/libs/hwui/utils/StringUtils.h
@@ -42,7 +42,7 @@
static const char* SUFFIXES[] = {"B", "KiB", "MiB"};
size_t suffix = 0;
double temp = d.bytes;
- while (temp > 1000 && suffix < 2) {
+ while (temp > 1024 && suffix < 2) {
temp /= 1024.0;
suffix++;
}
diff --git a/location/java/android/location/GnssClock.java b/location/java/android/location/GnssClock.java
index 37ef3df79..6a7801e 100644
--- a/location/java/android/location/GnssClock.java
+++ b/location/java/android/location/GnssClock.java
@@ -16,64 +16,37 @@
package android.location;
-import android.annotation.IntDef;
import android.os.Parcel;
import android.os.Parcelable;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
/**
* A class containing a GPS clock timestamp.
* It represents a measurement of the GPS receiver's clock.
*/
public final class GnssClock implements Parcelable {
-
// The following enumerations must be in sync with the values declared in gps.h
- /** The type of the GPS Clock. */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({CLOCK_TYPE_UNKNOWN, CLOCK_TYPE_LOCAL_HW_TIME, CLOCK_TYPE_GPS_TIME})
- public @interface GnssClockType {}
-
- /**
- * The type of the time stored is not available or it is unknown.
- */
- public static final byte CLOCK_TYPE_UNKNOWN = 0;
-
- /**
- * The source of the time value reported by this class is the 'Local Hardware Clock'.
- */
- public static final byte CLOCK_TYPE_LOCAL_HW_TIME = 1;
-
- /**
- * The source of the time value reported by this class is the 'GPS time' derived from
- * satellites (epoch = Jan 6, 1980).
- */
- public static final byte CLOCK_TYPE_GPS_TIME = 2;
-
- private static final short HAS_NO_FLAGS = 0;
- private static final short HAS_LEAP_SECOND = (1<<0);
- private static final short HAS_TIME_UNCERTAINTY = (1<<1);
- private static final short HAS_FULL_BIAS = (1<<2);
- private static final short HAS_BIAS = (1<<3);
- private static final short HAS_BIAS_UNCERTAINTY = (1<<4);
- private static final short HAS_DRIFT = (1<<5);
- private static final short HAS_DRIFT_UNCERTAINTY = (1<<6);
+ private static final int HAS_NO_FLAGS = 0;
+ private static final int HAS_LEAP_SECOND = (1<<0);
+ private static final int HAS_TIME_UNCERTAINTY = (1<<1);
+ private static final int HAS_FULL_BIAS = (1<<2);
+ private static final int HAS_BIAS = (1<<3);
+ private static final int HAS_BIAS_UNCERTAINTY = (1<<4);
+ private static final int HAS_DRIFT = (1<<5);
+ private static final int HAS_DRIFT_UNCERTAINTY = (1<<6);
// End enumerations in sync with gps.h
- private short mFlags;
- private short mLeapSecond;
- private byte mType;
- private long mTimeInNs;
- private double mTimeUncertaintyInNs;
- private long mFullBiasInNs;
- private double mBiasInNs;
- private double mBiasUncertaintyInNs;
- private double mDriftInNsPerSec;
- private double mDriftUncertaintyInNsPerSec;
- private long mTimeOfLastHwClockDiscontinuityInNs;
+ private int mFlags;
+ private int mLeapSecond;
+ private long mTimeNanos;
+ private double mTimeUncertaintyNanos;
+ private long mFullBiasNanos;
+ private double mBiasNanos;
+ private double mBiasUncertaintyNanos;
+ private double mDriftNanosPerSecond;
+ private double mDriftUncertaintyNanosPerSecond;
+ private int mHardwareClockDiscontinuityCount;
GnssClock() {
initialize();
@@ -85,15 +58,14 @@
public void set(GnssClock clock) {
mFlags = clock.mFlags;
mLeapSecond = clock.mLeapSecond;
- mType = clock.mType;
- mTimeInNs = clock.mTimeInNs;
- mTimeUncertaintyInNs = clock.mTimeUncertaintyInNs;
- mFullBiasInNs = clock.mFullBiasInNs;
- mBiasInNs = clock.mBiasInNs;
- mBiasUncertaintyInNs = clock.mBiasUncertaintyInNs;
- mDriftInNsPerSec = clock.mDriftInNsPerSec;
- mDriftUncertaintyInNsPerSec = clock.mDriftUncertaintyInNsPerSec;
- mTimeOfLastHwClockDiscontinuityInNs = clock.mTimeOfLastHwClockDiscontinuityInNs;
+ mTimeNanos = clock.mTimeNanos;
+ mTimeUncertaintyNanos = clock.mTimeUncertaintyNanos;
+ mFullBiasNanos = clock.mFullBiasNanos;
+ mBiasNanos = clock.mBiasNanos;
+ mBiasUncertaintyNanos = clock.mBiasUncertaintyNanos;
+ mDriftNanosPerSecond = clock.mDriftNanosPerSecond;
+ mDriftUncertaintyNanosPerSecond = clock.mDriftUncertaintyNanosPerSecond;
+ mHardwareClockDiscontinuityCount = clock.mHardwareClockDiscontinuityCount;
}
/**
@@ -104,38 +76,6 @@
}
/**
- * Gets the type of time reported by {@link #getTimeInNs()}.
- */
- @GnssClockType
- public byte getType() {
- return mType;
- }
-
- /**
- * Sets the type of time reported.
- */
- public void setType(@GnssClockType byte value) {
- mType = value;
- }
-
- /**
- * Gets a string representation of the 'type'.
- * For internal and logging use only.
- */
- private String getTypeString() {
- switch (mType) {
- case CLOCK_TYPE_UNKNOWN:
- return "Unknown";
- case CLOCK_TYPE_GPS_TIME:
- return "GpsTime";
- case CLOCK_TYPE_LOCAL_HW_TIME:
- return "LocalHwClock";
- default:
- return "<Invalid:" + mType + ">";
- }
- }
-
- /**
* Returns true if {@link #getLeapSecond()} is available, false otherwise.
*/
public boolean hasLeapSecond() {
@@ -149,14 +89,14 @@
*
* The value is only available if {@link #hasLeapSecond()} is true.
*/
- public short getLeapSecond() {
+ public int getLeapSecond() {
return mLeapSecond;
}
/**
* Sets the leap second associated with the clock's time.
*/
- public void setLeapSecond(short leapSecond) {
+ public void setLeapSecond(int leapSecond) {
setFlag(HAS_LEAP_SECOND);
mLeapSecond = leapSecond;
}
@@ -166,41 +106,38 @@
*/
public void resetLeapSecond() {
resetFlag(HAS_LEAP_SECOND);
- mLeapSecond = Short.MIN_VALUE;
+ mLeapSecond = Integer.MIN_VALUE;
}
/**
- * Gets the GPS receiver internal clock value in nanoseconds.
- * This can be either the 'local hardware clock' value ({@link #CLOCK_TYPE_LOCAL_HW_TIME}), or the
- * current GPS time derived inside GPS receiver ({@link #CLOCK_TYPE_GPS_TIME}).
- * {@link #getType()} defines the time reported.
+ * Gets the GNSS receiver internal clock value in nanoseconds.
*
* For 'local hardware clock' this value is expected to be monotonically increasing during the
* reporting session. The real GPS time can be derived by compensating
- * {@link #getFullBiasInNs()} (when it is available) from this value.
+ * {@link #getFullBiasNanos()} (when it is available) from this value.
*
* For 'GPS time' this value is expected to be the best estimation of current GPS time that GPS
- * receiver can achieve. {@link #getTimeUncertaintyInNs()} should be available when GPS time is
+ * receiver can achieve. {@link #getTimeUncertaintyNanos()} should be available when GPS time is
* specified.
*
- * Sub-nanosecond accuracy can be provided by means of {@link #getBiasInNs()}.
- * The reported time includes {@link #getTimeUncertaintyInNs()}.
+ * Sub-nanosecond accuracy can be provided by means of {@link #getBiasNanos()}.
+ * The reported time includes {@link #getTimeUncertaintyNanos()}.
*/
- public long getTimeInNs() {
- return mTimeInNs;
+ public long getTimeNanos() {
+ return mTimeNanos;
}
/**
- * Sets the GPS receiver internal clock in nanoseconds.
+ * Sets the GNSS receiver internal clock in nanoseconds.
*/
- public void setTimeInNs(long timeInNs) {
- mTimeInNs = timeInNs;
+ public void setTimeNanos(long timeNanos) {
+ mTimeNanos = timeNanos;
}
/**
- * Returns true if {@link #getTimeUncertaintyInNs()} is available, false otherwise.
+ * Returns true if {@link #getTimeUncertaintyNanos()} is available, false otherwise.
*/
- public boolean hasTimeUncertaintyInNs() {
+ public boolean hasTimeUncertaintyNanos() {
return isFlagSet(HAS_TIME_UNCERTAINTY);
}
@@ -208,212 +145,211 @@
* Gets the clock's time Uncertainty (1-Sigma) in nanoseconds.
* The uncertainty is represented as an absolute (single sided) value.
*
- * The value is only available if {@link #hasTimeUncertaintyInNs()} is true.
+ * The value is only available if {@link #hasTimeUncertaintyNanos()} is true.
*/
- public double getTimeUncertaintyInNs() {
- return mTimeUncertaintyInNs;
+ public double getTimeUncertaintyNanos() {
+ return mTimeUncertaintyNanos;
}
/**
* Sets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
*/
- public void setTimeUncertaintyInNs(double timeUncertaintyInNs) {
+ public void setTimeUncertaintyNanos(double timeUncertaintyNanos) {
setFlag(HAS_TIME_UNCERTAINTY);
- mTimeUncertaintyInNs = timeUncertaintyInNs;
+ mTimeUncertaintyNanos = timeUncertaintyNanos;
}
/**
* Resets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
*/
- public void resetTimeUncertaintyInNs() {
+ public void resetTimeUncertaintyNanos() {
resetFlag(HAS_TIME_UNCERTAINTY);
- mTimeUncertaintyInNs = Double.NaN;
+ mTimeUncertaintyNanos = Double.NaN;
}
/**
- * Returns true if {@link #getFullBiasInNs()} is available, false otherwise.
+ * Returns true if {@link #getFullBiasNanos()} is available, false otherwise.
*/
- public boolean hasFullBiasInNs() {
+ public boolean hasFullBiasNanos() {
return isFlagSet(HAS_FULL_BIAS);
}
/**
- * Gets the difference between hardware clock ({@link #getTimeInNs()}) inside GPS receiver and
+ * Gets the difference between hardware clock ({@link #getTimeNanos()}) inside GPS receiver and
* the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
*
- * This value is available if {@link #CLOCK_TYPE_LOCAL_HW_TIME} is set, and GPS receiver has solved
- * the clock for GPS time.
- * {@link #getBiasUncertaintyInNs()} should be used for quality check.
+ * This value is available if the receiver has estimated GPS time. If the computed time is for a
+ * non-GPS constellation, the time offset of that constellation to GPS has to be applied to fill
+ * this value. The value contains the 'bias uncertainty' {@link #getBiasUncertaintyNanos()} in
+ * it, and it should be used for quality check. The value is only available if
+ * {@link #hasFullBiasNanos()} is true.
*
* The sign of the value is defined by the following equation:
- * true time (GPS time) = time_ns + (full_bias_ns + bias_ns)
- *
- * The reported full bias includes {@link #getBiasUncertaintyInNs()}.
- * The value is onl available if {@link #hasFullBiasInNs()} is true.
+ * local estimate of GPS time = time_ns + (full_bias_ns + bias_ns)
*/
- public long getFullBiasInNs() {
- return mFullBiasInNs;
+ public long getFullBiasNanos() {
+ return mFullBiasNanos;
}
/**
* Sets the full bias in nanoseconds.
*/
- public void setFullBiasInNs(long value) {
+ public void setFullBiasNanos(long value) {
setFlag(HAS_FULL_BIAS);
- mFullBiasInNs = value;
+ mFullBiasNanos = value;
}
/**
* Resets the full bias in nanoseconds.
*/
- public void resetFullBiasInNs() {
+ public void resetFullBiasNanos() {
resetFlag(HAS_FULL_BIAS);
- mFullBiasInNs = Long.MIN_VALUE;
+ mFullBiasNanos = Long.MIN_VALUE;
}
/**
- * Returns true if {@link #getBiasInNs()} is available, false otherwise.
+ * Returns true if {@link #getBiasNanos()} is available, false otherwise.
*/
- public boolean hasBiasInNs() {
+ public boolean hasBiasNanos() {
return isFlagSet(HAS_BIAS);
}
/**
* Gets the clock's sub-nanosecond bias.
- * The reported bias includes {@link #getBiasUncertaintyInNs()}.
+ * The reported bias includes {@link #getBiasUncertaintyNanos()}.
*
- * The value is only available if {@link #hasBiasInNs()} is true.
+ * The value is only available if {@link #hasBiasNanos()} is true.
*/
- public double getBiasInNs() {
- return mBiasInNs;
+ public double getBiasNanos() {
+ return mBiasNanos;
}
/**
* Sets the sub-nanosecond bias.
*/
- public void setBiasInNs(double biasInNs) {
+ public void setBiasNanos(double biasNanos) {
setFlag(HAS_BIAS);
- mBiasInNs = biasInNs;
+ mBiasNanos = biasNanos;
}
/**
* Resets the clock's Bias in nanoseconds.
*/
- public void resetBiasInNs() {
+ public void resetBiasNanos() {
resetFlag(HAS_BIAS);
- mBiasInNs = Double.NaN;
+ mBiasNanos = Double.NaN;
}
/**
- * Returns true if {@link #getBiasUncertaintyInNs()} is available, false otherwise.
+ * Returns true if {@link #getBiasUncertaintyNanos()} is available, false otherwise.
*/
- public boolean hasBiasUncertaintyInNs() {
+ public boolean hasBiasUncertaintyNanos() {
return isFlagSet(HAS_BIAS_UNCERTAINTY);
}
/**
* Gets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
*
- * The value is only available if {@link #hasBiasUncertaintyInNs()} is true.
+ * The value is only available if {@link #hasBiasUncertaintyNanos()} is true.
*/
- public double getBiasUncertaintyInNs() {
- return mBiasUncertaintyInNs;
+ public double getBiasUncertaintyNanos() {
+ return mBiasUncertaintyNanos;
}
/**
* Sets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
*/
- public void setBiasUncertaintyInNs(double biasUncertaintyInNs) {
+ public void setBiasUncertaintyNanos(double biasUncertaintyNanos) {
setFlag(HAS_BIAS_UNCERTAINTY);
- mBiasUncertaintyInNs = biasUncertaintyInNs;
+ mBiasUncertaintyNanos = biasUncertaintyNanos;
}
/**
* Resets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
*/
- public void resetBiasUncertaintyInNs() {
+ public void resetBiasUncertaintyNanos() {
resetFlag(HAS_BIAS_UNCERTAINTY);
- mBiasUncertaintyInNs = Double.NaN;
+ mBiasUncertaintyNanos = Double.NaN;
}
/**
- * Returns true if {@link #getDriftInNsPerSec()} is available, false otherwise.
+ * Returns true if {@link #getDriftNanosPerSecond()} is available, false otherwise.
*/
- public boolean hasDriftInNsPerSec() {
+ public boolean hasDriftNanosPerSecond() {
return isFlagSet(HAS_DRIFT);
}
/**
* Gets the clock's Drift in nanoseconds per second.
* A positive value indicates that the frequency is higher than the nominal frequency.
- * The reported drift includes {@link #getDriftUncertaintyInNsPerSec()}.
+ * The reported drift includes {@link #getDriftUncertaintyNanosPerSecond()}.
*
- * The value is only available if {@link #hasDriftInNsPerSec()} is true.
+ * The value is only available if {@link #hasDriftNanosPerSecond()} is true.
*/
- public double getDriftInNsPerSec() {
- return mDriftInNsPerSec;
+ public double getDriftNanosPerSecond() {
+ return mDriftNanosPerSecond;
}
/**
* Sets the clock's Drift in nanoseconds per second.
*/
- public void setDriftInNsPerSec(double driftInNsPerSec) {
+ public void setDriftNanosPerSecond(double driftNanosPerSecond) {
setFlag(HAS_DRIFT);
- mDriftInNsPerSec = driftInNsPerSec;
+ mDriftNanosPerSecond = driftNanosPerSecond;
}
/**
* Resets the clock's Drift in nanoseconds per second.
*/
- public void resetDriftInNsPerSec() {
+ public void resetDriftNanosPerSecond() {
resetFlag(HAS_DRIFT);
- mDriftInNsPerSec = Double.NaN;
+ mDriftNanosPerSecond = Double.NaN;
}
/**
- * Returns true if {@link #getDriftUncertaintyInNsPerSec()} is available, false otherwise.
+ * Returns true if {@link #getDriftUncertaintyNanosPerSecond()} is available, false otherwise.
*/
- public boolean hasDriftUncertaintyInNsPerSec() {
+ public boolean hasDriftUncertaintyNanosPerSecond() {
return isFlagSet(HAS_DRIFT_UNCERTAINTY);
}
/**
* Gets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
*
- * The value is only available if {@link #hasDriftUncertaintyInNsPerSec()} is true.
+ * The value is only available if {@link #hasDriftUncertaintyNanosPerSecond()} is true.
*/
- public double getDriftUncertaintyInNsPerSec() {
- return mDriftUncertaintyInNsPerSec;
+ public double getDriftUncertaintyNanosPerSecond() {
+ return mDriftUncertaintyNanosPerSecond;
}
/**
* Sets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
*/
- public void setDriftUncertaintyInNsPerSec(double driftUncertaintyInNsPerSec) {
+ public void setDriftUncertaintyNanosPerSecond(double driftUncertaintyNanosPerSecond) {
setFlag(HAS_DRIFT_UNCERTAINTY);
- mDriftUncertaintyInNsPerSec = driftUncertaintyInNsPerSec;
+ mDriftUncertaintyNanosPerSecond = driftUncertaintyNanosPerSecond;
}
/**
- * Gets time of last hardware clock discontinuity.
+ * Gets count of last hardware clock discontinuity.
*/
- public long getTimeOfLastHwClockDiscontinuityInNs() {
- return mTimeOfLastHwClockDiscontinuityInNs;
+ public int getHardwareClockDiscontinuityCount() {
+ return mHardwareClockDiscontinuityCount;
}
/**
- * Sets time of last hardware clock discontinuity.
+ * Sets count of last hardware clock discontinuity.
*/
- public void setTimeOfLastHwClockDiscontinuityInNs(long timeOfLastHwClockDiscontinuityInNs) {
- mTimeOfLastHwClockDiscontinuityInNs = timeOfLastHwClockDiscontinuityInNs;
+ public void setHardwareClockDiscontinuityCount(int value) {
+ mHardwareClockDiscontinuityCount = value;
}
/**
* Resets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
*/
- public void resetDriftUncertaintyInNsPerSec() {
+ public void resetDriftUncertaintyNanosPerSecond() {
resetFlag(HAS_DRIFT_UNCERTAINTY);
- mDriftUncertaintyInNsPerSec = Double.NaN;
+ mDriftUncertaintyNanosPerSecond = Double.NaN;
}
public static final Creator<GnssClock> CREATOR = new Creator<GnssClock>() {
@@ -421,17 +357,16 @@
public GnssClock createFromParcel(Parcel parcel) {
GnssClock gpsClock = new GnssClock();
- gpsClock.mFlags = (short) parcel.readInt();
- gpsClock.mLeapSecond = (short) parcel.readInt();
- gpsClock.mType = parcel.readByte();
- gpsClock.mTimeInNs = parcel.readLong();
- gpsClock.mTimeUncertaintyInNs = parcel.readDouble();
- gpsClock.mFullBiasInNs = parcel.readLong();
- gpsClock.mBiasInNs = parcel.readDouble();
- gpsClock.mBiasUncertaintyInNs = parcel.readDouble();
- gpsClock.mDriftInNsPerSec = parcel.readDouble();
- gpsClock.mDriftUncertaintyInNsPerSec = parcel.readDouble();
- gpsClock.mTimeOfLastHwClockDiscontinuityInNs = parcel.readLong();
+ gpsClock.mFlags = parcel.readInt();
+ gpsClock.mLeapSecond = parcel.readInt();
+ gpsClock.mTimeNanos = parcel.readLong();
+ gpsClock.mTimeUncertaintyNanos = parcel.readDouble();
+ gpsClock.mFullBiasNanos = parcel.readLong();
+ gpsClock.mBiasNanos = parcel.readDouble();
+ gpsClock.mBiasUncertaintyNanos = parcel.readDouble();
+ gpsClock.mDriftNanosPerSecond = parcel.readDouble();
+ gpsClock.mDriftUncertaintyNanosPerSecond = parcel.readDouble();
+ gpsClock.mHardwareClockDiscontinuityCount = parcel.readInt();
return gpsClock;
}
@@ -442,18 +377,18 @@
}
};
+ @Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeInt(mFlags);
parcel.writeInt(mLeapSecond);
- parcel.writeByte(mType);
- parcel.writeLong(mTimeInNs);
- parcel.writeDouble(mTimeUncertaintyInNs);
- parcel.writeLong(mFullBiasInNs);
- parcel.writeDouble(mBiasInNs);
- parcel.writeDouble(mBiasUncertaintyInNs);
- parcel.writeDouble(mDriftInNsPerSec);
- parcel.writeDouble(mDriftUncertaintyInNsPerSec);
- parcel.writeLong(mTimeOfLastHwClockDiscontinuityInNs);
+ parcel.writeLong(mTimeNanos);
+ parcel.writeDouble(mTimeUncertaintyNanos);
+ parcel.writeLong(mFullBiasNanos);
+ parcel.writeDouble(mBiasNanos);
+ parcel.writeDouble(mBiasUncertaintyNanos);
+ parcel.writeDouble(mDriftNanosPerSecond);
+ parcel.writeDouble(mDriftUncertaintyNanosPerSecond);
+ parcel.writeInt(mHardwareClockDiscontinuityCount);
}
@Override
@@ -467,39 +402,33 @@
final String formatWithUncertainty = " %-15s = %-25s %-26s = %s\n";
StringBuilder builder = new StringBuilder("GnssClock:\n");
- builder.append(String.format(format, "Type", getTypeString()));
-
builder.append(String.format(format, "LeapSecond", hasLeapSecond() ? mLeapSecond : null));
builder.append(String.format(
formatWithUncertainty,
- "TimeInNs",
- mTimeInNs,
- "TimeUncertaintyInNs",
- hasTimeUncertaintyInNs() ? mTimeUncertaintyInNs : null));
+ "TimeNanos",
+ mTimeNanos,
+ "TimeUncertaintyNanos",
+ hasTimeUncertaintyNanos() ? mTimeUncertaintyNanos : null));
builder.append(String.format(
format,
- "FullBiasInNs",
- hasFullBiasInNs() ? mFullBiasInNs : null));
+ "FullBiasNanos",
+ hasFullBiasNanos() ? mFullBiasNanos : null));
builder.append(String.format(
formatWithUncertainty,
- "BiasInNs",
- hasBiasInNs() ? mBiasInNs : null,
- "BiasUncertaintyInNs",
- hasBiasUncertaintyInNs() ? mBiasUncertaintyInNs : null));
+ "BiasNanos",
+ hasBiasNanos() ? mBiasNanos : null,
+ "BiasUncertaintyNanos",
+ hasBiasUncertaintyNanos() ? mBiasUncertaintyNanos : null));
builder.append(String.format(
formatWithUncertainty,
- "DriftInNsPerSec",
- hasDriftInNsPerSec() ? mDriftInNsPerSec : null,
- "DriftUncertaintyInNsPerSec",
- hasDriftUncertaintyInNsPerSec() ? mDriftUncertaintyInNsPerSec : null));
-
- builder.append(String.format(format, "TimeOfLastHwClockDiscontinuityInNs",
- getType() == CLOCK_TYPE_LOCAL_HW_TIME
- ? mTimeOfLastHwClockDiscontinuityInNs : null));
+ "DriftNanosPerSecond",
+ hasDriftNanosPerSecond() ? mDriftNanosPerSecond : null,
+ "DriftUncertaintyNanosPerSecond",
+ hasDriftUncertaintyNanosPerSecond() ? mDriftUncertaintyNanosPerSecond : null));
return builder.toString();
}
@@ -507,26 +436,25 @@
private void initialize() {
mFlags = HAS_NO_FLAGS;
resetLeapSecond();
- setType(CLOCK_TYPE_UNKNOWN);
- setTimeInNs(Long.MIN_VALUE);
- resetTimeUncertaintyInNs();
- resetFullBiasInNs();
- resetBiasInNs();
- resetBiasUncertaintyInNs();
- resetDriftInNsPerSec();
- resetDriftUncertaintyInNsPerSec();
- setTimeOfLastHwClockDiscontinuityInNs(Long.MIN_VALUE);
+ setTimeNanos(Long.MIN_VALUE);
+ resetTimeUncertaintyNanos();
+ resetFullBiasNanos();
+ resetBiasNanos();
+ resetBiasUncertaintyNanos();
+ resetDriftNanosPerSecond();
+ resetDriftUncertaintyNanosPerSecond();
+ setHardwareClockDiscontinuityCount(Integer.MIN_VALUE);
}
- private void setFlag(short flag) {
+ private void setFlag(int flag) {
mFlags |= flag;
}
- private void resetFlag(short flag) {
+ private void resetFlag(int flag) {
mFlags &= ~flag;
}
- private boolean isFlagSet(short flag) {
+ private boolean isFlagSet(int flag) {
return (mFlags & flag) == flag;
}
}
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index a490685..367c52f 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -24,86 +24,38 @@
import java.lang.annotation.RetentionPolicy;
/**
- * A class representing a GPS satellite measurement, containing raw and computed information.
+ * A class representing a GNSS satellite measurement, containing raw and computed information.
*/
public final class GnssMeasurement implements Parcelable {
private int mFlags;
- private short mSvid;
- private double mTimeOffsetInNs;
- private short mState;
- private long mReceivedGpsTowInNs;
- private long mReceivedGpsTowUncertaintyInNs;
- private double mCn0InDbHz;
- private double mPseudorangeRateInMetersPerSec;
- private double mPseudorangeRateUncertaintyInMetersPerSec;
- private short mAccumulatedDeltaRangeState;
- private double mAccumulatedDeltaRangeInMeters;
- private double mAccumulatedDeltaRangeUncertaintyInMeters;
- private double mPseudorangeInMeters;
- private double mPseudorangeUncertaintyInMeters;
- private double mCodePhaseInChips;
- private double mCodePhaseUncertaintyInChips;
- private float mCarrierFrequencyInHz;
+ private int mSvid;
+ private int mConstellationType;
+ private double mTimeOffsetNanos;
+ private int mState;
+ private long mReceivedSvTimeNanos;
+ private long mReceivedSvTimeUncertaintyNanos;
+ private double mCn0DbHz;
+ private double mPseudorangeRateMetersPerSecond;
+ private double mPseudorangeRateUncertaintyMetersPerSecond;
+ private int mAccumulatedDeltaRangeState;
+ private double mAccumulatedDeltaRangeMeters;
+ private double mAccumulatedDeltaRangeUncertaintyMeters;
+ private float mCarrierFrequencyHz;
private long mCarrierCycles;
private double mCarrierPhase;
private double mCarrierPhaseUncertainty;
- private byte mLossOfLock;
- private int mBitNumber;
- private short mTimeFromLastBitInMs;
- private double mDopplerShiftInHz;
- private double mDopplerShiftUncertaintyInHz;
- private byte mMultipathIndicator;
+ private int mMultipathIndicator;
private double mSnrInDb;
- private double mElevationInDeg;
- private double mElevationUncertaintyInDeg;
- private double mAzimuthInDeg;
- private double mAzimuthUncertaintyInDeg;
- private boolean mUsedInFix;
- private double mPseudorangeRateCarrierInMetersPerSec;
- private double mPseudorangeRateCarrierUncertaintyInMetersPerSec;
// The following enumerations must be in sync with the values declared in gps.h
private static final int HAS_NO_FLAGS = 0;
private static final int HAS_SNR = (1<<0);
- private static final int HAS_ELEVATION = (1<<1);
- private static final int HAS_ELEVATION_UNCERTAINTY = (1<<2);
- private static final int HAS_AZIMUTH = (1<<3);
- private static final int HAS_AZIMUTH_UNCERTAINTY = (1<<4);
- private static final int HAS_PSEUDORANGE = (1<<5);
- private static final int HAS_PSEUDORANGE_UNCERTAINTY = (1<<6);
- private static final int HAS_CODE_PHASE = (1<<7);
- private static final int HAS_CODE_PHASE_UNCERTAINTY = (1<<8);
private static final int HAS_CARRIER_FREQUENCY = (1<<9);
private static final int HAS_CARRIER_CYCLES = (1<<10);
private static final int HAS_CARRIER_PHASE = (1<<11);
private static final int HAS_CARRIER_PHASE_UNCERTAINTY = (1<<12);
- private static final int HAS_BIT_NUMBER = (1<<13);
- private static final int HAS_TIME_FROM_LAST_BIT = (1<<14);
- private static final int HAS_DOPPLER_SHIFT = (1<<15);
- private static final int HAS_DOPPLER_SHIFT_UNCERTAINTY = (1<<16);
- private static final int HAS_USED_IN_FIX = (1<<17);
- private static final int GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE = (1<<18);
-
- /** The status of 'loss of lock'. */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({LOSS_OF_LOCK_UNKNOWN, LOSS_OF_LOCK_OK, LOSS_OF_LOCK_CYCLE_SLIP})
- public @interface LossOfLockStatus {}
-
- /**
- * The indicator is not available or it is unknown.
- */
- public static final byte LOSS_OF_LOCK_UNKNOWN = 0;
-
- /**
- * The measurement does not present any indication of 'loss of lock'.
- */
- public static final byte LOSS_OF_LOCK_OK = 1;
-
- /**
- * 'Loss of lock' detected between the previous and current observation: cycle slip possible.
- */
- public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2;
+ private static final int HAS_UNCORRECTED_PSEUDORANGE_RATE = (1<<18);
/** The status of multipath. */
@Retention(RetentionPolicy.SOURCE)
@@ -114,78 +66,78 @@
/**
* The indicator is not available or it is unknown.
*/
- public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0;
+ public static final int MULTIPATH_INDICATOR_UNKNOWN = 0;
/**
* The measurement has been indicated to use multi-path.
*/
- public static final byte MULTIPATH_INDICATOR_DETECTED = 1;
+ public static final int MULTIPATH_INDICATOR_DETECTED = 1;
/**
* The measurement has been indicated not tu use multi-path.
*/
- public static final byte MULTIPATH_INDICATOR_NOT_USED = 2;
+ public static final int MULTIPATH_INDICATOR_NOT_USED = 2;
/**
- * The state of GPS receiver the measurement is invalid or unknown.
+ * The state of GNSS receiver the measurement is invalid or unknown.
*/
- public static final short STATE_UNKNOWN = 0;
+ public static final int STATE_UNKNOWN = 0;
/**
- * The state of the GPS receiver is ranging code lock.
+ * The state of the GNSS receiver is ranging code lock.
*/
- public static final short STATE_CODE_LOCK = (1<<0);
+ public static final int STATE_CODE_LOCK = (1<<0);
/**
- * The state of the GPS receiver is in bit sync.
+ * The state of the GNSS receiver is in bit sync.
*/
- public static final short STATE_BIT_SYNC = (1<<1);
+ public static final int STATE_BIT_SYNC = (1<<1);
/**
- *The state of the GPS receiver is in sub-frame sync.
+ *The state of the GNSS receiver is in sub-frame sync.
*/
- public static final short STATE_SUBFRAME_SYNC = (1<<2);
+ public static final int STATE_SUBFRAME_SYNC = (1<<2);
/**
- * The state of the GPS receiver has TOW decoded.
+ * The state of the GNSS receiver has TOW decoded.
*/
- public static final short STATE_TOW_DECODED = (1<<3);
+ public static final int STATE_TOW_DECODED = (1<<3);
/**
- * The state of the GPS receiver contains millisecond ambiguity.
+ * The state of the GNSS receiver contains millisecond ambiguity.
*/
- public static final short STATE_MSEC_AMBIGUOUS = (1<<4);
+ public static final int STATE_MSEC_AMBIGUOUS = (1<<4);
/**
- * All the GPS receiver state flags.
+ * All the GNSS receiver state flags.
*/
- private static final short STATE_ALL = STATE_CODE_LOCK | STATE_BIT_SYNC | STATE_SUBFRAME_SYNC
+ private static final int STATE_ALL = STATE_CODE_LOCK | STATE_BIT_SYNC | STATE_SUBFRAME_SYNC
| STATE_TOW_DECODED | STATE_MSEC_AMBIGUOUS;
/**
* The state of the 'Accumulated Delta Range' is invalid or unknown.
*/
- public static final short ADR_STATE_UNKNOWN = 0;
+ public static final int ADR_STATE_UNKNOWN = 0;
/**
* The state of the 'Accumulated Delta Range' is valid.
*/
- public static final short ADR_STATE_VALID = (1<<0);
+ public static final int ADR_STATE_VALID = (1<<0);
/**
* The state of the 'Accumulated Delta Range' has detected a reset.
*/
- public static final short ADR_STATE_RESET = (1<<1);
+ public static final int ADR_STATE_RESET = (1<<1);
/**
* The state of the 'Accumulated Delta Range' has a cycle slip detected.
*/
- public static final short ADR_STATE_CYCLE_SLIP = (1<<2);
+ public static final int ADR_STATE_CYCLE_SLIP = (1<<2);
/**
* All the 'Accumulated Delta Range' flags.
*/
- private static final short ADR_ALL = ADR_STATE_VALID | ADR_STATE_RESET | ADR_STATE_CYCLE_SLIP;
+ private static final int ADR_ALL = ADR_STATE_VALID | ADR_STATE_RESET | ADR_STATE_CYCLE_SLIP;
// End enumerations in sync with gps.h
@@ -199,42 +151,25 @@
public void set(GnssMeasurement measurement) {
mFlags = measurement.mFlags;
mSvid = measurement.mSvid;
- mTimeOffsetInNs = measurement.mTimeOffsetInNs;
+ mConstellationType = measurement.mConstellationType;
+ mTimeOffsetNanos = measurement.mTimeOffsetNanos;
mState = measurement.mState;
- mReceivedGpsTowInNs = measurement.mReceivedGpsTowInNs;
- mReceivedGpsTowUncertaintyInNs = measurement.mReceivedGpsTowUncertaintyInNs;
- mCn0InDbHz = measurement.mCn0InDbHz;
- mPseudorangeRateInMetersPerSec = measurement.mPseudorangeRateInMetersPerSec;
- mPseudorangeRateUncertaintyInMetersPerSec =
- measurement.mPseudorangeRateUncertaintyInMetersPerSec;
+ mReceivedSvTimeNanos = measurement.mReceivedSvTimeNanos;
+ mReceivedSvTimeUncertaintyNanos = measurement.mReceivedSvTimeUncertaintyNanos;
+ mCn0DbHz = measurement.mCn0DbHz;
+ mPseudorangeRateMetersPerSecond = measurement.mPseudorangeRateMetersPerSecond;
+ mPseudorangeRateUncertaintyMetersPerSecond =
+ measurement.mPseudorangeRateUncertaintyMetersPerSecond;
mAccumulatedDeltaRangeState = measurement.mAccumulatedDeltaRangeState;
- mAccumulatedDeltaRangeInMeters = measurement.mAccumulatedDeltaRangeInMeters;
- mAccumulatedDeltaRangeUncertaintyInMeters =
- measurement.mAccumulatedDeltaRangeUncertaintyInMeters;
- mPseudorangeInMeters = measurement.mPseudorangeInMeters;
- mPseudorangeUncertaintyInMeters = measurement.mPseudorangeUncertaintyInMeters;
- mCodePhaseInChips = measurement.mCodePhaseInChips;
- mCodePhaseUncertaintyInChips = measurement.mCodePhaseUncertaintyInChips;
- mCarrierFrequencyInHz = measurement.mCarrierFrequencyInHz;
+ mAccumulatedDeltaRangeMeters = measurement.mAccumulatedDeltaRangeMeters;
+ mAccumulatedDeltaRangeUncertaintyMeters =
+ measurement.mAccumulatedDeltaRangeUncertaintyMeters;
+ mCarrierFrequencyHz = measurement.mCarrierFrequencyHz;
mCarrierCycles = measurement.mCarrierCycles;
mCarrierPhase = measurement.mCarrierPhase;
mCarrierPhaseUncertainty = measurement.mCarrierPhaseUncertainty;
- mLossOfLock = measurement.mLossOfLock;
- mBitNumber = measurement.mBitNumber;
- mTimeFromLastBitInMs = measurement.mTimeFromLastBitInMs;
- mDopplerShiftInHz = measurement.mDopplerShiftInHz;
- mDopplerShiftUncertaintyInHz = measurement.mDopplerShiftUncertaintyInHz;
mMultipathIndicator = measurement.mMultipathIndicator;
mSnrInDb = measurement.mSnrInDb;
- mElevationInDeg = measurement.mElevationInDeg;
- mElevationUncertaintyInDeg = measurement.mElevationUncertaintyInDeg;
- mAzimuthInDeg = measurement.mAzimuthInDeg;
- mAzimuthUncertaintyInDeg = measurement.mAzimuthUncertaintyInDeg;
- mUsedInFix = measurement.mUsedInFix;
- mPseudorangeRateCarrierInMetersPerSec =
- measurement.mPseudorangeRateCarrierInMetersPerSec;
- mPseudorangeRateCarrierUncertaintyInMetersPerSec =
- measurement.mPseudorangeRateCarrierUncertaintyInMetersPerSec;
}
/**
@@ -248,21 +183,37 @@
* Gets the Pseudo-random number (PRN).
* Range: [1, 32]
*/
- public short getSvid() {
+ public int getSvid() {
return mSvid;
}
/**
* Sets the Pseud-random number (PRN).
*/
- public void setSvid(short value) {
+ public void setSvid(int value) {
mSvid = value;
}
/**
+ * Getst the constellation type.
+ */
+ @GnssStatus.ConstellationType
+ public int getConstellationType() {
+ return mConstellationType;
+ }
+
+ /**
+ * Sets the constellation type.
+ */
+ public void setConstellationType(@GnssStatus.ConstellationType int value) {
+ mConstellationType = value;
+ }
+
+ /**
* Gets the time offset at which the measurement was taken in nanoseconds.
- * The reference receiver's time is specified by {@link GnssClock#getTimeInNs()} and should be
- * interpreted in the same way as indicated by {@link GnssClock#getType()}.
+ *
+ * The reference receiver's time from which this is offset is specified by
+ * {@link GnssClock#getTimeNanos()}.
*
* The sign of this value is given by the following equation:
* measurement time = time_ns + time_offset_ns
@@ -270,31 +221,31 @@
* The value provides an individual time-stamp for the measurement, and allows sub-nanosecond
* accuracy.
*/
- public double getTimeOffsetInNs() {
- return mTimeOffsetInNs;
+ public double getTimeOffsetNanos() {
+ return mTimeOffsetNanos;
}
/**
* Sets the time offset at which the measurement was taken in nanoseconds.
*/
- public void setTimeOffsetInNs(double value) {
- mTimeOffsetInNs = value;
+ public void setTimeOffsetNanos(double value) {
+ mTimeOffsetNanos = value;
}
/**
* Gets per-satellite sync state.
* It represents the current sync state for the associated satellite.
*
- * This value helps interpret {@link #getReceivedGpsTowInNs()}.
+ * This value helps interpret {@link #getReceivedSvTimeNanos()}.
*/
- public short getState() {
+ public int getState() {
return mState;
}
/**
* Sets the sync state.
*/
- public void setState(short value) {
+ public void setState(int value) {
mState = value;
}
@@ -333,39 +284,92 @@
}
/**
- * Gets the received GPS Time-of-Week at the measurement time, in nanoseconds.
- * The value is relative to the beginning of the current GPS week.
+ * Gets the received GNSS satellite time, at the measurement time, in nanoseconds.
*
- * Given {@link #getState()} of the GPS receiver, the range of this field can be:
- * Searching : [ 0 ] : {@link #STATE_UNKNOWN} is set
- * Ranging code lock : [ 0 1 ms ] : {@link #STATE_CODE_LOCK} is set
- * Bit sync : [ 0 20 ms ] : {@link #STATE_BIT_SYNC} is set
- * Subframe sync : [ 0 6 ms ] : {@link #STATE_SUBFRAME_SYNC} is set
- * TOW decoded : [ 0 1 week ] : {@link #STATE_TOW_DECODED} is set
+ * For GPS & QZSS, this is:
+ * Received GPS Time-of-Week at the measurement time, in nanoseconds.
+ * The value is relative to the beginning of the current GPS week.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range
+ * for this field can be:
+ * Searching : [ 0 ] : STATE_UNKNOWN
+ * C/A code lock : [ 0 1ms ] : STATE_CODE_LOCK is set
+ * Bit sync : [ 0 20ms ] : STATE_BIT_SYNC is set
+ * Subframe sync : [ 0 6s ] : STATE_SUBFRAME_SYNC is set
+ * TOW decoded : [ 0 1week ] : STATE_TOW_DECODED is set
+ *
+ * Note well: if there is any ambiguity in integer millisecond,
+ * STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field.
+ *
+ * This value must be populated if 'state' != STATE_UNKNOWN.
+ *
+ * For Glonass, this is:
+ * Received Glonass time of day, at the measurement time in nanoseconds.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range for
+ * this field can be:
+ * Searching : [ 0 ] : STATE_UNKNOWN
+ * C/A code lock : [ 0 1ms ] : STATE_CODE_LOCK is set
+ * Symbol sync : [ 0 10ms ] : STATE_SYMBOL_SYNC is set
+ * Bit sync : [ 0 20ms ] : STATE_BIT_SYNC is set
+ * String sync : [ 0 2s ] : STATE_GLO_STRING_SYNC is set
+ * Time of day : [ 0 1day ] : STATE_GLO_TOD_DECODED is set
+ *
+ * For Beidou, this is:
+ * Received Beidou time of week, at the measurement time in nanoseconds.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range for
+ * this field can be:
+ * Searching : [ 0 ] : STATE_UNKNOWN
+ * C/A code lock : [ 0 1ms ] : STATE_CODE_LOCK is set
+ * Bit sync (D2) : [ 0 2ms ] : STATE_BDS_D2_BIT_SYNC is set
+ * Bit sync (D1) : [ 0 20ms ] : STATE_BIT_SYNC is set
+ * Subframe (D2) : [ 0 0.6s ] : STATE_BDS_D2_SUBFRAME_SYNC is set
+ * Subframe (D1) : [ 0 6s ] : STATE_SUBFRAME_SYNC is set
+ * Time of week : [ 0 1week ] : STATE_TOW_DECODED is set
+ *
+ * For Galileo, this is:
+ * Received Galileo time of week, at the measurement time in nanoseconds.
+ *
+ * E1BC code lock : [ 0 4ms ] : STATE_GAL_E1BC_CODE_LOCK is set
+ * E1C 2nd code lock : [ 0 100ms ] : STATE_GAL_E1C_2ND_CODE_LOCK is set
+ *
+ * E1B page : [ 0 2s ] : STATE_GAL_E1B_PAGE_SYNC is set
+ * Time of week : [ 0 1week ] : STATE_GAL_TOW_DECODED is set
+ *
+ * For SBAS, this is:
+ * Received SBAS time, at the measurement time in nanoseconds.
+ *
+ * Given the highest sync state that can be achieved, per each satellite, valid range for
+ * this field can be:
+ * Searching : [ 0 ] : STATE_UNKNOWN
+ * C/A code lock : [ 0 1ms ] : STATE_CODE_LOCK is set
+ * Symbol sync : [ 0 2ms ] : STATE_SYMBOL_SYNC is set
+ * Message : [ 0 1s ] : STATE_SBAS_SYNC is set
*/
- public long getReceivedGpsTowInNs() {
- return mReceivedGpsTowInNs;
+ public long getReceivedSvTimeNanos() {
+ return mReceivedSvTimeNanos;
}
/**
- * Sets the received GPS time-of-week in nanoseconds.
+ * Sets the received GNSS time in nanoseconds.
*/
- public void setReceivedGpsTowInNs(long value) {
- mReceivedGpsTowInNs = value;
+ public void setReceivedSvTimeNanos(long value) {
+ mReceivedSvTimeNanos = value;
}
/**
- * Gets the received GPS time-of-week's uncertainty (1-Sigma) in nanoseconds.
+ * Gets the received GNSS time uncertainty (1-Sigma) in nanoseconds.
*/
- public long getReceivedGpsTowUncertaintyInNs() {
- return mReceivedGpsTowUncertaintyInNs;
+ public long getReceivedSvTimeUncertaintyNanos() {
+ return mReceivedSvTimeUncertaintyNanos;
}
/**
- * Sets the received GPS time-of-week's uncertainty (1-Sigma) in nanoseconds.
+ * Sets the received GNSS time uncertainty (1-Sigma) in nanoseconds.
*/
- public void setReceivedGpsTowUncertaintyInNs(long value) {
- mReceivedGpsTowUncertaintyInNs = value;
+ public void setReceivedSvTimeUncertaintyNanos(long value) {
+ mReceivedSvTimeUncertaintyNanos = value;
}
/**
@@ -374,79 +378,80 @@
*
* The value contains the measured C/N0 for the signal at the antenna input.
*/
- public double getCn0InDbHz() {
- return mCn0InDbHz;
+ public double getCn0DbHz() {
+ return mCn0DbHz;
}
/**
* Sets the carrier-to-noise density in dB-Hz.
*/
- public void setCn0InDbHz(double value) {
- mCn0InDbHz = value;
+ public void setCn0DbHz(double value) {
+ mCn0DbHz = value;
}
/**
* Gets the Pseudorange rate at the timestamp in m/s.
- * The reported value includes {@link #getPseudorangeRateUncertaintyInMetersPerSec()}.
*
- * The correction of a given Pseudorange Rate value includes corrections from receiver and
- * satellite clock frequency errors.
- * {@link #isPseudorangeRateCorrected()} identifies the type of value reported.
+ * The reported value includes {@link #getPseudorangeRateUncertaintyMetersPerSecond()}.
*
- * A positive 'uncorrected' value indicates that the SV is moving away from the receiver.
- * The sign of the 'uncorrected' Pseudorange Rate and its relation to the sign of
- * {@link #getDopplerShiftInHz()} is given by the equation:
+ * The value is uncorrected, hence corrections for receiver and satellite clock frequency errors
+ * should not be included.
+ *
+ * A positive 'uncorrected' value indicates that the SV is moving away from the receiver. The
+ * sign of the 'uncorrected' 'pseudorange rate' and its relation to the sign of 'doppler shift'
+ * is given by the equation:
+ *
* pseudorange rate = -k * doppler shift (where k is a constant)
*/
- public double getPseudorangeRateInMetersPerSec() {
- return mPseudorangeRateInMetersPerSec;
+ public double getPseudorangeRateMetersPerSecond() {
+ return mPseudorangeRateMetersPerSecond;
}
/**
* Sets the pseudorange rate at the timestamp in m/s.
*/
- public void setPseudorangeRateInMetersPerSec(double value) {
- mPseudorangeRateInMetersPerSec = value;
+ public void setPseudorangeRateMetersPerSecond(double value) {
+ mPseudorangeRateMetersPerSecond = value;
}
/**
- * See {@link #getPseudorangeRateInMetersPerSec()} for more details.
+ * See {@link #getPseudorangeRateMetersPerSecond()} for more details.
*
- * @return {@code true} if {@link #getPseudorangeRateInMetersPerSec()} contains a corrected
+ * @return {@code true} if {@link #getPseudorangeRateMetersPerSecond()} contains a corrected
* value, {@code false} if it contains an uncorrected value.
*/
public boolean isPseudorangeRateCorrected() {
- return !isFlagSet(GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE);
+ return !isFlagSet(HAS_UNCORRECTED_PSEUDORANGE_RATE);
}
/**
* Gets the pseudorange's rate uncertainty (1-Sigma) in m/s.
* The uncertainty is represented as an absolute (single sided) value.
*/
- public double getPseudorangeRateUncertaintyInMetersPerSec() {
- return mPseudorangeRateUncertaintyInMetersPerSec;
+ public double getPseudorangeRateUncertaintyMetersPerSecond() {
+ return mPseudorangeRateUncertaintyMetersPerSecond;
}
/**
* Sets the pseudorange's rate uncertainty (1-Sigma) in m/s.
*/
- public void setPseudorangeRateUncertaintyInMetersPerSec(double value) {
- mPseudorangeRateUncertaintyInMetersPerSec = value;
+ public void setPseudorangeRateUncertaintyMetersPerSecond(double value) {
+ mPseudorangeRateUncertaintyMetersPerSecond = value;
}
/**
* Gets 'Accumulated Delta Range' state.
- * It indicates whether {@link #getAccumulatedDeltaRangeInMeters()} is reset or there is a
+ * It indicates whether {@link #getAccumulatedDeltaRangeMeters()} is reset or there is a
* cycle slip (indicating 'loss of lock').
*/
- public short getAccumulatedDeltaRangeState() {
+ public int getAccumulatedDeltaRangeState() {
return mAccumulatedDeltaRangeState;
}
/**
* Sets the 'Accumulated Delta Range' state.
*/
- public void setAccumulatedDeltaRangeState(short value) {
+ public void setAccumulatedDeltaRangeState(int value) {
mAccumulatedDeltaRangeState = value;
}
@@ -480,24 +485,24 @@
/**
* Gets the accumulated delta range since the last channel reset, in meters.
- * The reported value includes {@link #getAccumulatedDeltaRangeUncertaintyInMeters()}.
+ * The reported value includes {@link #getAccumulatedDeltaRangeUncertaintyMeters()}.
*
* The availability of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
*
* A positive value indicates that the SV is moving away from the receiver.
- * The sign of {@link #getAccumulatedDeltaRangeInMeters()} and its relation to the sign of
+ * The sign of {@link #getAccumulatedDeltaRangeMeters()} and its relation to the sign of
* {@link #getCarrierPhase()} is given by the equation:
* accumulated delta range = -k * carrier phase (where k is a constant)
*/
- public double getAccumulatedDeltaRangeInMeters() {
- return mAccumulatedDeltaRangeInMeters;
+ public double getAccumulatedDeltaRangeMeters() {
+ return mAccumulatedDeltaRangeMeters;
}
/**
* Sets the accumulated delta range in meters.
*/
- public void setAccumulatedDeltaRangeInMeters(double value) {
- mAccumulatedDeltaRangeInMeters = value;
+ public void setAccumulatedDeltaRangeMeters(double value) {
+ mAccumulatedDeltaRangeMeters = value;
}
/**
@@ -506,8 +511,8 @@
*
* The status of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
*/
- public double getAccumulatedDeltaRangeUncertaintyInMeters() {
- return mAccumulatedDeltaRangeUncertaintyInMeters;
+ public double getAccumulatedDeltaRangeUncertaintyMeters() {
+ return mAccumulatedDeltaRangeUncertaintyMeters;
}
/**
@@ -515,149 +520,14 @@
*
* The status of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
*/
- public void setAccumulatedDeltaRangeUncertaintyInMeters(double value) {
- mAccumulatedDeltaRangeUncertaintyInMeters = value;
+ public void setAccumulatedDeltaRangeUncertaintyMeters(double value) {
+ mAccumulatedDeltaRangeUncertaintyMeters = value;
}
/**
- * Returns true if {@link #getPseudorangeInMeters()} is available, false otherwise.
+ * Returns true if {@link #getCarrierFrequencyHz()} is available, false otherwise.
*/
- public boolean hasPseudorangeInMeters() {
- return isFlagSet(HAS_PSEUDORANGE);
- }
-
- /**
- * Gets the best derived pseudorange by the chipset, in meters.
- * The reported pseudorange includes {@link #getPseudorangeUncertaintyInMeters()}.
- *
- * The value is only available if {@link #hasPseudorangeInMeters()} is true.
- */
- public double getPseudorangeInMeters() {
- return mPseudorangeInMeters;
- }
-
- /**
- * Sets the Pseudo-range in meters.
- */
- public void setPseudorangeInMeters(double value) {
- setFlag(HAS_PSEUDORANGE);
- mPseudorangeInMeters = value;
- }
-
- /**
- * Resets the Pseudo-range in meters.
- */
- public void resetPseudorangeInMeters() {
- resetFlag(HAS_PSEUDORANGE);
- mPseudorangeInMeters = Double.NaN;
- }
-
- /**
- * Returns true if {@link #getPseudorangeUncertaintyInMeters()} is available, false otherwise.
- */
- public boolean hasPseudorangeUncertaintyInMeters() {
- return isFlagSet(HAS_PSEUDORANGE_UNCERTAINTY);
- }
-
- /**
- * Gets the pseudorange's uncertainty (1-Sigma) in meters.
- * The value contains the 'pseudorange' and 'clock' uncertainty in it.
- * The uncertainty is represented as an absolute (single sided) value.
- *
- * The value is only available if {@link #hasPseudorangeUncertaintyInMeters()} is true.
- */
- public double getPseudorangeUncertaintyInMeters() {
- return mPseudorangeUncertaintyInMeters;
- }
-
- /**
- * Sets the pseudo-range's uncertainty (1-Sigma) in meters.
- */
- public void setPseudorangeUncertaintyInMeters(double value) {
- setFlag(HAS_PSEUDORANGE_UNCERTAINTY);
- mPseudorangeUncertaintyInMeters = value;
- }
-
- /**
- * Resets the pseudo-range's uncertainty (1-Sigma) in meters.
- */
- public void resetPseudorangeUncertaintyInMeters() {
- resetFlag(HAS_PSEUDORANGE_UNCERTAINTY);
- mPseudorangeUncertaintyInMeters = Double.NaN;
- }
-
- /**
- * Returns true if {@link #getCodePhaseInChips()} is available, false otherwise.
- */
- public boolean hasCodePhaseInChips() {
- return isFlagSet(HAS_CODE_PHASE);
- }
-
- /**
- * Gets the fraction of the current C/A code cycle.
- * Range: [0, 1023]
- * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}.
- * The reported code-phase includes {@link #getCodePhaseUncertaintyInChips()}.
- *
- * The value is only available if {@link #hasCodePhaseInChips()} is true.
- */
- public double getCodePhaseInChips() {
- return mCodePhaseInChips;
- }
-
- /**
- * Sets the Code-phase in chips.
- */
- public void setCodePhaseInChips(double value) {
- setFlag(HAS_CODE_PHASE);
- mCodePhaseInChips = value;
- }
-
- /**
- * Resets the Code-phase in chips.
- */
- public void resetCodePhaseInChips() {
- resetFlag(HAS_CODE_PHASE);
- mCodePhaseInChips = Double.NaN;
- }
-
- /**
- * Returns true if {@link #getCodePhaseUncertaintyInChips()} is available, false otherwise.
- */
- public boolean hasCodePhaseUncertaintyInChips() {
- return isFlagSet(HAS_CODE_PHASE_UNCERTAINTY);
- }
-
- /**
- * Gets the code-phase's uncertainty (1-Sigma) as a fraction of chips.
- * The uncertainty is represented as an absolute (single sided) value.
- *
- * The value is only available if {@link #hasCodePhaseUncertaintyInChips()} is true.
- */
- public double getCodePhaseUncertaintyInChips() {
- return mCodePhaseUncertaintyInChips;
- }
-
- /**
- * Sets the Code-phase's uncertainty (1-Sigma) in fractions of chips.
- */
- public void setCodePhaseUncertaintyInChips(double value) {
- setFlag(HAS_CODE_PHASE_UNCERTAINTY);
- mCodePhaseUncertaintyInChips = value;
- }
-
- /**
- * Resets the Code-phase's uncertainty (1-Sigma) in fractions of chips.
- */
- public void resetCodePhaseUncertaintyInChips() {
- resetFlag(HAS_CODE_PHASE_UNCERTAINTY);
- mCodePhaseUncertaintyInChips = Double.NaN;
- }
-
- /**
- * Returns true if {@link #getCarrierFrequencyInHz()} is available, false otherwise.
- */
- public boolean hasCarrierFrequencyInHz() {
+ public boolean hasCarrierFrequencyHz() {
return isFlagSet(HAS_CARRIER_FREQUENCY);
}
@@ -665,26 +535,26 @@
* Gets the carrier frequency at which codes and messages are modulated, it can be L1 or L2.
* If the field is not set, the carrier frequency corresponds to L1.
*
- * The value is only available if {@link #hasCarrierFrequencyInHz()} is true.
+ * The value is only available if {@link #hasCarrierFrequencyHz()} is true.
*/
- public float getCarrierFrequencyInHz() {
- return mCarrierFrequencyInHz;
+ public float getCarrierFrequencyHz() {
+ return mCarrierFrequencyHz;
}
/**
* Sets the Carrier frequency (L1 or L2) in Hz.
*/
- public void setCarrierFrequencyInHz(float carrierFrequencyInHz) {
+ public void setCarrierFrequencyHz(float carrierFrequencyHz) {
setFlag(HAS_CARRIER_FREQUENCY);
- mCarrierFrequencyInHz = carrierFrequencyInHz;
+ mCarrierFrequencyHz = carrierFrequencyHz;
}
/**
* Resets the Carrier frequency (L1 or L2) in Hz.
*/
- public void resetCarrierFrequencyInHz() {
+ public void resetCarrierFrequencyHz() {
resetFlag(HAS_CARRIER_FREQUENCY);
- mCarrierFrequencyInHz = Float.NaN;
+ mCarrierFrequencyHz = Float.NaN;
}
/**
@@ -696,7 +566,7 @@
/**
* The number of full carrier cycles between the satellite and the receiver.
- * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}.
+ * The reference frequency is given by the value of {@link #getCarrierFrequencyHz()}.
*
* The value is only available if {@link #hasCarrierCycles()} is true.
*/
@@ -732,7 +602,7 @@
* Range: [0.0, 1.0].
* This is usually the fractional part of the complete carrier phase measurement.
*
- * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}.
+ * The reference frequency is given by the value of {@link #getCarrierFrequencyHz()}.
* The reported carrier-phase includes {@link #getCarrierPhaseUncertainty()}.
*
* The value is only available if {@link #hasCarrierPhase()} is true.
@@ -791,183 +661,17 @@
}
/**
- * Gets a value indicating the 'loss of lock' state of the event.
- */
- @LossOfLockStatus
- public byte getLossOfLock() {
- return mLossOfLock;
- }
-
- /**
- * Sets the 'loss of lock' status.
- */
- public void setLossOfLock(@LossOfLockStatus byte value) {
- mLossOfLock = value;
- }
-
- /**
- * Gets a string representation of the 'loss of lock'.
- * For internal and logging use only.
- */
- private String getLossOfLockString() {
- switch (mLossOfLock) {
- case LOSS_OF_LOCK_UNKNOWN:
- return "Unknown";
- case LOSS_OF_LOCK_OK:
- return "Ok";
- case LOSS_OF_LOCK_CYCLE_SLIP:
- return "CycleSlip";
- default:
- return "<Invalid:" + mLossOfLock + ">";
- }
- }
-
- /**
- * Returns true if {@link #getBitNumber()} is available, false otherwise.
- */
- public boolean hasBitNumber() {
- return isFlagSet(HAS_BIT_NUMBER);
- }
-
- /**
- * Gets the number of GPS bits transmitted since Sat-Sun midnight (GPS week).
- *
- * The value is only available if {@link #hasBitNumber()} is true.
- */
- public int getBitNumber() {
- return mBitNumber;
- }
-
- /**
- * Sets the bit number within the broadcast frame.
- */
- public void setBitNumber(int bitNumber) {
- setFlag(HAS_BIT_NUMBER);
- mBitNumber = bitNumber;
- }
-
- /**
- * Resets the bit number within the broadcast frame.
- */
- public void resetBitNumber() {
- resetFlag(HAS_BIT_NUMBER);
- mBitNumber = Integer.MIN_VALUE;
- }
-
- /**
- * Returns true if {@link #getTimeFromLastBitInMs()} is available, false otherwise.
- */
- public boolean hasTimeFromLastBitInMs() {
- return isFlagSet(HAS_TIME_FROM_LAST_BIT);
- }
-
- /**
- * Gets the elapsed time since the last received bit in milliseconds.
- * Range: [0, 20].
- *
- * The value is only available if {@link #hasTimeFromLastBitInMs()} is true.
- */
- public short getTimeFromLastBitInMs() {
- return mTimeFromLastBitInMs;
- }
-
- /**
- * Sets the elapsed time since the last received bit in milliseconds.
- */
- public void setTimeFromLastBitInMs(short value) {
- setFlag(HAS_TIME_FROM_LAST_BIT);
- mTimeFromLastBitInMs = value;
- }
-
- /**
- * Resets the elapsed time since the last received bit in milliseconds.
- */
- public void resetTimeFromLastBitInMs() {
- resetFlag(HAS_TIME_FROM_LAST_BIT);
- mTimeFromLastBitInMs = Short.MIN_VALUE;
- }
-
- /**
- * Returns true if {@link #getDopplerShiftInHz()} is available, false otherwise.
- */
- public boolean hasDopplerShiftInHz() {
- return isFlagSet(HAS_DOPPLER_SHIFT);
- }
-
- /**
- * Gets the Doppler Shift in Hz.
- * A positive value indicates that the SV is moving toward the receiver.
- *
- * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}.
- * The reported doppler shift includes {@link #getDopplerShiftUncertaintyInHz()}.
- *
- * The value is only available if {@link #hasDopplerShiftInHz()} is true.
- */
- public double getDopplerShiftInHz() {
- return mDopplerShiftInHz;
- }
-
- /**
- * Sets the Doppler shift in Hz.
- */
- public void setDopplerShiftInHz(double value) {
- setFlag(HAS_DOPPLER_SHIFT);
- mDopplerShiftInHz = value;
- }
-
- /**
- * Resets the Doppler shift in Hz.
- */
- public void resetDopplerShiftInHz() {
- resetFlag(HAS_DOPPLER_SHIFT);
- mDopplerShiftInHz = Double.NaN;
- }
-
- /**
- * Returns true if {@link #getDopplerShiftUncertaintyInHz()} is available, false otherwise.
- */
- public boolean hasDopplerShiftUncertaintyInHz() {
- return isFlagSet(HAS_DOPPLER_SHIFT_UNCERTAINTY);
- }
-
- /**
- * Gets the Doppler's Shift uncertainty (1-Sigma) in Hz.
- * The uncertainty is represented as an absolute (single sided) value.
- *
- * The value is only available if {@link #hasDopplerShiftUncertaintyInHz()} is true.
- */
- public double getDopplerShiftUncertaintyInHz() {
- return mDopplerShiftUncertaintyInHz;
- }
-
- /**
- * Sets the Doppler's shift uncertainty (1-Sigma) in Hz.
- */
- public void setDopplerShiftUncertaintyInHz(double value) {
- setFlag(HAS_DOPPLER_SHIFT_UNCERTAINTY);
- mDopplerShiftUncertaintyInHz = value;
- }
-
- /**
- * Resets the Doppler's shift uncertainty (1-Sigma) in Hz.
- */
- public void resetDopplerShiftUncertaintyInHz() {
- resetFlag(HAS_DOPPLER_SHIFT_UNCERTAINTY);
- mDopplerShiftUncertaintyInHz = Double.NaN;
- }
-
- /**
* Gets a value indicating the 'multipath' state of the event.
*/
@MultipathIndicator
- public byte getMultipathIndicator() {
+ public int getMultipathIndicator() {
return mMultipathIndicator;
}
/**
* Sets the 'multi-path' indicator.
*/
- public void setMultipathIndicator(@MultipathIndicator byte value) {
+ public void setMultipathIndicator(@MultipathIndicator int value) {
mMultipathIndicator = value;
}
@@ -1020,229 +724,30 @@
mSnrInDb = Double.NaN;
}
- /**
- * Returns true if {@link #getElevationInDeg()} is available, false otherwise.
- */
- public boolean hasElevationInDeg() {
- return isFlagSet(HAS_ELEVATION);
- }
-
- /**
- * Gets the Elevation in degrees.
- * Range: [-90, 90]
- * The reported elevation includes {@link #getElevationUncertaintyInDeg()}.
- *
- * The value is only available if {@link #hasElevationInDeg()} is true.
- */
- public double getElevationInDeg() {
- return mElevationInDeg;
- }
-
- /**
- * Sets the Elevation in degrees.
- */
- public void setElevationInDeg(double elevationInDeg) {
- setFlag(HAS_ELEVATION);
- mElevationInDeg = elevationInDeg;
- }
-
- /**
- * Resets the Elevation in degrees.
- */
- public void resetElevationInDeg() {
- resetFlag(HAS_ELEVATION);
- mElevationInDeg = Double.NaN;
- }
-
- /**
- * Returns true if {@link #getElevationUncertaintyInDeg()} is available, false otherwise.
- */
- public boolean hasElevationUncertaintyInDeg() {
- return isFlagSet(HAS_ELEVATION_UNCERTAINTY);
- }
-
- /**
- * Gets the elevation's uncertainty (1-Sigma) in degrees.
- * Range: [0, 90]
- *
- * The uncertainty is represented as an absolute (single sided) value.
- *
- * The value is only available if {@link #hasElevationUncertaintyInDeg()} is true.
- */
- public double getElevationUncertaintyInDeg() {
- return mElevationUncertaintyInDeg;
- }
-
- /**
- * Sets the elevation's uncertainty (1-Sigma) in degrees.
- */
- public void setElevationUncertaintyInDeg(double value) {
- setFlag(HAS_ELEVATION_UNCERTAINTY);
- mElevationUncertaintyInDeg = value;
- }
-
- /**
- * Resets the elevation's uncertainty (1-Sigma) in degrees.
- */
- public void resetElevationUncertaintyInDeg() {
- resetFlag(HAS_ELEVATION_UNCERTAINTY);
- mElevationUncertaintyInDeg = Double.NaN;
- }
-
- /**
- * Returns true if {@link #getAzimuthInDeg()} is available, false otherwise.
- */
- public boolean hasAzimuthInDeg() {
- return isFlagSet(HAS_AZIMUTH);
- }
-
- /**
- * Gets the azimuth in degrees.
- * Range: [0, 360).
- *
- * The reported azimuth includes {@link #getAzimuthUncertaintyInDeg()}.
- *
- * The value is only available if {@link #hasAzimuthInDeg()} is true.
- */
- public double getAzimuthInDeg() {
- return mAzimuthInDeg;
- }
-
- /**
- * Sets the Azimuth in degrees.
- */
- public void setAzimuthInDeg(double value) {
- setFlag(HAS_AZIMUTH);
- mAzimuthInDeg = value;
- }
-
- /**
- * Resets the Azimuth in degrees.
- */
- public void resetAzimuthInDeg() {
- resetFlag(HAS_AZIMUTH);
- mAzimuthInDeg = Double.NaN;
- }
-
- /**
- * Returns true if {@link #getAzimuthUncertaintyInDeg()} is available, false otherwise.
- */
- public boolean hasAzimuthUncertaintyInDeg() {
- return isFlagSet(HAS_AZIMUTH_UNCERTAINTY);
- }
-
- /**
- * Gets the azimuth's uncertainty (1-Sigma) in degrees.
- * Range: [0, 180].
- *
- * The uncertainty is represented as an absolute (single sided) value.
- *
- * The value is only available if {@link #hasAzimuthUncertaintyInDeg()} is true.
- */
- public double getAzimuthUncertaintyInDeg() {
- return mAzimuthUncertaintyInDeg;
- }
-
- /**
- * Sets the Azimuth's uncertainty (1-Sigma) in degrees.
- */
- public void setAzimuthUncertaintyInDeg(double value) {
- setFlag(HAS_AZIMUTH_UNCERTAINTY);
- mAzimuthUncertaintyInDeg = value;
- }
-
- /**
- * Resets the Azimuth's uncertainty (1-Sigma) in degrees.
- */
- public void resetAzimuthUncertaintyInDeg() {
- resetFlag(HAS_AZIMUTH_UNCERTAINTY);
- mAzimuthUncertaintyInDeg = Double.NaN;
- }
-
- /**
- * Gets a flag indicating whether the GPS represented by the measurement was used for computing
- * the most recent fix.
- *
- * @return A non-null value if the data is available, null otherwise.
- */
- public boolean isUsedInFix() {
- return mUsedInFix;
- }
-
- /**
- * Sets the Used-in-Fix flag.
- */
- public void setUsedInFix(boolean value) {
- mUsedInFix = value;
- }
-
- /**
- * Gets pseudorange rate (based on carrier phase changes) at the timestamp in m/s.
- */
- public double getPseudorangeRateCarrierInMetersPerSec() {
- return mPseudorangeRateCarrierInMetersPerSec;
- }
-
- /**
- * Sets pseudorange rate (based on carrier phase changes) at the timestamp in m/s.
- */
- public void setPseudorangeRateCarrierInMetersPerSec(double value) {
- mPseudorangeRateCarrierInMetersPerSec = value;
- }
-
- /**
- * Gets 1-Sigma uncertainty of the pseudorange rate carrier.
- */
- public double getPseudorangeRateCarrierUncertaintyInMetersPerSec() {
- return mPseudorangeRateCarrierUncertaintyInMetersPerSec;
- }
-
- /**
- * Sets 1-Sigma uncertainty of the pseudorange rate carrier.
- */
- public void setPseudorangeRateCarrierUncertaintyInMetersPerSec(double value) {
- mPseudorangeRateCarrierUncertaintyInMetersPerSec = value;
- }
-
public static final Creator<GnssMeasurement> CREATOR = new Creator<GnssMeasurement>() {
@Override
public GnssMeasurement createFromParcel(Parcel parcel) {
GnssMeasurement gnssMeasurement = new GnssMeasurement();
gnssMeasurement.mFlags = parcel.readInt();
- gnssMeasurement.mSvid = (short) parcel.readInt();
- gnssMeasurement.mTimeOffsetInNs = parcel.readDouble();
- gnssMeasurement.mState = (short) parcel.readInt();
- gnssMeasurement.mReceivedGpsTowInNs = parcel.readLong();
- gnssMeasurement.mReceivedGpsTowUncertaintyInNs = parcel.readLong();
- gnssMeasurement.mCn0InDbHz = parcel.readDouble();
- gnssMeasurement.mPseudorangeRateInMetersPerSec = parcel.readDouble();
- gnssMeasurement.mPseudorangeRateUncertaintyInMetersPerSec = parcel.readDouble();
- gnssMeasurement.mAccumulatedDeltaRangeState = (short) parcel.readInt();
- gnssMeasurement.mAccumulatedDeltaRangeInMeters = parcel.readDouble();
- gnssMeasurement.mAccumulatedDeltaRangeUncertaintyInMeters = parcel.readDouble();
- gnssMeasurement.mPseudorangeInMeters = parcel.readDouble();
- gnssMeasurement.mPseudorangeUncertaintyInMeters = parcel.readDouble();
- gnssMeasurement.mCodePhaseInChips = parcel.readDouble();
- gnssMeasurement.mCodePhaseUncertaintyInChips = parcel.readDouble();
- gnssMeasurement.mCarrierFrequencyInHz = parcel.readFloat();
+ gnssMeasurement.mSvid = parcel.readInt();
+ gnssMeasurement.mConstellationType = parcel.readInt();
+ gnssMeasurement.mTimeOffsetNanos = parcel.readDouble();
+ gnssMeasurement.mState = parcel.readInt();
+ gnssMeasurement.mReceivedSvTimeNanos = parcel.readLong();
+ gnssMeasurement.mReceivedSvTimeUncertaintyNanos = parcel.readLong();
+ gnssMeasurement.mCn0DbHz = parcel.readDouble();
+ gnssMeasurement.mPseudorangeRateMetersPerSecond = parcel.readDouble();
+ gnssMeasurement.mPseudorangeRateUncertaintyMetersPerSecond = parcel.readDouble();
+ gnssMeasurement.mAccumulatedDeltaRangeState = parcel.readInt();
+ gnssMeasurement.mAccumulatedDeltaRangeMeters = parcel.readDouble();
+ gnssMeasurement.mAccumulatedDeltaRangeUncertaintyMeters = parcel.readDouble();
+ gnssMeasurement.mCarrierFrequencyHz = parcel.readFloat();
gnssMeasurement.mCarrierCycles = parcel.readLong();
gnssMeasurement.mCarrierPhase = parcel.readDouble();
gnssMeasurement.mCarrierPhaseUncertainty = parcel.readDouble();
- gnssMeasurement.mLossOfLock = parcel.readByte();
- gnssMeasurement.mBitNumber = parcel.readInt();
- gnssMeasurement.mTimeFromLastBitInMs = (short) parcel.readInt();
- gnssMeasurement.mDopplerShiftInHz = parcel.readDouble();
- gnssMeasurement.mDopplerShiftUncertaintyInHz = parcel.readDouble();
- gnssMeasurement.mMultipathIndicator = parcel.readByte();
+ gnssMeasurement.mMultipathIndicator = parcel.readInt();
gnssMeasurement.mSnrInDb = parcel.readDouble();
- gnssMeasurement.mElevationInDeg = parcel.readDouble();
- gnssMeasurement.mElevationUncertaintyInDeg = parcel.readDouble();
- gnssMeasurement.mAzimuthInDeg = parcel.readDouble();
- gnssMeasurement.mAzimuthUncertaintyInDeg = parcel.readDouble();
- gnssMeasurement.mUsedInFix = parcel.readInt() != 0;
- gnssMeasurement.mPseudorangeRateCarrierInMetersPerSec = parcel.readDouble();
- gnssMeasurement.mPseudorangeRateCarrierUncertaintyInMetersPerSec = parcel.readDouble();
return gnssMeasurement;
}
@@ -1257,38 +762,23 @@
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeInt(mFlags);
parcel.writeInt(mSvid);
- parcel.writeDouble(mTimeOffsetInNs);
+ parcel.writeInt(mConstellationType);
+ parcel.writeDouble(mTimeOffsetNanos);
parcel.writeInt(mState);
- parcel.writeLong(mReceivedGpsTowInNs);
- parcel.writeLong(mReceivedGpsTowUncertaintyInNs);
- parcel.writeDouble(mCn0InDbHz);
- parcel.writeDouble(mPseudorangeRateInMetersPerSec);
- parcel.writeDouble(mPseudorangeRateUncertaintyInMetersPerSec);
+ parcel.writeLong(mReceivedSvTimeNanos);
+ parcel.writeLong(mReceivedSvTimeUncertaintyNanos);
+ parcel.writeDouble(mCn0DbHz);
+ parcel.writeDouble(mPseudorangeRateMetersPerSecond);
+ parcel.writeDouble(mPseudorangeRateUncertaintyMetersPerSecond);
parcel.writeInt(mAccumulatedDeltaRangeState);
- parcel.writeDouble(mAccumulatedDeltaRangeInMeters);
- parcel.writeDouble(mAccumulatedDeltaRangeUncertaintyInMeters);
- parcel.writeDouble(mPseudorangeInMeters);
- parcel.writeDouble(mPseudorangeUncertaintyInMeters);
- parcel.writeDouble(mCodePhaseInChips);
- parcel.writeDouble(mCodePhaseUncertaintyInChips);
- parcel.writeFloat(mCarrierFrequencyInHz);
+ parcel.writeDouble(mAccumulatedDeltaRangeMeters);
+ parcel.writeDouble(mAccumulatedDeltaRangeUncertaintyMeters);
+ parcel.writeFloat(mCarrierFrequencyHz);
parcel.writeLong(mCarrierCycles);
parcel.writeDouble(mCarrierPhase);
parcel.writeDouble(mCarrierPhaseUncertainty);
- parcel.writeByte(mLossOfLock);
- parcel.writeInt(mBitNumber);
- parcel.writeInt(mTimeFromLastBitInMs);
- parcel.writeDouble(mDopplerShiftInHz);
- parcel.writeDouble(mDopplerShiftUncertaintyInHz);
- parcel.writeByte(mMultipathIndicator);
+ parcel.writeInt(mMultipathIndicator);
parcel.writeDouble(mSnrInDb);
- parcel.writeDouble(mElevationInDeg);
- parcel.writeDouble(mElevationUncertaintyInDeg);
- parcel.writeDouble(mAzimuthInDeg);
- parcel.writeDouble(mAzimuthUncertaintyInDeg);
- parcel.writeInt(mUsedInFix ? 1 : 0);
- parcel.writeDouble(mPseudorangeRateCarrierInMetersPerSec);
- parcel.writeDouble(mPseudorangeRateCarrierUncertaintyInMetersPerSec);
}
@Override
@@ -1303,26 +793,26 @@
StringBuilder builder = new StringBuilder("GnssMeasurement:\n");
builder.append(String.format(format, "Svid", mSvid));
-
- builder.append(String.format(format, "TimeOffsetInNs", mTimeOffsetInNs));
+ builder.append(String.format(format, "ConstellationType", mConstellationType));
+ builder.append(String.format(format, "TimeOffsetNanos", mTimeOffsetNanos));
builder.append(String.format(format, "State", getStateString()));
builder.append(String.format(
formatWithUncertainty,
- "ReceivedGpsTowInNs",
- mReceivedGpsTowInNs,
- "ReceivedGpsTowUncertaintyInNs",
- mReceivedGpsTowUncertaintyInNs));
+ "ReceivedSvTimeNanos",
+ mReceivedSvTimeNanos,
+ "ReceivedSvTimeUncertaintyNanos",
+ mReceivedSvTimeUncertaintyNanos));
- builder.append(String.format(format, "Cn0InDbHz", mCn0InDbHz));
+ builder.append(String.format(format, "Cn0DbHz", mCn0DbHz));
builder.append(String.format(
formatWithUncertainty,
- "PseudorangeRateInMetersPerSec",
- mPseudorangeRateInMetersPerSec,
- "PseudorangeRateUncertaintyInMetersPerSec",
- mPseudorangeRateUncertaintyInMetersPerSec));
+ "PseudorangeRateMetersPerSecond",
+ mPseudorangeRateMetersPerSecond,
+ "PseudorangeRateUncertaintyMetersPerSecond",
+ mPseudorangeRateUncertaintyMetersPerSecond));
builder.append(String.format(
format,
"PseudorangeRateIsCorrected",
@@ -1335,29 +825,15 @@
builder.append(String.format(
formatWithUncertainty,
- "AccumulatedDeltaRangeInMeters",
- mAccumulatedDeltaRangeInMeters,
- "AccumulatedDeltaRangeUncertaintyInMeters",
- mAccumulatedDeltaRangeUncertaintyInMeters));
-
- builder.append(String.format(
- formatWithUncertainty,
- "PseudorangeInMeters",
- hasPseudorangeInMeters() ? mPseudorangeInMeters : null,
- "PseudorangeUncertaintyInMeters",
- hasPseudorangeUncertaintyInMeters() ? mPseudorangeUncertaintyInMeters : null));
-
- builder.append(String.format(
- formatWithUncertainty,
- "CodePhaseInChips",
- hasCodePhaseInChips() ? mCodePhaseInChips : null,
- "CodePhaseUncertaintyInChips",
- hasCodePhaseUncertaintyInChips() ? mCodePhaseUncertaintyInChips : null));
+ "AccumulatedDeltaRangeMeters",
+ mAccumulatedDeltaRangeMeters,
+ "AccumulatedDeltaRangeUncertaintyMeters",
+ mAccumulatedDeltaRangeUncertaintyMeters));
builder.append(String.format(
format,
- "CarrierFrequencyInHz",
- hasCarrierFrequencyInHz() ? mCarrierFrequencyInHz : null));
+ "CarrierFrequencyHz",
+ hasCarrierFrequencyHz() ? mCarrierFrequencyHz : null));
builder.append(String.format(
format,
@@ -1371,25 +847,6 @@
"CarrierPhaseUncertainty",
hasCarrierPhaseUncertainty() ? mCarrierPhaseUncertainty : null));
- builder.append(String.format(format, "LossOfLock", getLossOfLockString()));
-
- builder.append(String.format(
- format,
- "BitNumber",
- hasBitNumber() ? mBitNumber : null));
-
- builder.append(String.format(
- format,
- "TimeFromLastBitInMs",
- hasTimeFromLastBitInMs() ? mTimeFromLastBitInMs : null));
-
- builder.append(String.format(
- formatWithUncertainty,
- "DopplerShiftInHz",
- hasDopplerShiftInHz() ? mDopplerShiftInHz : null,
- "DopplerShiftUncertaintyInHz",
- hasDopplerShiftUncertaintyInHz() ? mDopplerShiftUncertaintyInHz : null));
-
builder.append(String.format(format, "MultipathIndicator", getMultipathIndicatorString()));
builder.append(String.format(
@@ -1397,65 +854,28 @@
"SnrInDb",
hasSnrInDb() ? mSnrInDb : null));
- builder.append(String.format(
- formatWithUncertainty,
- "ElevationInDeg",
- hasElevationInDeg() ? mElevationInDeg : null,
- "ElevationUncertaintyInDeg",
- hasElevationUncertaintyInDeg() ? mElevationUncertaintyInDeg : null));
-
- builder.append(String.format(
- formatWithUncertainty,
- "AzimuthInDeg",
- hasAzimuthInDeg() ? mAzimuthInDeg : null,
- "AzimuthUncertaintyInDeg",
- hasAzimuthUncertaintyInDeg() ? mAzimuthUncertaintyInDeg : null));
-
- builder.append(String.format(format, "UsedInFix", mUsedInFix));
-
- builder.append(String.format(format, "PseudorangeRateCarrierInMetersPerSec",
- mPseudorangeRateCarrierInMetersPerSec));
- builder.append(String.format(format, "PseudorangeRateCarrierUncertaintyInMetersPerSec",
- mPseudorangeRateCarrierUncertaintyInMetersPerSec));
-
return builder.toString();
}
private void initialize() {
mFlags = HAS_NO_FLAGS;
- setSvid((short) 0);
- setTimeOffsetInNs(Long.MIN_VALUE);
+ setSvid(0);
+ setTimeOffsetNanos(Long.MIN_VALUE);
setState(STATE_UNKNOWN);
- setReceivedGpsTowInNs(Long.MIN_VALUE);
- setReceivedGpsTowUncertaintyInNs(Long.MAX_VALUE);
- setCn0InDbHz(Double.MIN_VALUE);
- setPseudorangeRateInMetersPerSec(Double.MIN_VALUE);
- setPseudorangeRateUncertaintyInMetersPerSec(Double.MIN_VALUE);
+ setReceivedSvTimeNanos(Long.MIN_VALUE);
+ setReceivedSvTimeUncertaintyNanos(Long.MAX_VALUE);
+ setCn0DbHz(Double.MIN_VALUE);
+ setPseudorangeRateMetersPerSecond(Double.MIN_VALUE);
+ setPseudorangeRateUncertaintyMetersPerSecond(Double.MIN_VALUE);
setAccumulatedDeltaRangeState(ADR_STATE_UNKNOWN);
- setAccumulatedDeltaRangeInMeters(Double.MIN_VALUE);
- setAccumulatedDeltaRangeUncertaintyInMeters(Double.MIN_VALUE);
- resetPseudorangeInMeters();
- resetPseudorangeUncertaintyInMeters();
- resetCodePhaseInChips();
- resetCodePhaseUncertaintyInChips();
- resetCarrierFrequencyInHz();
+ setAccumulatedDeltaRangeMeters(Double.MIN_VALUE);
+ setAccumulatedDeltaRangeUncertaintyMeters(Double.MIN_VALUE);
+ resetCarrierFrequencyHz();
resetCarrierCycles();
resetCarrierPhase();
resetCarrierPhaseUncertainty();
- setLossOfLock(LOSS_OF_LOCK_UNKNOWN);
- resetBitNumber();
- resetTimeFromLastBitInMs();
- resetDopplerShiftInHz();
- resetDopplerShiftUncertaintyInHz();
setMultipathIndicator(MULTIPATH_INDICATOR_UNKNOWN);
resetSnrInDb();
- resetElevationInDeg();
- resetElevationUncertaintyInDeg();
- resetAzimuthInDeg();
- resetAzimuthUncertaintyInDeg();
- setUsedInFix(false);
- setPseudorangeRateCarrierInMetersPerSec(Double.MIN_VALUE);
- setPseudorangeRateCarrierUncertaintyInMetersPerSec(Double.MIN_VALUE);
}
private void setFlag(int flag) {
diff --git a/location/java/android/location/GnssMeasurementsEvent.java b/location/java/android/location/GnssMeasurementsEvent.java
index b744a03..86841ff 100644
--- a/location/java/android/location/GnssMeasurementsEvent.java
+++ b/location/java/android/location/GnssMeasurementsEvent.java
@@ -33,46 +33,46 @@
* Events are delivered to registered instances of {@link Callback}.
*/
public final class GnssMeasurementsEvent implements Parcelable {
- /** The status of GPS measurements event. */
+ /** The status of GNSS measurements event. */
@Retention(RetentionPolicy.SOURCE)
- @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GPS_LOCATION_DISABLED})
+ @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GNSS_LOCATION_DISABLED})
public @interface GnssMeasurementsStatus {}
/**
- * The system does not support tracking of GPS Measurements. This status will not change in the
+ * The system does not support tracking of GNSS Measurements. This status will not change in the
* future.
*/
public static final int STATUS_NOT_SUPPORTED = 0;
/**
- * GPS Measurements are successfully being tracked, it will receive updates once they are
+ * GNSS Measurements are successfully being tracked, it will receive updates once they are
* available.
*/
public static final int STATUS_READY = 1;
/**
- * GPS provider or Location is disabled, updates will not be received until they are enabled.
+ * GNSS provider or Location is disabled, updates will not be received until they are enabled.
*/
- public static final int STATUS_GPS_LOCATION_DISABLED = 2;
+ public static final int STATUS_GNSS_LOCATION_DISABLED = 2;
private final GnssClock mClock;
private final Collection<GnssMeasurement> mReadOnlyMeasurements;
/**
- * Used for receiving GPS satellite measurements from the GPS engine.
+ * Used for receiving GNSS satellite measurements from the GNSS engine.
* Each measurement contains raw and computed data identifying a satellite.
* You can implement this interface and call
- * {@link LocationManager#registerGnssMeasurementCallback}.
+ * {@link LocationManager#registerGnssMeasurementsCallback}.
*/
public static abstract class Callback {
/**
- * Returns the latest collected GPS Measurements.
+ * Reports the latest collected GNSS Measurements.
*/
public void onGnssMeasurementsReceived(GnssMeasurementsEvent eventArgs) {}
/**
- * Returns the latest status of the GPS Measurements sub-system.
+ * Reports the latest status of the GNSS Measurements sub-system.
*/
public void onStatusChanged(@GnssMeasurementsStatus int status) {}
}
diff --git a/location/java/android/location/GnssNavigationMessage.java b/location/java/android/location/GnssNavigationMessage.java
index 86328eb..c0608e0 100644
--- a/location/java/android/location/GnssNavigationMessage.java
+++ b/location/java/android/location/GnssNavigationMessage.java
@@ -34,61 +34,57 @@
/** The type of the GPS Clock. */
@Retention(RetentionPolicy.SOURCE)
- @IntDef({MESSAGE_TYPE_UNKNOWN, MESSAGE_TYPE_L1CA, MESSAGE_TYPE_L2CNAV, MESSAGE_TYPE_L5CNAV,
- MESSAGE_TYPE_CNAV2})
+ @IntDef({TYPE_UNKNOWN, TYPE_GPS_L1CA, TYPE_GPS_L2CNAV, TYPE_GPS_L5CNAV, TYPE_GPS_CNAV2,
+ TYPE_GLO_L1CA, TYPE_BDS_D1, TYPE_BDS_D2, TYPE_GAL_I, TYPE_GAL_F})
public @interface GnssNavigationMessageType {}
// The following enumerations must be in sync with the values declared in gps.h
- /**
- * The type of the navigation message is not available or unknown.
- */
- public static final byte MESSAGE_TYPE_UNKNOWN = 0;
-
- /**
- * The Navigation Message is of type L1 C/A.
- */
- public static final byte MESSAGE_TYPE_L1CA = 1;
-
- /**
- * The Navigation Message is of type L1-CNAV.
- */
- public static final byte MESSAGE_TYPE_L2CNAV = 2;
-
- /**
- * The Navigation Message is of type L5-CNAV.
- */
- public static final byte MESSAGE_TYPE_L5CNAV = 3;
-
- /**
- * The Navigation Message is of type CNAV-2.
- */
- public static final byte MESSAGE_TYPE_CNAV2 = 4;
+ /** Message type unknown */
+ public static final int TYPE_UNKNOWN = 0;
+ /** GPS L1 C/A message contained in the structure. */
+ public static final int TYPE_GPS_L1CA = 0x0101;
+ /** GPS L2-CNAV message contained in the structure. */
+ public static final int TYPE_GPS_L2CNAV = 0x0102;
+ /** GPS L5-CNAV message contained in the structure. */
+ public static final int TYPE_GPS_L5CNAV = 0x0103;
+ /** GPS CNAV-2 message contained in the structure. */
+ public static final int TYPE_GPS_CNAV2 = 0x0104;
+ /** Glonass L1 CA message contained in the structure. */
+ public static final int TYPE_GLO_L1CA = 0x0301;
+ /** Beidou D1 message contained in the structure. */
+ public static final int TYPE_BDS_D1 = 0x0501;
+ /** Beidou D2 message contained in the structure. */
+ public static final int TYPE_BDS_D2 = 0x0502;
+ /** Galileo I/NAV message contained in the structure. */
+ public static final int TYPE_GAL_I = 0x0601;
+ /** Galileo F/NAV message contained in the structure. */
+ public static final int TYPE_GAL_F = 0x0602;
/**
* The Navigation Message Status is 'unknown'.
*/
- public static final short STATUS_UNKNOWN = 0;
+ public static final int STATUS_UNKNOWN = 0;
/**
* The Navigation Message was received without any parity error in its navigation words.
*/
- public static final short STATUS_PARITY_PASSED = (1<<0);
+ public static final int STATUS_PARITY_PASSED = (1<<0);
/**
* The Navigation Message was received with words that failed parity check, but the receiver was
* able to correct those words.
*/
- public static final short STATUS_PARITY_REBUILT = (1<<1);
+ public static final int STATUS_PARITY_REBUILT = (1<<1);
// End enumerations in sync with gps.h
- private byte mType;
- private short mSvid;
- private short mMessageId;
- private short mSubmessageId;
+ private int mType;
+ private int mSvid;
+ private int mMessageId;
+ private int mSubmessageId;
private byte[] mData;
- private short mStatus;
+ private int mStatus;
GnssNavigationMessage() {
initialize();
@@ -117,14 +113,14 @@
* Gets the type of the navigation message contained in the object.
*/
@GnssNavigationMessageType
- public byte getType() {
+ public int getType() {
return mType;
}
/**
* Sets the type of the navigation message.
*/
- public void setType(@GnssNavigationMessageType byte value) {
+ public void setType(@GnssNavigationMessageType int value) {
mType = value;
}
@@ -134,16 +130,26 @@
*/
private String getTypeString() {
switch (mType) {
- case MESSAGE_TYPE_UNKNOWN:
+ case TYPE_UNKNOWN:
return "Unknown";
- case MESSAGE_TYPE_L1CA:
- return "L1 C/A";
- case MESSAGE_TYPE_L2CNAV:
- return "L2-CNAV";
- case MESSAGE_TYPE_L5CNAV:
- return "L5-CNAV";
- case MESSAGE_TYPE_CNAV2:
- return "CNAV-2";
+ case TYPE_GPS_L1CA:
+ return "GPS L1 C/A";
+ case TYPE_GPS_L2CNAV:
+ return "GPS L2-CNAV";
+ case TYPE_GPS_L5CNAV:
+ return "GPS L5-CNAV";
+ case TYPE_GPS_CNAV2:
+ return "GPS CNAV2";
+ case TYPE_GLO_L1CA:
+ return "Glonass L1 C/A";
+ case TYPE_BDS_D1:
+ return "Beidou D1";
+ case TYPE_BDS_D2:
+ return "Beidou D2";
+ case TYPE_GAL_I:
+ return "Galileo I";
+ case TYPE_GAL_F:
+ return "Galileo F";
default:
return "<Invalid:" + mType + ">";
}
@@ -153,14 +159,14 @@
* Gets the Pseudo-random number.
* Range: [1, 32].
*/
- public short getSvid() {
+ public int getSvid() {
return mSvid;
}
/**
* Sets the Pseud-random number.
*/
- public void setSvid(short value) {
+ public void setSvid(int value) {
mSvid = value;
}
@@ -170,14 +176,14 @@
* subframe 4 and 5, this value corresponds to the 'frame id' of the navigation message.
* Subframe 1, 2, 3 does not contain a 'frame id' and this might be reported as -1.
*/
- public short getMessageId() {
+ public int getMessageId() {
return mMessageId;
}
/**
* Sets the Message Identifier.
*/
- public void setMessageId(short value) {
+ public void setMessageId(int value) {
mMessageId = value;
}
@@ -187,14 +193,14 @@
* (or frame) that is being transmitted. i.e. for L1 C/A the sub-message identifier corresponds
* to the sub-frame Id of the navigation message.
*/
- public short getSubmessageId() {
+ public int getSubmessageId() {
return mSubmessageId;
}
/**
* Sets the Sub-message identifier.
*/
- public void setSubmessageId(short value) {
+ public void setSubmessageId(int value) {
mSubmessageId = value;
}
@@ -221,14 +227,14 @@
/**
* Gets the Status of the navigation message contained in the object.
*/
- public short getStatus() {
+ public int getStatus() {
return mStatus;
}
/**
* Sets the status of the navigation message.
*/
- public void setStatus(short value) {
+ public void setStatus(int value) {
mStatus = value;
}
@@ -255,10 +261,10 @@
public GnssNavigationMessage createFromParcel(Parcel parcel) {
GnssNavigationMessage navigationMessage = new GnssNavigationMessage();
- navigationMessage.setType(parcel.readByte());
- navigationMessage.setSvid((short) parcel.readInt());
- navigationMessage.setMessageId((short) parcel.readInt());
- navigationMessage.setSubmessageId((short) parcel.readInt());
+ navigationMessage.setType(parcel.readInt());
+ navigationMessage.setSvid(parcel.readInt());
+ navigationMessage.setMessageId(parcel.readInt());
+ navigationMessage.setSubmessageId(parcel.readInt());
int dataLength = parcel.readInt();
byte[] data = new byte[dataLength];
@@ -267,7 +273,7 @@
if (parcel.dataAvail() >= Integer.SIZE) {
int status = parcel.readInt();
- navigationMessage.setStatus((short) status);
+ navigationMessage.setStatus(status);
} else {
navigationMessage.setStatus(STATUS_UNKNOWN);
}
@@ -283,7 +289,7 @@
@Override
public void writeToParcel(Parcel parcel, int flags) {
- parcel.writeByte(mType);
+ parcel.writeInt(mType);
parcel.writeInt(mSvid);
parcel.writeInt(mMessageId);
parcel.writeInt(mSubmessageId);
@@ -321,7 +327,7 @@
}
private void initialize() {
- mType = MESSAGE_TYPE_UNKNOWN;
+ mType = TYPE_UNKNOWN;
mSvid = 0;
mMessageId = -1;
mSubmessageId = -1;
diff --git a/location/java/android/location/GnssNavigationMessageEvent.java b/location/java/android/location/GnssNavigationMessageEvent.java
index 19c82e9..0df730d 100644
--- a/location/java/android/location/GnssNavigationMessageEvent.java
+++ b/location/java/android/location/GnssNavigationMessageEvent.java
@@ -32,7 +32,7 @@
public final class GnssNavigationMessageEvent implements Parcelable {
/** The status of GPS measurements event. */
@Retention(RetentionPolicy.SOURCE)
- @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GPS_LOCATION_DISABLED})
+ @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GNSS_LOCATION_DISABLED})
public @interface GnssNavigationMessageStatus {}
/**
@@ -50,7 +50,7 @@
/**
* GPS provider or Location is disabled, updated will not be received until they are enabled.
*/
- public static final int STATUS_GPS_LOCATION_DISABLED = 2;
+ public static final int STATUS_GNSS_LOCATION_DISABLED = 2;
private final GnssNavigationMessage mNavigationMessage;
diff --git a/location/java/android/location/GnssStatus.java b/location/java/android/location/GnssStatus.java
index 906e944..2a42fc6 100644
--- a/location/java/android/location/GnssStatus.java
+++ b/location/java/android/location/GnssStatus.java
@@ -16,6 +16,11 @@
package android.location;
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* This class represents the current state of the GNSS engine.
* This class is used in conjunction with the {@link GnssStatusCallback}.
@@ -36,6 +41,12 @@
/** Constellation type constant for Galileo. */
public static final int CONSTELLATION_GALILEO = 6;
+ /** Constellation type. */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({CONSTELLATION_UNKNOWN, CONSTELLATION_GPS, CONSTELLATION_SBAS, CONSTELLATION_GLONASS,
+ CONSTELLATION_QZSS, CONSTELLATION_BEIDOU, CONSTELLATION_GALILEO})
+ public @interface ConstellationType {}
+
// these must match the definitions in gps.h
/** @hide */
public static final int GNSS_SV_FLAGS_NONE = 0;
@@ -55,16 +66,16 @@
/* These package private values are modified by the LocationManager class */
/* package */ int[] mSvidWithFlags;
- /* package */ float[] mSnrs;
+ /* package */ float[] mCn0DbHz;
/* package */ float[] mElevations;
/* package */ float[] mAzimuths;
/* package */ int mSvCount;
- GnssStatus(int svCount, int[] svidWithFlags, float[] snrs, float[] elevations,
+ GnssStatus(int svCount, int[] svidWithFlags, float[] cn0s, float[] elevations,
float[] azimuths) {
mSvCount = svCount;
mSvidWithFlags = svidWithFlags;
- mSnrs = snrs;
+ mCn0DbHz = cn0s;
mElevations = elevations;
mAzimuths = azimuths;
}
@@ -80,9 +91,10 @@
* Retrieves the constellation type of the satellite at the specified position.
* @param satIndex the index of the satellite in the list.
*/
+ @ConstellationType
public int getConstellationType(int satIndex) {
- return (mSvidWithFlags[satIndex] >> CONSTELLATION_TYPE_SHIFT_WIDTH)
- & CONSTELLATION_TYPE_MASK;
+ return ((mSvidWithFlags[satIndex] >> CONSTELLATION_TYPE_SHIFT_WIDTH)
+ & CONSTELLATION_TYPE_MASK);
}
/**
@@ -97,15 +109,15 @@
* Retrieves the signal-noise ration of the satellite at the specified position.
* @param satIndex the index of the satellite in the list.
*/
- public float getSnr(int satIndex) {
- return mSnrs[satIndex];
+ public float getCn0DbHz(int satIndex) {
+ return mCn0DbHz[satIndex];
}
/**
* Retrieves the elevation of the satellite at the specified position.
* @param satIndex the index of the satellite in the list.
*/
- public float getElevation(int satIndex) {
+ public float getElevationDegrees(int satIndex) {
return 0f;
}
@@ -113,7 +125,7 @@
* Retrieves the azimuth the satellite at the specified position.
* @param satIndex the index of the satellite in the list.
*/
- public float getAzimuth(int satIndex) {
+ public float getAzimuthDegrees(int satIndex) {
return mAzimuths[satIndex];
}
diff --git a/location/java/android/location/GnssStatusCallback.java b/location/java/android/location/GnssStatusCallback.java
index b86171b..0d2955a 100644
--- a/location/java/android/location/GnssStatusCallback.java
+++ b/location/java/android/location/GnssStatusCallback.java
@@ -32,13 +32,13 @@
/**
* Called when the GNSS system has received its first fix since starting.
- * @param ttff the time from start to first fix.
+ * @param ttffMillis the time from start to first fix in milliseconds.
*/
- public void onFirstFix(int ttff) {}
+ public void onFirstFix(int ttffMillis) {}
/**
* Called periodically to report GNSS satellite status.
* @param status the current status of all satellites.
*/
public void onSatelliteStatusChanged(GnssStatus status) {}
-}
\ No newline at end of file
+}
diff --git a/location/java/android/location/GpsStatus.java b/location/java/android/location/GpsStatus.java
index e41e20c..bc518f9 100644
--- a/location/java/android/location/GpsStatus.java
+++ b/location/java/android/location/GpsStatus.java
@@ -138,7 +138,7 @@
// For API-compat a public ctor() is not available
GpsStatus() {}
- private void setStatus(int svCount, int[] svidWithFlags, float[] snrs, float[] elevations,
+ private void setStatus(int svCount, int[] svidWithFlags, float[] cn0s, float[] elevations,
float[] azimuths) {
clearSatellites();
for (int i = 0; i < svCount; i++) {
@@ -147,7 +147,6 @@
& GnssStatus.CONSTELLATION_TYPE_MASK;
// Skip all non-GPS satellites.
if (constellationType != GnssStatus.CONSTELLATION_GPS) {
- // TODO: translate the defacto pre-N use of prn's >32 to new struct
continue;
}
int prn = svidWithFlags[i] >> GnssStatus.SVID_SHIFT_WIDTH;
@@ -159,7 +158,7 @@
}
satellite.mValid = true;
- satellite.mSnr = snrs[i];
+ satellite.mSnr = cn0s[i];
satellite.mElevation = elevations[i];
satellite.mAzimuth = azimuths[i];
satellite.mHasEphemeris =
@@ -180,7 +179,7 @@
*/
void setStatus(GnssStatus status, int timeToFirstFix) {
mTimeToFirstFix = timeToFirstFix;
- setStatus(status.mSvCount, status.mSvidWithFlags, status.mSnrs, status.mElevations,
+ setStatus(status.mSvCount, status.mSvidWithFlags, status.mCn0DbHz, status.mElevations,
status.mAzimuths);
}
diff --git a/location/java/android/location/IGnssStatusListener.aidl b/location/java/android/location/IGnssStatusListener.aidl
index 8c7d06e..d84614f 100644
--- a/location/java/android/location/IGnssStatusListener.aidl
+++ b/location/java/android/location/IGnssStatusListener.aidl
@@ -26,7 +26,7 @@
void onGnssStarted();
void onGnssStopped();
void onFirstFix(int ttff);
- void onSvStatusChanged(int svCount, in int[] svidWithFlags, in float[] snrs,
+ void onSvStatusChanged(int svCount, in int[] svidWithFlags, in float[] cn0s,
in float[] elevations, in float[] azimuths);
void onNmeaReceived(long timestamp, String nmea);
}
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 4f1e039..bc8b026 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -69,7 +69,7 @@
in String packageName);
void removeGnssNavigationMessageListener(in IGnssNavigationMessageListener listener);
- int getGpsYearOfHardware();
+ int getGnssYearOfHardware();
// --- deprecated ---
List<String> getAllProviders();
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 23f0710..28db099 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -307,7 +307,7 @@
try {
mService.locationCallbackFinished(this);
} catch (RemoteException e) {
- Log.e(TAG, "locationCallbackFinished: RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -341,9 +341,8 @@
try {
return mService.getAllProviders();
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
- return null;
}
/**
@@ -357,9 +356,8 @@
try {
return mService.getProviders(null, enabledOnly);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
- return null;
}
/**
@@ -382,9 +380,8 @@
}
return createProvider(name, properties);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
- return null;
}
/**
@@ -402,9 +399,8 @@
try {
return mService.getProviders(criteria, enabledOnly);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
- return null;
}
/**
@@ -434,9 +430,8 @@
try {
return mService.getBestProvider(criteria, enabledOnly);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
- return null;
}
/**
@@ -885,7 +880,7 @@
try {
mService.requestLocationUpdates(request, transport, intent, packageName);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -911,7 +906,7 @@
try {
mService.removeUpdates(transport, null, packageName);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -930,7 +925,7 @@
try {
mService.removeUpdates(null, intent, packageName);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -992,7 +987,7 @@
try {
mService.requestGeofence(request, fence, intent, mContext.getPackageName());
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1040,7 +1035,7 @@
try {
mService.requestGeofence(request, fence, intent, mContext.getPackageName());
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1067,7 +1062,7 @@
try {
mService.removeGeofence(null, intent, packageName);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1095,7 +1090,7 @@
try {
mService.removeGeofence(fence, intent, packageName);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1117,7 +1112,7 @@
try {
mService.removeGeofence(null, intent, packageName);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1148,8 +1143,7 @@
try {
return mService.isProviderEnabled(provider);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException", e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1173,8 +1167,7 @@
try {
return mService.getLastLocation(null, packageName);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException", e);
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1205,8 +1198,7 @@
try {
return mService.getLastLocation(request, packageName);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException", e);
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1237,7 +1229,7 @@
try {
mService.addTestProvider(name, properties, mContext.getOpPackageName());
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1255,7 +1247,7 @@
try {
mService.removeTestProvider(provider, mContext.getOpPackageName());
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1292,7 +1284,7 @@
try {
mService.setTestProviderLocation(provider, loc, mContext.getOpPackageName());
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1310,7 +1302,7 @@
try {
mService.clearTestProviderLocation(provider, mContext.getOpPackageName());
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1330,7 +1322,7 @@
try {
mService.setTestProviderEnabled(provider, enabled, mContext.getOpPackageName());
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1348,7 +1340,7 @@
try {
mService.clearTestProviderEnabled(provider, mContext.getOpPackageName());
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1371,7 +1363,7 @@
mService.setTestProviderStatus(provider, status, extras, updateTime,
mContext.getOpPackageName());
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1389,7 +1381,7 @@
try {
mService.clearTestProviderStatus(provider, mContext.getOpPackageName());
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1562,9 +1554,9 @@
@Override
public void onSvStatusChanged(int svCount, int[] prnWithFlags,
- float[] snrs, float[] elevations, float[] azimuths) {
+ float[] cn0s, float[] elevations, float[] azimuths) {
if (mGnssCallback != null) {
- mGnssStatus = new GnssStatus(svCount, prnWithFlags, snrs, elevations, azimuths);
+ mGnssStatus = new GnssStatus(svCount, prnWithFlags, cn0s, elevations, azimuths);
Message msg = Message.obtain();
msg.what = GpsStatus.GPS_EVENT_SATELLITE_STATUS;
@@ -1615,8 +1607,7 @@
mGpsStatusListeners.put(listener, transport);
}
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in registerGpsStatusListener: ", e);
- result = false;
+ throw e.rethrowFromSystemServer();
}
return result;
@@ -1635,7 +1626,7 @@
mService.unregisterGnssStatusCallback(transport);
}
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in unregisterGpsStatusListener: ", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1679,8 +1670,7 @@
mGnssStatusListeners.put(callback, transport);
}
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in registerGnssStatusCallback: ", e);
- result = false;
+ throw e.rethrowFromSystemServer();
}
return result;
@@ -1698,7 +1688,7 @@
mService.unregisterGnssStatusCallback(transport);
}
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in unregisterGnssStatusCallback: ", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1728,8 +1718,7 @@
mGpsNmeaListeners.put(listener, transport);
}
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in registerGpsStatusListener: ", e);
- result = false;
+ throw e.rethrowFromSystemServer();
}
return result;
@@ -1748,7 +1737,7 @@
mService.unregisterGnssStatusCallback(transport);
}
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in unregisterGpsStatusListener: ", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1792,8 +1781,7 @@
mGnssNmeaListeners.put(listener, transport);
}
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in registerGnssStatusCallback: ", e);
- result = false;
+ throw e.rethrowFromSystemServer();
}
return result;
@@ -1811,13 +1799,13 @@
mService.unregisterGnssStatusCallback(transport);
}
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in unregisterGnssStatusCallback: ", e);
+ throw e.rethrowFromSystemServer();
}
}
/**
* No-op method to keep backward-compatibility.
- * Don't use it. Use {@link #registerGnssMeasurementCallback} instead.
+ * Don't use it. Use {@link #registerGnssMeasurementsCallback} instead.
* @hide
* @deprecated
*/
@@ -1834,8 +1822,8 @@
* @return {@code true} if the callback was added successfully, {@code false} otherwise.
*/
@RequiresPermission(ACCESS_FINE_LOCATION)
- public boolean registerGnssMeasurementCallback(GnssMeasurementsEvent.Callback callback) {
- return registerGnssMeasurementCallback(callback, null);
+ public boolean registerGnssMeasurementsCallback(GnssMeasurementsEvent.Callback callback) {
+ return registerGnssMeasurementsCallback(callback, null);
}
/**
@@ -1846,14 +1834,14 @@
* @return {@code true} if the callback was added successfully, {@code false} otherwise.
*/
@RequiresPermission(ACCESS_FINE_LOCATION)
- public boolean registerGnssMeasurementCallback(GnssMeasurementsEvent.Callback callback,
+ public boolean registerGnssMeasurementsCallback(GnssMeasurementsEvent.Callback callback,
Handler handler) {
return mGnssMeasurementCallbackTransport.add(callback, handler);
}
/**
* No-op method to keep backward-compatibility.
- * Don't use it. Use {@link #unregisterGnssMeasurementCallback} instead.
+ * Don't use it. Use {@link #unregisterGnssMeasurementsCallback} instead.
* @hide
* @deprecated
*/
@@ -1867,7 +1855,7 @@
*
* @param callback a {@link GnssMeasurementsEvent.Callback} object to remove.
*/
- public void unregisterGnssMeasurementCallback(GnssMeasurementsEvent.Callback callback) {
+ public void unregisterGnssMeasurementsCallback(GnssMeasurementsEvent.Callback callback) {
mGnssMeasurementCallbackTransport.remove(callback);
}
@@ -1959,12 +1947,11 @@
* @hide
*/
@TestApi
- public int getGpsYearOfHardware() {
+ public int getGnssYearOfHardware() {
try {
- return mService.getGpsYearOfHardware();
+ return mService.getGnssYearOfHardware();
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in getGpsSystemInfo: ", e);
- return 0;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1983,8 +1970,7 @@
try {
return mService.sendExtraCommand(provider, command, extras);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in sendExtraCommand: ", e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1998,8 +1984,7 @@
try {
return mService.sendNiResponse(notifId, userResponse);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in sendNiResponse: ", e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
diff --git a/location/tests/locationtests/src/android/location/GpsStatusTest.java b/location/tests/locationtests/src/android/location/GpsStatusTest.java
index 4808faf..316e88d 100644
--- a/location/tests/locationtests/src/android/location/GpsStatusTest.java
+++ b/location/tests/locationtests/src/android/location/GpsStatusTest.java
@@ -40,7 +40,7 @@
private GpsStatus mStatus;
private int mCount;
private int[] mPrns;
- private float[] mSnrs;
+ private float[] mCn0s;
private float[] mElevations;
private float[] mAzimuth;
private int mEphemerisMask;
@@ -179,7 +179,7 @@
private void verifySatellites(GpsStatus status) {
verifySatelliteCount(status, mCount);
- verifySatellites(status, mCount, mPrns, mSnrs, mElevations, mAzimuth, mEphemerisMask,
+ verifySatellites(status, mCount, mPrns, mCn0s, mElevations, mAzimuth, mEphemerisMask,
mAlmanacMask, mUsedInFixMask);
}
@@ -187,7 +187,7 @@
GpsStatus status,
int count,
int[] prns,
- float[] snrs,
+ float[] cn0s,
float[] elevations,
float[] azimuth,
int ephemerisMask,
@@ -197,7 +197,7 @@
int prn = prns[i];
GpsSatellite satellite = getSatellite(status, prn);
assertNotNull(getSatelliteAssertInfo(i, prn, "non-null"), satellite);
- assertEquals(getSatelliteAssertInfo(i, prn, "Snr"), snrs[i], satellite.getSnr());
+ assertEquals(getSatelliteAssertInfo(i, prn, "Snr"), cn0s[i], satellite.getSnr());
assertEquals(
getSatelliteAssertInfo(i, prn, "Elevation"),
elevations[i],
@@ -247,7 +247,7 @@
}
private void setSatellites(GpsStatus status) throws Exception {
- set(status, mCount, mPrns, mSnrs, mElevations, mAzimuth, mEphemerisMask, mAlmanacMask,
+ set(status, mCount, mPrns, mCn0s, mElevations, mAzimuth, mEphemerisMask, mAlmanacMask,
mUsedInFixMask);
}
@@ -255,7 +255,7 @@
GpsStatus status,
int count,
int[] prns,
- float[] snrs,
+ float[] cn0s,
float[] elevations,
float[] azimuth,
int ephemerisMask,
@@ -279,7 +279,7 @@
status,
count,
prns,
- snrs,
+ cn0s,
elevations,
azimuth,
ephemerisMask,
@@ -333,7 +333,7 @@
if (!reusePrns) {
mPrns = generateIntArray(count);
}
- mSnrs = generateFloatArray(count);
+ mCn0s = generateFloatArray(count);
mElevations = generateFloatArray(count);
mAzimuth = generateFloatArray(count);
mEphemerisMask = generateMask(mPrns);
diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index 45529ef..9922b72 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -111,6 +111,10 @@
* A device type connected over IP.
*/
public static final int TYPE_IP = 20;
+ /**
+ * A type-agnostic device used for communication with external audio systems
+ */
+ public static final int TYPE_BUS = 21;
private final AudioDevicePort mPort;
@@ -279,6 +283,7 @@
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_FM, TYPE_FM);
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_AUX_LINE, TYPE_AUX_LINE);
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_IP, TYPE_IP);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BUS, TYPE_BUS);
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BUILTIN_MIC, TYPE_BUILTIN_MIC);
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET, TYPE_BLUETOOTH_SCO);
@@ -296,6 +301,7 @@
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_SPDIF, TYPE_LINE_DIGITAL);
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, TYPE_BLUETOOTH_A2DP);
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_IP, TYPE_IP);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BUS, TYPE_BUS);
// not covered here, legacy
//AudioSystem.DEVICE_OUT_REMOTE_SUBMIX
@@ -323,6 +329,7 @@
EXT_TO_INT_DEVICE_MAPPING.put(TYPE_TELEPHONY, AudioSystem.DEVICE_OUT_TELEPHONY_TX);
EXT_TO_INT_DEVICE_MAPPING.put(TYPE_AUX_LINE, AudioSystem.DEVICE_OUT_AUX_LINE);
EXT_TO_INT_DEVICE_MAPPING.put(TYPE_IP, AudioSystem.DEVICE_OUT_IP);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BUS, AudioSystem.DEVICE_OUT_BUS);
}
}
diff --git a/core/java/android/hardware/CameraInfo.aidl b/media/java/android/media/AudioFormat.aidl
similarity index 82%
copy from core/java/android/hardware/CameraInfo.aidl
copy to media/java/android/media/AudioFormat.aidl
index e21e694..8613f55 100644
--- a/core/java/android/hardware/CameraInfo.aidl
+++ b/media/java/android/media/AudioFormat.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-package android.hardware;
+package android.media;
-/** @hide */
-parcelable CameraInfo;
+parcelable AudioFormat;
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index 000a56d..abb6f4e 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -18,10 +18,13 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
+import java.util.Objects;
/**
* The {@link AudioFormat} class is used to access a number of audio format and
@@ -209,7 +212,7 @@
* AudioTrack.getPlaybackHeadPosition()}),
* depending on the context where audio frame is used.
*/
-public class AudioFormat {
+public final class AudioFormat implements Parcelable {
//---------------------------------------------------------
// Constants
@@ -332,6 +335,24 @@
CHANNEL_OUT_LOW_FREQUENCY);
// CHANNEL_OUT_ALL is not yet defined; if added then it should match AUDIO_CHANNEL_OUT_ALL
+ /** Minimum value for sample rate,
+ * assuming AudioTrack and AudioRecord share the same limitations.
+ * @hide
+ */
+ // never unhide
+ public static final int SAMPLE_RATE_HZ_MIN = 4000;
+ /** Maximum value for sample rate,
+ * assuming AudioTrack and AudioRecord share the same limitations.
+ * @hide
+ */
+ // never unhide
+ public static final int SAMPLE_RATE_HZ_MAX = 192000;
+ /** Sample rate will be a route-dependent value.
+ * For AudioTrack, it is usually the sink sample rate,
+ * and for AudioRecord it is usually the source sample rate.
+ */
+ public static final int SAMPLE_RATE_UNSPECIFIED = 0;
+
/**
* @hide
* Return the input channel mask corresponding to an output channel mask.
@@ -558,7 +579,7 @@
}
/**
- * Constructor used by the JNI
+ * Constructor used by the JNI. Parameters are not checked for validity.
*/
// Update sound trigger JNI in core/jni/android_hardware_SoundTrigger.cpp when modifying this
// constructor
@@ -607,12 +628,9 @@
/**
* Return the sample rate.
* @return one of the values that can be set in {@link Builder#setSampleRate(int)} or
- * 0 if not set.
+ * {@link #SAMPLE_RATE_UNSPECIFIED} if not set.
*/
public int getSampleRate() {
- if ((mPropertySetMask & AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE) == 0) {
- return 0;
- }
return mSampleRate;
}
@@ -684,7 +702,7 @@
*/
public static class Builder {
private int mEncoding = ENCODING_INVALID;
- private int mSampleRate = 0;
+ private int mSampleRate = SAMPLE_RATE_UNSPECIFIED;
private int mChannelMask = CHANNEL_INVALID;
private int mChannelIndexMask = 0;
private int mPropertySetMask = AUDIO_FORMAT_HAS_PROPERTY_NONE;
@@ -715,6 +733,8 @@
public AudioFormat build() {
AudioFormat af = new AudioFormat(1980/*ignored*/);
af.mEncoding = mEncoding;
+ // not calling setSampleRate is equivalent to calling
+ // setSampleRate(SAMPLE_RATE_UNSPECIFIED)
af.mSampleRate = mSampleRate;
af.mChannelMask = mChannelMask;
af.mChannelIndexMask = mChannelIndexMask;
@@ -792,7 +812,7 @@
* are specified but do not have the same channel count.
*/
public @NonNull Builder setChannelMask(int channelMask) {
- if (channelMask == 0) {
+ if (channelMask == CHANNEL_INVALID) {
throw new IllegalArgumentException("Invalid zero channel mask");
} else if (/* channelMask != 0 && */ mChannelIndexMask != 0 &&
Integer.bitCount(channelMask) != Integer.bitCount(mChannelIndexMask)) {
@@ -864,7 +884,11 @@
* @throws java.lang.IllegalArgumentException
*/
public Builder setSampleRate(int sampleRate) throws IllegalArgumentException {
- if ((sampleRate <= 0) || (sampleRate > 192000)) {
+ // TODO Consider whether to keep the MIN and MAX range checks here.
+ // It is not necessary and poses the problem of defining the limits independently from
+ // native implementation or platform capabilities.
+ if (((sampleRate < SAMPLE_RATE_HZ_MIN) || (sampleRate > SAMPLE_RATE_HZ_MAX)) &&
+ sampleRate != SAMPLE_RATE_UNSPECIFIED) {
throw new IllegalArgumentException("Invalid sample rate " + sampleRate);
}
mSampleRate = sampleRate;
@@ -874,6 +898,64 @@
}
@Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ AudioFormat that = (AudioFormat) o;
+
+ if (mPropertySetMask != that.mPropertySetMask) return false;
+
+ // return false if any of the properties is set and the values differ
+ return !((((mPropertySetMask & AUDIO_FORMAT_HAS_PROPERTY_ENCODING) != 0)
+ && (mEncoding != that.mEncoding))
+ || (((mPropertySetMask & AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE) != 0)
+ && (mSampleRate != that.mSampleRate))
+ || (((mPropertySetMask & AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK) != 0)
+ && (mChannelMask != that.mChannelMask))
+ || (((mPropertySetMask & AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_INDEX_MASK) != 0)
+ && (mChannelIndexMask != that.mChannelIndexMask)));
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mPropertySetMask, mSampleRate, mEncoding, mChannelMask,
+ mChannelIndexMask);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mPropertySetMask);
+ dest.writeInt(mEncoding);
+ dest.writeInt(mSampleRate);
+ dest.writeInt(mChannelMask);
+ dest.writeInt(mChannelIndexMask);
+ }
+
+ private AudioFormat(Parcel in) {
+ mPropertySetMask = in.readInt();
+ mEncoding = in.readInt();
+ mSampleRate = in.readInt();
+ mChannelMask = in.readInt();
+ mChannelIndexMask = in.readInt();
+ }
+
+ public static final Parcelable.Creator<AudioFormat> CREATOR =
+ new Parcelable.Creator<AudioFormat>() {
+ public AudioFormat createFromParcel(Parcel p) {
+ return new AudioFormat(p);
+ }
+ public AudioFormat[] newArray(int size) {
+ return new AudioFormat[size];
+ }
+ };
+
+ @Override
public String toString () {
return new String("AudioFormat:"
+ " props=" + mPropertySetMask
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index dc534be..8206d23 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -177,16 +177,6 @@
"android.media.MASTER_MUTE_CHANGED_ACTION";
/**
- * @hide Broadcast intent when the master mono state changes.
- * Includes the new mono state
- *
- * @see #EXTRA_MASTER_MONO
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String MASTER_MONO_CHANGED_ACTION =
- "android.media.MASTER_MONO_CHANGED_ACTION";
-
- /**
* The new vibrate setting for a particular type.
*
* @see #VIBRATE_SETTING_CHANGED_ACTION
@@ -265,13 +255,6 @@
"android.media.EXTRA_STREAM_VOLUME_MUTED";
/**
- * @hide The new master mono state for the master mono changed intent.
- * Value is boolean
- */
- public static final String EXTRA_MASTER_MONO =
- "android.media.EXTRA_MASTER_MONO";
-
- /**
* Broadcast Action: Wired Headset plugged in or unplugged.
*
* You <em>cannot</em> receive this through components declared
@@ -826,7 +809,7 @@
service.adjustStreamVolume(streamType, direction, flags,
getContext().getOpPackageName());
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in adjustStreamVolume", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -894,18 +877,7 @@
service.setMasterMute(mute, flags, getContext().getOpPackageName(),
UserHandle.getCallingUserId());
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in setMasterMute", e);
- }
- }
-
- /** @hide */
- public void setMasterMono(boolean mono) {
- IAudioService service = getService();
- try {
- service.setMasterMono(mono, getContext().getOpPackageName(),
- UserHandle.getCallingUserId());
- } catch (RemoteException e) {
- Log.e(TAG, "Dead object in setMasterMono", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -921,8 +893,7 @@
try {
return service.getRingerModeExternal();
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in getRingerMode", e);
- return RINGER_MODE_NORMAL;
+ throw e.rethrowFromSystemServer();
}
}
@@ -942,8 +913,7 @@
try {
return service.isValidRingerMode(ringerMode);
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in isValidRingerMode", e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -959,8 +929,7 @@
try {
return service.getStreamMaxVolume(streamType);
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in getStreamMaxVolume", e);
- return 0;
+ throw e.rethrowFromSystemServer();
}
}
@@ -977,8 +946,7 @@
try {
return service.getStreamMinVolume(streamType);
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in getStreamMinVolume", e);
- return 0;
+ throw e.rethrowFromSystemServer();
}
}
@@ -995,8 +963,7 @@
try {
return service.getStreamVolume(streamType);
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in getStreamVolume", e);
- return 0;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1010,8 +977,7 @@
try {
return service.getLastAudibleStreamVolume(streamType);
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in getLastAudibleStreamVolume", e);
- return 0;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1026,8 +992,7 @@
try {
return service.getUiSoundsStreamType();
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in getUiSoundsStreamType", e);
- return STREAM_RING;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1052,7 +1017,7 @@
try {
service.setRingerModeExternal(ringerMode, getContext().getOpPackageName());
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in setRingerMode", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1073,7 +1038,7 @@
try {
service.setStreamVolume(streamType, index, flags, getContext().getOpPackageName());
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in setStreamVolume", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1150,8 +1115,7 @@
try {
return service.isStreamMute(streamType);
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in isStreamMute", e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1165,23 +1129,7 @@
try {
return service.isMasterMute();
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in isMasterMute", e);
- return false;
- }
- }
-
- /**
- * get master mono state.
- *
- * @hide
- */
- public boolean isMasterMono() {
- IAudioService service = getService();
- try {
- return service.isMasterMono();
- } catch (RemoteException e) {
- Log.e(TAG, "Dead object in isMasterMono", e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1197,7 +1145,7 @@
try {
service.forceVolumeControlStream(streamType, mICallBack);
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in forceVolumeControlStream", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1225,8 +1173,7 @@
try {
return service.shouldVibrate(vibrateType);
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in shouldVibrate", e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1252,8 +1199,7 @@
try {
return service.getVibrateSetting(vibrateType);
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in getVibrateSetting", e);
- return VIBRATE_SETTING_OFF;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1280,7 +1226,7 @@
try {
service.setVibrateSetting(vibrateType, vibrateSetting);
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in setVibrateSetting", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1298,7 +1244,7 @@
try {
service.setSpeakerphoneOn(on);
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in setSpeakerphoneOn", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1312,8 +1258,7 @@
try {
return service.isSpeakerphoneOn();
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in isSpeakerphoneOn", e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1454,7 +1399,7 @@
service.startBluetoothSco(mICallBack,
getContext().getApplicationInfo().targetSdkVersion);
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in startBluetoothSco", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1478,7 +1423,7 @@
try {
service.startBluetoothScoVirtualCall(mICallBack);
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in startBluetoothScoVirtualCall", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1497,7 +1442,7 @@
try {
service.stopBluetoothSco(mICallBack);
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in stopBluetoothSco", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1515,7 +1460,7 @@
try {
service.setBluetoothScoOn(on);
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in setBluetoothScoOn", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1530,8 +1475,7 @@
try {
return service.isBluetoothScoOn();
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in isBluetoothScoOn", e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1603,7 +1547,7 @@
service.setMicrophoneMute(on, getContext().getOpPackageName(),
UserHandle.getCallingUserId());
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in setMicrophoneMute", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1636,7 +1580,7 @@
try {
service.setMode(mode, mICallBack, mApplicationContext.getOpPackageName());
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in setMode", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1652,8 +1596,7 @@
try {
return service.getMode();
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in getMode", e);
- return MODE_INVALID;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1790,8 +1733,7 @@
try {
return service.getCurrentAudioFocus() == AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE;
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in isAudioFocusExclusive()", e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1957,7 +1899,7 @@
try {
service.playSoundEffect(effectType);
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in playSoundEffect"+e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1992,7 +1934,7 @@
try {
service.playSoundEffect(effectType);
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in playSoundEffect"+e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2024,7 +1966,7 @@
try {
service.playSoundEffectVolume(effectType, volume);
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in playSoundEffect"+e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2046,7 +1988,7 @@
try {
service.loadSoundEffects();
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in loadSoundEffects"+e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2060,7 +2002,7 @@
try {
service.unloadSoundEffects();
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in unloadSoundEffects"+e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2205,9 +2147,10 @@
}
break;
case MSSG_RECORDING_CONFIG_CHANGE:
- final AudioRecordingCallback cb = (AudioRecordingCallback) msg.obj;
- if (cb != null) {
- cb.onRecordConfigChanged();
+ final RecordConfigChangeCallbackData cbData =
+ (RecordConfigChangeCallbackData) msg.obj;
+ if (cbData.mCb != null) {
+ cbData.mCb.onRecordConfigChanged(cbData.mConfigs);
}
break;
default:
@@ -2471,7 +2414,7 @@
getContext().getOpPackageName() /* package name */, flags,
ap != null ? ap.cb() : null);
} catch (RemoteException e) {
- Log.e(TAG, "Can't call requestAudioFocus() on AudioService:", e);
+ throw e.rethrowFromSystemServer();
}
return status;
}
@@ -2497,7 +2440,7 @@
AUDIOFOCUS_FLAG_LOCK,
null /* policy token */);
} catch (RemoteException e) {
- Log.e(TAG, "Can't call requestAudioFocusForCall() on AudioService:", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2513,7 +2456,7 @@
service.abandonAudioFocus(null, AudioSystem.IN_VOICE_COMM_FOCUS_ID,
null /*AudioAttributes, legacy behavior*/);
} catch (RemoteException e) {
- Log.e(TAG, "Can't call abandonAudioFocusForCall() on AudioService:", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2542,7 +2485,7 @@
status = service.abandonAudioFocus(mAudioFocusDispatcher,
getIdForAudioFocusListener(l), aa);
} catch (RemoteException e) {
- Log.e(TAG, "Can't call abandonAudioFocus() on AudioService:", e);
+ throw e.rethrowFromSystemServer();
}
return status;
}
@@ -2756,8 +2699,7 @@
}
// successful registration
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in registerAudioPolicyAsync()", e);
- return ERROR;
+ throw e.rethrowFromSystemServer();
}
return SUCCESS;
}
@@ -2776,7 +2718,7 @@
service.unregisterAudioPolicyAsync(policy.cb());
policy.setRegistration(null);
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in unregisterAudioPolicyAsync()", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2793,8 +2735,10 @@
public static abstract class AudioRecordingCallback {
/**
* Called whenever the device recording configuration has changed.
+ * @param configs array containing the results of
+ * {@link AudioManager#getActiveRecordConfigurations()}.
*/
- public void onRecordConfigChanged() {}
+ public void onRecordConfigChanged(AudioRecordConfiguration[] configs) {}
}
private static class AudioRecordingCallbackInfo {
@@ -2806,6 +2750,17 @@
}
}
+ private final static class RecordConfigChangeCallbackData {
+ final AudioRecordingCallback mCb;
+ final AudioRecordConfiguration[] mConfigs;
+
+ RecordConfigChangeCallbackData(AudioRecordingCallback cb,
+ AudioRecordConfiguration[] configs) {
+ mCb = cb;
+ mConfigs = configs;
+ }
+ }
+
/**
* Register a callback to be notified of audio recording changes through
* {@link AudioRecordingCallback}
@@ -2836,7 +2791,7 @@
try {
service.registerRecordingCallback(mRecCb);
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in registerRecordingCallback", e);
+ throw e.rethrowFromSystemServer();
}
}
} else {
@@ -2868,7 +2823,7 @@
try {
service.unregisterRecordingCallback(mRecCb);
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in unregisterRecordingCallback", e);
+ throw e.rethrowFromSystemServer();
}
}
} else {
@@ -2888,8 +2843,7 @@
try {
return service.getActiveRecordConfigurations();
} catch (RemoteException e) {
- Log.e(TAG, "Unable to retrieve active record configurations", e);
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2942,14 +2896,15 @@
private final IRecordingConfigDispatcher mRecCb = new IRecordingConfigDispatcher.Stub() {
- public void dispatchRecordingConfigChange() {
+ public void dispatchRecordingConfigChange(AudioRecordConfiguration[] configs) {
synchronized(mRecordCallbackLock) {
if (mRecordCallbackList != null) {
for (int i=0 ; i < mRecordCallbackList.size() ; i++) {
final AudioRecordingCallbackInfo arci = mRecordCallbackList.get(i);
if (arci.mHandler != null) {
final Message m = arci.mHandler.obtainMessage(
- MSSG_RECORDING_CONFIG_CHANGE/*what*/, arci.mCb/*obj*/);
+ MSSG_RECORDING_CONFIG_CHANGE/*what*/,
+ new RecordConfigChangeCallbackData(arci.mCb, configs)/*obj*/);
arci.mHandler.sendMessage(m);
}
}
@@ -2972,7 +2927,7 @@
try {
service.reloadAudioSettings();
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in reloadAudioSettings"+e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2987,7 +2942,7 @@
try {
service.avrcpSupportsAbsoluteVolume(address, support);
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in avrcpSupportsAbsoluteVolume", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -3281,7 +3236,7 @@
service.setWiredDeviceConnectionState(type, state, address, name,
mApplicationContext.getOpPackageName());
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in setWiredDeviceConnectionState "+e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -3303,7 +3258,7 @@
try {
delay = service.setBluetoothA2dpDeviceConnectionState(device, state, profile);
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in setBluetoothA2dpDeviceConnectionState "+e);
+ throw e.rethrowFromSystemServer();
}
return delay;
}
@@ -3313,7 +3268,7 @@
try {
return getService().getRingtonePlayer();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -3321,6 +3276,7 @@
* Used as a key for {@link #getProperty} to request the native or optimal output sample rate
* for this device's primary output stream, in decimal Hz.
*/
+ // FIXME Deprecate
public static final String PROPERTY_OUTPUT_SAMPLE_RATE =
"android.media.property.OUTPUT_SAMPLE_RATE";
@@ -3328,6 +3284,7 @@
* Used as a key for {@link #getProperty} to request the native or optimal output buffer size
* for this device's primary output stream, in decimal PCM frames.
*/
+ // FIXME Deprecate
public static final String PROPERTY_OUTPUT_FRAMES_PER_BUFFER =
"android.media.property.OUTPUT_FRAMES_PER_BUFFER";
@@ -3406,7 +3363,7 @@
try {
getService().setVolumeController(controller);
} catch (RemoteException e) {
- Log.w(TAG, "Error setting volume controller", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -3420,7 +3377,7 @@
try {
getService().notifyVolumeControllerVisible(controller, visible);
} catch (RemoteException e) {
- Log.w(TAG, "Error notifying about volume controller visibility", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -3432,8 +3389,7 @@
try {
return getService().isStreamAffectedByRingerMode(streamType);
} catch (RemoteException e) {
- Log.w(TAG, "Error calling isStreamAffectedByRingerMode", e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -3445,8 +3401,7 @@
try {
return getService().isStreamAffectedByMute(streamType);
} catch (RemoteException e) {
- Log.w(TAG, "Error calling isStreamAffectedByMute", e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -3458,7 +3413,7 @@
try {
getService().disableSafeMediaVolume(mApplicationContext.getOpPackageName());
} catch (RemoteException e) {
- Log.w(TAG, "Error disabling safe media volume", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -3470,7 +3425,7 @@
try {
getService().setRingerModeInternal(ringerMode, getContext().getOpPackageName());
} catch (RemoteException e) {
- Log.w(TAG, "Error calling setRingerModeInternal", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -3482,8 +3437,7 @@
try {
return getService().getRingerModeInternal();
} catch (RemoteException e) {
- Log.w(TAG, "Error calling getRingerModeInternal", e);
- return RINGER_MODE_NORMAL;
+ throw e.rethrowFromSystemServer();
}
}
@@ -3495,7 +3449,7 @@
try {
getService().setVolumePolicy(policy);
} catch (RemoteException e) {
- Log.w(TAG, "Error calling setVolumePolicy", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -3510,8 +3464,7 @@
try {
return getService().setHdmiSystemAudioSupported(on);
} catch (RemoteException e) {
- Log.w(TAG, "Error setting system audio mode", e);
- return AudioSystem.DEVICE_NONE;
+ throw e.rethrowFromSystemServer();
}
}
@@ -3525,8 +3478,7 @@
try {
return getService().isHdmiSystemAudioSupported();
} catch (RemoteException e) {
- Log.w(TAG, "Error querying system audio mode", e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
diff --git a/media/java/android/media/AudioPatch.java b/media/java/android/media/AudioPatch.java
index acadb41..6c70213 100644
--- a/media/java/android/media/AudioPatch.java
+++ b/media/java/android/media/AudioPatch.java
@@ -53,6 +53,13 @@
return mSinks;
}
+ /**
+ * Get the system unique patch ID.
+ */
+ public int id() {
+ return mHandle.id();
+ }
+
@Override
public String toString() {
StringBuilder s = new StringBuilder();
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index e342385..b8f0717 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -57,10 +57,6 @@
// Constants
//--------------------
- /** Minimum value for sample rate */
- private static final int SAMPLE_RATE_HZ_MIN = 4000;
- /** Maximum value for sample rate */
- private static final int SAMPLE_RATE_HZ_MAX = 192000;
/**
* indicates AudioRecord state is not successfully initialized.
@@ -168,8 +164,9 @@
//--------------------
/**
* The audio data sampling rate in Hz.
+ * Never {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED}.
*/
- private int mSampleRate;
+ private int mSampleRate; // initialized by all constructors via audioParamCheck()
/**
* The number of input audio channels (1 is mono, 2 is stereo)
*/
@@ -251,6 +248,9 @@
* @param sampleRateInHz the sample rate expressed in Hertz. 44100Hz is currently the only
* rate that is guaranteed to work on all devices, but other rates such as 22050,
* 16000, and 11025 may work on some devices.
+ * {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED} means to use a route-dependent value
+ * which is usually the sample rate of the source.
+ * {@link #getSampleRate()} can be used to retrieve the actual sample rate chosen.
* @param channelConfig describes the configuration of the audio channels.
* See {@link AudioFormat#CHANNEL_IN_MONO} and
* {@link AudioFormat#CHANNEL_IN_STEREO}. {@link AudioFormat#CHANNEL_IN_MONO} is guaranteed
@@ -337,16 +337,9 @@
mAudioAttributes = attributes;
}
- int rate = 0;
- if ((format.getPropertySetMask()
- & AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE) != 0)
- {
- rate = format.getSampleRate();
- } else {
- rate = AudioSystem.getPrimaryOutputSamplingRate();
- if (rate <= 0) {
- rate = 44100;
- }
+ int rate = format.getSampleRate();
+ if (rate == AudioFormat.SAMPLE_RATE_UNSPECIFIED) {
+ rate = 0;
}
int encoding = AudioFormat.ENCODING_DEFAULT;
@@ -373,19 +366,21 @@
audioBuffSizeCheck(bufferSizeInBytes);
+ int[] sampleRate = new int[] {mSampleRate};
int[] session = new int[1];
session[0] = sessionId;
//TODO: update native initialization when information about hardware init failure
// due to capture device already open is available.
int initResult = native_setup( new WeakReference<AudioRecord>(this),
- mAudioAttributes, mSampleRate, mChannelMask, mChannelIndexMask,
+ mAudioAttributes, sampleRate, mChannelMask, mChannelIndexMask,
mAudioFormat, mNativeBufferSizeInBytes,
- session, ActivityThread.currentOpPackageName());
+ session, ActivityThread.currentOpPackageName(), 0 /*nativeRecordInJavaObj*/);
if (initResult != SUCCESS) {
loge("Error code "+initResult+" when initializing native AudioRecord object.");
return; // with mState == STATE_UNINITIALIZED
}
+ mSampleRate = sampleRate[0];
mSessionId = session[0];
mState = STATE_INITIALIZED;
@@ -395,12 +390,32 @@
* A constructor which explicitly connects a Native (C++) AudioRecord. For use by
* the AudioRecordRoutingProxy subclass.
* @param nativeRecordInJavaObj A C/C++ pointer to a native AudioRecord
- * (associated with an OpenSL ES recorder).
+ * (associated with an OpenSL ES recorder). Note: the caller must ensure a correct
+ * value here as no error checking is or can be done.
*/
/*package*/ AudioRecord(long nativeRecordInJavaObj) {
- mNativeRecorderInJavaObj = nativeRecordInJavaObj;
+ int[] session = { 0 };
+ int[] rates = { 0 };
+ //TODO: update native initialization when information about hardware init failure
+ // due to capture device already open is available.
+ // Note that for this native_setup, we are providing an already created/initialized
+ // *Native* AudioRecord, so the attributes parameters to native_setup() are ignored.
+ int initResult = native_setup(new WeakReference<AudioRecord>(this),
+ null /*mAudioAttributes*/,
+ rates /*mSampleRates*/,
+ 0 /*mChannelMask*/,
+ 0 /*mChannelIndexMask*/,
+ 0 /*mAudioFormat*/,
+ 0 /*mNativeBufferSizeInBytes*/,
+ session,
+ ActivityThread.currentOpPackageName(),
+ nativeRecordInJavaObj);
+ if (initResult != SUCCESS) {
+ loge("Error code "+initResult+" when initializing native AudioRecord object.");
+ return; // with mState == STATE_UNINITIALIZED
+ }
- // other initialization here...
+ mSessionId = session[0];
mState = STATE_INITIALIZED;
}
@@ -623,6 +638,7 @@
return mask;
}
+
// postconditions:
// mRecordSource is valid
// mAudioFormat is valid
@@ -642,7 +658,9 @@
//--------------
// sample rate
- if ((sampleRateInHz < SAMPLE_RATE_HZ_MIN) || (sampleRateInHz > SAMPLE_RATE_HZ_MAX)) {
+ if ((sampleRateInHz < AudioFormat.SAMPLE_RATE_HZ_MIN ||
+ sampleRateInHz > AudioFormat.SAMPLE_RATE_HZ_MAX) &&
+ sampleRateInHz != AudioFormat.SAMPLE_RATE_UNSPECIFIED) {
throw new IllegalArgumentException(sampleRateInHz
+ "Hz is not a supported sample rate.");
}
@@ -714,7 +732,11 @@
// Getters
//--------------------
/**
- * Returns the configured audio data sample rate in Hz
+ * Returns the configured audio sink sample rate in Hz.
+ * The sink sample rate never changes after construction.
+ * If the constructor had a specific sample rate, then the sink sample rate is that value.
+ * If the constructor had {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED},
+ * then the sink sample rate is a route-dependent default value based on the source [sic].
*/
public int getSampleRate() {
return mSampleRate;
@@ -861,6 +883,7 @@
* See {@link #AudioRecord(int, int, int, int, int)} for more information on valid
* configuration values.
* @param sampleRateInHz the sample rate expressed in Hertz.
+ * {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED} is not permitted.
* @param channelConfig describes the configuration of the audio channels.
* See {@link AudioFormat#CHANNEL_IN_MONO} and
* {@link AudioFormat#CHANNEL_IN_STEREO}
@@ -1708,8 +1731,9 @@
private native final int native_setup(Object audiorecord_this,
Object /*AudioAttributes*/ attributes,
- int sampleRate, int channelMask, int channelIndexMask, int audioFormat,
- int buffSizeInBytes, int[] sessionId, String opPackageName);
+ int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,
+ int buffSizeInBytes, int[] sessionId, String opPackageName,
+ long nativeRecordInJavaObj);
// TODO remove: implementation calls directly into implementation of native_release()
private native final void native_finalize();
diff --git a/media/java/android/media/AudioRecordConfiguration.java b/media/java/android/media/AudioRecordConfiguration.java
index 69df88f..de78a5a 100644
--- a/media/java/android/media/AudioRecordConfiguration.java
+++ b/media/java/android/media/AudioRecordConfiguration.java
@@ -16,9 +16,14 @@
package android.media;
+import android.annotation.IntDef;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.Log;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
import java.util.Objects;
/**
@@ -27,7 +32,8 @@
* {@link AudioManager#getActiveRecordConfigurations()} method.
*
*/
-public class AudioRecordConfiguration implements Parcelable {
+public final class AudioRecordConfiguration implements Parcelable {
+ private final static String TAG = new String("AudioRecordConfiguration");
private final int mSessionId;
@@ -36,31 +42,33 @@
private final AudioFormat mDeviceFormat;
private final AudioFormat mClientFormat;
- private final AudioDeviceInfo mRecDevice;
-
- /**
- * @hide
- */
- public AudioRecordConfiguration(int session, int source) {
- mSessionId = session;
- mClientSource = source;
- mDeviceFormat = new AudioFormat.Builder().build();
- mClientFormat = new AudioFormat.Builder().build();
- mRecDevice = null;
- }
+ private final int mPatchHandle;
/**
* @hide
*/
public AudioRecordConfiguration(int session, int source, AudioFormat devFormat,
- AudioFormat clientFormat, AudioDeviceInfo device) {
+ AudioFormat clientFormat, int patchHandle) {
mSessionId = session;
mClientSource = source;
mDeviceFormat = devFormat;
mClientFormat = clientFormat;
- mRecDevice = device;
+ mPatchHandle = patchHandle;
}
+ /** @hide */
+ @IntDef({
+ MediaRecorder.AudioSource.DEFAULT,
+ MediaRecorder.AudioSource.VOICE_UPLINK,
+ MediaRecorder.AudioSource.VOICE_DOWNLINK,
+ MediaRecorder.AudioSource.VOICE_CALL,
+ MediaRecorder.AudioSource.CAMCORDER,
+ MediaRecorder.AudioSource.VOICE_RECOGNITION,
+ MediaRecorder.AudioSource.VOICE_COMMUNICATION
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AudioSource {}
+
/**
* Returns the audio source being used for the recording.
* @return one of {@link MediaRecorder.AudioSource#MIC},
@@ -71,7 +79,7 @@
* {@link MediaRecorder.AudioSource#VOICE_RECOGNITION},
* {@link MediaRecorder.AudioSource#VOICE_COMMUNICATION}.
*/
- public int getClientAudioSource() { return mClientSource; }
+ public @AudioSource int getClientAudioSource() { return mClientSource; }
/**
* Returns the session number of the recording, see {@link AudioRecord#getAudioSessionId()}.
@@ -95,10 +103,38 @@
public AudioFormat getClientFormat() { return mClientFormat; }
/**
- * Returns the audio input device used for this recording.
- * @return the audio recording device
+ * Returns information about the audio input device used for this recording.
+ * @return the audio recording device or null if this information cannot be retrieved
*/
- public AudioDeviceInfo getAudioDevice() { return mRecDevice; }
+ public AudioDeviceInfo getAudioDevice() {
+ // build the AudioDeviceInfo from the patch handle
+ ArrayList<AudioPatch> patches = new ArrayList<AudioPatch>();
+ if (AudioManager.listAudioPatches(patches) != AudioManager.SUCCESS) {
+ Log.e(TAG, "Error retrieving list of audio patches");
+ return null;
+ }
+ for (int i = 0 ; i < patches.size() ; i++) {
+ final AudioPatch patch = patches.get(i);
+ if (patch.id() == mPatchHandle) {
+ final AudioPortConfig[] sources = patch.sources();
+ if ((sources != null) && (sources.length > 0)) {
+ // not supporting multiple sources, so just look at the first source
+ final int devId = sources[0].port().id();
+ final AudioDeviceInfo[] devices =
+ AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_INPUTS);
+ for (int j = 0; j < devices.length; j++) {
+ if (devices[j].getId() == devId) {
+ return devices[j];
+ }
+ }
+ }
+ // patch handle is unique, there won't be another with the same handle
+ break;
+ }
+ }
+ Log.e(TAG, "Couldn't find device for recording, did recording end already?");
+ return null;
+ }
public static final Parcelable.Creator<AudioRecordConfiguration> CREATOR
= new Parcelable.Creator<AudioRecordConfiguration>() {
@@ -129,14 +165,17 @@
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mSessionId);
dest.writeInt(mClientSource);
+ mClientFormat.writeToParcel(dest, 0);
+ mDeviceFormat.writeToParcel(dest, 0);
+ dest.writeInt(mPatchHandle);
}
private AudioRecordConfiguration(Parcel in) {
mSessionId = in.readInt();
mClientSource = in.readInt();
- mDeviceFormat = new AudioFormat.Builder().build();
- mClientFormat = new AudioFormat.Builder().build();
- mRecDevice = null;
+ mClientFormat = AudioFormat.CREATOR.createFromParcel(in);
+ mDeviceFormat = AudioFormat.CREATOR.createFromParcel(in);
+ mPatchHandle = in.readInt();
}
@Override
@@ -144,8 +183,12 @@
if (this == o) return true;
if (o == null || !(o instanceof AudioRecordConfiguration)) return false;
- final AudioRecordConfiguration that = (AudioRecordConfiguration) o;
- return ((mSessionId == that.mSessionId)
- && (mClientSource == that.mClientSource));
+ AudioRecordConfiguration that = (AudioRecordConfiguration) o;
+
+ return ((mSessionId == that.mSessionId)
+ && (mClientSource == that.mClientSource)
+ && (mPatchHandle == that.mPatchHandle)
+ && (mClientFormat.equals(that.mClientFormat))
+ && (mDeviceFormat.equals(that.mDeviceFormat)));
}
}
\ No newline at end of file
diff --git a/media/java/android/media/AudioRouting.java b/media/java/android/media/AudioRouting.java
index 2161cf3..41f92d4 100644
--- a/media/java/android/media/AudioRouting.java
+++ b/media/java/android/media/AudioRouting.java
@@ -41,6 +41,14 @@
public AudioDeviceInfo getPreferredDevice();
/**
+ * Returns an {@link AudioDeviceInfo} identifying the current routing of this
+ * AudioTrack/AudioRecord.
+ * Note: The query is only valid if the AudioTrack/AudioRecord is currently playing.
+ * If it is not, <code>getRoutedDevice()</code> will return null.
+ */
+ public AudioDeviceInfo getRoutedDevice();
+
+ /**
* Adds an {@link AudioRouting.OnRoutingChangedListener} to receive notifications of routing
* changes on this AudioTrack/AudioRecord.
* @param listener The {@link AudioRouting.OnRoutingChangedListener} interface to receive
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index aa0d78d..f597440 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -273,7 +273,23 @@
*/
public interface AudioRecordingCallback
{
- void onRecordingConfigurationChanged(int event, int session, int source);
+ /**
+ * Callback for recording activity notifications events
+ * @param event
+ * @param session
+ * @param source
+ * @param recordingFormat an array of ints containing respectively the client and device
+ * recording configurations (2*3 ints), followed by the patch handle:
+ * index 0: client format
+ * 1: client channel mask
+ * 2: client sample rate
+ * 3: device format
+ * 4: device channel mask
+ * 5: device sample rate
+ * 6: patch handle
+ */
+ void onRecordingConfigurationChanged(int event, int session, int source,
+ int[] recordingFormat);
}
private static AudioRecordingCallback sRecordingCallback;
@@ -285,13 +301,23 @@
}
}
- private static void recordingCallbackFromNative(int event, int session, int source) {
+ /**
+ * Callback from native for recording configuration updates.
+ * @param event
+ * @param session
+ * @param source
+ * @param recordingFormat see
+ * {@link AudioRecordingCallback#onRecordingConfigurationChanged(int, int, int, int[])} for
+ * the description of the record format.
+ */
+ private static void recordingCallbackFromNative(int event, int session, int source,
+ int[] recordingFormat) {
AudioRecordingCallback cb = null;
synchronized (AudioSystem.class) {
cb = sRecordingCallback;
}
if (cb != null) {
- cb.onRecordingConfigurationChanged(event, session, source);
+ cb.onRecordingConfigurationChanged(event, session, source, recordingFormat);
}
}
@@ -346,6 +372,7 @@
public static final int DEVICE_OUT_AUX_LINE = 0x200000;
public static final int DEVICE_OUT_SPEAKER_SAFE = 0x400000;
public static final int DEVICE_OUT_IP = 0x800000;
+ public static final int DEVICE_OUT_BUS = 0x1000000;
public static final int DEVICE_OUT_DEFAULT = DEVICE_BIT_DEFAULT;
@@ -373,6 +400,7 @@
DEVICE_OUT_AUX_LINE |
DEVICE_OUT_SPEAKER_SAFE |
DEVICE_OUT_IP |
+ DEVICE_OUT_BUS |
DEVICE_OUT_DEFAULT);
public static final int DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP |
DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
@@ -412,6 +440,7 @@
public static final int DEVICE_IN_BLUETOOTH_A2DP = DEVICE_BIT_IN | 0x20000;
public static final int DEVICE_IN_LOOPBACK = DEVICE_BIT_IN | 0x40000;
public static final int DEVICE_IN_IP = DEVICE_BIT_IN | 0x80000;
+ public static final int DEVICE_IN_BUS = DEVICE_BIT_IN | 0x100000;
public static final int DEVICE_IN_DEFAULT = DEVICE_BIT_IN | DEVICE_BIT_DEFAULT;
public static final int DEVICE_IN_ALL = (DEVICE_IN_COMMUNICATION |
@@ -434,6 +463,7 @@
DEVICE_IN_BLUETOOTH_A2DP |
DEVICE_IN_LOOPBACK |
DEVICE_IN_IP |
+ DEVICE_IN_BUS |
DEVICE_IN_DEFAULT);
public static final int DEVICE_IN_ALL_SCO = DEVICE_IN_BLUETOOTH_SCO_HEADSET;
public static final int DEVICE_IN_ALL_USB = (DEVICE_IN_USB_ACCESSORY |
@@ -469,6 +499,7 @@
public static final String DEVICE_OUT_AUX_LINE_NAME = "aux_line";
public static final String DEVICE_OUT_SPEAKER_SAFE_NAME = "speaker_safe";
public static final String DEVICE_OUT_IP_NAME = "ip";
+ public static final String DEVICE_OUT_BUS_NAME = "bus";
public static final String DEVICE_IN_COMMUNICATION_NAME = "communication";
public static final String DEVICE_IN_AMBIENT_NAME = "ambient";
@@ -490,6 +521,7 @@
public static final String DEVICE_IN_BLUETOOTH_A2DP_NAME = "bt_a2dp";
public static final String DEVICE_IN_LOOPBACK_NAME = "loopback";
public static final String DEVICE_IN_IP_NAME = "ip";
+ public static final String DEVICE_IN_BUS_NAME = "bus";
public static String getOutputDeviceName(int device)
{
@@ -542,6 +574,8 @@
return DEVICE_OUT_SPEAKER_SAFE_NAME;
case DEVICE_OUT_IP:
return DEVICE_OUT_IP_NAME;
+ case DEVICE_OUT_BUS:
+ return DEVICE_OUT_BUS_NAME;
case DEVICE_OUT_DEFAULT:
default:
return Integer.toString(device);
@@ -591,6 +625,8 @@
return DEVICE_IN_LOOPBACK_NAME;
case DEVICE_IN_IP:
return DEVICE_IN_IP_NAME;
+ case DEVICE_IN_BUS:
+ return DEVICE_IN_BUS_NAME;
case DEVICE_IN_DEFAULT:
default:
return Integer.toString(device);
@@ -602,7 +638,7 @@
public static final int PHONE_STATE_RINGING = 1;
public static final int PHONE_STATE_INCALL = 2;
- // device categories config for setForceUse, must match AudioSystem::forced_config
+ // device categories config for setForceUse, must match audio_policy_forced_cfg_t
public static final int FORCE_NONE = 0;
public static final int FORCE_SPEAKER = 1;
public static final int FORCE_HEADPHONES = 2;
@@ -616,17 +652,20 @@
public static final int FORCE_NO_BT_A2DP = 10;
public static final int FORCE_SYSTEM_ENFORCED = 11;
public static final int FORCE_HDMI_SYSTEM_AUDIO_ENFORCED = 12;
- private static final int NUM_FORCE_CONFIG = 13;
+ public static final int FORCE_ENCODED_SURROUND_NEVER = 13;
+ public static final int FORCE_ENCODED_SURROUND_ALWAYS = 14;
+ public static final int NUM_FORCE_CONFIG = 15;
public static final int FORCE_DEFAULT = FORCE_NONE;
- // usage for setForceUse, must match AudioSystem::force_use
+ // usage for setForceUse, must match audio_policy_force_use_t
public static final int FOR_COMMUNICATION = 0;
public static final int FOR_MEDIA = 1;
public static final int FOR_RECORD = 2;
public static final int FOR_DOCK = 3;
public static final int FOR_SYSTEM = 4;
public static final int FOR_HDMI_SYSTEM_AUDIO = 5;
- private static final int NUM_FORCE_USE = 6;
+ public static final int FOR_ENCODED_SURROUND = 6;
+ private static final int NUM_FORCE_USE = 7;
// usage for AudioRecord.startRecordingSync(), must match AudioSystem::sync_event_t
public static final int SYNC_EVENT_NONE = 0;
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 6fc2f87..c48bfc5 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -91,11 +91,6 @@
*/
private static final float GAIN_MAX = 1.0f;
- /** Minimum value for sample rate */
- private static final int SAMPLE_RATE_HZ_MIN = 4000;
- /** Maximum value for sample rate */
- private static final int SAMPLE_RATE_HZ_MAX = 192000;
-
/** Maximum value for AudioTrack channel count
* @hide public for MediaCode only, do not un-hide or change to a numeric literal
*/
@@ -254,6 +249,7 @@
private final Looper mInitializationLooper;
/**
* The audio data source sampling rate in Hz.
+ * Never {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED}.
*/
private int mSampleRate; // initialized by all constructors via audioParamCheck()
/**
@@ -340,6 +336,9 @@
* {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC},
* {@link AudioManager#STREAM_ALARM}, and {@link AudioManager#STREAM_NOTIFICATION}.
* @param sampleRateInHz the initial source sample rate expressed in Hz.
+ * {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED} means to use a route-dependent value
+ * which is usually the sample rate of the sink.
+ * {@link #getSampleRate()} can be used to retrieve the actual sample rate chosen.
* @param channelConfig describes the configuration of the audio channels.
* See {@link AudioFormat#CHANNEL_OUT_MONO} and
* {@link AudioFormat#CHANNEL_OUT_STEREO}
@@ -389,6 +388,8 @@
* {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC},
* {@link AudioManager#STREAM_ALARM}, and {@link AudioManager#STREAM_NOTIFICATION}.
* @param sampleRateInHz the initial source sample rate expressed in Hz.
+ * {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED} means to use a route-dependent value
+ * which is usually the sample rate of the sink.
* @param channelConfig describes the configuration of the audio channels.
* See {@link AudioFormat#CHANNEL_OUT_MONO} and
* {@link AudioFormat#CHANNEL_OUT_STEREO}
@@ -461,16 +462,11 @@
looper = Looper.getMainLooper();
}
- int rate = 0;
- if ((format.getPropertySetMask() & AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE) != 0)
- {
- rate = format.getSampleRate();
- } else {
- rate = AudioSystem.getPrimaryOutputSamplingRate();
- if (rate <= 0) {
- rate = 44100;
- }
+ int rate = format.getSampleRate();
+ if (rate == AudioFormat.SAMPLE_RATE_UNSPECIFIED) {
+ rate = 0;
}
+
int channelIndexMask = 0;
if ((format.getPropertySetMask()
& AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_INDEX_MASK) != 0) {
@@ -503,17 +499,19 @@
throw new IllegalArgumentException("Invalid audio session ID: "+sessionId);
}
+ int[] sampleRate = new int[] {mSampleRate};
int[] session = new int[1];
session[0] = sessionId;
// native initialization
int initResult = native_setup(new WeakReference<AudioTrack>(this), mAttributes,
- mSampleRate, mChannelMask, mChannelIndexMask, mAudioFormat,
- mNativeBufferSizeInBytes, mDataLoadMode, session);
+ sampleRate, mChannelMask, mChannelIndexMask, mAudioFormat,
+ mNativeBufferSizeInBytes, mDataLoadMode, session, 0 /*nativeTrackInJavaObj*/);
if (initResult != SUCCESS) {
loge("Error code "+initResult+" when initializing AudioTrack.");
return; // with mState == STATE_UNINITIALIZED
}
+ mSampleRate = sampleRate[0];
mSessionId = session[0];
if (mDataLoadMode == MODE_STATIC) {
@@ -530,8 +528,6 @@
* (associated with an OpenSL ES player).
*/
/*package*/ AudioTrack(long nativeTrackInJavaObj) {
- mNativeTrackInJavaObj = nativeTrackInJavaObj;
-
// "final"s
mAttributes = null;
mAppOps = null;
@@ -544,6 +540,26 @@
mInitializationLooper = looper;
// other initialization...
+ // Note that for this native_setup, we are providing an already created/initialized
+ // *Native* AudioTrack, so the attributes parameters to native_setup() are ignored.
+ int[] session = { 0 };
+ int[] rates = { 0 };
+ int initResult = native_setup(new WeakReference<AudioTrack>(this),
+ null /*mAttributes - NA*/,
+ rates /*sampleRate - NA*/,
+ 0 /*mChannelMask - NA*/,
+ 0 /*mChannelIndexMask - NA*/,
+ 0 /*mAudioFormat - NA*/,
+ 0 /*mNativeBufferSizeInBytes - NA*/,
+ 0 /*mDataLoadMode - NA*/,
+ session,
+ nativeTrackInJavaObj);
+ if (initResult != SUCCESS) {
+ loge("Error code "+initResult+" when initializing AudioTrack.");
+ return; // with mState == STATE_UNINITIALIZED
+ }
+
+ mSessionId = session[0];
mState = STATE_INITIALIZED;
}
@@ -712,7 +728,7 @@
if (mFormat == null) {
mFormat = new AudioFormat.Builder()
.setChannelMask(AudioFormat.CHANNEL_OUT_STEREO)
- .setSampleRate(AudioSystem.getPrimaryOutputSamplingRate())
+ //.setSampleRate(AudioFormat.SAMPLE_RATE_UNSPECIFIED)
.setEncoding(AudioFormat.ENCODING_DEFAULT)
.build();
}
@@ -762,7 +778,9 @@
int audioFormat, int mode) {
//--------------
// sample rate, note these values are subject to change
- if (sampleRateInHz < SAMPLE_RATE_HZ_MIN || sampleRateInHz > SAMPLE_RATE_HZ_MAX) {
+ if ((sampleRateInHz < AudioFormat.SAMPLE_RATE_HZ_MIN ||
+ sampleRateInHz > AudioFormat.SAMPLE_RATE_HZ_MAX) &&
+ sampleRateInHz != AudioFormat.SAMPLE_RATE_UNSPECIFIED) {
throw new IllegalArgumentException(sampleRateInHz
+ "Hz is not a supported sample rate.");
}
@@ -948,7 +966,13 @@
}
/**
- * Returns the configured audio data sample rate in Hz
+ * Returns the configured audio source sample rate in Hz.
+ * The initial source sample rate depends on the constructor parameters,
+ * but the source sample rate may change if {@link #setPlaybackRate(int)} is called.
+ * If the constructor had a specific sample rate, then the initial sink sample rate is that
+ * value.
+ * If the constructor had {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED},
+ * then the initial sink sample rate is a route-dependent default value based on the source [sic].
*/
public int getSampleRate() {
return mSampleRate;
@@ -1190,13 +1214,12 @@
* An underrun occurs if the application does not write audio
* data quickly enough, causing the buffer to underflow
* and a potential audio glitch or pop.
+ * <p>
* Underruns are less likely when buffer sizes are large.
- * <p> Though the "int" type is signed 32-bits, the value should be reinterpreted
- * as if it is unsigned 32-bits.
- * That is, the next position after 0x7FFFFFFF is (int) 0x80000000.
- * This is a continuously advancing counter. It can wrap around to zero
- * if there are too many underruns. If there were, for example, 68 underruns per
- * second then the counter would wrap in 2 years.
+ * It may be possible to eliminate underruns by recreating the AudioTrack with
+ * a larger buffer.
+ * Or by using {@link #setBufferSizeInFrames(int)} to dynamically increase the
+ * effective size of the buffer.
*/
public int getUnderrunCount() {
return native_get_underrun_count();
@@ -1218,6 +1241,7 @@
* to a higher value than the initial source sample rate, be sure to configure the buffer size
* based on the highest planned sample rate.
* @param sampleRateInHz the source sample rate expressed in Hz.
+ * {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED} is not permitted.
* @param channelConfig describes the configuration of the audio channels.
* See {@link AudioFormat#CHANNEL_OUT_MONO} and
* {@link AudioFormat#CHANNEL_OUT_STEREO}
@@ -1255,7 +1279,9 @@
}
// sample rate, note these values are subject to change
- if ( (sampleRateInHz < SAMPLE_RATE_HZ_MIN) || (sampleRateInHz > SAMPLE_RATE_HZ_MAX) ) {
+ // Note: AudioFormat.SAMPLE_RATE_UNSPECIFIED is not allowed
+ if ( (sampleRateInHz < AudioFormat.SAMPLE_RATE_HZ_MIN) ||
+ (sampleRateInHz > AudioFormat.SAMPLE_RATE_HZ_MAX) ) {
loge("getMinBufferSize(): " + sampleRateInHz + " Hz is not a supported sample rate.");
return ERROR_BAD_VALUE;
}
@@ -2763,8 +2789,8 @@
// AudioAttributes.USAGE_MEDIA will map to AudioManager.STREAM_MUSIC
private native final int native_setup(Object /*WeakReference<AudioTrack>*/ audiotrack_this,
Object /*AudioAttributes*/ attributes,
- int sampleRate, int channelMask, int channelIndexMask, int audioFormat,
- int buffSizeInBytes, int mode, int[] sessionId);
+ int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,
+ int buffSizeInBytes, int mode, int[] sessionId, long nativeAudioTrack);
private native final void native_finalize();
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 7fb67ee..1a387be 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -16,22 +16,51 @@
package android.media;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
+import android.util.Log;
+import android.util.Pair;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.EOFException;
+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.RandomAccessFile;
-import java.util.regex.Pattern;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteOrder;
+import java.nio.charset.Charset;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
+import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;
+import java.util.regex.Pattern;
+
+import libcore.io.IoUtils;
+import libcore.io.Streams;
/**
* This is a class for reading and writing Exif tags in a JPEG file or a RAW image file.
* <p>
* Supported formats are: JPEG, DNG, CR2, NEF, NRW, ARW, RW2, ORF and RAF.
+ * <p>
+ * Attribute mutation is supported for JPEG image files.
*/
public class ExifInterface {
+ private static final String TAG = "ExifInterface";
+ private static final boolean DEBUG = false;
+
// The Exif tag names
/** Type is int. */
public static final String TAG_ORIENTATION = "Orientation";
@@ -97,6 +126,20 @@
public static final String TAG_FOCAL_LENGTH = "FocalLength";
/** Type is String. Name of GPS processing method used for location finding. */
public static final String TAG_GPS_PROCESSING_METHOD = "GPSProcessingMethod";
+ /** Type is double. */
+ public static final String TAG_DIGITAL_ZOOM_RATIO = "DigitalZoomRatio";
+ /** Type is double. */
+ public static final String TAG_SUBJECT_DISTANCE = "SubjectDistance";
+ /** Type is double. */
+ public static final String TAG_EXPOSURE_BIAS_VALUE = "ExposureBiasValue";
+ /** Type is int. */
+ public static final String TAG_LIGHT_SOURCE = "LightSource";
+ /** Type is int. */
+ public static final String TAG_METERING_MODE = "MeteringMode";
+ /** Type is int. */
+ public static final String TAG_EXPOSURE_PROGRAM = "ExposureProgram";
+ /** Type is int. */
+ public static final String TAG_EXPOSURE_MODE = "ExposureMode";
// Private tags used for thumbnail information.
private static final String TAG_HAS_THUMBNAIL = "hasThumbnail";
@@ -119,30 +162,321 @@
// Constants used for white balance
public static final int WHITEBALANCE_AUTO = 0;
public static final int WHITEBALANCE_MANUAL = 1;
+
private static SimpleDateFormat sFormatter;
+ // See Exchangeable image file format for digital still cameras: Exif version 2.2.
+ // The following values are for parsing EXIF data area. There are tag groups in EXIF data area.
+ // They are called "Image File Directory". They have multiple data formats to cover various
+ // image metadata from GPS longitude to camera model name.
+
+ // Types of Exif byte alignments (see JEITA CP-3451 page 10)
+ private static final short BYTE_ALIGN_II = 0x4949; // II: Intel order
+ private static final short BYTE_ALIGN_MM = 0x4d4d; // MM: Motorola order
+
+ // Formats for the value in IFD entry (See TIFF 6.0 spec Types page 15).
+ private static final int IFD_FORMAT_BYTE = 1;
+ private static final int IFD_FORMAT_STRING = 2;
+ private static final int IFD_FORMAT_USHORT = 3;
+ private static final int IFD_FORMAT_ULONG = 4;
+ private static final int IFD_FORMAT_URATIONAL = 5;
+ private static final int IFD_FORMAT_SBYTE = 6;
+ private static final int IFD_FORMAT_UNDEFINED = 7;
+ private static final int IFD_FORMAT_SSHORT = 8;
+ private static final int IFD_FORMAT_SLONG = 9;
+ private static final int IFD_FORMAT_SRATIONAL = 10;
+ private static final int IFD_FORMAT_SINGLE = 11;
+ private static final int IFD_FORMAT_DOUBLE = 12;
+ // Sizes of the components of each IFD value format
+ private static final int[] IFD_FORMAT_BYTES_PER_FORMAT = new int[] {
+ 0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8
+ };
+ private static final byte[] EXIF_ASCII_PREFIX = new byte[] {
+ 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0
+ };
+
+ // A class for indicating EXIF tag.
+ private static class ExifTag {
+ public final int number;
+ public final String name;
+
+ private ExifTag(String name, int number) {
+ this.name = name;
+ this.number = number;
+ }
+ }
+
+ // Primary image IFD TIFF tags (See JEITA CP-3451 Table 14. page 54).
+ private static final ExifTag[] IFD_TIFF_TAGS = new ExifTag[] {
+ new ExifTag("ImageWidth", 256),
+ new ExifTag("ImageLength", 257),
+ new ExifTag("BitsPerSample", 258),
+ new ExifTag("Compression", 259),
+ new ExifTag("PhotometricInterpretation", 262),
+ new ExifTag("ImageDescription", 270),
+ new ExifTag("Make", 271),
+ new ExifTag("Model", 272),
+ new ExifTag("StripOffsets", 273),
+ new ExifTag("Orientation", 274),
+ new ExifTag("SamplesPerPixel", 277),
+ new ExifTag("RowsPerStrip", 278),
+ new ExifTag("StripByteCounts", 279),
+ new ExifTag("XResolution", 282),
+ new ExifTag("YResolution", 283),
+ new ExifTag("PlanarConfiguration", 284),
+ new ExifTag("ResolutionUnit", 296),
+ new ExifTag("TransferFunction", 301),
+ new ExifTag("Software", 305),
+ new ExifTag("DateTime", 306),
+ new ExifTag("Artist", 315),
+ new ExifTag("WhitePoint", 318),
+ new ExifTag("PrimaryChromaticities", 319),
+ new ExifTag("JPEGInterchangeFormat", 513),
+ new ExifTag("JPEGInterchangeFormatLength", 514),
+ new ExifTag("YCbCrCoefficients", 529),
+ new ExifTag("YCbCrSubSampling", 530),
+ new ExifTag("YCbCrPositioning", 531),
+ new ExifTag("ReferenceBlackWhite", 532),
+ new ExifTag("Copyright", 33432),
+ new ExifTag("ExifIFDPointer", 34665),
+ new ExifTag("GPSInfoIFDPointer", 34853),
+ };
+ // Primary image IFD Exif Private tags (See JEITA CP-3451 Table 15. page 55).
+ private static final ExifTag[] IFD_EXIF_TAGS = new ExifTag[] {
+ new ExifTag("ExposureTime", 33434),
+ new ExifTag("FNumber", 33437),
+ new ExifTag("ExposureProgram", 34850),
+ new ExifTag("SpectralSensitivity", 34852),
+ new ExifTag("ISOSpeedRatings", 34855),
+ new ExifTag("OECF", 34856),
+ new ExifTag("ExifVersion", 36864),
+ new ExifTag("DateTimeOriginal", 36867),
+ new ExifTag("DateTimeDigitized", 36868),
+ new ExifTag("ComponentsConfiguration", 37121),
+ new ExifTag("CompressedBitsPerPixel", 37122),
+ new ExifTag("ShutterSpeedValue", 37377),
+ new ExifTag("ApertureValue", 37378),
+ new ExifTag("BrightnessValue", 37379),
+ new ExifTag("ExposureBiasValue", 37380),
+ new ExifTag("MaxApertureValue", 37381),
+ new ExifTag("SubjectDistance", 37382),
+ new ExifTag("MeteringMode", 37383),
+ new ExifTag("LightSource", 37384),
+ new ExifTag("Flash", 37385),
+ new ExifTag("FocalLength", 37386),
+ new ExifTag("SubjectArea", 37396),
+ new ExifTag("MakerNote", 37500),
+ new ExifTag("UserComment", 37510),
+ new ExifTag("SubSecTime", 37520),
+ new ExifTag("SubSecTimeOriginal", 37521),
+ new ExifTag("SubSecTimeDigitized", 37522),
+ new ExifTag("FlashpixVersion", 40960),
+ new ExifTag("ColorSpace", 40961),
+ new ExifTag("PixelXDimension", 40962),
+ new ExifTag("PixelYDimension", 40963),
+ new ExifTag("RelatedSoundFile", 40964),
+ new ExifTag("InteroperabilityIFDPointer", 40965),
+ new ExifTag("FlashEnergy", 41483),
+ new ExifTag("SpatialFrequencyResponse", 41484),
+ new ExifTag("FocalPlaneXResolution", 41486),
+ new ExifTag("FocalPlaneYResolution", 41487),
+ new ExifTag("FocalPlaneResolutionUnit", 41488),
+ new ExifTag("SubjectLocation", 41492),
+ new ExifTag("ExposureIndex", 41493),
+ new ExifTag("SensingMethod", 41495),
+ new ExifTag("FileSource", 41728),
+ new ExifTag("SceneType", 41729),
+ new ExifTag("CFAPattern", 41730),
+ new ExifTag("CustomRendered", 41985),
+ new ExifTag("ExposureMode", 41986),
+ new ExifTag("WhiteBalance", 41987),
+ new ExifTag("DigitalZoomRatio", 41988),
+ new ExifTag("FocalLengthIn35mmFilm", 41989),
+ new ExifTag("SceneCaptureType", 41990),
+ new ExifTag("GainControl", 41991),
+ new ExifTag("Contrast", 41992),
+ new ExifTag("Saturation", 41993),
+ new ExifTag("Sharpness", 41994),
+ new ExifTag("DeviceSettingDescription", 41995),
+ new ExifTag("SubjectDistanceRange", 41996),
+ new ExifTag("ImageUniqueID", 42016),
+ };
+ // Primary image IFD GPS Info tags (See JEITA CP-3451 Table 16. page 56).
+ private static final ExifTag[] IFD_GPS_TAGS = new ExifTag[] {
+ new ExifTag("GPSVersionID", 0),
+ new ExifTag("GPSLatitudeRef", 1),
+ new ExifTag("GPSLatitude", 2),
+ new ExifTag("GPSLongitudeRef", 3),
+ new ExifTag("GPSLongitude", 4),
+ new ExifTag("GPSAltitudeRef", 5),
+ new ExifTag("GPSAltitude", 6),
+ new ExifTag("GPSTimeStamp", 7),
+ new ExifTag("GPSSatellites", 8),
+ new ExifTag("GPSStatus", 9),
+ new ExifTag("GPSMeasureMode", 10),
+ new ExifTag("GPSDOP", 11),
+ new ExifTag("GPSSpeedRef", 12),
+ new ExifTag("GPSSpeed", 13),
+ new ExifTag("GPSTrackRef", 14),
+ new ExifTag("GPSTrack", 15),
+ new ExifTag("GPSImgDirectionRef", 16),
+ new ExifTag("GPSImgDirection", 17),
+ new ExifTag("GPSMapDatum", 18),
+ new ExifTag("GPSDestLatitudeRef", 19),
+ new ExifTag("GPSDestLatitude", 20),
+ new ExifTag("GPSDestLongitudeRef", 21),
+ new ExifTag("GPSDestLongitude", 22),
+ new ExifTag("GPSDestBearingRef", 23),
+ new ExifTag("GPSDestBearing", 24),
+ new ExifTag("GPSDestDistanceRef", 25),
+ new ExifTag("GPSDestDistance", 26),
+ new ExifTag("GPSProcessingMethod", 27),
+ new ExifTag("GPSAreaInformation", 28),
+ new ExifTag("GPSDateStamp", 29),
+ new ExifTag("GPSDifferential", 30),
+ };
+ // Primary image IFD Interoperability tag (See JEITA CP-3451 Table 17. page 56).
+ private static final ExifTag[] IFD_INTEROPERABILITY_TAGS = new ExifTag[] {
+ new ExifTag("InteroperabilityIndex", 1),
+ };
+ // IFD Thumbnail tags (See JEITA CP-3451 Table 18. page 57).
+ private static final ExifTag[] IFD_THUMBNAIL_TAGS = new ExifTag[] {
+ new ExifTag("ThumbnailImageWidth", 256),
+ new ExifTag("ThumbnailImageLength", 257),
+ new ExifTag("BitsPerSample", 258),
+ new ExifTag("Compression", 259),
+ new ExifTag("PhotometricInterpretation", 262),
+ new ExifTag("ImageDescription", 270),
+ new ExifTag("Make", 271),
+ new ExifTag("Model", 272),
+ new ExifTag("StripOffsets", 273),
+ new ExifTag("Orientation", 274),
+ new ExifTag("SamplesPerPixel", 277),
+ new ExifTag("RowsPerStrip", 278),
+ new ExifTag("StripByteCounts", 279),
+ new ExifTag("XResolution", 282),
+ new ExifTag("YResolution", 283),
+ new ExifTag("PlanarConfiguration", 284),
+ new ExifTag("ResolutionUnit", 296),
+ new ExifTag("TransferFunction", 301),
+ new ExifTag("Software", 305),
+ new ExifTag("DateTime", 306),
+ new ExifTag("Artist", 315),
+ new ExifTag("WhitePoint", 318),
+ new ExifTag("PrimaryChromaticities", 319),
+ new ExifTag("JPEGInterchangeFormat", 513),
+ new ExifTag("JPEGInterchangeFormatLength", 514),
+ new ExifTag("YCbCrCoefficients", 529),
+ new ExifTag("YCbCrSubSampling", 530),
+ new ExifTag("YCbCrPositioning", 531),
+ new ExifTag("ReferenceBlackWhite", 532),
+ new ExifTag("Copyright", 33432),
+ new ExifTag("ExifIFDPointer", 34665),
+ new ExifTag("GPSInfoIFDPointer", 34853),
+ };
+
+ // See JEITA CP-3451 Figure 5. page 9.
+ // The following values are used for indicating pointers to the other Image File Directorys.
+
+ // Indices of Exif Ifd tag groups
+ private static final int IFD_TIFF_HINT = 0;
+ private static final int IFD_EXIF_HINT = 1;
+ private static final int IFD_GPS_HINT = 2;
+ private static final int IFD_INTEROPERABILITY_HINT = 3;
+ private static final int IFD_THUMBNAIL_HINT = 4;
+ // List of Exif tag groups
+ private static final ExifTag[][] EXIF_TAGS = new ExifTag[][] {
+ IFD_TIFF_TAGS, IFD_EXIF_TAGS, IFD_GPS_TAGS, IFD_INTEROPERABILITY_TAGS,
+ IFD_THUMBNAIL_TAGS
+ };
+ // List of tags for pointing to the other image file directory offset.
+ private static final ExifTag[] IFD_POINTER_TAGS = new ExifTag[] {
+ new ExifTag("ExifIFDPointer", 34665),
+ new ExifTag("GPSInfoPointer", 34853),
+ new ExifTag("InteroperabilityIFDPointer", 40965),
+ };
+ // List of indices of the indicated tag groups according to the IFD_POINTER_TAGS
+ private static final int[] IFD_POINTER_TAG_HINTS = new int[] {
+ IFD_EXIF_HINT, IFD_GPS_HINT, IFD_INTEROPERABILITY_HINT
+ };
+ // Tags for indicating the thumbnail offset and length
+ private static final ExifTag JPEG_INTERCHANGE_FORMAT_TAG =
+ new ExifTag("JPEGInterchangeFormat", 513);
+ private static final ExifTag JPEG_INTERCHANGE_FORMAT_LENGTH_TAG =
+ new ExifTag("JPEGInterchangeFormatLength", 514);
+
+ // Mappings from tag number to tag name and each item represents one IFD tag group.
+ private static final HashMap[] sExifTagMapsForReading = new HashMap[EXIF_TAGS.length];
+ // Mapping from tag name to tag number and the corresponding tag group.
+ private static final HashMap<String, Pair<Integer, Integer>> sExifTagMapForWriting
+ = new HashMap<>();
+
+ // See JPEG File Interchange Format Version 1.02.
+ // The following values are defined for handling JPEG streams. In this implementation, we are
+ // not only getting information from EXIF but also from some JPEG special segments such as
+ // MARKER_COM for user comment and MARKER_SOFx for image width and height.
+
+ // Identifier for APP1 segment in JPEG
+ private static final byte[] IDENTIFIER_APP1 = "Exif\0\0".getBytes(Charset.forName("US-ASCII"));
+ // JPEG segment markers, that each marker consumes two bytes beginning with 0xff and ending with
+ // the indicator. There is no SOF4, SOF8, SOF16 markers in JPEG and SOFx markers indicates start
+ // of frame(baseline DCT) and the image size info exists in its beginning part.
+ private static final byte MARKER = (byte) 0xff;
+ private static final byte MARKER_SOI = (byte) 0xd8;
+ private static final byte MARKER_SOF0 = (byte) 0xc0;
+ private static final byte MARKER_SOF1 = (byte) 0xc1;
+ private static final byte MARKER_SOF2 = (byte) 0xc2;
+ private static final byte MARKER_SOF3 = (byte) 0xc3;
+ private static final byte MARKER_SOF5 = (byte) 0xc5;
+ private static final byte MARKER_SOF6 = (byte) 0xc6;
+ private static final byte MARKER_SOF7 = (byte) 0xc7;
+ private static final byte MARKER_SOF9 = (byte) 0xc9;
+ private static final byte MARKER_SOF10 = (byte) 0xca;
+ private static final byte MARKER_SOF11 = (byte) 0xcb;
+ private static final byte MARKER_SOF13 = (byte) 0xcd;
+ private static final byte MARKER_SOF14 = (byte) 0xce;
+ private static final byte MARKER_SOF15 = (byte) 0xcf;
+ private static final byte MARKER_SOS = (byte) 0xda;
+ private static final byte MARKER_APP1 = (byte) 0xe1;
+ private static final byte MARKER_COM = (byte) 0xfe;
+ private static final byte MARKER_EOI = (byte) 0xd9;
+
static {
- System.loadLibrary("jhead_jni");
System.loadLibrary("media_jni");
initRawNative();
-
sFormatter = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
sFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
+
+ // Build up the hash tables to look up Exif tags for reading Exif tags.
+ for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
+ sExifTagMapsForReading[hint] = new HashMap();
+ for (ExifTag tag : EXIF_TAGS[hint]) {
+ sExifTagMapsForReading[hint].put(tag.number, tag.name);
+ }
+ }
+
+ // Build up the hash tables to look up Exif tags for writing Exif tags.
+ // There are some tags that have the same tag name in the different group. For that tags,
+ // Primary image TIFF IFD and Exif private IFD have a higher priority to map than the other
+ // tag groups. For the same tags, it writes one tag in the only one IFD group, which has the
+ // higher priority group.
+ for (int hint = EXIF_TAGS.length - 1; hint >= 0; --hint) {
+ for (ExifTag tag : EXIF_TAGS[hint]) {
+ sExifTagMapForWriting.put(tag.name, new Pair<>(tag.number, hint));
+ }
+ }
}
private final String mFilename;
- private final HashMap<String, String> mAttributes = new HashMap<>();
+ private final FileDescriptor mFileDescriptor;
+ private final InputStream mInputStream;
private boolean mIsRaw;
+ private final HashMap<String, String> mAttributes = new HashMap<>();
private boolean mHasThumbnail;
// The following values used for indicating a thumbnail position.
private int mThumbnailOffset;
private int mThumbnailLength;
-
- // Because the underlying implementation (jhead) uses static variables,
- // there can only be one user at a time for the native functions (and
- // they cannot keep state in the native code across function calls). We
- // use sLock to serialize the accesses.
- private static final Object sLock = new Object();
+ private byte[] mThumbnailBytes;
// Pattern to check non zero timestamp
private static final Pattern sNonZeroTimePattern = Pattern.compile(".*[1-9].*");
@@ -155,7 +489,35 @@
throw new IllegalArgumentException("filename cannot be null");
}
mFilename = filename;
- // First test whether a given file is a one of RAW format or not.
+ mFileDescriptor = null;
+ mInputStream = new FileInputStream(filename);
+ loadAttributes();
+ }
+
+ /**
+ * Reads Exif tags from the specified image file descriptor.
+ */
+ public ExifInterface(FileDescriptor fileDescriptor) throws IOException {
+ if (fileDescriptor == null) {
+ throw new IllegalArgumentException("parcelFileDescriptor cannot be null");
+ }
+ mFilename = null;
+ mFileDescriptor = fileDescriptor;
+ mInputStream = new FileInputStream(fileDescriptor);
+ loadAttributes();
+ }
+
+ /**
+ * Reads Exif tags from the specified image input stream. Attribute mutation is not supported
+ * for input streams.
+ */
+ public ExifInterface(InputStream inputStream) throws IOException {
+ if (inputStream == null) {
+ throw new IllegalArgumentException("inputStream cannot be null");
+ }
+ mFilename = null;
+ mFileDescriptor = null;
+ mInputStream = inputStream;
loadAttributes();
}
@@ -188,9 +550,9 @@
}
/**
- * Returns the double value of the specified rational tag. If there is no
- * such tag in the image file or the value cannot be parsed as double, return
- * <var>defaultValue</var>.
+ * Returns the double value of the tag that is specified as rational or contains a
+ * double-formatted value. If there is no such tag in the image file or the value cannot be
+ * parsed as double, return <var>defaultValue</var>.
*
* @param tag the name of the tag.
* @param defaultValue the value to return if the tag is not available.
@@ -200,7 +562,7 @@
if (value == null) return defaultValue;
try {
int index = value.indexOf("/");
- if (index == -1) return defaultValue;
+ if (index == -1) return Double.parseDouble(value);
double denom = Double.parseDouble(value.substring(index + 1));
if (denom == 0) return defaultValue;
double num = Double.parseDouble(value.substring(0, index));
@@ -217,6 +579,10 @@
* @param value the value of the tag.
*/
public void setAttribute(String tag, String value) {
+ if (value == null) {
+ mAttributes.remove(tag);
+ return;
+ }
mAttributes.put(tag, value);
}
@@ -231,68 +597,74 @@
* file has a thumbnail inside.
*/
private void loadAttributes() throws IOException {
- HashMap map = getRawAttributesNative(mFilename);
- mIsRaw = map != null;
- if (mIsRaw) {
- for (Object o : map.entrySet()) {
- Map.Entry entry = (Map.Entry) o;
- String attrName = (String) entry.getKey();
- String attrValue = (String) entry.getValue();
+ FileInputStream in = null;
+ try {
+ if (mFilename != null) {
+ in = new FileInputStream(mFilename);
+ }
+ if (mFileDescriptor != null) {
+ in = new FileInputStream(mFileDescriptor);
+ }
+ if (in != null) {
+ // First test whether a given file is a one of RAW format or not.
+ HashMap map = getRawAttributesNative(Os.dup(in.getFD()));
+ mIsRaw = map != null;
+ if (mIsRaw) {
+ for (Object obj : map.entrySet()) {
+ Map.Entry entry = (Map.Entry) obj;
+ String attrName = (String) entry.getKey();
+ String attrValue = (String) entry.getValue();
- switch (attrName) {
- case TAG_HAS_THUMBNAIL:
- mHasThumbnail = attrValue.equalsIgnoreCase("true");
- break;
- case TAG_THUMBNAIL_OFFSET:
- mThumbnailOffset = Integer.parseInt(attrValue);
- break;
- case TAG_THUMBNAIL_LENGTH:
- mThumbnailLength = Integer.parseInt(attrValue);
- break;
- default:
- mAttributes.put(attrName, attrValue);
- break;
+ switch (attrName) {
+ case TAG_HAS_THUMBNAIL:
+ mHasThumbnail = attrValue.equalsIgnoreCase("true");
+ break;
+ case TAG_THUMBNAIL_OFFSET:
+ mThumbnailOffset = Integer.parseInt(attrValue);
+ break;
+ case TAG_THUMBNAIL_LENGTH:
+ mThumbnailLength = Integer.parseInt(attrValue);
+ break;
+ default:
+ mAttributes.put(attrName, attrValue);
+ break;
+ }
+ }
+
+ if (DEBUG) {
+ printAttributes();
+ }
+ return;
}
}
- return;
+ } catch (ErrnoException e) {
+ e.rethrowAsIOException();
+ } finally {
+ IoUtils.closeQuietly(in);
}
- // format of string passed from native C code:
- // "attrCnt attr1=valueLen value1attr2=value2Len value2..."
- // example:
- // "4 attrPtr ImageLength=4 1024Model=6 FooImageWidth=4 1280Make=3 FOO"
-
- String attrStr;
- synchronized (sLock) {
- attrStr = getAttributesNative(mFilename);
- }
-
- // get count
- int ptr = attrStr.indexOf(' ');
- int count = Integer.parseInt(attrStr.substring(0, ptr));
- // skip past the space between item count and the rest of the attributes
- ++ptr;
-
- for (int i = 0; i < count; i++) {
- // extract the attribute name
- int equalPos = attrStr.indexOf('=', ptr);
- String attrName = attrStr.substring(ptr, equalPos);
- ptr = equalPos + 1; // skip past =
-
- // extract the attribute value length
- int lenPos = attrStr.indexOf(' ', ptr);
- int attrLen = Integer.parseInt(attrStr.substring(ptr, lenPos));
- ptr = lenPos + 1; // skip pas the space
-
- // extract the attribute value
- String attrValue = attrStr.substring(ptr, ptr + attrLen);
- ptr += attrLen;
-
- if (attrName.equals(TAG_HAS_THUMBNAIL)) {
- mHasThumbnail = attrValue.equalsIgnoreCase("true");
- } else {
- mAttributes.put(attrName, attrValue);
+ try {
+ if (mFileDescriptor != null) {
+ Os.lseek(mFileDescriptor, 0, OsConstants.SEEK_SET);
}
+
+ getJpegAttributes(mInputStream);
+ } catch (ErrnoException e) {
+ e.rethrowAsIOException();
+ } finally {
+ IoUtils.closeQuietly(mInputStream);
+ }
+
+ if (DEBUG) {
+ printAttributes();
+ }
+ }
+
+ // Prints out attributes for debugging.
+ private void printAttributes() {
+ Log.d(TAG, "The size of tags: " + mAttributes.size());
+ for (Map.Entry<String, String> entry : mAttributes.entrySet()) {
+ Log.d(TAG, "tagName: " + entry.getKey() + ", tagValue: " + entry.getValue());
}
}
@@ -307,33 +679,63 @@
throw new UnsupportedOperationException(
"ExifInterface does not support saving attributes on RAW formats.");
}
+ if (mFileDescriptor == null && mFilename == null) {
+ throw new UnsupportedOperationException(
+ "ExifInterface does not support saving attributes for input streams.");
+ }
- // format of string passed to native C code:
- // "attrCnt attr1=valueLen value1attr2=value2Len value2..."
- // example:
- // "4 attrPtr ImageLength=4 1024Model=6 FooImageWidth=4 1280Make=3 FOO"
- StringBuilder sb = new StringBuilder();
- int size = mAttributes.size();
- if (mAttributes.containsKey(TAG_HAS_THUMBNAIL)) {
- --size;
- }
- sb.append(size).append(" ");
- for (Map.Entry<String, String> entry : mAttributes.entrySet()) {
- String key = entry.getKey();
- if (key.equals(TAG_HAS_THUMBNAIL)) {
- // this is a fake attribute not saved as an exif tag
- continue;
+ // Keep the thumbnail in memory
+ mThumbnailBytes = getThumbnail();
+
+ FileInputStream in = null;
+ FileOutputStream out = null;
+ File tempFile = null;
+ try {
+ // Move the original file to temporary file.
+ if (mFilename != null) {
+ tempFile = new File(mFilename + ".tmp");
+ File originalFile = new File(mFilename);
+ if (!originalFile.renameTo(tempFile)) {
+ throw new IOException("Could'nt rename to " + tempFile.getAbsolutePath());
+ }
}
- String val = entry.getValue();
- sb.append(key).append("=");
- sb.append(val.length()).append(" ");
- sb.append(val);
+ if (mFileDescriptor != null) {
+ tempFile = File.createTempFile("temp", "jpg");
+ Os.lseek(mFileDescriptor, 0, OsConstants.SEEK_SET);
+ in = new FileInputStream(mFileDescriptor);
+ out = new FileOutputStream(tempFile);
+ Streams.copy(in, out);
+ }
+ } catch (ErrnoException e) {
+ e.rethrowAsIOException();
+ } finally {
+ IoUtils.closeQuietly(in);
+ IoUtils.closeQuietly(out);
}
- String s = sb.toString();
- synchronized (sLock) {
- saveAttributesNative(mFilename, s);
- commitChangesNative(mFilename);
+
+ in = null;
+ out = null;
+ try {
+ // Save the new file.
+ in = new FileInputStream(tempFile);
+ if (mFilename != null) {
+ out = new FileOutputStream(mFilename);
+ }
+ if (mFileDescriptor != null) {
+ Os.lseek(mFileDescriptor, 0, OsConstants.SEEK_SET);
+ out = new FileOutputStream(mFileDescriptor);
+ }
+ saveJpegAttributes(in, out);
+ } catch (ErrnoException e) {
+ e.rethrowAsIOException();
+ } finally {
+ IoUtils.closeQuietly(in);
+ IoUtils.closeQuietly(out);
+ tempFile.delete();
}
+
+ // Discard the thumbnail in memory
+ mThumbnailBytes = null;
}
/**
@@ -349,27 +751,41 @@
* {@link android.graphics.BitmapFactory#decodeByteArray(byte[],int,int)}
*/
public byte[] getThumbnail() {
- if (mIsRaw) {
- if (mHasThumbnail) {
- try (RandomAccessFile file = new RandomAccessFile(mFilename, "r")) {
- if (file.length() < mThumbnailLength + mThumbnailOffset) {
- throw new IOException("Corrupted image.");
- }
- file.seek(mThumbnailOffset);
-
- byte[] buffer = new byte[mThumbnailLength];
- file.readFully(buffer);
- return buffer;
- } catch (IOException e) {
- // Couldn't get a thumbnail image.
- }
- }
+ if (!mHasThumbnail) {
return null;
}
-
- synchronized (sLock) {
- return getThumbnailNative(mFilename);
+ if (mThumbnailBytes != null) {
+ return mThumbnailBytes;
}
+
+ // Read the thumbnail.
+ FileInputStream in = null;
+ try {
+ if (mFileDescriptor != null) {
+ Os.lseek(mFileDescriptor, 0, OsConstants.SEEK_SET);
+ in = new FileInputStream(mFileDescriptor);
+ }
+ if (mFilename != null) {
+ in = new FileInputStream(mFilename);
+ }
+ if (in == null) {
+ // Should not be reached this.
+ throw new FileNotFoundException();
+ }
+ if (in.skip(mThumbnailOffset) != mThumbnailOffset) {
+ throw new IOException("Corrupted image");
+ }
+ byte[] buffer = new byte[mThumbnailLength];
+ if (in.read(buffer) != mThumbnailLength) {
+ throw new IOException("Corrupted image");
+ }
+ return buffer;
+ } catch (IOException | ErrnoException e) {
+ // Couldn't get a thumbnail image.
+ } finally {
+ IoUtils.closeQuietly(in);
+ }
+ return null;
}
/**
@@ -381,16 +797,10 @@
* @hide
*/
public long[] getThumbnailRange() {
- if (mIsRaw) {
- long[] range = new long[2];
- range[0] = mThumbnailOffset;
- range[1] = mThumbnailLength;
- return range;
- }
-
- synchronized (sLock) {
- return getThumbnailRangeNative(mFilename);
- }
+ long[] range = new long[2];
+ range[0] = mThumbnailOffset;
+ range[1] = mThumbnailLength;
+ return range;
}
/**
@@ -399,10 +809,10 @@
* Exif tags are not available.
*/
public boolean getLatLong(float output[]) {
- String latValue = mAttributes.get(ExifInterface.TAG_GPS_LATITUDE);
- String latRef = mAttributes.get(ExifInterface.TAG_GPS_LATITUDE_REF);
- String lngValue = mAttributes.get(ExifInterface.TAG_GPS_LONGITUDE);
- String lngRef = mAttributes.get(ExifInterface.TAG_GPS_LONGITUDE_REF);
+ String latValue = mAttributes.get(TAG_GPS_LATITUDE);
+ String latRef = mAttributes.get(TAG_GPS_LATITUDE_REF);
+ String lngValue = mAttributes.get(TAG_GPS_LONGITUDE);
+ String lngRef = mAttributes.get(TAG_GPS_LONGITUDE_REF);
if (latValue != null && latRef != null && lngValue != null && lngRef != null) {
try {
@@ -428,7 +838,7 @@
int ref = getAttributeInt(TAG_GPS_ALTITUDE_REF, -1);
if (altitude >= 0 && ref >= 0) {
- return (double) (altitude * ((ref == 1) ? -1 : 1));
+ return (altitude * ((ref == 1) ? -1 : 1));
} else {
return defaultValue;
}
@@ -461,6 +871,7 @@
}
msecs += sub;
} catch (NumberFormatException e) {
+ // Ignored
}
}
return msecs;
@@ -493,8 +904,7 @@
}
}
- private static float convertRationalLatLonToFloat(
- String rationalString, String ref) {
+ private static float convertRationalLatLonToFloat(String rationalString, String ref) {
try {
String [] parts = rationalString.split(",");
@@ -522,22 +932,1062 @@
}
}
- // JNI methods for JPEG.
- private static native boolean appendThumbnailNative(String fileName,
- String thumbnailFileName);
+ // Loads EXIF attributes from a JPEG input stream.
+ private void getJpegAttributes(InputStream inputStream) throws IOException {
+ // See JPEG File Interchange Format Specification page 5.
+ if (DEBUG) {
+ Log.d(TAG, "getJpegAttributes starting with: " + inputStream);
+ }
+ DataInputStream dataInputStream = new DataInputStream(inputStream);
+ byte marker;
+ int bytesRead = 0;
+ ++bytesRead;
+ if ((marker = dataInputStream.readByte()) != MARKER) {
+ throw new IOException("Invalid marker: " + Integer.toHexString(marker & 0xff));
+ }
+ ++bytesRead;
+ if (dataInputStream.readByte() != MARKER_SOI) {
+ throw new IOException("Invalid marker: " + Integer.toHexString(marker & 0xff));
+ }
+ while (true) {
+ ++bytesRead;
+ marker = dataInputStream.readByte();
+ if (marker != MARKER) {
+ throw new IOException("Invalid marker:" + Integer.toHexString(marker & 0xff));
+ }
+ ++bytesRead;
+ marker = dataInputStream.readByte();
+ if (DEBUG) {
+ Log.d(TAG, "Found JPEG segment indicator: " + Integer.toHexString(marker & 0xff));
+ }
- private static native void saveAttributesNative(String fileName,
- String compressedAttributes);
+ // EOI indicates the end of an image and in case of SOS, JPEG image stream starts and
+ // the image data will terminate right after.
+ if (marker == MARKER_EOI || marker == MARKER_SOS) {
+ break;
+ }
+ bytesRead += 2;
+ int length = dataInputStream.readUnsignedShort() - 2;
+ if (length < 0)
+ throw new IOException("Invalid length");
+ bytesRead += length;
+ switch (marker) {
+ case MARKER_APP1: {
+ if (DEBUG) {
+ Log.d(TAG, "MARKER_APP1");
+ }
+ bytesRead -= length;
+ if (length < 6) {
+ throw new IOException("Invalid exif");
+ }
+ byte[] identifier = new byte[6];
+ if (inputStream.read(identifier) != 6) {
+ throw new IOException("Invalid exif");
+ }
+ if (!Arrays.equals(identifier, IDENTIFIER_APP1)) {
+ throw new IOException("Invalid app1 identifier");
+ }
+ bytesRead += 6;
+ length -= 6;
+ if (length <= 0) {
+ throw new IOException("Invalid exif");
+ }
+ byte[] bytes = new byte[length];
+ if (dataInputStream.read(bytes) != length) {
+ throw new IOException("Invalid exif");
+ }
+ readExifSegment(bytes, bytesRead);
+ bytesRead += length;
+ length = 0;
+ break;
+ }
- private static native String getAttributesNative(String fileName);
+ case MARKER_COM: {
+ byte[] bytes = new byte[length];
+ if (dataInputStream.read(bytes) != length) {
+ throw new IOException("Invalid exif");
+ }
+ mAttributes.put("UserComment",
+ new String(bytes, Charset.forName("US-ASCII")));
+ break;
+ }
- private static native void commitChangesNative(String fileName);
+ case MARKER_SOF0:
+ case MARKER_SOF1:
+ case MARKER_SOF2:
+ case MARKER_SOF3:
+ case MARKER_SOF5:
+ case MARKER_SOF6:
+ case MARKER_SOF7:
+ case MARKER_SOF9:
+ case MARKER_SOF10:
+ case MARKER_SOF11:
+ case MARKER_SOF13:
+ case MARKER_SOF14:
+ case MARKER_SOF15: {
+ dataInputStream.skipBytes(1);
+ mAttributes.put("ImageLength",
+ String.valueOf(dataInputStream.readUnsignedShort()));
+ mAttributes.put("ImageWidth",
+ String.valueOf(dataInputStream.readUnsignedShort()));
+ length -= 5;
+ break;
+ }
- private static native byte[] getThumbnailNative(String fileName);
+ default: {
+ break;
+ }
+ }
+ if (length < 0) {
+ throw new IOException("Invalid length");
+ }
+ dataInputStream.skipBytes(length);
+ }
+ }
- private static native long[] getThumbnailRangeNative(String fileName);
+ // Stores a new JPEG image with EXIF attributes into a given output stream.
+ private void saveJpegAttributes(InputStream inputStream, OutputStream outputStream)
+ throws IOException {
+ // See JPEG File Interchange Format Specification page 5.
+ if (DEBUG) {
+ Log.d(TAG, "saveJpegAttributes starting with (inputStream: " + inputStream
+ + ", outputStream: " + outputStream + ")");
+ }
+ DataInputStream dataInputStream = new DataInputStream(inputStream);
+ ExifDataOutputStream dataOutputStream = new ExifDataOutputStream(outputStream);
+ int bytesRead = 0;
+ ++bytesRead;
+ if (dataInputStream.readByte() != MARKER) {
+ throw new IOException("Invalid marker");
+ }
+ dataOutputStream.writeByte(MARKER);
+ ++bytesRead;
+ if (dataInputStream.readByte() != MARKER_SOI) {
+ throw new IOException("Invalid marker");
+ }
+ dataOutputStream.writeByte(MARKER_SOI);
+
+ byte[] bytes = new byte[4096];
+
+ while (true) {
+ ++bytesRead;
+ if (dataInputStream.readByte() != MARKER) {
+ throw new IOException("Invalid marker");
+ }
+ dataOutputStream.writeByte(MARKER);
+ ++bytesRead;
+ byte marker = dataInputStream.readByte();
+ dataOutputStream.writeByte(marker);
+ switch (marker) {
+ case MARKER_APP1: {
+ // Rewrite EXIF segment
+ int length = dataInputStream.readUnsignedShort() - 2;
+ if (length < 0)
+ throw new IOException("Invalid length");
+ bytesRead += 2;
+ int read;
+ while ((read = dataInputStream.read(
+ bytes, 0, Math.min(length, bytes.length))) > 0) {
+ length -= read;
+ }
+ bytesRead += length;
+ writeExifSegment(dataOutputStream, bytesRead);
+ break;
+ }
+ case MARKER_EOI:
+ case MARKER_SOS: {
+ // Copy all the remaining data
+ Streams.copy(dataInputStream, dataOutputStream);
+ return;
+ }
+ default: {
+ // Copy JPEG segment
+ int length = dataInputStream.readUnsignedShort();
+ dataOutputStream.writeUnsignedShort(length);
+ if (length < 0)
+ throw new IOException("Invalid length");
+ length -= 2;
+ bytesRead += 2;
+ int read;
+ while ((read = dataInputStream.read(
+ bytes, 0, Math.min(length, bytes.length))) > 0) {
+ dataOutputStream.write(bytes, 0, read);
+ length -= read;
+ }
+ bytesRead += length;
+ break;
+ }
+ }
+ }
+ }
+
+ // Reads the given EXIF byte area and save its tag data into attributes.
+ private void readExifSegment(byte[] exifBytes, int exifOffsetFromBeginning) throws IOException {
+ // Parse TIFF Headers. See JEITA CP-3451C Table 1. page 10.
+ ByteOrderAwarenessDataInputStream dataInputStream =
+ new ByteOrderAwarenessDataInputStream(exifBytes);
+
+ // Read byte align
+ short byteOrder = dataInputStream.readShort();
+ switch (byteOrder) {
+ case BYTE_ALIGN_II:
+ if (DEBUG) {
+ Log.d(TAG, "readExifSegment: Byte Align II");
+ }
+ dataInputStream.setByteOrder(ByteOrder.LITTLE_ENDIAN);
+ break;
+ case BYTE_ALIGN_MM:
+ if (DEBUG) {
+ Log.d(TAG, "readExifSegment: Byte Align MM");
+ }
+ dataInputStream.setByteOrder(ByteOrder.BIG_ENDIAN);
+ break;
+ default:
+ throw new IOException("Invalid byte order: " + Integer.toHexString(byteOrder));
+ }
+
+ int startCode = dataInputStream.readUnsignedShort();
+ if (startCode != 0x2a) {
+ throw new IOException("Invalid exif start: " + Integer.toHexString(startCode));
+ }
+
+ // Read first ifd offset
+ long firstIfdOffset = dataInputStream.readUnsignedInt();
+ if (firstIfdOffset < 8 || firstIfdOffset >= exifBytes.length) {
+ throw new IOException("Invalid first Ifd offset: " + firstIfdOffset);
+ }
+ firstIfdOffset -= 8;
+ if (firstIfdOffset > 0) {
+ if (dataInputStream.skip(firstIfdOffset) != firstIfdOffset)
+ throw new IOException("Couldn't jump to first Ifd: " + firstIfdOffset);
+ }
+
+ // Read primary image TIFF image file directory.
+ readImageFileDirectory(dataInputStream, IFD_TIFF_HINT);
+
+ // Process thumbnail.
+ try {
+ int jpegInterchangeFormat = Integer.parseInt(
+ mAttributes.get(JPEG_INTERCHANGE_FORMAT_TAG.name));
+ int jpegInterchangeFormatLength = Integer.parseInt(
+ mAttributes.get(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name));
+ // The following code limits the size of thumbnail size not to overflow EXIF data area.
+ jpegInterchangeFormatLength = Math.min(jpegInterchangeFormat
+ + jpegInterchangeFormatLength, exifOffsetFromBeginning + exifBytes.length)
+ - jpegInterchangeFormat;
+ if (jpegInterchangeFormat > 0 && jpegInterchangeFormatLength > 0) {
+ mHasThumbnail = true;
+ mThumbnailOffset = exifOffsetFromBeginning + jpegInterchangeFormat;
+ mThumbnailLength = jpegInterchangeFormatLength;
+
+ // Do not store a thumbnail in memory if the given input can be re-read.
+ if (mFileDescriptor == null && mFilename == null) {
+ byte[] thumbnailBytes = new byte[jpegInterchangeFormatLength];
+ dataInputStream.seek(jpegInterchangeFormat);
+ dataInputStream.readFully(thumbnailBytes);
+ mThumbnailBytes = thumbnailBytes;
+
+ if (DEBUG) {
+ Bitmap bitmap = BitmapFactory.decodeByteArray(
+ thumbnailBytes, 0, thumbnailBytes.length);
+ Log.d(TAG, "Thumbnail offset: " + mThumbnailOffset + ", length: "
+ + mThumbnailLength + ", width: " + bitmap.getWidth() + ", height: "
+ + bitmap.getHeight());
+ }
+ }
+ }
+ } catch (NumberFormatException e) {
+ // Ignored the corrupted image.
+ }
+
+ // For compatibility, keep data formats as follows.
+ convertToInt(TAG_IMAGE_WIDTH);
+ convertToInt(TAG_IMAGE_LENGTH);
+ convertToInt(TAG_ORIENTATION);
+ convertToInt(TAG_FLASH);
+ convertToRational(TAG_FOCAL_LENGTH);
+ convertToDouble(TAG_DIGITAL_ZOOM_RATIO);
+ convertToDouble(TAG_EXPOSURE_TIME);
+ convertToDouble(TAG_APERTURE);
+ convertToDouble(TAG_SUBJECT_DISTANCE);
+ convertToInt(TAG_ISO);
+ convertToDouble(TAG_EXPOSURE_BIAS_VALUE);
+ convertToInt(TAG_WHITE_BALANCE);
+ convertToInt(TAG_LIGHT_SOURCE);
+ convertToInt(TAG_METERING_MODE);
+ convertToInt(TAG_EXPOSURE_PROGRAM);
+ convertToInt(TAG_EXPOSURE_MODE);
+ convertToRational(TAG_GPS_ALTITUDE);
+ convertToInt(TAG_GPS_ALTITUDE_REF);
+ convertToRational(TAG_GPS_LONGITUDE);
+ convertToRational(TAG_GPS_LATITUDE);
+ convertToTimetamp(TAG_GPS_TIMESTAMP);
+
+ // The value of DATETIME tag has the same value of DATETIME_ORIGINAL tag.
+ String valueOfDateTimeOriginal = mAttributes.get("DateTimeOriginal");
+ if (valueOfDateTimeOriginal != null) {
+ mAttributes.put(TAG_DATETIME, valueOfDateTimeOriginal);
+ }
+
+ // Add the default value.
+ if (!mAttributes.containsKey(TAG_IMAGE_WIDTH)) {
+ mAttributes.put(TAG_IMAGE_WIDTH, "0");
+ }
+ if (!mAttributes.containsKey(TAG_IMAGE_LENGTH)) {
+ mAttributes.put(TAG_IMAGE_LENGTH, "0");
+ }
+ if (!mAttributes.containsKey(TAG_ORIENTATION)) {
+ mAttributes.put(TAG_ORIENTATION, "0");
+ }
+ if (!mAttributes.containsKey(TAG_LIGHT_SOURCE)) {
+ mAttributes.put(TAG_LIGHT_SOURCE, "0");
+ }
+ }
+
+ // Converts the tag value to timestamp; Otherwise deletes the given tag.
+ private void convertToTimetamp(String tagName) {
+ String entryValue = mAttributes.get(tagName);
+ if (entryValue == null) return;
+ int dataFormat = getDataFormatOfExifEntryValue(entryValue);
+ String[] components = entryValue.split(",");
+ if (dataFormat == IFD_FORMAT_SRATIONAL && components.length == 3) {
+ StringBuilder stringBuilder = new StringBuilder();
+ for (String component : components) {
+ if (stringBuilder.length() > 0) {
+ stringBuilder.append(":");
+ }
+ String[] rationalNumber = component.split("/");
+ int numerator = Integer.parseInt(rationalNumber[0]);
+ int denominator = Integer.parseInt(rationalNumber[1]);
+ if (denominator == 0) {
+ numerator = 0;
+ denominator = 1;
+ }
+ int value = numerator / denominator;
+ stringBuilder.append(String.format("%02d", value));
+ }
+ mAttributes.put(tagName, stringBuilder.toString());
+ } else if (dataFormat != IFD_FORMAT_STRING) {
+ mAttributes.remove(tagName);
+ }
+ }
+
+ // Checks the tag value of a given tag formatted in double type; Otherwise try to convert it to
+ // double type or delete it.
+ private void convertToDouble(String tagName) {
+ String entryValue = mAttributes.get(tagName);
+ if (entryValue == null) return;
+ int dataFormat = getDataFormatOfExifEntryValue(entryValue);
+ switch (dataFormat) {
+ case IFD_FORMAT_SRATIONAL: {
+ StringBuilder stringBuilder = new StringBuilder();
+ String[] components = entryValue.split(",");
+ for (String component : components) {
+ if (stringBuilder.length() > 0) {
+ stringBuilder.append(",");
+ }
+ String[] rationalNumber = component.split("/");
+ int numerator = Integer.parseInt(rationalNumber[0]);
+ int denominator = Integer.parseInt(rationalNumber[1]);
+ if (denominator == 0) {
+ numerator = 0;
+ denominator = 1;
+ }
+ stringBuilder.append((double) numerator / denominator);
+ }
+ mAttributes.put(tagName, stringBuilder.toString());
+ break;
+ }
+ case IFD_FORMAT_DOUBLE:
+ // Keep it as is.
+ break;
+ default:
+ mAttributes.remove(tagName);
+ break;
+ }
+ }
+
+ // Checks the tag value of a given tag formatted in int type; Otherwise deletes the tag value.
+ private void convertToRational(String tagName) {
+ String entryValue = mAttributes.get(tagName);
+ if (entryValue == null) return;
+ int dataFormat = getDataFormatOfExifEntryValue(entryValue);
+ switch (dataFormat) {
+ case IFD_FORMAT_SLONG:
+ case IFD_FORMAT_DOUBLE: {
+ StringBuilder stringBuilder = new StringBuilder();
+ String[] components = entryValue.split(",");
+ for (String component : components) {
+ if (stringBuilder.length() > 0) {
+ stringBuilder.append(",");
+ }
+ double doubleValue = Double.parseDouble(component);
+ stringBuilder.append((int) (doubleValue * 10000.0)).append("/").append(10000);
+ }
+ mAttributes.put(tagName, stringBuilder.toString());
+ break;
+ }
+ case IFD_FORMAT_SRATIONAL:
+ // Keep it as is.
+ break;
+ default:
+ mAttributes.remove(tagName);
+ break;
+ }
+ }
+
+ // Checks the tag value of a given tag formatted in int type; Otherwise deletes the tag value.
+ private void convertToInt(String tagName) {
+ String entryValue = mAttributes.get(tagName);
+ if (entryValue == null) return;
+ int dataFormat = getDataFormatOfExifEntryValue(entryValue);
+ if (dataFormat != IFD_FORMAT_SLONG) {
+ mAttributes.remove(tagName);
+ }
+ }
+
+ // Reads image file directory, which is a tag group in EXIF.
+ private void readImageFileDirectory(ByteOrderAwarenessDataInputStream dataInputStream, int hint)
+ throws IOException {
+ // See JEITA CP-3451 Figure 5. page 9.
+ short numberOfDirectoryEntry = dataInputStream.readShort();
+
+ if (DEBUG) {
+ Log.d(TAG, "numberOfDirectoryEntry: " + numberOfDirectoryEntry);
+ }
+
+ for (short i = 0; i < numberOfDirectoryEntry; ++i) {
+ int tagNumber = dataInputStream.readUnsignedShort();
+ int dataFormat = dataInputStream.readUnsignedShort();
+ int numberOfComponents = dataInputStream.readInt();
+ long nextEntryOffset = dataInputStream.peek() + 4; // next four bytes is for data
+ // offset or value.
+
+ if (DEBUG) {
+ Log.d(TAG, String.format("tagNumber: %d, dataFormat: %d, numberOfComponents: %d",
+ tagNumber, dataFormat, numberOfComponents));
+ }
+
+ // Read a value from data field or seek to the value offset which is stored in data
+ // field if the size of the entry value is bigger than 4.
+ int byteCount = numberOfComponents * IFD_FORMAT_BYTES_PER_FORMAT[dataFormat];
+ if (byteCount > 4) {
+ long offset = dataInputStream.readUnsignedInt();
+ if (DEBUG) {
+ Log.d(TAG, "seek to data offset: " + offset);
+ }
+ dataInputStream.seek(offset);
+ }
+
+ // Look up a corresponding tag from tag number
+ String tagName = (String) sExifTagMapsForReading[hint].get(tagNumber);
+ // Skip if the parsed tag number is not defined.
+ if (tagName == null) {
+ dataInputStream.seek(nextEntryOffset);
+ continue;
+ }
+
+ // Recursively parse IFD when a IFD pointer tag appears.
+ int innerIfdHint = getIfdHintFromTagNumber(tagNumber);
+ if (innerIfdHint >= 0) {
+ long offset = -1L;
+ // Get offset from data field
+ switch (dataFormat) {
+ case IFD_FORMAT_USHORT: {
+ offset = dataInputStream.readUnsignedShort();
+ break;
+ }
+ case IFD_FORMAT_SSHORT: {
+ offset = dataInputStream.readShort();
+ break;
+ }
+ case IFD_FORMAT_ULONG: {
+ offset = dataInputStream.readUnsignedInt();
+ break;
+ }
+ case IFD_FORMAT_SLONG: {
+ offset = dataInputStream.readInt();
+ break;
+ }
+ default: {
+ // Nothing to do
+ break;
+ }
+ }
+ if (DEBUG) {
+ Log.d(TAG, String.format("Offset: %d, tagName: %s", offset, tagName));
+ }
+ if (offset > 0L) {
+ dataInputStream.seek(offset);
+ readImageFileDirectory(dataInputStream, innerIfdHint);
+ }
+
+ dataInputStream.seek(nextEntryOffset);
+ continue;
+ }
+
+ if (numberOfComponents == 1 || dataFormat == IFD_FORMAT_STRING
+ || dataFormat == IFD_FORMAT_UNDEFINED) {
+ String entryValue = readExifEntryValue(
+ dataInputStream, dataFormat, numberOfComponents);
+ if (entryValue != null) {
+ mAttributes.put(tagName, entryValue);
+ }
+ } else {
+ StringBuilder entryValueBuilder = new StringBuilder();
+ for (int c = 0; c < numberOfComponents; ++c) {
+ if (entryValueBuilder.length() > 0) {
+ entryValueBuilder.append(",");
+ }
+ entryValueBuilder.append(readExifEntryValue(
+ dataInputStream, dataFormat, numberOfComponents));
+ }
+ mAttributes.put(tagName, entryValueBuilder.toString());
+ }
+
+ if (dataInputStream.peek() != nextEntryOffset) {
+ dataInputStream.seek(nextEntryOffset);
+ }
+ }
+
+ long nextIfdOffset = dataInputStream.readUnsignedInt();
+ if (DEBUG) {
+ Log.d(TAG, String.format("nextIfdOffset: %d", nextIfdOffset));
+ }
+ // The next IFD offset needs to be bigger than 8 since the first IFD offset is at least 8.
+ if (nextIfdOffset > 8) {
+ dataInputStream.seek(nextIfdOffset);
+ readImageFileDirectory(dataInputStream, IFD_THUMBNAIL_HINT);
+ }
+ }
+
+ // Reads a value from where the entry value are stored.
+ private String readExifEntryValue(ByteOrderAwarenessDataInputStream dataInputStream,
+ int dataFormat, int numberOfComponents) throws IOException {
+ // See TIFF 6.0 spec Types. page 15.
+ switch (dataFormat) {
+ case IFD_FORMAT_BYTE: {
+ return String.valueOf(dataInputStream.readByte());
+ }
+ case IFD_FORMAT_SBYTE: {
+ return String.valueOf(dataInputStream.readByte() & 0xff);
+ }
+ case IFD_FORMAT_USHORT: {
+ return String.valueOf(dataInputStream.readUnsignedShort());
+ }
+ case IFD_FORMAT_SSHORT: {
+ return String.valueOf(dataInputStream.readUnsignedInt());
+ }
+ case IFD_FORMAT_ULONG: {
+ return String.valueOf(dataInputStream.readInt());
+ }
+ case IFD_FORMAT_SLONG: {
+ return String.valueOf(dataInputStream.readInt());
+ }
+ case IFD_FORMAT_URATIONAL:
+ case IFD_FORMAT_SRATIONAL: {
+ int numerator = dataInputStream.readInt();
+ int denominator = dataInputStream.readInt();
+ return numerator + "/" + denominator;
+ }
+ case IFD_FORMAT_SINGLE: {
+ return String.valueOf(dataInputStream.readFloat());
+ }
+ case IFD_FORMAT_DOUBLE: {
+ return String.valueOf(dataInputStream.readDouble());
+ }
+ case IFD_FORMAT_UNDEFINED: // Usually UNDEFINED format is ASCII.
+ case IFD_FORMAT_STRING: {
+ byte[] bytes = new byte[numberOfComponents];
+ dataInputStream.readFully(bytes);
+ int index = 0;
+ if (numberOfComponents >= EXIF_ASCII_PREFIX.length) {
+ boolean same = true;
+ for (int i = 0; i < EXIF_ASCII_PREFIX.length; ++i) {
+ if (bytes[i] != EXIF_ASCII_PREFIX[i]) {
+ same = false;
+ break;
+ }
+ }
+ if (same) {
+ index = EXIF_ASCII_PREFIX.length;
+ }
+ }
+
+ StringBuilder stringBuilder = new StringBuilder();
+ while (true) {
+ int ch = bytes[index];
+ if (ch < 0)
+ throw new EOFException();
+ if (ch == 0)
+ break;
+ if (ch >= 32)
+ stringBuilder.append((char) ch);
+ else
+ stringBuilder.append('?');
+ ++index;
+ if (index == numberOfComponents)
+ break;
+ }
+ return stringBuilder.toString();
+ }
+ default: {
+ // Nothing to do
+ return null;
+ }
+ }
+ }
+
+ // Gets the corresponding IFD group index of the given tag number for writing Exif Tags.
+ private static int getIfdHintFromTagNumber(int tagNumber) {
+ for (int i = 0; i < IFD_POINTER_TAG_HINTS.length; ++i) {
+ if (IFD_POINTER_TAGS[i].number == tagNumber)
+ return IFD_POINTER_TAG_HINTS[i];
+ }
+ return -1;
+ }
+
+ // Writes an Exif segment into the given output stream.
+ private int writeExifSegment(ExifDataOutputStream dataOutputStream, int exifOffsetFromBeginning)
+ throws IOException {
+ // The following variables are for calculating each IFD tag group size in bytes.
+ int[] ifdOffsets = new int[EXIF_TAGS.length];
+ int[] ifdDataSizes = new int[EXIF_TAGS.length];
+
+ // Maps to store tags per IFD tag group
+ HashMap[] ifdTags = new HashMap[EXIF_TAGS.length];
+ for (int i = 0; i < EXIF_TAGS.length; ++i) {
+ ifdTags[i] = new HashMap();
+ }
+
+ // Remove IFD pointer tags (we'll re-add it later.)
+ for (ExifTag tag : IFD_POINTER_TAGS) {
+ mAttributes.remove(tag.name);
+ }
+
+ // Assign tags to the corresponding group
+ for (Map.Entry<String, String> entry : mAttributes.entrySet()) {
+ Pair<Integer, Integer> pair = sExifTagMapForWriting.get(entry.getKey());
+ if (pair != null) {
+ int tagNumber = pair.first;
+ int hint = pair.second;
+ ifdTags[hint].put(tagNumber, entry.getValue());
+ }
+ }
+
+ // Add IFD pointer tags. The next offset of primary image TIFF IFD will have thumbnail IFD
+ // offset when there is one or more tags in the thumbnail IFD.
+ if (!ifdTags[IFD_INTEROPERABILITY_HINT].isEmpty()) {
+ ifdTags[IFD_EXIF_HINT].put(IFD_POINTER_TAGS[2].number, "0");
+ }
+ if (!ifdTags[IFD_EXIF_HINT].isEmpty()) {
+ ifdTags[IFD_TIFF_HINT].put(IFD_POINTER_TAGS[0].number, "0");
+ }
+ if (!ifdTags[IFD_GPS_HINT].isEmpty()) {
+ ifdTags[IFD_TIFF_HINT].put(IFD_POINTER_TAGS[1].number, "0");
+ }
+ if (mHasThumbnail) {
+ ifdTags[IFD_TIFF_HINT].put(JPEG_INTERCHANGE_FORMAT_TAG.number, "0");
+ ifdTags[IFD_TIFF_HINT].put(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.number,
+ String.valueOf(mThumbnailLength));
+ }
+
+ // Calculate IFD group data area sizes. IFD group data area is assigned to save the entry
+ // value which has a bigger size than 4 bytes.
+ for (int i = 0; i < 5; ++i) {
+ int sum = 0;
+ for (Object entry : ifdTags[i].entrySet()) {
+ String entryValue = (String) ((Map.Entry) entry).getValue();
+ int dataFormat = getDataFormatOfExifEntryValue(entryValue);
+ int size = getSizeOfExifEntryValue(dataFormat, entryValue);
+ if (size > 4) {
+ sum += size;
+ }
+ }
+ ifdDataSizes[i] += sum;
+ }
+
+ // Calculate IFD offsets.
+ int position = 8;
+ for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
+ if (!ifdTags[hint].isEmpty()) {
+ ifdOffsets[hint] = position;
+ position += 2 + ifdTags[hint].size() * 12 + 4 + ifdDataSizes[hint];
+ }
+ }
+ if (mHasThumbnail) {
+ int thumbnailOffset = position;
+ ifdTags[IFD_TIFF_HINT].put(JPEG_INTERCHANGE_FORMAT_TAG.number,
+ String.valueOf(thumbnailOffset));
+ ifdTags[IFD_TIFF_HINT].put(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.number,
+ String.valueOf(mThumbnailLength));
+ mThumbnailOffset = exifOffsetFromBeginning + thumbnailOffset;
+ position += mThumbnailLength;
+ }
+
+ // Calculate the total size
+ int totalSize = position + 8; // eight bytes is for header part.
+ if (DEBUG) {
+ Log.d(TAG, "totalSize length: " + totalSize);
+ for (int i = 0; i < 5; ++i) {
+ Log.d(TAG, String.format("index: %d, offsets: %d, tag count: %d, data sizes: %d",
+ i, ifdOffsets[i], ifdTags[i].size(), ifdDataSizes[i]));
+ }
+ }
+
+ // Update IFD pointer tags with the calculated offsets.
+ if (!ifdTags[IFD_EXIF_HINT].isEmpty()) {
+ ifdTags[IFD_TIFF_HINT].put(IFD_POINTER_TAGS[0].number,
+ String.valueOf(ifdOffsets[IFD_EXIF_HINT]));
+ }
+ if (!ifdTags[IFD_GPS_HINT].isEmpty()) {
+ ifdTags[IFD_TIFF_HINT].put(IFD_POINTER_TAGS[1].number,
+ String.valueOf(ifdOffsets[IFD_GPS_HINT]));
+ }
+ if (!ifdTags[IFD_INTEROPERABILITY_HINT].isEmpty()) {
+ ifdTags[IFD_EXIF_HINT].put(IFD_POINTER_TAGS[2].number,
+ String.valueOf(ifdOffsets[IFD_INTEROPERABILITY_HINT]));
+ }
+
+ // Write TIFF Headers. See JEITA CP-3451C Table 1. page 10.
+ dataOutputStream.writeUnsignedShort(totalSize);
+ dataOutputStream.write(IDENTIFIER_APP1);
+ dataOutputStream.writeShort(BYTE_ALIGN_MM);
+ dataOutputStream.writeUnsignedShort(0x2a);
+ dataOutputStream.writeUnsignedInt(8);
+
+ // Write IFD groups. See JEITA CP-3451C Figure 7. page 12.
+ for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
+ if (!ifdTags[hint].isEmpty()) {
+ // See JEITA CP-3451C 4.6.2 IFD structure. page 13.
+ // Write entry count
+ dataOutputStream.writeUnsignedShort(ifdTags[hint].size());
+
+ // Write entry info
+ int dataOffset = ifdOffsets[hint] + 2 + ifdTags[hint].size() * 12 + 4;
+ for (Object obj : ifdTags[hint].entrySet()) {
+ Map.Entry entry = (Map.Entry) obj;
+ int tagNumber = (int) entry.getKey();
+ String entryValue = (String) entry.getValue();
+
+ int dataFormat = getDataFormatOfExifEntryValue(entryValue);
+ int numberOfComponents = getNumberOfComponentsInExifEntryValue(dataFormat,
+ entryValue);
+ int byteCount = getSizeOfExifEntryValue(dataFormat, entryValue);
+
+ dataOutputStream.writeUnsignedShort(tagNumber);
+ dataOutputStream.writeUnsignedShort(dataFormat);
+ dataOutputStream.writeInt(numberOfComponents);
+ if (byteCount > 4) {
+ dataOutputStream.writeUnsignedInt(dataOffset);
+ dataOffset += byteCount;
+ } else {
+ int bytesWritten = writeExifEntryValue(dataOutputStream, entryValue);
+ // Fill zero up to 4 bytes
+ if (bytesWritten < 4) {
+ for (int i = bytesWritten; i < 4; ++i) {
+ dataOutputStream.write(0);
+ }
+ }
+ }
+ }
+
+ // Write the next offset. It writes the offset of thumbnail IFD if there is one or
+ // more tags in the thumbnail IFD when the current IFD is the primary image TIFF
+ // IFD; Otherwise 0.
+ if (hint == 0 && !ifdTags[IFD_THUMBNAIL_HINT].isEmpty()) {
+ dataOutputStream.writeUnsignedInt(ifdOffsets[IFD_THUMBNAIL_HINT]);
+ } else {
+ dataOutputStream.writeUnsignedInt(0);
+ }
+
+ // Write values of data field exceeding 4 bytes after the next offset.
+ for (Object obj : ifdTags[hint].entrySet()) {
+ Map.Entry entry = (Map.Entry) obj;
+ String entryValue = (String) entry.getValue();
+
+ int dataFormat = getDataFormatOfExifEntryValue(entryValue);
+ int byteCount = getSizeOfExifEntryValue(dataFormat, entryValue);
+ if (byteCount > 4) {
+ writeExifEntryValue(dataOutputStream, entryValue);
+ }
+ }
+ }
+ }
+
+ // Write thumbnail
+ if (mHasThumbnail) {
+ dataOutputStream.write(getThumbnail());
+ }
+
+ return totalSize;
+ }
+
+ // Writes EXIF entry value and its entry value type will be automatically determined.
+ private static int writeExifEntryValue(ExifDataOutputStream dataOutputStream, String entryValue)
+ throws IOException {
+ int bytesWritten = 0;
+ int dataFormat = getDataFormatOfExifEntryValue(entryValue);
+
+ // Values can be composed of several components. Each component is separated by char ','.
+ String[] components = entryValue.split(",");
+ for (String component : components) {
+ switch (dataFormat) {
+ case IFD_FORMAT_SLONG:
+ dataOutputStream.writeInt(Integer.parseInt(component));
+ bytesWritten += 4;
+ break;
+ case IFD_FORMAT_DOUBLE:
+ dataOutputStream.writeDouble(Double.parseDouble(component));
+ bytesWritten += 8;
+ break;
+ case IFD_FORMAT_STRING:
+ byte[] asciiArray = (component + '\0').getBytes(Charset.forName("US-ASCII"));
+ dataOutputStream.write(asciiArray);
+ bytesWritten += asciiArray.length;
+ break;
+ case IFD_FORMAT_SRATIONAL:
+ String[] rationalNumber = component.split("/");
+ dataOutputStream.writeInt(Integer.parseInt(rationalNumber[0]));
+ dataOutputStream.writeInt(Integer.parseInt(rationalNumber[1]));
+ bytesWritten += 8;
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+ return bytesWritten;
+ }
+
+ // Determines the data format of EXIF entry value.
+ private static int getDataFormatOfExifEntryValue(String entryValue) {
+ // See TIFF 6.0 spec Types. page 15.
+ // Take the first component if there are more than one component.
+ if (entryValue.contains(",")) {
+ entryValue = entryValue.split(",")[0];
+ }
+
+ if (entryValue.contains("/")) {
+ return IFD_FORMAT_SRATIONAL;
+ }
+ try {
+ Integer.parseInt(entryValue);
+ return IFD_FORMAT_SLONG;
+ } catch (NumberFormatException e) {
+ // Ignored
+ }
+ try {
+ Double.parseDouble(entryValue);
+ return IFD_FORMAT_DOUBLE;
+ } catch (NumberFormatException e) {
+ // Ignored
+ }
+ return IFD_FORMAT_STRING;
+ }
+
+ // Determines the size of EXIF entry value.
+ private static int getSizeOfExifEntryValue(int dataFormat, String entryValue) {
+ // See TIFF 6.0 spec Types page 15.
+ int bytesEstimated = 0;
+ String[] components = entryValue.split(",");
+ for (String component : components) {
+ switch (dataFormat) {
+ case IFD_FORMAT_SLONG:
+ bytesEstimated += 4;
+ break;
+ case IFD_FORMAT_DOUBLE:
+ bytesEstimated += 8;
+ break;
+ case IFD_FORMAT_STRING:
+ bytesEstimated
+ += (component + '\0').getBytes(Charset.forName("US-ASCII")).length;
+ break;
+ case IFD_FORMAT_SRATIONAL:
+ bytesEstimated += 8;
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+ return bytesEstimated;
+ }
+
+ // Determines the number of components of EXIF entry value.
+ private static int getNumberOfComponentsInExifEntryValue(int dataFormat, String entryValue) {
+ if (dataFormat == IFD_FORMAT_STRING) {
+ return (entryValue + '\0').getBytes(Charset.forName("US-ASCII")).length;
+ }
+ int count = 1;
+ for (int i = 0; i < entryValue.length(); ++i) {
+ if (entryValue.charAt(i) == ',') {
+ ++count;
+ }
+ }
+ return count;
+ }
+
+ // An input stream to parse EXIF data area, which can be written in either little or big endian
+ // order.
+ private static class ByteOrderAwarenessDataInputStream extends ByteArrayInputStream {
+ private static final ByteOrder LITTLE_ENDIAN = ByteOrder.LITTLE_ENDIAN;
+ private static final ByteOrder BIG_ENDIAN = ByteOrder.BIG_ENDIAN;
+
+ private ByteOrder mByteOrder = ByteOrder.BIG_ENDIAN;
+ private final long mLength;
+ private long mPosition;
+
+ public ByteOrderAwarenessDataInputStream(byte[] bytes) {
+ super(bytes);
+ mLength = bytes.length;
+ mPosition = 0L;
+ }
+
+ public void setByteOrder(ByteOrder byteOrder) {
+ mByteOrder = byteOrder;
+ }
+
+ public void seek(long byteCount) throws IOException {
+ mPosition = 0L;
+ reset();
+ if (skip(byteCount) != byteCount)
+ throw new IOException("Couldn't seek up to the byteCount");
+ }
+
+ public long peek() {
+ return mPosition;
+ }
+
+ public void readFully(byte[] buffer) throws IOException {
+ mPosition += buffer.length;
+ if (mPosition > mLength)
+ throw new EOFException();
+ if (super.read(buffer, 0, buffer.length) != buffer.length) {
+ throw new IOException("Couldn't read up to the length of buffer");
+ }
+ }
+
+ public byte readByte() throws IOException {
+ ++mPosition;
+ if (mPosition > mLength)
+ throw new EOFException();
+ int ch = super.read();
+ if (ch < 0)
+ throw new EOFException();
+ return (byte) ch;
+ }
+
+ public short readShort() throws IOException {
+ mPosition += 2;
+ if (mPosition > mLength)
+ throw new EOFException();
+ int ch1 = super.read();
+ int ch2 = super.read();
+ if ((ch1 | ch2) < 0)
+ throw new EOFException();
+ if (mByteOrder == LITTLE_ENDIAN) {
+ return (short) ((ch2 << 8) + (ch1));
+ } else if (mByteOrder == BIG_ENDIAN) {
+ return (short) ((ch1 << 8) + (ch2));
+ }
+ throw new IOException("Invalid byte order: " + mByteOrder);
+ }
+
+ public int readInt() throws IOException {
+ mPosition += 4;
+ if (mPosition > mLength)
+ throw new EOFException();
+ int ch1 = super.read();
+ int ch2 = super.read();
+ int ch3 = super.read();
+ int ch4 = super.read();
+ if ((ch1 | ch2 | ch3 | ch4) < 0)
+ throw new EOFException();
+ if (mByteOrder == LITTLE_ENDIAN) {
+ return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + ch1);
+ } else if (mByteOrder == BIG_ENDIAN) {
+ return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + ch4);
+ }
+ throw new IOException("Invalid byte order: " + mByteOrder);
+ }
+
+ @Override
+ public long skip(long byteCount) {
+ long skipped = super.skip(Math.min(byteCount, mLength - mPosition));
+ mPosition += skipped;
+ return skipped;
+ }
+
+ public int readUnsignedShort() throws IOException {
+ mPosition += 2;
+ if (mPosition > mLength)
+ throw new EOFException();
+ int ch1 = super.read();
+ int ch2 = super.read();
+ if ((ch1 | ch2) < 0)
+ throw new EOFException();
+ if (mByteOrder == LITTLE_ENDIAN) {
+ return ((ch2 << 8) + (ch1));
+ } else if (mByteOrder == BIG_ENDIAN) {
+ return ((ch1 << 8) + (ch2));
+ }
+ throw new IOException("Invalid byte order: " + mByteOrder);
+ }
+
+ public long readUnsignedInt() throws IOException {
+ return readInt() & 0xffffffffL;
+ }
+
+ public long readLong() throws IOException {
+ mPosition += 8;
+ if (mPosition > mLength)
+ throw new EOFException();
+ int ch1 = super.read();
+ int ch2 = super.read();
+ int ch3 = super.read();
+ int ch4 = super.read();
+ int ch5 = super.read();
+ int ch6 = super.read();
+ int ch7 = super.read();
+ int ch8 = super.read();
+ if ((ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8) < 0)
+ throw new EOFException();
+ if (mByteOrder == LITTLE_ENDIAN) {
+ return (((long) ch8 << 56) + ((long) ch7 << 48) + ((long) ch6 << 40)
+ + ((long) ch5 << 32) + ((long) ch4 << 24) + ((long) ch3 << 16)
+ + ((long) ch2 << 8) + (long) ch1);
+ } else if (mByteOrder == BIG_ENDIAN) {
+ return (((long) ch1 << 56) + ((long) ch2 << 48) + ((long) ch3 << 40)
+ + ((long) ch4 << 32) + ((long) ch5 << 24) + ((long) ch6 << 16)
+ + ((long) ch7 << 8) + (long) ch8);
+ }
+ throw new IOException("Invalid byte order: " + mByteOrder);
+ }
+
+ public float readFloat() throws IOException {
+ return Float.intBitsToFloat(readInt());
+ }
+
+ public double readDouble() throws IOException {
+ return Double.longBitsToDouble(readLong());
+ }
+ }
+
+ // An output stream to write EXIF data area, that will be written in big endian byte order.
+ private static class ExifDataOutputStream extends DataOutputStream {
+ public ExifDataOutputStream(OutputStream out) {
+ super(out);
+ }
+
+ public void writeUnsignedShort(int val) throws IOException {
+ writeShort((short) val);
+ }
+
+ public void writeUnsignedInt(long val) throws IOException {
+ writeInt((int) val);
+ }
+ }
// JNI methods for RAW formats.
private static native void initRawNative();
- private static native HashMap getRawAttributesNative(String filename);
+ private static native HashMap getRawAttributesNative(FileDescriptor fileDescriptor);
}
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index abe92c7..987a8b6 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -54,10 +54,6 @@
void setMasterMute(boolean mute, int flags, String callingPackage, int userId);
- boolean isMasterMono();
-
- void setMasterMono(boolean mute, String callingPackage, int userId);
-
int getStreamVolume(int streamType);
int getStreamMinVolume(int streamType);
diff --git a/media/java/android/media/IRecordingConfigDispatcher.aidl b/media/java/android/media/IRecordingConfigDispatcher.aidl
index a5eb8b9f..eaa92ca 100644
--- a/media/java/android/media/IRecordingConfigDispatcher.aidl
+++ b/media/java/android/media/IRecordingConfigDispatcher.aidl
@@ -16,6 +16,8 @@
package android.media;
+import android.media.AudioRecordConfiguration;
+
/**
* AIDL for the RecordingActivity monitor in AudioService to signal audio recording updates.
*
@@ -23,6 +25,6 @@
*/
oneway interface IRecordingConfigDispatcher {
- void dispatchRecordingConfigChange();
+ void dispatchRecordingConfigChange(in AudioRecordConfiguration[] configs);
}
diff --git a/media/java/android/media/IRingtonePlayer.aidl b/media/java/android/media/IRingtonePlayer.aidl
index 8091421..4b1e39f 100644
--- a/media/java/android/media/IRingtonePlayer.aidl
+++ b/media/java/android/media/IRingtonePlayer.aidl
@@ -18,6 +18,7 @@
import android.media.AudioAttributes;
import android.net.Uri;
+import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
/**
@@ -36,4 +37,6 @@
/** Return the title of the media. */
String getTitle(in Uri uri);
+
+ ParcelFileDescriptor openRingtone(in Uri uri);
}
diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java
index 397ab15..c08f4bf 100644
--- a/media/java/android/media/ImageReader.java
+++ b/media/java/android/media/ImageReader.java
@@ -153,6 +153,7 @@
mSurface = nativeGetSurface();
+ mIsReaderValid = true;
// Estimate the native buffer allocation size and register it so it gets accounted for
// during GC. Note that this doesn't include the buffers required by the buffer queue
// itself and the buffers requested by the producer.
@@ -326,7 +327,11 @@
*/
private int acquireNextSurfaceImage(SurfaceImage si) {
synchronized (mCloseLock) {
- int status = nativeImageSetup(si);
+ // A null image will eventually be returned if ImageReader is already closed.
+ int status = ACQUIRE_NO_BUFS;
+ if (mIsReaderValid) {
+ status = nativeImageSetup(si);
+ }
switch (status) {
case ACQUIRE_SUCCESS:
@@ -498,6 +503,7 @@
* acquire operations.
*/
synchronized (mCloseLock) {
+ mIsReaderValid = false;
for (Image image : mAcquiredImages) {
image.close();
}
@@ -613,6 +619,7 @@
private final Object mListenerLock = new Object();
private final Object mCloseLock = new Object();
+ private boolean mIsReaderValid = false;
private OnImageAvailableListener mListener;
private ListenerHandler mListenerHandler;
// Keep track of the successfully acquired Images. This need to be thread safe as the images
@@ -638,7 +645,14 @@
synchronized (mListenerLock) {
listener = mListener;
}
- if (listener != null) {
+
+ // It's dangerous to fire onImageAvailable() callback when the ImageReader is being
+ // closed, as application could acquire next image in the onImageAvailable() callback.
+ boolean isReaderValid = false;
+ synchronized (mCloseLock) {
+ isReaderValid = mIsReaderValid;
+ }
+ if (listener != null && isReaderValid) {
listener.onImageAvailable(ImageReader.this);
}
}
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index f1f8437..4c6f0e6 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -2221,7 +2221,10 @@
public int mode;
/**
- * Metadata describing encryption pattern for the protected bytes in a subsample.
+ * Metadata describing an encryption pattern for the protected bytes in
+ * a subsample. An encryption pattern consists of a repeating sequence
+ * of crypto blocks comprised of a number of encrypted blocks followed
+ * by a number of unencrypted, or skipped, blocks.
*/
public final static class Pattern {
/**
@@ -2273,6 +2276,10 @@
*/
private Pattern pattern;
+ /**
+ * Set the subsample count, clear/encrypted sizes, key, IV and mode fields of
+ * a {@link MediaCodec.CryptoInfo} instance.
+ */
public void set(
int newNumSubSamples,
@NonNull int[] newNumBytesOfClearData,
@@ -2289,6 +2296,10 @@
pattern = new Pattern(0, 0);
}
+ /**
+ * Set the encryption pattern on a {@link MediaCodec.CryptoInfo} instance.
+ * See {@link MediaCodec.CryptoInfo.Pattern}.
+ */
public void setPattern(Pattern newPattern) {
pattern = newPattern;
}
@@ -3339,14 +3350,6 @@
}
- private int readInt(@NonNull ByteBuffer buffer, boolean asLong) {
- if (asLong) {
- return (int)buffer.getLong();
- } else {
- return buffer.getInt();
- }
- }
-
public MediaImage(
@NonNull ByteBuffer buffer, @NonNull ByteBuffer info, boolean readOnly,
long timestamp, int xOffset, int yOffset, @Nullable Rect cropRect) {
@@ -3361,39 +3364,46 @@
mYOffset = yOffset;
mInfo = info;
- // read media-info. the size of media info can be 80 or 156/160 depending on
- // whether it was created on a 32- or 64-bit process. See MediaImage
- if (info.remaining() == 80 || info.remaining() == 156 || info.remaining() == 160) {
- boolean sizeIsLong = info.remaining() != 80;
- int type = readInt(info, info.remaining() == 160);
+ // read media-info. See MediaImage2
+ if (info.remaining() == 104) {
+ int type = info.getInt();
if (type != TYPE_YUV) {
throw new UnsupportedOperationException("unsupported type: " + type);
}
- int numPlanes = readInt(info, sizeIsLong);
+ int numPlanes = info.getInt();
if (numPlanes != 3) {
throw new RuntimeException("unexpected number of planes: " + numPlanes);
}
- mWidth = readInt(info, sizeIsLong);
- mHeight = readInt(info, sizeIsLong);
+ mWidth = info.getInt();
+ mHeight = info.getInt();
if (mWidth < 1 || mHeight < 1) {
throw new UnsupportedOperationException(
"unsupported size: " + mWidth + "x" + mHeight);
}
- int bitDepth = readInt(info, sizeIsLong);
+ int bitDepth = info.getInt();
if (bitDepth != 8) {
throw new UnsupportedOperationException("unsupported bit depth: " + bitDepth);
}
+ int bitDepthAllocated = info.getInt();
+ if (bitDepthAllocated != 8) {
+ throw new UnsupportedOperationException(
+ "unsupported allocated bit depth: " + bitDepthAllocated);
+ }
mPlanes = new MediaPlane[numPlanes];
for (int ix = 0; ix < numPlanes; ix++) {
- int planeOffset = readInt(info, sizeIsLong);
- int colInc = readInt(info, sizeIsLong);
- int rowInc = readInt(info, sizeIsLong);
- int horiz = readInt(info, sizeIsLong);
- int vert = readInt(info, sizeIsLong);
+ int planeOffset = info.getInt();
+ int colInc = info.getInt();
+ int rowInc = info.getInt();
+ int horiz = info.getInt();
+ int vert = info.getInt();
if (horiz != vert || horiz != (ix == 0 ? 1 : 2)) {
throw new UnsupportedOperationException("unexpected subsampling: "
+ horiz + "x" + vert + " on plane " + ix);
}
+ if (colInc < 1 || rowInc < 1) {
+ throw new UnsupportedOperationException("unexpected strides: "
+ + colInc + " pixel, " + rowInc + " row on plane " + ix);
+ }
buffer.clear();
buffer.position(mBuffer.position() + planeOffset
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index d9690f0..b1c1b79 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -2231,6 +2231,7 @@
switch (profileLevel.profile) {
case CodecProfileLevel.HEVCProfileMain:
case CodecProfileLevel.HEVCProfileMain10:
+ case CodecProfileLevel.HEVCProfileMain10HDR10:
break;
default:
Log.w(TAG, "Unrecognized profile "
@@ -2632,8 +2633,9 @@
public static final int VP9Level62 = 0x1000;
// from OMX_VIDEO_HEVCPROFILETYPE
- public static final int HEVCProfileMain = 0x01;
- public static final int HEVCProfileMain10 = 0x02;
+ public static final int HEVCProfileMain = 0x01;
+ public static final int HEVCProfileMain10 = 0x02;
+ public static final int HEVCProfileMain10HDR10 = 0x1000;
// from OMX_VIDEO_HEVCLEVELTYPE
public static final int HEVCMainTierLevel1 = 0x1;
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index b339925..177344a 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -28,6 +28,8 @@
import android.net.Uri;
import android.os.IBinder;
+import com.android.internal.util.Preconditions;
+
import java.io.FileDescriptor;
import java.io.IOException;
import java.lang.annotation.Retention;
@@ -189,6 +191,26 @@
}
/**
+ * Sets the data source (AssetFileDescriptor) to use. It is the caller's
+ * responsibility to close the file descriptor. It is safe to do so as soon
+ * as this call returns.
+ *
+ * @param afd the AssetFileDescriptor for the file you want to extract from.
+ */
+ public final void setDataSource(@NonNull AssetFileDescriptor afd)
+ throws IOException, IllegalArgumentException, IllegalStateException {
+ Preconditions.checkNotNull(afd);
+ // Note: using getDeclaredLength so that our behavior is the same
+ // as previous versions when the content provider is returning
+ // a full file.
+ if (afd.getDeclaredLength() < 0) {
+ setDataSource(afd.getFileDescriptor());
+ } else {
+ setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getDeclaredLength());
+ }
+ }
+
+ /**
* Sets the data source (FileDescriptor) to use. It is the caller's responsibility
* to close the file descriptor. It is safe to do so as soon as this call returns.
*
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index d06da97..a0e2481 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -65,6 +65,7 @@
* <tr><th>Name</th><th>Value Type</th><th>Description</th></tr>
* <tr><td>{@link #KEY_CHANNEL_COUNT}</td><td>Integer</td><td></td></tr>
* <tr><td>{@link #KEY_SAMPLE_RATE}</td><td>Integer</td><td></td></tr>
+ * <tr><td>{@link #KEY_PCM_ENCODING}</td><td>Integer</td><td>optional</td></tr>
* <tr><td>{@link #KEY_IS_ADTS}</td><td>Integer</td><td>optional, if <em>decoding</em> AAC audio content, setting this key to 1 indicates that each audio frame is prefixed by the ADTS header.</td></tr>
* <tr><td>{@link #KEY_AAC_PROFILE}</td><td>Integer</td><td><b>encoder-only</b>, optional, if content is AAC audio, specifies the desired profile.</td></tr>
* <tr><td>{@link #KEY_AAC_SBR_MODE}</td><td>Integer</td><td><b>encoder-only</b>, optional, if content is AAC audio, specifies the desired SBR mode.</td></tr>
@@ -197,6 +198,26 @@
public static final String KEY_FRAME_RATE = "frame-rate";
/**
+ * A key describing the raw audio sample encoding/format.
+ *
+ * <p>The associated value is an integer, using one of the
+ * {@link AudioFormat}.ENCODING_PCM_ values.</p>
+ *
+ * <p>This is an optional key for audio decoders and encoders specifying the
+ * desired raw audio sample format during {@link MediaCodec#configure
+ * MediaCodec.configure(…)} call. Use {@link MediaCodec#getInputFormat
+ * MediaCodec.getInput}/{@link MediaCodec#getOutputFormat OutputFormat(…)}
+ * to confirm the actual format. For the PCM decoder this key specifies both
+ * input and output sample encodings.</p>
+ *
+ * <p>This key is also used by {@link MediaExtractor} to specify the sample
+ * format of audio data, if it is specified.</p>
+ *
+ * <p>If this key is missing, the raw audio sample format is signed 16-bit short.</p>
+ */
+ public static final String KEY_PCM_ENCODING = "pcm-encoding";
+
+ /**
* A key describing the capture rate of a video format in frames/sec.
* <p>
* When capture rate is different than the frame rate, it means that the
@@ -564,7 +585,7 @@
public static final String KEY_IS_TIMED_TEXT = "is-timed-text";
// The following color aspect values must be in sync with the ones in HardwareAPI.h.
- /*
+ /**
* An optional key describing the color primaries, white point and
* luminance factors for video content.
*
@@ -623,6 +644,21 @@
/** Full range. Y, Cr and Cb component values range from 0 to 255 for 8-bit content. */
public static final int COLOR_RANGE_FULL = 1;
+ /**
+ * A key describing a unique ID for the content of a media track.
+ *
+ * <p>This key is used by {@link MediaExtractor}. Some extractors provide multiple encodings
+ * of the same track (e.g. float audio tracks for FLAC and WAV may be expressed as two
+ * tracks via MediaExtractor: a normal PCM track for backward compatibility, and a float PCM
+ * track for added fidelity. Similarly, Dolby Vision extractor may provide a baseline SDR
+ * version of a DV track.) This key can be used to identify which MediaExtractor tracks refer
+ * to the same underlying content.
+ * </p>
+ *
+ * The associated value is an integer.
+ */
+ public static final String KEY_TRACK_ID = "track-id";
+
/* package private */ MediaFormat(Map<String, Object> map) {
mMap = map;
}
diff --git a/media/java/android/media/MediaMetadata.java b/media/java/android/media/MediaMetadata.java
index 39bcef5..722605f 100644
--- a/media/java/android/media/MediaMetadata.java
+++ b/media/java/android/media/MediaMetadata.java
@@ -16,6 +16,7 @@
package android.media;
import android.annotation.NonNull;
+import android.annotation.StringDef;
import android.content.ContentResolver;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -30,6 +31,8 @@
import android.util.Log;
import android.util.SparseArray;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Set;
/**
@@ -39,6 +42,40 @@
private static final String TAG = "MediaMetadata";
/**
+ * @hide
+ */
+ @StringDef({METADATA_KEY_TITLE, METADATA_KEY_ARTIST, METADATA_KEY_ALBUM, METADATA_KEY_AUTHOR,
+ METADATA_KEY_WRITER, METADATA_KEY_COMPOSER, METADATA_KEY_COMPILATION,
+ METADATA_KEY_DATE, METADATA_KEY_GENRE, METADATA_KEY_ALBUM_ARTIST, METADATA_KEY_ART_URI,
+ METADATA_KEY_ALBUM_ART_URI, METADATA_KEY_DISPLAY_TITLE, METADATA_KEY_DISPLAY_SUBTITLE,
+ METADATA_KEY_DISPLAY_DESCRIPTION, METADATA_KEY_DISPLAY_ICON_URI,
+ METADATA_KEY_MEDIA_ID})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TextKey {}
+
+ /**
+ * @hide
+ */
+ @StringDef({METADATA_KEY_DURATION, METADATA_KEY_YEAR, METADATA_KEY_TRACK_NUMBER,
+ METADATA_KEY_NUM_TRACKS, METADATA_KEY_DISC_NUMBER})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface LongKey {}
+
+ /**
+ * @hide
+ */
+ @StringDef({METADATA_KEY_ART, METADATA_KEY_ALBUM_ART, METADATA_KEY_DISPLAY_ICON})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface BitmapKey {}
+
+ /**
+ * @hide
+ */
+ @StringDef({METADATA_KEY_USER_RATING, METADATA_KEY_RATING})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface RatingKey {}
+
+ /**
* The title of the media.
*/
public static final String METADATA_KEY_TITLE = "android.media.metadata.TITLE";
@@ -232,7 +269,7 @@
*/
public static final String METADATA_KEY_MEDIA_ID = "android.media.metadata.MEDIA_ID";
- private static final String[] PREFERRED_DESCRIPTION_ORDER = {
+ private static final @TextKey String[] PREFERRED_DESCRIPTION_ORDER = {
METADATA_KEY_TITLE,
METADATA_KEY_ARTIST,
METADATA_KEY_ALBUM,
@@ -242,13 +279,13 @@
METADATA_KEY_COMPOSER
};
- private static final String[] PREFERRED_BITMAP_ORDER = {
+ private static final @BitmapKey String[] PREFERRED_BITMAP_ORDER = {
METADATA_KEY_DISPLAY_ICON,
METADATA_KEY_ART,
METADATA_KEY_ALBUM_ART
};
- private static final String[] PREFERRED_URI_ORDER = {
+ private static final @TextKey String[] PREFERRED_URI_ORDER = {
METADATA_KEY_DISPLAY_ICON_URI,
METADATA_KEY_ART_URI,
METADATA_KEY_ALBUM_ART_URI
@@ -349,7 +386,7 @@
* @param key The key the value is stored under
* @return a CharSequence value, or null
*/
- public CharSequence getText(String key) {
+ public CharSequence getText(@TextKey String key) {
return mBundle.getCharSequence(key);
}
@@ -362,7 +399,7 @@
* @param key The key the value is stored under
* @return a String value, or null
*/
- public String getString(String key) {
+ public String getString(@TextKey String key) {
CharSequence text = getText(key);
if (text != null) {
return text.toString();
@@ -377,7 +414,7 @@
* @param key The key the value is stored under
* @return a long value
*/
- public long getLong(String key) {
+ public long getLong(@LongKey String key) {
return mBundle.getLong(key, 0);
}
@@ -388,7 +425,7 @@
* @param key The key the value is stored under
* @return A {@link Rating} or null
*/
- public Rating getRating(String key) {
+ public Rating getRating(@RatingKey String key) {
Rating rating = null;
try {
rating = mBundle.getParcelable(key);
@@ -406,7 +443,7 @@
* @param key The key the value is stored under
* @return A {@link Bitmap} or null
*/
- public Bitmap getBitmap(String key) {
+ public Bitmap getBitmap(@BitmapKey String key) {
Bitmap bmp = null;
try {
bmp = mBundle.getParcelable(key);
@@ -612,7 +649,7 @@
* @param value The CharSequence value to store
* @return The Builder to allow chaining
*/
- public Builder putText(String key, CharSequence value) {
+ public Builder putText(@TextKey String key, CharSequence value) {
if (METADATA_KEYS_TYPE.containsKey(key)) {
if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) {
throw new IllegalArgumentException("The " + key
@@ -654,7 +691,7 @@
* @param value The String value to store
* @return The Builder to allow chaining
*/
- public Builder putString(String key, String value) {
+ public Builder putString(@TextKey String key, String value) {
if (METADATA_KEYS_TYPE.containsKey(key)) {
if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) {
throw new IllegalArgumentException("The " + key
@@ -681,7 +718,7 @@
* @param value The long value to store
* @return The Builder to allow chaining
*/
- public Builder putLong(String key, long value) {
+ public Builder putLong(@LongKey String key, long value) {
if (METADATA_KEYS_TYPE.containsKey(key)) {
if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_LONG) {
throw new IllegalArgumentException("The " + key
@@ -705,7 +742,7 @@
* @param value The Rating value to store
* @return The Builder to allow chaining
*/
- public Builder putRating(String key, Rating value) {
+ public Builder putRating(@RatingKey String key, Rating value) {
if (METADATA_KEYS_TYPE.containsKey(key)) {
if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_RATING) {
throw new IllegalArgumentException("The " + key
@@ -734,7 +771,7 @@
* @param value The Bitmap to store
* @return The Builder to allow chaining
*/
- public Builder putBitmap(String key, Bitmap value) {
+ public Builder putBitmap(@BitmapKey String key, Bitmap value) {
if (METADATA_KEYS_TYPE.containsKey(key)) {
if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_BITMAP) {
throw new IllegalArgumentException("The " + key
diff --git a/media/java/android/media/MediaMuxer.java b/media/java/android/media/MediaMuxer.java
index 8618ec9..ebe509c 100644
--- a/media/java/android/media/MediaMuxer.java
+++ b/media/java/android/media/MediaMuxer.java
@@ -127,7 +127,8 @@
* @param path The path of the output media file.
* @param format The format of the output media file.
* @see android.media.MediaMuxer.OutputFormat
- * @throws IOException if failed to open the file for write
+ * @throws IllegalArgumentException if path is invalid or format is not supported.
+ * @throws IOException if failed to open the file for write.
*/
public MediaMuxer(@NonNull String path, @Format int format) throws IOException {
if (path == null) {
@@ -165,6 +166,8 @@
* By default, the rotation degree is 0.</p>
* @param degrees the angle to be rotated clockwise in degrees.
* The supported angles are 0, 90, 180, and 270 degrees.
+ * @throws IllegalArgumentException if degree is not supported.
+ * @throws IllegalStateException If this method is called after {@link #start}.
*/
public void setOrientationHint(int degrees) {
if (degrees != 0 && degrees != 90 && degrees != 180 && degrees != 270) {
@@ -217,6 +220,8 @@
* Starts the muxer.
* <p>Make sure this is called after {@link #addTrack} and before
* {@link #writeSampleData}.</p>
+ * @throws IllegalStateException If this method is called after {@link #start}
+ * or Muxer is released
*/
public void start() {
if (mNativeObject == 0) {
@@ -233,6 +238,7 @@
/**
* Stops the muxer.
* <p>Once the muxer stops, it can not be restarted.</p>
+ * @throws IllegalStateException if muxer is in the wrong state.
*/
public void stop() {
if (mState == MUXER_STATE_STARTED) {
@@ -264,6 +270,8 @@
* MediaFormat.
* @return The track index for this newly added track, and it should be used
* in the {@link #writeSampleData}.
+ * @throws IllegalArgumentException if format is invalid.
+ * @throws IllegalStateException if muxer is in the wrong state.
*/
public int addTrack(@NonNull MediaFormat format) {
if (format == null) {
@@ -314,6 +322,8 @@
* @param byteBuf The encoded sample.
* @param trackIndex The track index for this sample.
* @param bufferInfo The buffer information related to this sample.
+ * @throws IllegalArgumentException if trackIndex, byteBuf or bufferInfo is invalid.
+ * @throws IllegalStateException if muxer is in wrong state.
* MediaMuxer uses the flags provided in {@link MediaCodec.BufferInfo},
* to signal sync frames.
*/
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 26e466e..b78869e 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -57,6 +57,7 @@
import android.media.SyncParams;
import com.android.internal.app.IAppOpsService;
+import com.android.internal.util.Preconditions;
import libcore.io.IoBridge;
import libcore.io.Libcore;
@@ -964,8 +965,8 @@
* @param uri the Content URI of the data you want to play
* @throws IllegalStateException if it is called in an invalid state
*/
- public void setDataSource(Context context, Uri uri)
- throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
+ public void setDataSource(@NonNull Context context, @NonNull Uri uri)
+ throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
setDataSource(context, uri, null);
}
@@ -981,47 +982,46 @@
* to disallow or allow cross domain redirection.
* @throws IllegalStateException if it is called in an invalid state
*/
- public void setDataSource(Context context, Uri uri, Map<String, String> headers)
- throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
+ public void setDataSource(@NonNull Context context, @NonNull Uri uri,
+ @Nullable Map<String, String> headers) throws IOException, IllegalArgumentException,
+ SecurityException, IllegalStateException {
+ final ContentResolver resolver = context.getContentResolver();
final String scheme = uri.getScheme();
if (ContentResolver.SCHEME_FILE.equals(scheme)) {
setDataSource(uri.getPath());
return;
} else if (ContentResolver.SCHEME_CONTENT.equals(scheme)
&& Settings.AUTHORITY.equals(uri.getAuthority())) {
- // Redirect ringtones to go directly to underlying provider
- uri = RingtoneManager.getActualDefaultRingtoneUri(context,
- RingtoneManager.getDefaultType(uri));
- if (uri == null) {
- throw new FileNotFoundException("Failed to resolve default ringtone");
- }
- }
-
- AssetFileDescriptor fd = null;
- try {
- ContentResolver resolver = context.getContentResolver();
- fd = resolver.openAssetFileDescriptor(uri, "r");
- if (fd == null) {
+ // Try cached ringtone first since the actual provider may not be
+ // encryption aware, or it may be stored on CE media storage
+ final int type = RingtoneManager.getDefaultType(uri);
+ final Uri cacheUri = RingtoneManager.getCacheForType(type);
+ final Uri actualUri = RingtoneManager.getActualDefaultRingtoneUri(context, type);
+ if (attemptDataSource(resolver, cacheUri)) {
return;
- }
- // Note: using getDeclaredLength so that our behavior is the same
- // as previous versions when the content provider is returning
- // a full file.
- if (fd.getDeclaredLength() < 0) {
- setDataSource(fd.getFileDescriptor());
+ } else if (attemptDataSource(resolver, actualUri)) {
+ return;
} else {
- setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getDeclaredLength());
+ setDataSource(uri.toString(), headers);
}
- return;
- } catch (SecurityException | IOException ex) {
- Log.w(TAG, "Couldn't open file on client side; trying server side: " + ex);
- } finally {
- if (fd != null) {
- fd.close();
+ } else {
+ // Try requested Uri locally first, or fallback to media server
+ if (attemptDataSource(resolver, uri)) {
+ return;
+ } else {
+ setDataSource(uri.toString(), headers);
}
}
+ }
- setDataSource(uri.toString(), headers);
+ private boolean attemptDataSource(ContentResolver resolver, Uri uri) {
+ try (AssetFileDescriptor afd = resolver.openAssetFileDescriptor(uri, "r")) {
+ setDataSource(afd);
+ return true;
+ } catch (NullPointerException | SecurityException | IOException ex) {
+ Log.w(TAG, "Couldn't open " + uri + ": " + ex);
+ return false;
+ }
}
/**
@@ -1102,6 +1102,26 @@
throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
/**
+ * Sets the data source (AssetFileDescriptor) to use. It is the caller's
+ * responsibility to close the file descriptor. It is safe to do so as soon
+ * as this call returns.
+ *
+ * @param afd the AssetFileDescriptor for the file you want to play
+ */
+ public void setDataSource(@NonNull AssetFileDescriptor afd)
+ throws IOException, IllegalArgumentException, IllegalStateException {
+ Preconditions.checkNotNull(afd);
+ // Note: using getDeclaredLength so that our behavior is the same
+ // as previous versions when the content provider is returning
+ // a full file.
+ if (afd.getDeclaredLength() < 0) {
+ setDataSource(afd.getFileDescriptor());
+ } else {
+ setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getDeclaredLength());
+ }
+ }
+
+ /**
* Sets the data source (FileDescriptor) to use. It is the caller's responsibility
* to close the file descriptor. It is safe to do so as soon as this call returns.
*
@@ -2825,13 +2845,17 @@
MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null);
sendMessage(msg2);
}
- if (mOnPreparedListener != null)
- mOnPreparedListener.onPrepared(mMediaPlayer);
+ OnPreparedListener onPreparedListener = mOnPreparedListener;
+ if (onPreparedListener != null)
+ onPreparedListener.onPrepared(mMediaPlayer);
return;
case MEDIA_PLAYBACK_COMPLETE:
- if (mOnCompletionListener != null)
- mOnCompletionListener.onCompletion(mMediaPlayer);
+ {
+ OnCompletionListener onCompletionListener = mOnCompletionListener;
+ if (onCompletionListener != null)
+ onCompletionListener.onCompletion(mMediaPlayer);
+ }
stayAwake(false);
return;
@@ -2855,13 +2879,15 @@
break;
case MEDIA_BUFFERING_UPDATE:
- if (mOnBufferingUpdateListener != null)
- mOnBufferingUpdateListener.onBufferingUpdate(mMediaPlayer, msg.arg1);
+ OnBufferingUpdateListener onBufferingUpdateListener = mOnBufferingUpdateListener;
+ if (onBufferingUpdateListener != null)
+ onBufferingUpdateListener.onBufferingUpdate(mMediaPlayer, msg.arg1);
return;
case MEDIA_SEEK_COMPLETE:
- if (mOnSeekCompleteListener != null) {
- mOnSeekCompleteListener.onSeekComplete(mMediaPlayer);
+ OnSeekCompleteListener onSeekCompleteListener = mOnSeekCompleteListener;
+ if (onSeekCompleteListener != null) {
+ onSeekCompleteListener.onSeekComplete(mMediaPlayer);
}
// fall through
@@ -2875,8 +2901,9 @@
return;
case MEDIA_SET_VIDEO_SIZE:
- if (mOnVideoSizeChangedListener != null) {
- mOnVideoSizeChangedListener.onVideoSizeChanged(
+ OnVideoSizeChangedListener onVideoSizeChangedListener = mOnVideoSizeChangedListener;
+ if (onVideoSizeChangedListener != null) {
+ onVideoSizeChangedListener.onVideoSizeChanged(
mMediaPlayer, msg.arg1, msg.arg2);
}
return;
@@ -2884,11 +2911,15 @@
case MEDIA_ERROR:
Log.e(TAG, "Error (" + msg.arg1 + "," + msg.arg2 + ")");
boolean error_was_handled = false;
- if (mOnErrorListener != null) {
- error_was_handled = mOnErrorListener.onError(mMediaPlayer, msg.arg1, msg.arg2);
+ OnErrorListener onErrorListener = mOnErrorListener;
+ if (onErrorListener != null) {
+ error_was_handled = onErrorListener.onError(mMediaPlayer, msg.arg1, msg.arg2);
}
- if (mOnCompletionListener != null && ! error_was_handled) {
- mOnCompletionListener.onCompletion(mMediaPlayer);
+ {
+ OnCompletionListener onCompletionListener = mOnCompletionListener;
+ if (onCompletionListener != null && ! error_was_handled) {
+ onCompletionListener.onCompletion(mMediaPlayer);
+ }
}
stayAwake(false);
return;
@@ -2924,47 +2955,52 @@
break;
}
- if (mOnInfoListener != null) {
- mOnInfoListener.onInfo(mMediaPlayer, msg.arg1, msg.arg2);
+ OnInfoListener onInfoListener = mOnInfoListener;
+ if (onInfoListener != null) {
+ onInfoListener.onInfo(mMediaPlayer, msg.arg1, msg.arg2);
}
// No real default action so far.
return;
case MEDIA_TIMED_TEXT:
- if (mOnTimedTextListener == null)
+ OnTimedTextListener onTimedTextListener = mOnTimedTextListener;
+ if (onTimedTextListener == null)
return;
if (msg.obj == null) {
- mOnTimedTextListener.onTimedText(mMediaPlayer, null);
+ onTimedTextListener.onTimedText(mMediaPlayer, null);
} else {
if (msg.obj instanceof Parcel) {
Parcel parcel = (Parcel)msg.obj;
TimedText text = new TimedText(parcel);
parcel.recycle();
- mOnTimedTextListener.onTimedText(mMediaPlayer, text);
+ onTimedTextListener.onTimedText(mMediaPlayer, text);
}
}
return;
case MEDIA_SUBTITLE_DATA:
- if (mOnSubtitleDataListener == null) {
+ OnSubtitleDataListener onSubtitleDataListener = mOnSubtitleDataListener;
+ if (onSubtitleDataListener == null) {
return;
}
if (msg.obj instanceof Parcel) {
Parcel parcel = (Parcel) msg.obj;
SubtitleData data = new SubtitleData(parcel);
parcel.recycle();
- mOnSubtitleDataListener.onSubtitleData(mMediaPlayer, data);
+ onSubtitleDataListener.onSubtitleData(mMediaPlayer, data);
}
return;
case MEDIA_META_DATA:
- if (mOnTimedMetaDataAvailableListener == null) {
+ OnTimedMetaDataAvailableListener onTimedMetaDataAvailableListener =
+ mOnTimedMetaDataAvailableListener;
+ if (onTimedMetaDataAvailableListener == null) {
return;
}
if (msg.obj instanceof Parcel) {
Parcel parcel = (Parcel) msg.obj;
TimedMetaData data = TimedMetaData.createTimedMetaDataFromParcel(parcel);
parcel.recycle();
- mOnTimedMetaDataAvailableListener.onTimedMetaDataAvailable(mMediaPlayer, data);
+ onTimedMetaDataAvailableListener.onTimedMetaDataAvailable(mMediaPlayer, data);
}
return;
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index bcc2b406..d8e0d6d 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -1547,18 +1547,30 @@
private Object mTag;
+ /** @hide */
+ @IntDef({PLAYBACK_TYPE_LOCAL, PLAYBACK_TYPE_REMOTE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PlaybackType {}
+
/**
* The default playback type, "local", indicating the presentation of the media is happening
* on the same device (e.g. a phone, a tablet) as where it is controlled from.
* @see #getPlaybackType()
*/
public final static int PLAYBACK_TYPE_LOCAL = 0;
+
/**
* A playback type indicating the presentation of the media is happening on
* a different device (i.e. the remote device) than where it is controlled from.
* @see #getPlaybackType()
*/
public final static int PLAYBACK_TYPE_REMOTE = 1;
+
+ /** @hide */
+ @IntDef({PLAYBACK_VOLUME_FIXED,PLAYBACK_VOLUME_VARIABLE})
+ @Retention(RetentionPolicy.SOURCE)
+ private @interface PlaybackVolume {}
+
/**
* Playback information indicating the playback volume is fixed, i.e. it cannot be
* controlled from this object. An example of fixed playback volume is a remote player,
@@ -1783,6 +1795,7 @@
* @return the type of playback associated with this route
* @see UserRouteInfo#setPlaybackType(int)
*/
+ @PlaybackType
public int getPlaybackType() {
return mPlaybackType;
}
@@ -1874,6 +1887,7 @@
* @return how volume is handling on the route
* @see UserRouteInfo#setVolumeHandling(int)
*/
+ @PlaybackVolume
public int getVolumeHandling() {
return mVolumeHandling;
}
@@ -2164,7 +2178,7 @@
* ({@link RouteInfo#PLAYBACK_TYPE_REMOTE}).
* @param type
*/
- public void setPlaybackType(int type) {
+ public void setPlaybackType(@RouteInfo.PlaybackType int type) {
if (mPlaybackType != type) {
mPlaybackType = type;
configureSessionVolume();
@@ -2177,7 +2191,7 @@
* ({@link RouteInfo#PLAYBACK_VOLUME_VARIABLE}).
* @param volumeHandling
*/
- public void setVolumeHandling(int volumeHandling) {
+ public void setVolumeHandling(@RouteInfo.PlaybackVolume int volumeHandling) {
if (mVolumeHandling != volumeHandling) {
mVolumeHandling = volumeHandling;
configureSessionVolume();
@@ -2268,7 +2282,8 @@
return;
}
if (mPlaybackType == RemoteControlClient.PLAYBACK_TYPE_REMOTE) {
- int volumeControl = VolumeProvider.VOLUME_CONTROL_FIXED;
+ @VolumeProvider.ControlType int volumeControl =
+ VolumeProvider.VOLUME_CONTROL_FIXED;
switch (mVolumeHandling) {
case RemoteControlClient.PLAYBACK_VOLUME_VARIABLE:
volumeControl = VolumeProvider.VOLUME_CONTROL_ABSOLUTE;
@@ -2294,7 +2309,8 @@
class SessionVolumeProvider extends VolumeProvider {
- public SessionVolumeProvider(int volumeControl, int maxVolume, int currentVolume) {
+ public SessionVolumeProvider(@VolumeProvider.ControlType int volumeControl,
+ int maxVolume, int currentVolume) {
super(volumeControl, maxVolume, currentVolume);
}
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 78f357f..5fd85d1 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -1042,13 +1042,13 @@
if(needToSetSettings) {
if (notifications) {
- setSettingIfNotSet(Settings.System.NOTIFICATION_SOUND, tableUri, rowId);
+ setRingtoneIfNotSet(Settings.System.NOTIFICATION_SOUND, tableUri, rowId);
mDefaultNotificationSet = true;
} else if (ringtones) {
- setSettingIfNotSet(Settings.System.RINGTONE, tableUri, rowId);
+ setRingtoneIfNotSet(Settings.System.RINGTONE, tableUri, rowId);
mDefaultRingtoneSet = true;
} else if (alarms) {
- setSettingIfNotSet(Settings.System.ALARM_ALERT, tableUri, rowId);
+ setRingtoneIfNotSet(Settings.System.ALARM_ALERT, tableUri, rowId);
mDefaultAlarmSet = true;
}
}
@@ -1063,18 +1063,18 @@
pathFilenameStart + filenameLength == path.length();
}
- private void setSettingIfNotSet(String settingName, Uri uri, long rowId) {
-
- if(wasSettingAlreadySet(settingName)) {
+ private void setRingtoneIfNotSet(String settingName, Uri uri, long rowId) {
+ if (wasRingtoneAlreadySet(settingName)) {
return;
}
ContentResolver cr = mContext.getContentResolver();
String existingSettingValue = Settings.System.getString(cr, settingName);
if (TextUtils.isEmpty(existingSettingValue)) {
- // Set the setting to the given URI
- Settings.System.putString(cr, settingName,
- ContentUris.withAppendedId(uri, rowId).toString());
+ final Uri settingUri = Settings.System.getUriFor(settingName);
+ final Uri ringtoneUri = ContentUris.withAppendedId(uri, rowId);
+ RingtoneManager.setActualDefaultRingtoneUri(mContext,
+ RingtoneManager.getDefaultType(settingUri), ringtoneUri);
}
Settings.System.putInt(cr, settingSetIndicatorName(settingName), 1);
}
@@ -1107,7 +1107,7 @@
return base + "_set";
}
- private boolean wasSettingAlreadySet(String name) {
+ private boolean wasRingtoneAlreadySet(String name) {
ContentResolver cr = mContext.getContentResolver();
String indicatorName = settingSetIndicatorName(name);
try {
@@ -1134,9 +1134,9 @@
selectionArgs = new String[] { "" };
}
- mDefaultRingtoneSet = wasSettingAlreadySet(Settings.System.RINGTONE);
- mDefaultNotificationSet = wasSettingAlreadySet(Settings.System.NOTIFICATION_SOUND);
- mDefaultAlarmSet = wasSettingAlreadySet(Settings.System.ALARM_ALERT);
+ mDefaultRingtoneSet = wasRingtoneAlreadySet(Settings.System.RINGTONE);
+ mDefaultNotificationSet = wasRingtoneAlreadySet(Settings.System.NOTIFICATION_SOUND);
+ mDefaultAlarmSet = wasRingtoneAlreadySet(Settings.System.ALARM_ALERT);
// Tell the provider to not delete the file.
// If the file is truly gone the delete is unnecessary, and we want to avoid
diff --git a/media/java/android/media/Rating.java b/media/java/android/media/Rating.java
index a518bb4..04d5364f 100644
--- a/media/java/android/media/Rating.java
+++ b/media/java/android/media/Rating.java
@@ -16,10 +16,14 @@
package android.media;
+import android.annotation.IntDef;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* A class to encapsulate rating information used as content metadata.
* A rating is defined by its rating style (see {@link #RATING_HEART},
@@ -32,6 +36,21 @@
private final static String TAG = "Rating";
/**
+ * @hide
+ */
+ @IntDef({RATING_NONE, RATING_HEART, RATING_THUMB_UP_DOWN, RATING_3_STARS, RATING_4_STARS,
+ RATING_5_STARS, RATING_PERCENTAGE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Style {}
+
+ /**
+ * @hide
+ */
+ @IntDef({RATING_3_STARS, RATING_4_STARS, RATING_5_STARS})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface StarStyle {}
+
+ /**
* Indicates a rating style is not supported. A Rating will never have this
* type, but can be used by other classes to indicate they do not support
* Rating.
@@ -75,7 +94,7 @@
private final float mRatingValue;
- private Rating(int ratingStyle, float rating) {
+ private Rating(@Style int ratingStyle, float rating) {
mRatingStyle = ratingStyle;
mRatingValue = rating;
}
@@ -124,7 +143,7 @@
* or {@link #RATING_PERCENTAGE}.
* @return null if an invalid rating style is passed, a new Rating instance otherwise.
*/
- public static Rating newUnratedRating(int ratingStyle) {
+ public static Rating newUnratedRating(@Style int ratingStyle) {
switch(ratingStyle) {
case RATING_HEART:
case RATING_THUMB_UP_DOWN:
@@ -172,7 +191,7 @@
* @return null if the rating style is invalid, or the rating is out of range,
* a new Rating instance otherwise.
*/
- public static Rating newStarRating(int starRatingStyle, float starRating) {
+ public static Rating newStarRating(@StarStyle int starRatingStyle, float starRating) {
float maxRating = -1.0f;
switch(starRatingStyle) {
case RATING_3_STARS:
@@ -225,6 +244,7 @@
* {@link #RATING_3_STARS}, {@link #RATING_4_STARS}, {@link #RATING_5_STARS},
* or {@link #RATING_PERCENTAGE}.
*/
+ @Style
public int getRatingStyle() {
return mRatingStyle;
}
@@ -285,4 +305,4 @@
return mRatingValue;
}
}
-}
\ No newline at end of file
+}
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 025029e..4977391 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -18,21 +18,29 @@
import com.android.internal.database.SortCursor;
+import libcore.io.Streams;
+
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.app.Activity;
+import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
+import android.os.ParcelFileDescriptor;
import android.os.Process;
+import android.os.RemoteException;
import android.provider.MediaStore;
import android.provider.Settings;
import android.provider.Settings.System;
import android.util.Log;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
@@ -217,9 +225,9 @@
*/
public static final int URI_COLUMN_INDEX = 2;
- private Activity mActivity;
- private Context mContext;
-
+ private final Activity mActivity;
+ private final Context mContext;
+
private Cursor mCursor;
private int mType = TYPE_RINGTONE;
@@ -240,7 +248,8 @@
* @param activity The activity used to get a managed cursor.
*/
public RingtoneManager(Activity activity) {
- mContext = mActivity = activity;
+ mActivity = activity;
+ mContext = activity;
setType(mType);
}
@@ -252,6 +261,7 @@
* @param context The context to used to get a cursor.
*/
public RingtoneManager(Context context) {
+ mActivity = null;
mContext = context;
setType(mType);
}
@@ -265,7 +275,6 @@
* @see #EXTRA_RINGTONE_TYPE
*/
public void setType(int type) {
-
if (mCursor != null) {
throw new IllegalStateException(
"Setting filter columns should be done before querying for ringtones.");
@@ -650,12 +659,48 @@
* @see #getActualDefaultRingtoneUri(Context, int)
*/
public static void setActualDefaultRingtoneUri(Context context, int type, Uri ringtoneUri) {
+ final ContentResolver resolver = context.getContentResolver();
+
String setting = getSettingForType(type);
if (setting == null) return;
- Settings.System.putString(context.getContentResolver(), setting,
+ Settings.System.putString(resolver, setting,
ringtoneUri != null ? ringtoneUri.toString() : null);
+
+ // Stream selected ringtone into cache so it's available for playback
+ // when CE storage is still locked
+ if (ringtoneUri != null) {
+ final Uri cacheUri = getCacheForType(type);
+ try (InputStream in = openRingtone(context, ringtoneUri);
+ OutputStream out = resolver.openOutputStream(cacheUri)) {
+ Streams.copy(in, out);
+ } catch (IOException e) {
+ Log.w(TAG, "Failed to cache ringtone: " + e);
+ }
+ }
}
-
+
+ /**
+ * Try opening the given ringtone locally first, but failover to
+ * {@link IRingtonePlayer} if we can't access it directly. Typically happens
+ * when process doesn't hold
+ * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE}.
+ */
+ private static InputStream openRingtone(Context context, Uri uri) throws IOException {
+ final ContentResolver resolver = context.getContentResolver();
+ try {
+ return resolver.openInputStream(uri);
+ } catch (SecurityException | IOException e) {
+ Log.w(TAG, "Failed to open directly; attempting failover: " + e);
+ final IRingtonePlayer player = context.getSystemService(AudioManager.class)
+ .getRingtonePlayer();
+ try {
+ return new ParcelFileDescriptor.AutoCloseInputStream(player.openRingtone(uri));
+ } catch (Exception e2) {
+ throw new IOException(e2);
+ }
+ }
+ }
+
private static String getSettingForType(int type) {
if ((type & TYPE_RINGTONE) != 0) {
return Settings.System.RINGTONE;
@@ -667,7 +712,20 @@
return null;
}
}
-
+
+ /** {@hide} */
+ public static Uri getCacheForType(int type) {
+ if ((type & TYPE_RINGTONE) != 0) {
+ return Settings.System.RINGTONE_CACHE_URI;
+ } else if ((type & TYPE_NOTIFICATION) != 0) {
+ return Settings.System.NOTIFICATION_SOUND_CACHE_URI;
+ } else if ((type & TYPE_ALARM) != 0) {
+ return Settings.System.ALARM_ALERT_CACHE_URI;
+ } else {
+ return null;
+ }
+ }
+
/**
* Returns whether the given {@link Uri} is one of the default ringtones.
*
diff --git a/media/java/android/media/VolumeProvider.java b/media/java/android/media/VolumeProvider.java
index 5d1e004..1c017c5 100644
--- a/media/java/android/media/VolumeProvider.java
+++ b/media/java/android/media/VolumeProvider.java
@@ -15,8 +15,12 @@
*/
package android.media;
+import android.annotation.IntDef;
import android.media.session.MediaSession;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Handles requests to adjust or set the volume on a session. This is also used
* to push volume updates back to the session. The provider must call
@@ -26,6 +30,14 @@
* {@link MediaSession#setPlaybackToRemote}.
*/
public abstract class VolumeProvider {
+
+ /**
+ * @hide
+ */
+ @IntDef({VOLUME_CONTROL_FIXED, VOLUME_CONTROL_RELATIVE, VOLUME_CONTROL_ABSOLUTE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ControlType {}
+
/**
* The volume is fixed and can not be modified. Requests to change volume
* should be ignored.
@@ -61,7 +73,7 @@
* @param maxVolume The maximum allowed volume.
* @param currentVolume The current volume on the output.
*/
- public VolumeProvider(int volumeControl, int maxVolume, int currentVolume) {
+ public VolumeProvider(@ControlType int volumeControl, int maxVolume, int currentVolume) {
mControlType = volumeControl;
mMaxVolume = maxVolume;
mCurrentVolume = currentVolume;
@@ -72,6 +84,7 @@
*
* @return The volume control type for this volume provider
*/
+ @ControlType
public final int getVolumeControl() {
return mControlType;
}
@@ -145,4 +158,4 @@
public static abstract class Callback {
public abstract void onVolumeChanged(VolumeProvider volumeProvider);
}
-}
\ No newline at end of file
+}
diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java
index 4ffac6d..55fb82b 100644
--- a/media/java/android/media/audiopolicy/AudioMix.java
+++ b/media/java/android/media/audiopolicy/AudioMix.java
@@ -277,6 +277,7 @@
mRouteFlags = ROUTE_FLAG_RENDER;
}
if (mFormat == null) {
+ // FIXME Can we eliminate this? Will AudioMix work with an unspecified sample rate?
int rate = AudioSystem.getPrimaryOutputSamplingRate();
if (rate <= 0) {
rate = 44100;
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index 2f72df6..ada0e2c 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -73,7 +73,6 @@
* Used as an int extra field to denote the page number to subscribe.
* The value of {@code EXTRA_PAGE} should be greater than or equal to 1.
*
- * @see android.service.media.MediaBrowserService.BrowserRoot
* @see #EXTRA_PAGE_SIZE
*/
public static final String EXTRA_PAGE = "android.media.browse.extra.PAGE";
@@ -82,7 +81,6 @@
* Used as an int extra field to denote the number of media items in a page.
* The value of {@code EXTRA_PAGE_SIZE} should be greater than or equal to 1.
*
- * @see android.service.media.MediaBrowserService.BrowserRoot
* @see #EXTRA_PAGE
*/
public static final String EXTRA_PAGE_SIZE = "android.media.browse.extra.PAGE_SIZE";
@@ -635,7 +633,6 @@
return;
}
- List<MediaItem> data = list == null ? null : list.getList();
if (DBG) {
Log.d(TAG, "onLoadChildren for " + mServiceComponent + " id=" + parentId);
}
@@ -646,10 +643,19 @@
// Tell the app.
SubscriptionCallback subscriptionCallback = subscription.getCallback(options);
if (subscriptionCallback != null) {
+ List<MediaItem> data = list == null ? null : list.getList();
if (options == null) {
- subscriptionCallback.onChildrenLoaded(parentId, data);
+ if (data == null) {
+ subscriptionCallback.onError(parentId);
+ } else {
+ subscriptionCallback.onChildrenLoaded(parentId, data);
+ }
} else {
- subscriptionCallback.onChildrenLoaded(parentId, data, options);
+ if (data == null) {
+ subscriptionCallback.onError(parentId, options);
+ } else {
+ subscriptionCallback.onChildrenLoaded(parentId, data, options);
+ }
}
return;
}
@@ -850,21 +856,21 @@
* Called when the list of children is loaded or updated.
*
* @param parentId The media id of the parent media item.
- * @param children The children which were loaded, or null if the id is invalid.
+ * @param children The children which were loaded.
*/
- public void onChildrenLoaded(@NonNull String parentId, List<MediaItem> children) {
+ public void onChildrenLoaded(@NonNull String parentId, @NonNull List<MediaItem> children) {
}
/**
* Called when the list of children is loaded or updated.
*
* @param parentId The media id of the parent media item.
- * @param children The children which were loaded, or null if the id is invalid.
- * @param options A bundle of service-specific arguments to send to the media
+ * @param children The children which were loaded.
+ * @param options A bundle of service-specific arguments sent to the media
* browse service. The contents of this bundle may affect the
* information returned when browsing.
*/
- public void onChildrenLoaded(@NonNull String parentId, List<MediaItem> children,
+ public void onChildrenLoaded(@NonNull String parentId, @NonNull List<MediaItem> children,
@NonNull Bundle options) {
}
diff --git a/media/java/android/media/midi/MidiManager.java b/media/java/android/media/midi/MidiManager.java
index 266b0d9..07c8ae8 100644
--- a/media/java/android/media/midi/MidiManager.java
+++ b/media/java/android/media/midi/MidiManager.java
@@ -186,8 +186,7 @@
try {
mService.registerListener(mToken, deviceListener);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in registerDeviceListener");
- return;
+ throw e.rethrowFromSystemServer();
}
mDeviceListeners.put(callback, deviceListener);
}
@@ -203,7 +202,7 @@
try {
mService.unregisterListener(mToken, deviceListener);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in unregisterDeviceListener");
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -217,8 +216,7 @@
try {
return mService.getDevices();
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in getDevices");
- return new MidiDeviceInfo[0];
+ throw e.rethrowFromSystemServer();
}
}
@@ -267,7 +265,7 @@
try {
mService.openDevice(mToken, deviceInfo, callback);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in openDevice");
+ throw e.rethrowFromSystemServer();
}
}
@@ -306,7 +304,7 @@
try {
mService.openBluetoothDevice(mToken, bluetoothDevice, callback);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in openDevice");
+ throw e.rethrowFromSystemServer();
}
}
@@ -326,8 +324,7 @@
}
return server;
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in createVirtualDevice");
- return null;
+ throw e.rethrowFromSystemServer();
}
}
}
diff --git a/media/java/android/media/session/ISession.aidl b/media/java/android/media/session/ISession.aidl
index bd0019f..3affee5c0 100644
--- a/media/java/android/media/session/ISession.aidl
+++ b/media/java/android/media/session/ISession.aidl
@@ -50,4 +50,6 @@
void setPlaybackToLocal(in AudioAttributes attributes);
void setPlaybackToRemote(int control, int max);
void setCurrentVolume(int currentVolume);
+
+ String getCallingPackage();
}
diff --git a/media/java/android/media/session/ISessionCallback.aidl b/media/java/android/media/session/ISessionCallback.aidl
index adb6b06..893bd3c 100644
--- a/media/java/android/media/session/ISessionCallback.aidl
+++ b/media/java/android/media/session/ISessionCallback.aidl
@@ -29,6 +29,10 @@
void onMediaButton(in Intent mediaButtonIntent, int sequenceNumber, in ResultReceiver cb);
// These callbacks are for the TransportPerformer
+ void onPrepare();
+ void onPrepareFromMediaId(String mediaId, in Bundle extras);
+ void onPrepareFromSearch(String query, in Bundle extras);
+ void onPrepareFromUri(in Uri uri, in Bundle extras);
void onPlay();
void onPlayFromMediaId(String mediaId, in Bundle extras);
void onPlayFromSearch(String query, in Bundle extras);
diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl
index 285e5f7..249bcdc 100644
--- a/media/java/android/media/session/ISessionController.aidl
+++ b/media/java/android/media/session/ISessionController.aidl
@@ -50,6 +50,10 @@
void setVolumeTo(int value, int flags, String packageName);
// These commands are for the TransportControls
+ void prepare();
+ void prepareFromMediaId(String mediaId, in Bundle extras);
+ void prepareFromSearch(String string, in Bundle extras);
+ void prepareFromUri(in Uri uri, in Bundle extras);
void play();
void playFromMediaId(String mediaId, in Bundle extras);
void playFromSearch(String string, in Bundle extras);
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 3d9b60d..622900f 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -592,6 +592,95 @@
}
/**
+ * Request that the player prepare its playback. In other words, other sessions can continue
+ * to play during the preparation of this session. This method can be used to speed up the
+ * start of the playback. Once the preparation is done, the session will change its playback
+ * state to {@link PlaybackState#STATE_PAUSED}. Afterwards, {@link #play} can be called to
+ * start playback.
+ */
+ public void prepare() {
+ try {
+ mSessionBinder.prepare();
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Error calling prepare.", e);
+ }
+ }
+
+ /**
+ * Request that the player prepare playback for a specific media id. In other words, other
+ * sessions can continue to play during the preparation of this session. This method can be
+ * used to speed up the start of the playback. Once the preparation is done, the session
+ * will change its playback state to {@link PlaybackState#STATE_PAUSED}. Afterwards,
+ * {@link #play} can be called to start playback. If the preparation is not needed,
+ * {@link #playFromMediaId} can be directly called without this method.
+ *
+ * @param mediaId The id of the requested media.
+ * @param extras Optional extras that can include extra information about the media item
+ * to be prepared.
+ */
+ public void prepareFromMediaId(String mediaId, Bundle extras) {
+ if (TextUtils.isEmpty(mediaId)) {
+ throw new IllegalArgumentException(
+ "You must specify a non-empty String for prepareFromMediaId.");
+ }
+ try {
+ mSessionBinder.prepareFromMediaId(mediaId, extras);
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Error calling prepare(" + mediaId + ").", e);
+ }
+ }
+
+ /**
+ * Request that the player prepare playback for a specific search query. An empty or null
+ * query should be treated as a request to prepare any music. In other words, other sessions
+ * can continue to play during the preparation of this session. This method can be used to
+ * speed up the start of the playback. Once the preparation is done, the session will
+ * change its playback state to {@link PlaybackState#STATE_PAUSED}. Afterwards,
+ * {@link #play} can be called to start playback. If the preparation is not needed,
+ * {@link #playFromSearch} can be directly called without this method.
+ *
+ * @param query The search query.
+ * @param extras Optional extras that can include extra information
+ * about the query.
+ */
+ public void prepareFromSearch(String query, Bundle extras) {
+ if (query == null) {
+ // This is to remain compatible with
+ // INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH
+ query = "";
+ }
+ try {
+ mSessionBinder.prepareFromSearch(query, extras);
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Error calling prepare(" + query + ").", e);
+ }
+ }
+
+ /**
+ * Request that the player prepare playback for a specific {@link Uri}. In other words,
+ * other sessions can continue to play during the preparation of this session. This method
+ * can be used to speed up the start of the playback. Once the preparation is done, the
+ * session will change its playback state to {@link PlaybackState#STATE_PAUSED}. Afterwards,
+ * {@link #play} can be called to start playback. If the preparation is not needed,
+ * {@link #playFromUri} can be directly called without this method.
+ *
+ * @param uri The URI of the requested media.
+ * @param extras Optional extras that can include extra information about the media item
+ * to be prepared.
+ */
+ public void prepareFromUri(Uri uri, Bundle extras) {
+ if (uri == null || Uri.EMPTY.equals(uri)) {
+ throw new IllegalArgumentException(
+ "You must specify a non-empty Uri for prepareFromUri.");
+ }
+ try {
+ mSessionBinder.prepareFromUri(uri, extras);
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Error calling prepare(" + uri + ").", e);
+ }
+ }
+
+ /**
* Request that the player start its playback at its current position.
*/
public void play() {
@@ -605,7 +694,6 @@
/**
* Request that the player start playback for a specific media id.
*
- * @see PlaybackState#EXTRA_PREPARE_ONLY
* @param mediaId The id of the requested media.
* @param extras Optional extras that can include extra information about the media item
* to be played.
@@ -627,10 +715,9 @@
* An empty or null query should be treated as a request to play any
* music.
*
- * @see PlaybackState#EXTRA_PREPARE_ONLY
* @param query The search query.
* @param extras Optional extras that can include extra information
- * about the query.
+ * about the query.
*/
public void playFromSearch(String query, Bundle extras) {
if (query == null) {
@@ -648,8 +735,7 @@
/**
* Request that the player start playback for a specific {@link Uri}.
*
- * @see PlaybackState#EXTRA_PREPARE_ONLY
- * @param uri The URI of the requested media.
+ * @param uri The URI of the requested media.
* @param extras Optional extras that can include extra information about the media item
* to be played.
*/
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index 8c5b19c..7f9653d 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -87,12 +87,6 @@
public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 1 << 1;
/**
- * Set this flag on the session to indicate that it can handle
- * the {@link PlaybackState#EXTRA_PREPARE_ONLY} field.
- */
- public static final int FLAG_HANDLES_PREPARE_ONLY = 1 << 2;
-
- /**
* System only flag for a session that needs to have priority over all other
* sessions. This flag ensures this session will receive media button events
* regardless of the current ordering in the system.
@@ -106,7 +100,6 @@
@IntDef(flag = true, value = {
FLAG_HANDLES_MEDIA_BUTTONS,
FLAG_HANDLES_TRANSPORT_CONTROLS,
- FLAG_HANDLES_PREPARE_ONLY,
FLAG_EXCLUSIVE_GLOBAL_PRIORITY })
public @interface SessionFlags { }
@@ -476,7 +469,7 @@
* <li>{@link Rating#RATING_THUMB_UP_DOWN}</li>
* </ul>
*/
- public void setRatingType(int type) {
+ public void setRatingType(@Rating.Style int type) {
try {
mBinder.setRatingType(type);
} catch (RemoteException e) {
@@ -519,6 +512,38 @@
}
}
+ /**
+ * Returns the name of the package that sent the last media button, transport control, or
+ * command from controllers and the system. This is only valid while in a request callback, such
+ * as {@link Callback#onPlay}.
+ *
+ * @hide
+ */
+ public String getCallingPackage() {
+ try {
+ return mBinder.getCallingPackage();
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Dead object in getCallingPackage.", e);
+ }
+ return null;
+ }
+
+ private void dispatchPrepare() {
+ postToCallback(CallbackMessageHandler.MSG_PREPARE);
+ }
+
+ private void dispatchPrepareFromMediaId(String mediaId, Bundle extras) {
+ postToCallback(CallbackMessageHandler.MSG_PREPARE_MEDIA_ID, mediaId, extras);
+ }
+
+ private void dispatchPrepareFromSearch(String query, Bundle extras) {
+ postToCallback(CallbackMessageHandler.MSG_PREPARE_SEARCH, query, extras);
+ }
+
+ private void dispatchPrepareFromUri(Uri uri, Bundle extras) {
+ postToCallback(CallbackMessageHandler.MSG_PREPARE_URI, uri, extras);
+ }
+
private void dispatchPlay() {
postToCallback(CallbackMessageHandler.MSG_PLAY);
}
@@ -805,16 +830,54 @@
}
/**
- * Override to handle requests to begin playback.
+ * Override to handle requests to prepare playback. During the preparation, a session should
+ * not hold audio focus in order to allow other sessions play seamlessly. The state of
+ * playback should be updated to {@link PlaybackState#STATE_PAUSED} after the preparation is
+ * done.
*/
- public void onPlay() {
+ public void onPrepare() {
}
/**
- * Override to handle requests to play a specific mediaId that was
- * provided by your app's {@link MediaBrowserService}.
+ * Override to handle requests to prepare for playing a specific mediaId that was provided
+ * by your app's {@link MediaBrowserService}. During the preparation, a session should not
+ * hold audio focus in order to allow other sessions play seamlessly. The state of playback
+ * should be updated to {@link PlaybackState#STATE_PAUSED} after the preparation is done.
+ * The playback of the prepared content should start in the implementation of
+ * {@link #onPlay}. Override {@link #onPlayFromMediaId} to handle requests for starting
+ * playback without preparation.
*/
- public void onPlayFromMediaId(String mediaId, Bundle extras) {
+ public void onPrepareFromMediaId(String mediaId, Bundle extras) {
+ }
+
+ /**
+ * Override to handle requests to prepare playback from a search query. An empty query
+ * indicates that the app may prepare any music. The implementation should attempt to make a
+ * smart choice about what to play. During the preparation, a session should not hold audio
+ * focus in order to allow other sessions play seamlessly. The state of playback should be
+ * updated to {@link PlaybackState#STATE_PAUSED} after the preparation is done. The playback
+ * of the prepared content should start in the implementation of {@link #onPlay}. Override
+ * {@link #onPlayFromSearch} to handle requests for starting playback without preparation.
+ */
+ public void onPrepareFromSearch(String query, Bundle extras) {
+ }
+
+ /**
+ * Override to handle requests to prepare a specific media item represented by a URI.
+ * During the preparation, a session should not hold audio focus in order to allow
+ * other sessions play seamlessly. The state of playback should be updated to
+ * {@link PlaybackState#STATE_PAUSED} after the preparation is done.
+ * The playback of the prepared content should start in the implementation of
+ * {@link #onPlay}. Override {@link #onPlayFromUri} to handle requests
+ * for starting playback without preparation.
+ */
+ public void onPrepareFromUri(Uri uri, Bundle extras) {
+ }
+
+ /**
+ * Override to handle requests to begin playback.
+ */
+ public void onPlay() {
}
/**
@@ -827,6 +890,13 @@
}
/**
+ * Override to handle requests to play a specific mediaId that was
+ * provided by your app's {@link MediaBrowserService}.
+ */
+ public void onPlayFromMediaId(String mediaId, Bundle extras) {
+ }
+
+ /**
* Override to handle requests to play a specific media item represented by a URI.
*/
public void onPlayFromUri(Uri uri, Bundle extras) {
@@ -937,6 +1007,38 @@
}
@Override
+ public void onPrepare() {
+ MediaSession session = mMediaSession.get();
+ if (session != null) {
+ session.dispatchPrepare();
+ }
+ }
+
+ @Override
+ public void onPrepareFromMediaId(String mediaId, Bundle extras) {
+ MediaSession session = mMediaSession.get();
+ if (session != null) {
+ session.dispatchPrepareFromMediaId(mediaId, extras);
+ }
+ }
+
+ @Override
+ public void onPrepareFromSearch(String query, Bundle extras) {
+ MediaSession session = mMediaSession.get();
+ if (session != null) {
+ session.dispatchPrepareFromSearch(query, extras);
+ }
+ }
+
+ @Override
+ public void onPrepareFromUri(Uri uri, Bundle extras) {
+ MediaSession session = mMediaSession.get();
+ if (session != null) {
+ session.dispatchPrepareFromUri(uri, extras);
+ }
+ }
+
+ @Override
public void onPlay() {
MediaSession session = mMediaSession.get();
if (session != null) {
@@ -1162,24 +1264,28 @@
private class CallbackMessageHandler extends Handler {
- private static final int MSG_PLAY = 1;
- private static final int MSG_PLAY_MEDIA_ID = 2;
- private static final int MSG_PLAY_SEARCH = 3;
- private static final int MSG_SKIP_TO_ITEM = 4;
- private static final int MSG_PAUSE = 5;
- private static final int MSG_STOP = 6;
- private static final int MSG_NEXT = 7;
- private static final int MSG_PREVIOUS = 8;
- private static final int MSG_FAST_FORWARD = 9;
- private static final int MSG_REWIND = 10;
- private static final int MSG_SEEK_TO = 11;
- private static final int MSG_RATE = 12;
- private static final int MSG_CUSTOM_ACTION = 13;
- private static final int MSG_MEDIA_BUTTON = 14;
- private static final int MSG_COMMAND = 15;
- private static final int MSG_ADJUST_VOLUME = 16;
- private static final int MSG_SET_VOLUME = 17;
- private static final int MSG_PLAY_URI = 18;
+ private static final int MSG_COMMAND = 1;
+ private static final int MSG_MEDIA_BUTTON = 2;
+ private static final int MSG_PREPARE = 3;
+ private static final int MSG_PREPARE_MEDIA_ID = 4;
+ private static final int MSG_PREPARE_SEARCH = 5;
+ private static final int MSG_PREPARE_URI = 6;
+ private static final int MSG_PLAY = 7;
+ private static final int MSG_PLAY_MEDIA_ID = 8;
+ private static final int MSG_PLAY_SEARCH = 9;
+ private static final int MSG_PLAY_URI = 10;
+ private static final int MSG_SKIP_TO_ITEM = 11;
+ private static final int MSG_PAUSE = 12;
+ private static final int MSG_STOP = 13;
+ private static final int MSG_NEXT = 14;
+ private static final int MSG_PREVIOUS = 15;
+ private static final int MSG_FAST_FORWARD = 16;
+ private static final int MSG_REWIND = 17;
+ private static final int MSG_SEEK_TO = 18;
+ private static final int MSG_RATE = 19;
+ private static final int MSG_CUSTOM_ACTION = 20;
+ private static final int MSG_ADJUST_VOLUME = 21;
+ private static final int MSG_SET_VOLUME = 22;
private MediaSession.Callback mCallback;
@@ -1210,6 +1316,25 @@
public void handleMessage(Message msg) {
VolumeProvider vp;
switch (msg.what) {
+ case MSG_COMMAND:
+ Command cmd = (Command) msg.obj;
+ mCallback.onCommand(cmd.command, cmd.extras, cmd.stub);
+ break;
+ case MSG_MEDIA_BUTTON:
+ mCallback.onMediaButtonEvent((Intent) msg.obj);
+ break;
+ case MSG_PREPARE:
+ mCallback.onPrepare();
+ break;
+ case MSG_PREPARE_MEDIA_ID:
+ mCallback.onPrepareFromMediaId((String) msg.obj, msg.getData());
+ break;
+ case MSG_PREPARE_SEARCH:
+ mCallback.onPrepareFromSearch((String) msg.obj, msg.getData());
+ break;
+ case MSG_PREPARE_URI:
+ mCallback.onPrepareFromUri((Uri) msg.obj, msg.getData());
+ break;
case MSG_PLAY:
mCallback.onPlay();
break;
@@ -1252,13 +1377,6 @@
case MSG_CUSTOM_ACTION:
mCallback.onCustomAction((String) msg.obj, msg.getData());
break;
- case MSG_MEDIA_BUTTON:
- mCallback.onMediaButtonEvent((Intent) msg.obj);
- break;
- case MSG_COMMAND:
- Command cmd = (Command) msg.obj;
- mCallback.onCommand(cmd.command, cmd.extras, cmd.stub);
- break;
case MSG_ADJUST_VOLUME:
synchronized (mLock) {
vp = mVolumeProvider;
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index 1079a1f..8283c8b 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -16,6 +16,7 @@
package android.media.session;
import android.annotation.DrawableRes;
+import android.annotation.IntDef;
import android.annotation.Nullable;
import android.media.RemoteControlClient;
import android.os.Bundle;
@@ -26,6 +27,9 @@
import java.util.ArrayList;
import java.util.List;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Playback state for a {@link MediaSession}. This includes a state like
* {@link PlaybackState#STATE_PLAYING}, the current playback position,
@@ -35,6 +39,17 @@
private static final String TAG = "PlaybackState";
/**
+ * @hide
+ */
+ @IntDef(flag=true, value={ACTION_STOP, ACTION_PAUSE, ACTION_PLAY, ACTION_REWIND,
+ ACTION_SKIP_TO_PREVIOUS, ACTION_SKIP_TO_NEXT, ACTION_FAST_FORWARD, ACTION_SET_RATING,
+ ACTION_SEEK_TO, ACTION_PLAY_PAUSE, ACTION_PLAY_FROM_MEDIA_ID, ACTION_PLAY_FROM_SEARCH,
+ ACTION_SKIP_TO_QUEUE_ITEM, ACTION_PLAY_FROM_URI, ACTION_PREPARE,
+ ACTION_PREPARE_FROM_MEDIA_ID, ACTION_PREPARE_FROM_SEARCH, ACTION_PREPARE_FROM_URI})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Actions {}
+
+ /**
* Indicates this session supports the stop command.
*
* @see Builder#setActions(long)
@@ -133,19 +148,41 @@
public static final long ACTION_PLAY_FROM_URI = 1 << 13;
/**
- * Used as an optional boolean extra field in
- * {@link MediaController.TransportControls#playFromMediaId},
- * {@link MediaController.TransportControls#playFromSearch}, and
- * {@link MediaController.TransportControls#playFromUri}. Value of {@code true} overrides
- * the default behavior of starting the playback after preparing. Check
- * {@link MediaSession#FLAG_HANDLES_PREPARE_ONLY} to see if the media session supports this.
+ * Indicates this session supports the prepare command.
*
- * @see MediaSession#FLAG_HANDLES_PREPARE_ONLY
- * @see MediaController.TransportControls#playFromMediaId
- * @see MediaController.TransportControls#playFromSearch
- * @see MediaController.TransportControls#playFromUri
+ * @see Builder#setActions(long)
*/
- public static final String EXTRA_PREPARE_ONLY = "android.media.session.extra.PREPARE_ONLY";
+ public static final long ACTION_PREPARE = 1 << 14;
+
+ /**
+ * Indicates this session supports the prepare from media id command.
+ *
+ * @see Builder#setActions(long)
+ */
+ public static final long ACTION_PREPARE_FROM_MEDIA_ID = 1 << 15;
+
+ /**
+ * Indicates this session supports the prepare from search command.
+ *
+ * @see Builder#setActions(long)
+ */
+ public static final long ACTION_PREPARE_FROM_SEARCH = 1 << 16;
+
+ /**
+ * Indicates this session supports the prepare from URI command.
+ *
+ * @see Builder#setActions(long)
+ */
+ public static final long ACTION_PREPARE_FROM_URI = 1 << 17;
+
+ /**
+ * @hide
+ */
+ @IntDef({STATE_NONE, STATE_STOPPED, STATE_PAUSED, STATE_PLAYING, STATE_FAST_FORWARDING,
+ STATE_REWINDING, STATE_BUFFERING, STATE_ERROR, STATE_CONNECTING,
+ STATE_SKIPPING_TO_PREVIOUS, STATE_SKIPPING_TO_NEXT, STATE_SKIPPING_TO_QUEUE_ITEM})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface State {}
/**
* This is the default playback state and indicates that no media has been
@@ -330,11 +367,17 @@
* <li> {@link PlaybackState#STATE_REWINDING}</li>
* <li> {@link PlaybackState#STATE_BUFFERING}</li>
* <li> {@link PlaybackState#STATE_ERROR}</li>
+ * <li> {@link PlaybackState#STATE_CONNECTING}</li>
+ * <li> {@link PlaybackState#STATE_SKIPPING_TO_PREVIOUS}</li>
+ * <li> {@link PlaybackState#STATE_SKIPPING_TO_NEXT}</li>
+ * <li> {@link PlaybackState#STATE_SKIPPING_TO_QUEUE_ITEM}</li>
* </ul>
*/
+ @State
public int getState() {
return mState;
}
+
/**
* Get the current playback position in ms.
*/
@@ -380,8 +423,13 @@
* <li> {@link PlaybackState#ACTION_PLAY_FROM_SEARCH}</li>
* <li> {@link PlaybackState#ACTION_SKIP_TO_QUEUE_ITEM}</li>
* <li> {@link PlaybackState#ACTION_PLAY_FROM_URI}</li>
+ * <li> {@link PlaybackState#ACTION_PREPARE}</li>
+ * <li> {@link PlaybackState#ACTION_PREPARE_FROM_MEDIA_ID}</li>
+ * <li> {@link PlaybackState#ACTION_PREPARE_FROM_SEARCH}</li>
+ * <li> {@link PlaybackState#ACTION_PREPARE_FROM_URI}</li>
* </ul>
*/
+ @Actions
public long getActions() {
return mActions;
}
@@ -831,6 +879,10 @@
* <li> {@link PlaybackState#STATE_REWINDING}</li>
* <li> {@link PlaybackState#STATE_BUFFERING}</li>
* <li> {@link PlaybackState#STATE_ERROR}</li>
+ * <li> {@link PlaybackState#STATE_CONNECTING}</li>
+ * <li> {@link PlaybackState#STATE_SKIPPING_TO_PREVIOUS}</li>
+ * <li> {@link PlaybackState#STATE_SKIPPING_TO_NEXT}</li>
+ * <li> {@link PlaybackState#STATE_SKIPPING_TO_QUEUE_ITEM}</li>
* </ul>
*
* @param state The current state of playback.
@@ -841,7 +893,8 @@
* timebase that the position was updated at.
* @return this
*/
- public Builder setState(int state, long position, float playbackSpeed, long updateTime) {
+ public Builder setState(@State int state, long position, float playbackSpeed,
+ long updateTime) {
mState = state;
mPosition = position;
mUpdateTime = updateTime;
@@ -870,6 +923,10 @@
* <li> {@link PlaybackState#STATE_REWINDING}</li>
* <li> {@link PlaybackState#STATE_BUFFERING}</li>
* <li> {@link PlaybackState#STATE_ERROR}</li>
+ * <li> {@link PlaybackState#STATE_CONNECTING}</li>
+ * <li> {@link PlaybackState#STATE_SKIPPING_TO_PREVIOUS}</li>
+ * <li> {@link PlaybackState#STATE_SKIPPING_TO_NEXT}</li>
+ * <li> {@link PlaybackState#STATE_SKIPPING_TO_QUEUE_ITEM}</li>
* </ul>
*
* @param state The current state of playback.
@@ -878,7 +935,7 @@
* normal playback.
* @return this
*/
- public Builder setState(int state, long position, float playbackSpeed) {
+ public Builder setState(@State int state, long position, float playbackSpeed) {
return setState(state, position, playbackSpeed, SystemClock.elapsedRealtime());
}
@@ -900,12 +957,16 @@
* <li> {@link PlaybackState#ACTION_PLAY_FROM_SEARCH}</li>
* <li> {@link PlaybackState#ACTION_SKIP_TO_QUEUE_ITEM}</li>
* <li> {@link PlaybackState#ACTION_PLAY_FROM_URI}</li>
+ * <li> {@link PlaybackState#ACTION_PREPARE}</li>
+ * <li> {@link PlaybackState#ACTION_PREPARE_FROM_MEDIA_ID}</li>
+ * <li> {@link PlaybackState#ACTION_PREPARE_FROM_SEARCH}</li>
+ * <li> {@link PlaybackState#ACTION_PREPARE_FROM_URI}</li>
* </ul>
*
* @param actions The set of actions allowed.
* @return this
*/
- public Builder setActions(long actions) {
+ public Builder setActions(@Actions long actions) {
mActions = actions;
return this;
}
diff --git a/media/java/android/media/soundtrigger/SoundTriggerDetector.java b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
index 8f022db..df0961b 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerDetector.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
@@ -289,8 +289,8 @@
* @hide
*/
@Override
- public void onDetected(SoundTrigger.RecognitionEvent event) {
- Slog.d(TAG, "onDetected()" + event);
+ public void onGenericSoundTriggerDetected(SoundTrigger.GenericRecognitionEvent event) {
+ Slog.d(TAG, "onGenericSoundTriggerDetected()" + event);
Message.obtain(mHandler,
MSG_SOUND_TRIGGER_DETECTED,
new EventPayload(event.triggerInData, event.captureAvailable,
@@ -298,6 +298,11 @@
.sendToTarget();
}
+ @Override
+ public void onKeyphraseDetected(SoundTrigger.KeyphraseRecognitionEvent event) {
+ Slog.e(TAG, "Ignoring onKeyphraseDetected() called for " + event);
+ }
+
/**
* @hide
*/
diff --git a/media/java/android/media/soundtrigger/SoundTriggerManager.java b/media/java/android/media/soundtrigger/SoundTriggerManager.java
index 4fd3310..fdd7fc2 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerManager.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerManager.java
@@ -69,6 +69,7 @@
try {
mSoundTriggerService.updateSoundModel(model.getGenericSoundModel());
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -81,7 +82,7 @@
return new Model(mSoundTriggerService.getSoundModel(
new ParcelUuid(soundModelId)));
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -92,6 +93,7 @@
try {
mSoundTriggerService.deleteSoundModel(new ParcelUuid(soundModelId));
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
diff --git a/media/java/android/media/tv/ITvInputClient.aidl b/media/java/android/media/tv/ITvInputClient.aidl
index 5dd4e85..72f8b57 100644
--- a/media/java/android/media/tv/ITvInputClient.aidl
+++ b/media/java/android/media/tv/ITvInputClient.aidl
@@ -45,7 +45,7 @@
void onTimeShiftCurrentPositionChanged(long timeMs, int seq);
// For the recording session
- void onTuned(int seq);
+ void onTuned(int seq, in Uri channelUri);
void onRecordingStopped(in Uri recordedProgramUri, int seq);
void onError(int error, int seq);
}
diff --git a/media/java/android/media/tv/ITvInputSessionCallback.aidl b/media/java/android/media/tv/ITvInputSessionCallback.aidl
index 60d6f0d..af76f90 100644
--- a/media/java/android/media/tv/ITvInputSessionCallback.aidl
+++ b/media/java/android/media/tv/ITvInputSessionCallback.aidl
@@ -42,7 +42,7 @@
void onTimeShiftCurrentPositionChanged(long timeMs);
// For the recording session
- void onTuned();
+ void onTuned(in Uri channelUri);
void onRecordingStopped(in Uri recordedProgramUri);
void onError(int error);
}
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index 9203ef2..a332195 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -16,6 +16,7 @@
package android.media.tv;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.ComponentName;
@@ -25,6 +26,7 @@
import android.net.Uri;
import android.os.IBinder;
import android.provider.BaseColumns;
+import android.text.TextUtils;
import android.util.ArraySet;
import java.util.ArrayList;
@@ -53,6 +55,13 @@
/** The authority for the TV provider. */
public static final String AUTHORITY = "android.media.tv";
+ /**
+ * Permission to read TV listings. This is required to read all the TV channel and program
+ * information available on the system.
+ * @hide
+ */
+ public static final String PERMISSION_READ_TV_LISTINGS = "android.permission.READ_TV_LISTINGS";
+
private static final String PATH_CHANNEL = "channel";
private static final String PATH_PROGRAM = "program";
private static final String PATH_RECORDED_PROGRAM = "recorded_program";
@@ -304,33 +313,28 @@
}
/**
- * Returns true, if {@code uri} is a channel URI.
- * @hide
+ * Returns {@code true}, if {@code uri} is a channel URI.
*/
public static final boolean isChannelUri(Uri uri) {
return isChannelUriForTunerInput(uri) || isChannelUriForPassthroughInput(uri);
}
/**
- * Returns true, if {@code uri} is a channel URI for a tuner input.
- * @hide
+ * Returns {@code true}, if {@code uri} is a channel URI for a tuner input.
*/
public static final boolean isChannelUriForTunerInput(Uri uri) {
return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_CHANNEL);
}
/**
- * Returns true, if {@code uri} is a channel URI for a passthrough input.
- * @hide
+ * Returns {@code true}, if {@code uri} is a channel URI for a pass-through input.
*/
- @SystemApi
public static final boolean isChannelUriForPassthroughInput(Uri uri) {
return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_PASSTHROUGH);
}
/**
- * Returns true, if {@code uri} is a program URI.
- * @hide
+ * Returns {@code true}, if {@code uri} is a program URI.
*/
public static final boolean isProgramUri(Uri uri) {
return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_PROGRAM);
@@ -962,8 +966,9 @@
* The title of this TV program.
*
* <p>If this program is an episodic TV show, it is recommended that the title is the series
- * title and its related fields ({@link #COLUMN_SEASON_NUMBER},
- * {@link #COLUMN_EPISODE_NUMBER}, and {@link #COLUMN_EPISODE_TITLE}) are filled in.
+ * title and its related fields ({@link #COLUMN_SEASON_TITLE} and/or
+ * {@link #COLUMN_SEASON_DISPLAY_NUMBER}, {@link #COLUMN_SEASON_DISPLAY_NUMBER},
+ * {@link #COLUMN_EPISODE_DISPLAY_NUMBER}, and {@link #COLUMN_EPISODE_TITLE}) are filled in.
*
* <p>Type: TEXT
*/
@@ -975,19 +980,65 @@
* <p>Can be empty.
*
* <p>Type: INTEGER
+ *
+ * @deprecated Use {@link #COLUMN_SEASON_DISPLAY_NUMBER} instead.
*/
+ @Deprecated
public static final String COLUMN_SEASON_NUMBER = "season_number";
/**
+ * The season display number of this TV program for episodic TV shows.
+ *
+ * <p>This is used to indicate the season number. (e.g. 1, 2 or 3) Note that the value
+ * does not necessarily be numeric. (e.g. 12B)
+ *
+ * <p>Can be empty.
+ *
+ * <p>Type: TEXT
+ */
+ public static final String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
+
+ /**
+ * The title of the season for this TV program for episodic TV shows.
+ *
+ * <p>This is an optional field supplied only when the season has a special title
+ * (e.g. The Final Season). If provided, the applications should display it instead of
+ * {@link #COLUMN_SEASON_DISPLAY_NUMBER}, and should display it without alterations.
+ * (e.g. for "The Final Season", displayed string should be "The Final Season", not
+ * "Season The Final Season"). When displaying multiple programs, the order should be based
+ * on {@link #COLUMN_SEASON_DISPLAY_NUMBER}, even when {@link #COLUMN_SEASON_TITLE} exists.
+ *
+ * <p>Can be empty.
+ *
+ * <p>Type: TEXT
+ */
+ public static final String COLUMN_SEASON_TITLE = "season_title";
+
+ /**
* The episode number of this TV program for episodic TV shows.
*
* <p>Can be empty.
*
* <p>Type: INTEGER
+ *
+ * @deprecated Use {@link #COLUMN_EPISODE_DISPLAY_NUMBER} instead.
*/
+ @Deprecated
public static final String COLUMN_EPISODE_NUMBER = "episode_number";
/**
+ * The episode display number of this TV program for episodic TV shows.
+ *
+ * <p>This is used to indicate the episode number. (e.g. 1, 2 or 3) Note that the value
+ * does not necessarily be numeric. (e.g. 12B)
+ *
+ * <p>Can be empty.
+ *
+ * <p>Type: TEXT
+ */
+ public static final String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
+
+ /**
* The episode title of this TV program for episodic TV shows.
*
* <p>Can be empty.
@@ -1314,6 +1365,8 @@
private static final char COMMA = ',';
private static final String DELIMITER = ",";
+ private static final String[] EMPTY_STRING_ARRAY = new String[0];
+
private Genres() {}
/**
@@ -1323,7 +1376,11 @@
* @return an encoded genre string that can be inserted into the
* {@link #COLUMN_BROADCAST_GENRE} or {@link #COLUMN_CANONICAL_GENRE} column.
*/
- public static String encode(String... genres) {
+ public static String encode(@NonNull String... genres) {
+ if (genres == null) {
+ // MNC and before will throw a NPE.
+ return null;
+ }
StringBuilder sb = new StringBuilder();
String separator = "";
for (String genre : genres) {
@@ -1358,7 +1415,14 @@
* {@link #COLUMN_BROADCAST_GENRE} or {@link #COLUMN_CANONICAL_GENRE} column.
* @return genre strings.
*/
- public static String[] decode(String genres) {
+ public static String[] decode(@NonNull String genres) {
+ if (TextUtils.isEmpty(genres)) {
+ // MNC and before will throw a NPE for {@code null} genres.
+ return EMPTY_STRING_ARRAY;
+ }
+ if (genres.indexOf(COMMA) == -1 && genres.indexOf(DOUBLE_QUOTE) == -1) {
+ return new String[] {genres.trim()};
+ }
StringBuilder sb = new StringBuilder();
List<String> results = new ArrayList<>();
int length = genres.length();
@@ -1394,13 +1458,11 @@
}
/**
- * Check whether a given genre is canonical or not.
+ * Returns whether a given text is a canonical genre defined in {@link Genres}.
*
* @param genre The name of genre to be checked.
* @return {@code true} if the genre is canonical, otherwise {@code false}.
- * @hide
*/
- @SystemApi
public static boolean isCanonical(String genre) {
return CANONICAL_GENRES.contains(genre);
}
@@ -1452,8 +1514,9 @@
* The title of this recorded TV program.
*
* <p>If this recorded program is an episodic TV show, it is recommended that the title is
- * the series title and its related fields ({@link #COLUMN_SEASON_NUMBER},
- * {@link #COLUMN_EPISODE_NUMBER}, and {@link #COLUMN_EPISODE_TITLE}) are filled in.
+ * the series title and its related fields ({@link #COLUMN_SEASON_TITLE} and/or
+ * {@link #COLUMN_SEASON_DISPLAY_NUMBER}, {@link #COLUMN_EPISODE_DISPLAY_NUMBER},
+ * and {@link #COLUMN_EPISODE_TITLE}) are filled in.
*
* <p>Type: TEXT
* @see Programs#COLUMN_TITLE
@@ -1461,24 +1524,46 @@
public static final String COLUMN_TITLE = Programs.COLUMN_TITLE;
/**
- * The season number of this recorded TV program for episodic TV shows.
+ * The season display number of this recorded TV program for episodic TV shows.
+ *
+ * <p>This is used to indicate the season number. (e.g. 1, 2 or 3) Note that the value
+ * does not necessarily be numeric. (e.g. 12B)
*
* <p>Can be empty.
*
- * <p>Type: INTEGER
- * @see Programs#COLUMN_SEASON_NUMBER
+ * <p>Type: TEXT
*/
- public static final String COLUMN_SEASON_NUMBER = Programs.COLUMN_SEASON_NUMBER;
+ public static final String COLUMN_SEASON_DISPLAY_NUMBER =
+ Programs.COLUMN_SEASON_DISPLAY_NUMBER;
/**
- * The episode number of this recorded TV program for episodic TV shows.
+ * The title of the season for this recorded TV program for episodic TV shows.
+ *
+ * <p>This is an optional field supplied only when the season has a special title
+ * (e.g. The Final Season). If provided, the applications should display it instead of
+ * {@link #COLUMN_SEASON_DISPLAY_NUMBER} without alterations.
+ * (e.g. for "The Final Season", displayed string should be "The Final Season", not
+ * "Season The Final Season"). When displaying multiple programs, the order should be based
+ * on {@link #COLUMN_SEASON_DISPLAY_NUMBER}, even when {@link #COLUMN_SEASON_TITLE} exists.
*
* <p>Can be empty.
*
- * <p>Type: INTEGER
- * @see Programs#COLUMN_EPISODE_NUMBER
+ * <p>Type: TEXT
*/
- public static final String COLUMN_EPISODE_NUMBER = Programs.COLUMN_EPISODE_NUMBER;
+ public static final String COLUMN_SEASON_TITLE = Programs.COLUMN_SEASON_TITLE;
+
+ /**
+ * The episode display number of this recorded TV program for episodic TV shows.
+ *
+ * <p>This is used to indicate the episode number. (e.g. 1, 2 or 3) Note that the value
+ * does not necessarily be numeric. (e.g. 12B)
+ *
+ * <p>Can be empty.
+ *
+ * <p>Type: TEXT
+ */
+ public static final String COLUMN_EPISODE_DISPLAY_NUMBER =
+ Programs.COLUMN_EPISODE_DISPLAY_NUMBER;
/**
* The episode title of this recorded TV program for episodic TV shows.
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index f0a9426..63e3edc 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -105,31 +105,38 @@
public static final int TYPE_DISPLAY_PORT = 1008;
/**
- * The ID of the TV input to provide to the setup activity and settings activity.
+ * Used as a String extra field in setup intents created by {@link #createSetupIntent()} to
+ * supply the ID of a specific TV input to set up.
*/
public static final String EXTRA_INPUT_ID = "android.media.tv.extra.INPUT_ID";
private final ResolveInfo mService;
+
private final String mId;
- private final String mParentId;
private final int mType;
- private final int mTunerCount;
- private final boolean mCanRecord;
private final boolean mIsHardwareInput;
- private final Bundle mExtras;
+
+ // TODO: Remove mLabel and mIconUri when createTvInputInfo() is removed.
+ private String mLabel;
+ private Uri mIconUri;
+
+ private final int mLabelResId;
+ private final Icon mIcon;
+ private final Icon mIconStandby;
+ private final Icon mIconDisconnected;
// Attributes from XML meta data.
- private String mSetupActivity;
- private String mSettingsActivity;
+ private final String mSetupActivity;
+ private final String mSettingsActivity;
+ private final boolean mCanRecord;
+ private final int mTunerCount;
- private HdmiDeviceInfo mHdmiDeviceInfo;
- private int mLabelResId;
- // TODO: Remove when createTvInputInfo() is removed.
- private String mLabel;
- private Icon mIcon;
- // TODO: Remove when createTvInputInfo() is removed.
- private Uri mIconUri;
- private boolean mIsConnectedToHdmiSwitch;
+ // Attributes specific to HDMI
+ private final HdmiDeviceInfo mHdmiDeviceInfo;
+ private final boolean mIsConnectedToHdmiSwitch;
+ private final String mParentId;
+
+ private final Bundle mExtras;
/**
* Create a new instance of the TvInputInfo class, instantiating it from the given Context,
@@ -239,31 +246,26 @@
.build();
}
- /**
- * Constructor.
- *
- * @param service The ResolveInfo returned from the package manager about this TV input service.
- * @param id ID of this TV input. Should be generated via generateInputId*().
- * @param parentId ID of this TV input's parent input. {@code null} if none exists.
- * @param type The type of this TV input service.
- * @param isHardwareInput {@code true} if this TV input represents a hardware device.
- * {@code false} otherwise.
- * @param isConnectedToHdmiSwitch Whether a CEC device for this TV input is connected to an HDMI
- * switch, i.e., the device isn't directly connected to a HDMI port.
- * @param tunerCount The number of tuners this TV input has.
- * @param canRecord Whether this TV input can record TV programs.
- */
- private TvInputInfo(ResolveInfo service, String id, String parentId, int type,
- boolean isHardwareInput, boolean isConnectedToHdmiSwitch, int tunerCount,
- boolean canRecord, Bundle extras) {
+ private TvInputInfo(ResolveInfo service, String id, int type, boolean isHardwareInput,
+ int labelResId, Icon icon, Icon iconStandby, Icon iconDisconnected,
+ String setupActivity, String settingsActivity, boolean canRecord, int tunerCount,
+ HdmiDeviceInfo hdmiDeviceInfo, boolean isConnectedToHdmiSwitch, String parentId,
+ Bundle extras) {
mService = service;
mId = id;
- mParentId = parentId;
mType = type;
mIsHardwareInput = isHardwareInput;
- mIsConnectedToHdmiSwitch = isConnectedToHdmiSwitch;
- mTunerCount = tunerCount;
+ mLabelResId = labelResId;
+ mIcon = icon;
+ mIconStandby = iconStandby;
+ mIconDisconnected = iconDisconnected;
+ mSetupActivity = setupActivity;
+ mSettingsActivity = settingsActivity;
mCanRecord = canRecord;
+ mTunerCount = tunerCount;
+ mHdmiDeviceInfo = hdmiDeviceInfo;
+ mIsConnectedToHdmiSwitch = isConnectedToHdmiSwitch;
+ mParentId = parentId;
mExtras = extras;
}
@@ -478,6 +480,36 @@
return loadServiceIcon(context);
}
+ /**
+ * Loads the user-displayed icon for this TV input per input state.
+ *
+ * @param context Supplies a {@link Context} used to load the icon.
+ * @param state The input state. Should be one of the followings.
+ * {@link TvInputManager#INPUT_STATE_CONNECTED},
+ * {@link TvInputManager#INPUT_STATE_CONNECTED_STANDBY} and
+ * {@link TvInputManager#INPUT_STATE_DISCONNECTED}.
+ * @return a Drawable containing the TV input's icon for the given state or {@code null} if such
+ * an icon is not defined.
+ * @hide
+ */
+ @SystemApi
+ public Drawable loadIcon(@NonNull Context context, int state) {
+ if (state == TvInputManager.INPUT_STATE_CONNECTED) {
+ return loadIcon(context);
+ } else if (state == TvInputManager.INPUT_STATE_CONNECTED_STANDBY) {
+ if (mIconStandby != null) {
+ return mIconStandby.loadDrawable(context);
+ }
+ } else if (state == TvInputManager.INPUT_STATE_DISCONNECTED) {
+ if (mIconDisconnected != null) {
+ return mIconDisconnected.loadDrawable(context);
+ }
+ } else {
+ throw new IllegalArgumentException("Unknown state: " + state);
+ }
+ return null;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -499,21 +531,23 @@
}
TvInputInfo obj = (TvInputInfo) o;
- return TextUtils.equals(mId, obj.mId)
- && TextUtils.equals(mParentId, obj.mParentId)
- && Objects.equals(mService, obj.mService)
- && TextUtils.equals(mSetupActivity, obj.mSetupActivity)
- && TextUtils.equals(mSettingsActivity, obj.mSettingsActivity)
+ return Objects.equals(mService, obj.mService)
+ && TextUtils.equals(mId, obj.mId)
&& mType == obj.mType
- && mTunerCount == obj.mTunerCount
- && mCanRecord == obj.mCanRecord
&& mIsHardwareInput == obj.mIsHardwareInput
- && Objects.equals(mHdmiDeviceInfo, obj.mHdmiDeviceInfo)
- && Objects.equals(mIcon, obj.mIcon)
+ && TextUtils.equals(mLabel, obj.mLabel)
&& Objects.equals(mIconUri, obj.mIconUri)
&& mLabelResId == obj.mLabelResId
- && TextUtils.equals(mLabel, obj.mLabel)
+ && Objects.equals(mIcon, obj.mIcon)
+ && Objects.equals(mIconStandby, obj.mIconStandby)
+ && Objects.equals(mIconDisconnected, obj.mIconDisconnected)
+ && TextUtils.equals(mSetupActivity, obj.mSetupActivity)
+ && TextUtils.equals(mSettingsActivity, obj.mSettingsActivity)
+ && mCanRecord == obj.mCanRecord
+ && mTunerCount == obj.mTunerCount
+ && Objects.equals(mHdmiDeviceInfo, obj.mHdmiDeviceInfo)
&& mIsConnectedToHdmiSwitch == obj.mIsConnectedToHdmiSwitch
+ && TextUtils.equals(mParentId, obj.mParentId)
&& Objects.equals(mExtras, obj.mExtras);
}
@@ -532,21 +566,23 @@
*/
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeString(mId);
- dest.writeString(mParentId);
mService.writeToParcel(dest, flags);
- dest.writeString(mSetupActivity);
- dest.writeString(mSettingsActivity);
+ dest.writeString(mId);
dest.writeInt(mType);
- dest.writeInt(mTunerCount);
- dest.writeByte(mCanRecord ? (byte) 1 : 0);
dest.writeByte(mIsHardwareInput ? (byte) 1 : 0);
- dest.writeParcelable(mHdmiDeviceInfo, flags);
- dest.writeParcelable(mIcon, flags);
+ dest.writeString(mLabel);
dest.writeParcelable(mIconUri, flags);
dest.writeInt(mLabelResId);
- dest.writeString(mLabel);
+ dest.writeParcelable(mIcon, flags);
+ dest.writeParcelable(mIconStandby, flags);
+ dest.writeParcelable(mIconDisconnected, flags);
+ dest.writeString(mSetupActivity);
+ dest.writeString(mSettingsActivity);
+ dest.writeByte(mCanRecord ? (byte) 1 : 0);
+ dest.writeInt(mTunerCount);
+ dest.writeParcelable(mHdmiDeviceInfo, flags);
dest.writeByte(mIsConnectedToHdmiSwitch ? (byte) 1 : 0);
+ dest.writeString(mParentId);
dest.writeBundle(mExtras);
}
@@ -572,21 +608,23 @@
};
private TvInputInfo(Parcel in) {
- mId = in.readString();
- mParentId = in.readString();
mService = ResolveInfo.CREATOR.createFromParcel(in);
- mSetupActivity = in.readString();
- mSettingsActivity = in.readString();
+ mId = in.readString();
mType = in.readInt();
- mTunerCount = in.readInt();
- mCanRecord = in.readByte() == 1;
mIsHardwareInput = in.readByte() == 1;
- mHdmiDeviceInfo = in.readParcelable(null);
- mIcon = in.readParcelable(null);
+ mLabel = in.readString();
mIconUri = in.readParcelable(null);
mLabelResId = in.readInt();
- mLabel = in.readString();
+ mIcon = in.readParcelable(null);
+ mIconStandby = in.readParcelable(null);
+ mIconDisconnected = in.readParcelable(null);
+ mSetupActivity = in.readString();
+ mSettingsActivity = in.readString();
+ mCanRecord = in.readByte() == 1;
+ mTunerCount = in.readInt();
+ mHdmiDeviceInfo = in.readParcelable(null);
mIsConnectedToHdmiSwitch = in.readByte() == 1;
+ mParentId = in.readString();
mExtras = in.readBundle();
}
@@ -622,24 +660,29 @@
private final Context mContext;
private final ResolveInfo mResolveInfo;
- private Icon mIcon;
private int mLabelResId;
- private int mTunerCount = 1;
- private boolean mCanRecord;
+ private Icon mIcon;
+ private Icon mIconStandby;
+ private Icon mIconDisconnected;
+ private String mSetupActivity;
+ private String mSettingsActivity;
+ private Boolean mCanRecord;
+ private Integer mTunerCount;
+ private TvInputHardwareInfo mTvInputHardwareInfo;
private HdmiDeviceInfo mHdmiDeviceInfo;
private String mParentId;
- private TvInputHardwareInfo mTvInputHardwareInfo;
private Bundle mExtras;
/**
* Constructs a new builder for {@link TvInputInfo}.
*
* @param context A Context of the application package implementing this class.
- * @param cls The component class that is to be used for the {@link TvInputService}.
+ * @param component The name of the application component to be used for the
+ * {@link TvInputService}.
*/
- public Builder(Context context, Class<?> cls) {
+ public Builder(Context context, ComponentName component) {
mContext = context;
- Intent intent = new Intent(TvInputService.SERVICE_INTERFACE).setClass(context, cls);
+ Intent intent = new Intent(TvInputService.SERVICE_INTERFACE).setComponent(component);
mResolveInfo = context.getPackageManager().resolveService(intent,
PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
}
@@ -676,6 +719,31 @@
}
/**
+ * Sets the icon for a given input state.
+ *
+ * @param icon The icon that represents this TV input for the given state.
+ * @param state The input state. Should be one of the followings.
+ * {@link TvInputManager#INPUT_STATE_CONNECTED},
+ * {@link TvInputManager#INPUT_STATE_CONNECTED_STANDBY} and
+ * {@link TvInputManager#INPUT_STATE_DISCONNECTED}.
+ * @return This Builder object to allow for chaining of calls to builder methods.
+ * @hide
+ */
+ @SystemApi
+ public Builder setIcon(Icon icon, int state) {
+ if (state == TvInputManager.INPUT_STATE_CONNECTED) {
+ this.mIcon = icon;
+ } else if (state == TvInputManager.INPUT_STATE_CONNECTED_STANDBY) {
+ this.mIconStandby = icon;
+ } else if (state == TvInputManager.INPUT_STATE_DISCONNECTED) {
+ this.mIconDisconnected = icon;
+ } else {
+ throw new IllegalArgumentException("Unknown state: " + state);
+ }
+ return this;
+ }
+
+ /**
* Sets the label.
*
* @param resId The resource ID of the text to use.
@@ -791,20 +859,19 @@
type = TYPE_HDMI;
isHardwareInput = true;
isConnectedToHdmiSwitch = (mHdmiDeviceInfo.getPhysicalAddress() & 0x0FFF) != 0;
- mTunerCount = 0;
} else if (mTvInputHardwareInfo != null) {
id = generateInputId(componentName, mTvInputHardwareInfo);
type = sHardwareTypeToTvInputType.get(mTvInputHardwareInfo.getType(), TYPE_TUNER);
isHardwareInput = true;
- mTunerCount = 0;
} else {
id = generateInputId(componentName);
type = TYPE_TUNER;
}
-
- TvInputInfo info = new TvInputInfo(mResolveInfo, id, mParentId, type, isHardwareInput,
- isConnectedToHdmiSwitch, mTunerCount, mCanRecord, mExtras);
- return parseServiceMetadata(type, info);
+ parseServiceMetadata(type);
+ return new TvInputInfo(mResolveInfo, id, type, isHardwareInput, mLabelResId, mIcon,
+ mIconStandby, mIconDisconnected, mSetupActivity, mSettingsActivity,
+ mCanRecord == null ? false : mCanRecord, mTunerCount == null ? 0 : mTunerCount,
+ mHdmiDeviceInfo, isConnectedToHdmiSwitch, mParentId, mExtras);
}
private static String generateInputId(ComponentName name) {
@@ -826,7 +893,7 @@
+ tvInputHardwareInfo.getDeviceId();
}
- private TvInputInfo parseServiceMetadata(int inputType, TvInputInfo info)
+ private void parseServiceMetadata(int inputType)
throws XmlPullParserException, IOException {
ServiceInfo si = mResolveInfo.serviceInfo;
PackageManager pm = mContext.getPackageManager();
@@ -853,26 +920,32 @@
TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.TvInputService);
- info.mSetupActivity = sa.getString(
+ mSetupActivity = sa.getString(
com.android.internal.R.styleable.TvInputService_setupActivity);
if (DEBUG) {
- Log.d(TAG, "Setup activity loaded. [" + info.mSetupActivity + "] for "
- + si.name);
+ Log.d(TAG, "Setup activity loaded. [" + mSetupActivity + "] for " + si.name);
}
- if (inputType == TYPE_TUNER && TextUtils.isEmpty(info.mSetupActivity)) {
+ if (inputType == TYPE_TUNER && TextUtils.isEmpty(mSetupActivity)) {
throw new XmlPullParserException("Setup activity not found in " + si.name);
}
- info.mSettingsActivity = sa.getString(
+ mSettingsActivity = sa.getString(
com.android.internal.R.styleable.TvInputService_settingsActivity);
if (DEBUG) {
- Log.d(TAG, "Settings activity loaded. [" + info.mSettingsActivity + "] for "
+ Log.d(TAG, "Settings activity loaded. [" + mSettingsActivity + "] for "
+ si.name);
}
+ if (mCanRecord == null) {
+ mCanRecord = sa.getBoolean(
+ com.android.internal.R.styleable.TvInputService_canRecord, false);
+ }
+ if (mTunerCount == null && inputType == TYPE_TUNER) {
+ mTunerCount = sa.getInt(
+ com.android.internal.R.styleable.TvInputService_tunerCount, 1);
+ }
sa.recycle();
} catch (NameNotFoundException e) {
throw new XmlPullParserException("Unable to create context for: " + si.packageName);
}
- return info;
}
}
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 51aae90..0b0306c 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -266,6 +266,14 @@
public static final String META_DATA_CONTENT_RATING_SYSTEMS =
"android.media.tv.metadata.CONTENT_RATING_SYSTEMS";
+ /**
+ * Activity action to set up channel sources i.e. TV inputs of type
+ * {@link TvInputInfo#TYPE_TUNER}. When invoked, the system will display an appropriate UI for
+ * the user to initiate the individual setup flow provided by
+ * {@link android.R.attr#setupActivity} of each TV input service.
+ */
+ public static final String ACTION_SETUP_INPUTS = "android.media.tv.action.SETUP_INPUTS";
+
private final ITvInputManager mService;
private final Object mLock = new Object();
@@ -470,8 +478,10 @@
/**
* This is called when the recording session has been tuned to the given channel and is
* ready to start recording.
+ *
+ * @param channelUri The URI of a channel.
*/
- void onTuned(Session session) {
+ void onTuned(Session session, Uri channelUri) {
}
// For the recording session only
@@ -645,11 +655,11 @@
}
// For the recording session only
- void postTuned() {
+ void postTuned(final Uri channelUri) {
mHandler.post(new Runnable() {
@Override
public void run() {
- mSessionCallback.onTuned(mSession);
+ mSessionCallback.onTuned(mSession, channelUri);
}
});
}
@@ -731,9 +741,7 @@
*
* <p>Because the system automatically creates a <code>TvInputInfo</code> object for each TV
* input based on the information collected from the <code>AndroidManifest.xml</code>, this
- * method is only called back when such information has changed dynamically or when the TV
- * input service implementation wants to pass additional information that is not specified
- * by the manifest file, such as ability to record and tuner count.
+ * method is only called back when such information has changed dynamically.
*
* @param inputInfo The <code>TvInputInfo</code> object that contains new information.
*/
@@ -1007,14 +1015,14 @@
}
@Override
- public void onTuned(int seq) {
+ public void onTuned(int seq, Uri channelUri) {
synchronized (mSessionCallbackRecordMap) {
SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
if (record == null) {
Log.e(TAG, "Callback not found for seq " + seq);
return;
}
- record.postTuned();
+ record.postTuned(channelUri);
}
}
@@ -1103,7 +1111,7 @@
}
}
} catch (RemoteException e) {
- Log.e(TAG, "TvInputManager initialization failed", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1116,7 +1124,7 @@
try {
return mService.getTvInputList(mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1132,7 +1140,7 @@
try {
return mService.getTvInputInfo(inputId, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1149,7 +1157,7 @@
try {
mService.updateTvInputInfo(inputInfo, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException("Error trying to update " + inputInfo, e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1220,7 +1228,7 @@
try {
return mService.isParentalControlsEnabled(mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1237,7 +1245,7 @@
try {
mService.setParentalControlsEnabled(enabled, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1252,7 +1260,7 @@
try {
return mService.isRatingBlocked(rating.flattenToString(), mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1271,7 +1279,7 @@
}
return ratings;
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1289,7 +1297,7 @@
try {
mService.addBlockedRating(rating.flattenToString(), mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1307,7 +1315,7 @@
try {
mService.removeBlockedRating(rating.flattenToString(), mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1320,7 +1328,7 @@
try {
return mService.getTvContentRatingSystemList(mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1370,7 +1378,7 @@
try {
mService.createSession(mClient, inputId, isRecordingSession, seq, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1394,7 +1402,7 @@
try {
return mService.getAvailableTvStreamConfigList(inputId, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1412,7 +1420,7 @@
try {
return mService.captureFrame(inputId, surface, config, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1426,7 +1434,7 @@
try {
return mService.isSingleSessionActive(mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1440,7 +1448,7 @@
try {
return mService.getHardwareList();
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1470,7 +1478,7 @@
}
}, info, mUserId));
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1484,7 +1492,7 @@
try {
mService.releaseTvInputHardware(deviceId, hardware.getInterface(), mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1498,7 +1506,7 @@
try {
return mService.getDvbDeviceList();
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1521,7 +1529,7 @@
}
return mService.openDvbDevice(info, device);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1592,7 +1600,7 @@
try {
mService.releaseSession(mToken, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
releaseInternal();
@@ -1612,7 +1620,7 @@
try {
mService.setMainSession(mToken, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1630,7 +1638,7 @@
try {
mService.setSurface(mToken, surface, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1652,7 +1660,7 @@
try {
mService.dispatchSurfaceChanged(mToken, format, width, height, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1673,7 +1681,7 @@
}
mService.setVolume(mToken, volume, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1713,7 +1721,7 @@
try {
mService.tune(mToken, channelUri, params, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1730,7 +1738,7 @@
try {
mService.setCaptionEnabled(mToken, enabled, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1772,7 +1780,7 @@
try {
mService.selectTrack(mToken, type, trackId, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1920,7 +1928,7 @@
try {
mService.timeShiftPlay(mToken, recordedProgramUri, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1935,7 +1943,7 @@
try {
mService.timeShiftPause(mToken, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1950,7 +1958,7 @@
try {
mService.timeShiftResume(mToken, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1971,7 +1979,7 @@
try {
mService.timeShiftSeekTo(mToken, timeMs, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1988,7 +1996,7 @@
try {
mService.timeShiftSetPlaybackParams(mToken, params, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2005,7 +2013,7 @@
try {
mService.timeShiftEnablePositionTracking(mToken, enable, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2023,7 +2031,7 @@
try {
mService.startRecording(mToken, programHint, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2038,7 +2046,7 @@
try {
mService.stopRecording(mToken, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2061,7 +2069,7 @@
try {
mService.sendAppPrivateCommand(mToken, action, data, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2089,7 +2097,7 @@
try {
mService.createOverlayView(mToken, view.getWindowToken(), frame, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2107,7 +2115,7 @@
try {
mService.relayoutOverlayView(mToken, frame, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2122,7 +2130,7 @@
try {
mService.removeOverlayView(mToken, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2138,7 +2146,7 @@
try {
mService.unblockContent(mToken, unblockedRating.flattenToString(), mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index da4a038..8fb58b5 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -262,10 +262,8 @@
*
* <p>The system automatically creates a <code>TvInputInfo</code> object for each TV input,
* based on the information collected from the <code>AndroidManifest.xml</code>, thus it is not
- * necessary to call this method unless such information has changed dynamically. This may be
- * also used to pass additional information that is not specified by the manifest file, such as
- * ability to record and tuner count. Use {@link TvInputInfo.Builder} to build a new
- * <code>TvInputInfo</code> object.
+ * necessary to call this method unless such information has changed dynamically.
+ * Use {@link TvInputInfo.Builder} to build a new <code>TvInputInfo</code> object.
*
* <p>Attempting to change information about a TV input that the calling package does not own
* does nothing.
@@ -1569,8 +1567,10 @@
* passed channel and call this method to indicate that it is now available for immediate
* recording. When {@link #onStartRecording(Uri)} is called, recording must start with
* minimal delay.
+ *
+ * @param channelUri The URI of a channel.
*/
- public void notifyTuned() {
+ public void notifyTuned(Uri channelUri) {
executeOrPostRunnableOnMainThread(new Runnable() {
@MainThread
@Override
@@ -1578,7 +1578,7 @@
try {
if (DEBUG) Log.d(TAG, "notifyTuned");
if (mSessionCallback != null) {
- mSessionCallback.onTuned();
+ mSessionCallback.onTuned(channelUri);
}
} catch (RemoteException e) {
Log.w(TAG, "error in notifyTuned", e);
@@ -1681,7 +1681,7 @@
* <p>The application may call this method before starting or after stopping recording, but
* not during recording.
*
- * <p>The session must call {@link #notifyTuned()} if the tune request was fulfilled, or
+ * <p>The session must call {@link #notifyTuned(Uri)} if the tune request was fulfilled, or
* {@link #notifyError(int)} otherwise.
*
* @param channelUri The URI of a channel.
@@ -1710,8 +1710,8 @@
* Called when the application requests to start TV program recording. Recording must start
* immediately when this method is called.
*
- * <p>The application may supply the URI for a TV program as a hint for filling in program
- * specific data fields in the {@link android.media.tv.TvContract.RecordedPrograms} table.
+ * <p>The application may supply the URI for a TV program for filling in program specific
+ * data fields in the {@link android.media.tv.TvContract.RecordedPrograms} table.
* A non-null {@code programHint} implies the started recording should be of that specific
* program, whereas null {@code programHint} does not impose such a requirement and the
* recording can span across multiple TV programs. In either case, the application must call
@@ -1720,10 +1720,10 @@
* <p>The session must call {@link #notifyError(int)} if the start request cannot be
* fulfilled.
*
- * @param programHint The URI for the TV program to record as a hint, built by
+ * @param programUri The URI for the TV program to record, built by
* {@link TvContract#buildProgramUri(long)}. Can be {@code null}.
*/
- public abstract void onStartRecording(@Nullable Uri programHint);
+ public abstract void onStartRecording(@Nullable Uri programUri);
/**
* Called when the application requests to stop TV program recording. Recording must stop
diff --git a/media/java/android/media/tv/TvRecordingClient.java b/media/java/android/media/tv/TvRecordingClient.java
index 1c920f5..d48ea21e 100644
--- a/media/java/android/media/tv/TvRecordingClient.java
+++ b/media/java/android/media/tv/TvRecordingClient.java
@@ -76,11 +76,12 @@
* during recording.
*
* <p>The recording session will respond by calling
- * {@link RecordingCallback#onTuned()} if the tune request was fulfilled, or
+ * {@link RecordingCallback#onTuned(Uri)} if the tune request was fulfilled, or
* {@link RecordingCallback#onError(int)} otherwise.
*
* @param inputId The ID of the TV input for the given channel.
* @param channelUri The URI of a channel.
+ * @throws IllegalStateException If recording is already started.
*/
public void tune(String inputId, Uri channelUri) {
tune(inputId, channelUri, null);
@@ -102,6 +103,7 @@
* @param inputId The ID of the TV input for the given channel.
* @param channelUri The URI of a channel.
* @param params Extra parameters.
+ * @throws IllegalStateException If recording is already started.
* @hide
*/
@SystemApi
@@ -152,8 +154,8 @@
* immediately when this method is called. If the current recording session has not yet tuned to
* any channel, this method throws an exception.
*
- * <p>The application may supply the URI for a TV program as a hint for filling in program
- * specific data fields in the {@link android.media.tv.TvContract.RecordedPrograms} table.
+ * <p>The application may supply the URI for a TV program for filling in program specific data
+ * fields in the {@link android.media.tv.TvContract.RecordedPrograms} table.
* A non-null {@code programHint} implies the started recording should be of that specific
* program, whereas null {@code programHint} does not impose such a requirement and the
* recording can span across multiple TV programs. In either case, the application must call
@@ -162,15 +164,16 @@
* <p>The recording session will respond by calling {@link RecordingCallback#onError(int)} if
* the start request cannot be fulfilled.
*
- * @param programHint The URI for the TV program to record as a hint, built by
+ * @param programUri The URI for the TV program to record, built by
* {@link TvContract#buildProgramUri(long)}. Can be {@code null}.
+ * @throws IllegalStateException If {@link #tune} request hasn't been handled yet.
*/
- public void startRecording(@Nullable Uri programHint) {
+ public void startRecording(@Nullable Uri programUri) {
if (!mIsTuned) {
throw new IllegalStateException("startRecording failed - not yet tuned");
}
if (mSession != null) {
- mSession.startRecording(programHint);
+ mSession.startRecording(programUri);
mIsRecordingStarted = true;
}
}
@@ -245,8 +248,10 @@
/**
* This is called when the recording session has been tuned to the given channel and is
* ready to start recording.
+ *
+ * @param channelUri The URI of a channel.
*/
- public void onTuned() {
+ public void onTuned(Uri channelUri) {
}
/**
@@ -327,7 +332,7 @@
}
@Override
- void onTuned(TvInputManager.Session session) {
+ void onTuned(TvInputManager.Session session, Uri channelUri) {
if (DEBUG) {
Log.d(TAG, "onTuned()");
}
@@ -336,7 +341,7 @@
return;
}
mIsTuned = true;
- mCallback.onTuned();
+ mCallback.onTuned(channelUri);
}
@Override
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index 29bcc19..760a2d1 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -713,8 +713,7 @@
};
}
-
- private MtpPropertyList getObjectPropertyList(long handle, int format, long property,
+ private MtpPropertyList getObjectPropertyList(int handle, int format, int property,
int groupCode, int depth) {
// FIXME - implement group support
if (groupCode != 0) {
@@ -722,29 +721,29 @@
}
MtpPropertyGroup propertyGroup;
- if (property == 0xFFFFFFFFL) {
- if (format == 0 && handle > 0) {
+ if (property == 0xffffffff) {
+ if (format == 0 && handle != 0 && handle != 0xffffffff) {
// return properties based on the object's format
- format = getObjectFormat((int)handle);
+ format = getObjectFormat(handle);
}
- propertyGroup = mPropertyGroupsByFormat.get(format);
- if (propertyGroup == null) {
+ propertyGroup = mPropertyGroupsByFormat.get(format);
+ if (propertyGroup == null) {
int[] propertyList = getSupportedObjectProperties(format);
propertyGroup = new MtpPropertyGroup(this, mMediaProvider,
mVolumeName, propertyList);
- mPropertyGroupsByFormat.put(new Integer(format), propertyGroup);
+ mPropertyGroupsByFormat.put(format, propertyGroup);
}
} else {
- propertyGroup = mPropertyGroupsByProperty.get(property);
- if (propertyGroup == null) {
- int[] propertyList = new int[] { (int)property };
- propertyGroup = new MtpPropertyGroup(this, mMediaProvider,
- mVolumeName, propertyList);
- mPropertyGroupsByProperty.put(new Integer((int)property), propertyGroup);
+ propertyGroup = mPropertyGroupsByProperty.get(property);
+ if (propertyGroup == null) {
+ final int[] propertyList = new int[] { property };
+ propertyGroup = new MtpPropertyGroup(
+ this, mMediaProvider, mVolumeName, propertyList);
+ mPropertyGroupsByProperty.put(property, propertyGroup);
}
}
- return propertyGroup.getPropertyList((int)handle, format, depth);
+ return propertyGroup.getPropertyList(handle, format, depth);
}
private int renameFile(int handle, String newName) {
@@ -970,7 +969,7 @@
Cursor c = null;
try {
c = mMediaProvider.query(mObjectsUri, FORMAT_PROJECTION,
- ID_WHERE, new String[] { Integer.toString(handle) }, null, null);
+ ID_WHERE, new String[] { Integer.toString(handle) }, null, null);
if (c != null && c.moveToNext()) {
return c.getInt(1);
} else {
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index 480acd9..f593685 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -45,6 +45,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -120,8 +121,8 @@
* they are done. If more than one of those methods is called, an exception will
* be thrown.
*
- * @see MediaBrowserService#onLoadChildren
- * @see MediaBrowserService#onLoadItem
+ * @see #onLoadChildren
+ * @see #onLoadItem
*/
public class Result<T> {
private Object mDebug;
@@ -367,11 +368,16 @@
* {@link Result#detach result.detach} may be called before returning from
* this function, and then {@link Result#sendResult result.sendResult}
* called when the loading is complete.
+ * </p><p>
+ * In case the media item does not have any children, call {@link Result#sendResult}
+ * with an empty list. When the given {@code parentId} is invalid, implementations must
+ * call {@link Result#sendResult result.sendResult} with {@code null}, which will invoke
+ * {@link MediaBrowser.SubscriptionCallback#onError}.
+ * </p>
*
* @param parentId The id of the parent media item whose children are to be
* queried.
- * @param result The Result to send the list of children to, or null if the
- * id is invalid.
+ * @param result The Result to send the list of children to.
*/
public abstract void onLoadChildren(@NonNull String parentId,
@NonNull Result<List<MediaBrowser.MediaItem>> result);
@@ -385,11 +391,16 @@
* {@link Result#detach result.detach} may be called before returning from
* this function, and then {@link Result#sendResult result.sendResult}
* called when the loading is complete.
+ * </p><p>
+ * In case the media item does not have any children, call {@link Result#sendResult}
+ * with an empty list. When the given {@code parentId} is invalid, implementations must
+ * call {@link Result#sendResult result.sendResult} with {@code null}, which will invoke
+ * {@link MediaBrowser.SubscriptionCallback#onError}.
+ * </p>
*
* @param parentId The id of the parent media item whose children are to be
* queried.
- * @param result The Result to send the list of children to, or null if the
- * id is invalid.
+ * @param result The Result to send the list of children to.
* @param options A bundle of service-specific arguments sent from the media
* browse. The information returned through the result should be
* affected by the contents of this bundle.
@@ -411,13 +422,18 @@
* result.detach} may be called before returning from this function, and
* then {@link Result#sendResult result.sendResult} called when the item has
* been loaded.
- * <p>
- * The default implementation sends a null result.
+ * </p><p>
+ * When the given {@code itemId} is invalid, implementations must call
+ * {@link Result#sendResult result.sendResult} with {@code null}, which will
+ * invoke {@link MediaBrowser.ItemCallback#onError}.
+ * </p><p>
+ * The default implementation calls {@link Result#sendResult result.sendResult}
+ * with {@code null}.
+ * </p>
*
* @param itemId The id for the specific
* {@link android.media.browse.MediaBrowser.MediaItem}.
- * @param result The Result to send the item to, or null if the id is
- * invalid.
+ * @param result The Result to send the item to.
*/
public void onLoadItem(String itemId, Result<MediaBrowser.MediaItem> result) {
result.sendResult(null);
@@ -630,6 +646,9 @@
private List<MediaBrowser.MediaItem> applyOptions(List<MediaBrowser.MediaItem> list,
final Bundle options) {
+ if (list == null) {
+ return null;
+ }
int page = options.getInt(MediaBrowser.EXTRA_PAGE, -1);
int pageSize = options.getInt(MediaBrowser.EXTRA_PAGE_SIZE, -1);
if (page == -1 && pageSize == -1) {
@@ -638,7 +657,7 @@
int fromIndex = pageSize * (page - 1);
int toIndex = fromIndex + pageSize;
if (page < 1 || pageSize < 1 || fromIndex >= list.size()) {
- return null;
+ return Collections.EMPTY_LIST;
}
if (toIndex > list.size()) {
toIndex = list.size();
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index a326f6f..29739ca 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -43,14 +43,10 @@
libcamera_client \
libmtp \
libusbhost \
- libjhead \
libexif \
libpiex \
libstagefright_amrnb_common
-LOCAL_REQUIRED_MODULES := \
- libjhead_jni
-
LOCAL_STATIC_LIBRARIES := \
libstagefright_amrnbenc
@@ -68,7 +64,6 @@
frameworks/av/media/mtp \
frameworks/native/include/media/openmax \
$(call include-path-for, libhardware)/hardware \
- system/media/camera/include \
$(PV_INCLUDES) \
$(JNI_H_INCLUDE)
diff --git a/media/jni/android_media_ExifInterface.cpp b/media/jni/android_media_ExifInterface.cpp
index ba38569..f7481af 100644
--- a/media/jni/android_media_ExifInterface.cpp
+++ b/media/jni/android_media_ExifInterface.cpp
@@ -83,28 +83,27 @@
}
static jobject ExifInterface_getRawMetadata(
- JNIEnv* env, jclass /* clazz */, jstring jfilename) {
- const char* filenameChars = env->GetStringUTFChars(jfilename, NULL);
- if (filenameChars == NULL) {
+ JNIEnv* env, jclass /* clazz */, jobject jfileDescriptor) {
+ int fd = jniGetFDFromFileDescriptor(env, jfileDescriptor);
+ if (fd < 0) {
+ ALOGI("Invalid file descriptor");
return NULL;
}
- String8 filename(filenameChars);
- env->ReleaseStringUTFChars(jfilename, filenameChars);
piex::PreviewImageData image_data;
- std::unique_ptr<FileStream> stream(new FileStream(filename));
+ std::unique_ptr<FileStream> stream(new FileStream(fd));
- if (!GetExifFromRawImage(stream.get(), filename, image_data)) {
- ALOGI("Raw image not detected: %s", filename.string());
+ if (!GetExifFromRawImage(stream.get(), String8("[file descriptor]"), image_data)) {
+ ALOGI("Raw image not detected");
return NULL;
}
KeyedVector<String8, String8> map;
- if (image_data.thumbnail_length > 0) {
+ if (image_data.thumbnail.length > 0) {
map.add(String8("hasThumbnail"), String8("true"));
- map.add(String8("thumbnailOffset"), String8::format("%d", image_data.thumbnail_offset));
- map.add(String8("thumbnailLength"), String8::format("%d", image_data.thumbnail_length));
+ map.add(String8("thumbnailOffset"), String8::format("%d", image_data.thumbnail.offset));
+ map.add(String8("thumbnailLength"), String8::format("%d", image_data.thumbnail.length));
} else {
map.add(String8("hasThumbnail"), String8("false"));
}
@@ -263,7 +262,7 @@
static JNINativeMethod gMethods[] = {
{ "initRawNative", "()V", (void *)ExifInterface_initRaw },
- { "getRawAttributesNative", "(Ljava/lang/String;)Ljava/util/HashMap;",
+ { "getRawAttributesNative", "(Ljava/io/FileDescriptor;)Ljava/util/HashMap;",
(void*)ExifInterface_getRawMetadata },
};
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 4ac62f5..9e90a19 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -1264,6 +1264,14 @@
int readerHalFormat = android_view_Surface_mapPublicFormatToHalFormat(
static_cast<PublicFormat>(readerFormat));
int32_t fmt = applyFormatOverrides(buffer->flexFormat, readerHalFormat);
+ // Override the image format to HAL_PIXEL_FORMAT_YCbCr_420_888 if the actual format is
+ // NV21 or YV12. This could only happen when the Gralloc HAL version is v0.1 thus doesn't
+ // support lockycbcr(), the CpuConsumer need to use the lock() method in the
+ // lockNextBuffer() call. For Gralloc HAL v0.2 or newer, this format should already be
+ // overridden to HAL_PIXEL_FORMAT_YCbCr_420_888 for the flexible YUV compatible formats.
+ if (fmt == HAL_PIXEL_FORMAT_YCrCb_420_SP || fmt == HAL_PIXEL_FORMAT_YV12) {
+ fmt = HAL_PIXEL_FORMAT_YCbCr_420_888;
+ }
PublicFormat publicFmt = android_view_Surface_mapHalFormatDataspaceToPublicFormat(
fmt, buffer->dataSpace);
return static_cast<jint>(publicFmt);
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 2004a3a..d6994b3 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -1302,7 +1302,10 @@
jobject patternObj = env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoPatternID);
CryptoPlugin::Pattern pattern;
- if (patternObj != NULL) {
+ if (patternObj == NULL) {
+ pattern.mEncryptBlocks = 0;
+ pattern.mSkipBlocks = 0;
+ } else {
pattern.mEncryptBlocks = env->GetIntField(patternObj, gFields.patternEncryptBlocksID);
pattern.mSkipBlocks = env->GetIntField(patternObj, gFields.patternSkipBlocksID);
}
diff --git a/media/jni/android_media_MediaDataSource.cpp b/media/jni/android_media_MediaDataSource.cpp
index 3b892cb..537b56d 100644
--- a/media/jni/android_media_MediaDataSource.cpp
+++ b/media/jni/android_media_MediaDataSource.cpp
@@ -116,7 +116,8 @@
return UNKNOWN_ERROR;
}
if (mSizeIsCached) {
- return mCachedSize;
+ *size = mCachedSize;
+ return OK;
}
JNIEnv* env = AndroidRuntime::getJNIEnv();
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 701f7ac..922ad79 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -26,7 +26,6 @@
#include <utils/Log.h>
#include <gui/Surface.h>
-#include <camera/ICameraService.h>
#include <camera/Camera.h>
#include <media/mediarecorder.h>
#include <media/stagefright/PersistentSurface.h>
diff --git a/media/jni/android_media_Utils.cpp b/media/jni/android_media_Utils.cpp
index c08a5e3..9c4f7c4 100644
--- a/media/jni/android_media_Utils.cpp
+++ b/media/jni/android_media_Utils.cpp
@@ -28,6 +28,19 @@
namespace android {
+FileStream::FileStream(const int fd)
+ : mPosition(0),
+ mSize(0) {
+ mFile = fdopen(fd, "r");
+ if (mFile == NULL) {
+ return;
+ }
+ // Get the size.
+ fseek(mFile, 0l, SEEK_END);
+ mSize = ftell(mFile);
+ fseek(mFile, 0l, SEEK_SET);
+}
+
FileStream::FileStream(const String8 filename)
: mPosition(0),
mSize(0) {
diff --git a/media/jni/android_media_Utils.h b/media/jni/android_media_Utils.h
index 762c904..a30e1be 100644
--- a/media/jni/android_media_Utils.h
+++ b/media/jni/android_media_Utils.h
@@ -35,6 +35,7 @@
size_t mSize;
public:
+ FileStream(const int fd);
FileStream(const String8 filename);
~FileStream();
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 556f2c7..5722cb0 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -231,11 +231,11 @@
}
MtpObjectHandle MyMtpDatabase::beginSendObject(const char* path,
- MtpObjectFormat format,
- MtpObjectHandle parent,
- MtpStorageID storage,
- uint64_t size,
- time_t modified) {
+ MtpObjectFormat format,
+ MtpObjectHandle parent,
+ MtpStorageID storage,
+ uint64_t size,
+ time_t modified) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
jstring pathStr = env->NewStringUTF(path);
MtpObjectHandle result = env->CallIntMethod(mDatabase, method_beginSendObject,
@@ -249,7 +249,7 @@
}
void MyMtpDatabase::endSendObject(const char* path, MtpObjectHandle handle,
- MtpObjectFormat format, bool succeeded) {
+ MtpObjectFormat format, bool succeeded) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
jstring pathStr = env->NewStringUTF(path);
env->CallVoidMethod(mDatabase, method_endSendObject, pathStr,
@@ -261,8 +261,8 @@
}
MtpObjectHandleList* MyMtpDatabase::getObjectList(MtpStorageID storageID,
- MtpObjectFormat format,
- MtpObjectHandle parent) {
+ MtpObjectFormat format,
+ MtpObjectHandle parent) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectList,
(jint)storageID, (jint)format, (jint)parent);
@@ -281,8 +281,8 @@
}
int MyMtpDatabase::getNumObjects(MtpStorageID storageID,
- MtpObjectFormat format,
- MtpObjectHandle parent) {
+ MtpObjectFormat format,
+ MtpObjectHandle parent) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
int result = env->CallIntMethod(mDatabase, method_getNumObjects,
(jint)storageID, (jint)format, (jint)parent);
@@ -364,11 +364,21 @@
}
MtpResponseCode MyMtpDatabase::getObjectPropertyValue(MtpObjectHandle handle,
- MtpObjectProperty property,
- MtpDataPacket& packet) {
+ MtpObjectProperty property,
+ MtpDataPacket& packet) {
+ static_assert(sizeof(jint) >= sizeof(MtpObjectHandle),
+ "Casting MtpObjectHandle to jint loses a value");
+ static_assert(sizeof(jint) >= sizeof(MtpObjectProperty),
+ "Casting MtpObjectProperty to jint loses a value");
JNIEnv* env = AndroidRuntime::getJNIEnv();
- jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList,
- (jlong)handle, 0, (jlong)property, 0, 0);
+ jobject list = env->CallObjectMethod(
+ mDatabase,
+ method_getObjectPropertyList,
+ static_cast<jint>(handle),
+ 0,
+ static_cast<jint>(property),
+ 0,
+ 0);
MtpResponseCode result = env->GetIntField(list, field_mResult);
int count = env->GetIntField(list, field_mCount);
if (result == MTP_RESPONSE_OK && count != 1)
@@ -532,8 +542,8 @@
}
MtpResponseCode MyMtpDatabase::setObjectPropertyValue(MtpObjectHandle handle,
- MtpObjectProperty property,
- MtpDataPacket& packet) {
+ MtpObjectProperty property,
+ MtpDataPacket& packet) {
int type;
if (!getObjectPropertyInfo(property, type))
@@ -563,7 +573,7 @@
}
MtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
- MtpDataPacket& packet) {
+ MtpDataPacket& packet) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
if (property == MTP_DEVICE_PROPERTY_BATTERY_LEVEL) {
@@ -636,7 +646,7 @@
}
MtpResponseCode MyMtpDatabase::setDevicePropertyValue(MtpDeviceProperty property,
- MtpDataPacket& packet) {
+ MtpDataPacket& packet) {
int type;
if (!getDevicePropertyInfo(property, type))
@@ -670,12 +680,20 @@
}
MtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle,
- uint32_t format, uint32_t property,
- int groupCode, int depth,
- MtpDataPacket& packet) {
+ uint32_t format, uint32_t property,
+ int groupCode, int depth,
+ MtpDataPacket& packet) {
+ static_assert(sizeof(jint) >= sizeof(MtpObjectHandle),
+ "Casting MtpObjectHandle to jint loses a value");
JNIEnv* env = AndroidRuntime::getJNIEnv();
- jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList,
- (jlong)handle, (jint)format, (jlong)property, (jint)groupCode, (jint)depth);
+ jobject list = env->CallObjectMethod(
+ mDatabase,
+ method_getObjectPropertyList,
+ static_cast<jint>(handle),
+ static_cast<jint>(format),
+ static_cast<jint>(property),
+ static_cast<jint>(groupCode),
+ static_cast<jint>(depth));
checkAndClearExceptionFromCallback(env, __FUNCTION__);
if (!list)
return MTP_RESPONSE_GENERAL_ERROR;
@@ -787,7 +805,7 @@
}
MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
- MtpObjectInfo& info) {
+ MtpObjectInfo& info) {
MtpString path;
int64_t length;
MtpObjectFormat format;
@@ -940,9 +958,9 @@
}
MtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle,
- MtpString& outFilePath,
- int64_t& outFileLength,
- MtpObjectFormat& outFormat) {
+ MtpString& outFilePath,
+ int64_t& outFileLength,
+ MtpObjectFormat& outFormat) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
jint result = env->CallIntMethod(mDatabase, method_getObjectFilePath,
(jint)handle, mStringBuffer, mLongBuffer);
@@ -1056,7 +1074,7 @@
}
MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle,
- MtpObjectHandleList* references) {
+ MtpObjectHandleList* references) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
int count = references->size();
jintArray array = env->NewIntArray(count);
@@ -1077,7 +1095,7 @@
}
MtpProperty* MyMtpDatabase::getObjectPropertyDesc(MtpObjectProperty property,
- MtpObjectFormat format) {
+ MtpObjectFormat format) {
static const int channelEnum[] = {
1, // mono
2, // stereo
@@ -1313,7 +1331,7 @@
return -1;
}
method_getObjectPropertyList = env->GetMethodID(clazz, "getObjectPropertyList",
- "(JIJII)Landroid/mtp/MtpPropertyList;");
+ "(IIIII)Landroid/mtp/MtpPropertyList;");
if (method_getObjectPropertyList == NULL) {
ALOGE("Can't find getObjectPropertyList");
return -1;
diff --git a/media/tests/MediaFrameworkTest/res/raw/image_exif_byte_order_ii.jpg b/media/tests/MediaFrameworkTest/res/raw/image_exif_byte_order_ii.jpg
new file mode 100644
index 0000000..477cd3a
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/res/raw/image_exif_byte_order_ii.jpg
Binary files differ
diff --git a/media/tests/MediaFrameworkTest/res/raw/image_exif_byte_order_mm.jpg b/media/tests/MediaFrameworkTest/res/raw/image_exif_byte_order_mm.jpg
new file mode 100644
index 0000000..78ac703
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/res/raw/image_exif_byte_order_mm.jpg
Binary files differ
diff --git a/media/tests/MediaFrameworkTest/res/raw/lg_g4_iso_800.dng b/media/tests/MediaFrameworkTest/res/raw/lg_g4_iso_800.dng
new file mode 100644
index 0000000..5fcc720
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/res/raw/lg_g4_iso_800.dng
Binary files differ
diff --git a/media/tests/MediaFrameworkTest/res/values/exifinterface.xml b/media/tests/MediaFrameworkTest/res/values/exifinterface.xml
new file mode 100644
index 0000000..8fc6adc
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/res/values/exifinterface.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <array name="exifbyteorderii_jpg">
+ <item>true</item>
+ <item>512</item>
+ <item>288</item>
+ <item>false</item>
+ <item>0.0</item>
+ <item>0.0</item>
+ <item>0.0</item>
+ <item>SAMSUNG</item>
+ <item>SM-N900S</item>
+ <item>2.200</item>
+ <item>2016:01:29 18:32:27</item>
+ <item>0.033</item>
+ <item>0</item>
+ <item>413/100</item>
+ <item />
+ <item />
+ <item />
+ <item />
+ <item />
+ <item />
+ <item />
+ <item />
+ <item />
+ <item>480</item>
+ <item>640</item>
+ <item>50</item>
+ <item>6</item>
+ <item>0</item>
+ </array>
+ <array name="exifbyteordermm_jpg">
+ <item>false</item>
+ <item>0</item>
+ <item>0</item>
+ <item>true</item>
+ <item>0.0</item>
+ <item>0.0</item>
+ <item>0.0</item>
+ <item>LGE</item>
+ <item>Nexus 5</item>
+ <item>2.400</item>
+ <item>2016:01:29 15:44:58</item>
+ <item>0.017</item>
+ <item>0</item>
+ <item>3970/1000</item>
+ <item>0/1000</item>
+ <item>0</item>
+ <item>1970:01:01</item>
+ <item>0/1,0/1,0/10000</item>
+ <item>N</item>
+ <item>0/1,0/1,0/10000</item>
+ <item>E</item>
+ <item>GPS</item>
+ <item>00:00:00</item>
+ <item>176</item>
+ <item>144</item>
+ <item>146</item>
+ <item>0</item>
+ <item>0</item>
+ </array>
+ <array name="lg_g4_iso_800_dng">
+ <item>false</item>
+ <item>0</item>
+ <item>0</item>
+ <item>true</item>
+ <item>53.834507</item>
+ <item>10.69585</item>
+ <item>0.0</item>
+ <item>LGE</item>
+ <item>LG-H815</item>
+ <item>1.800</item>
+ <item>2015:11:12 16:46:18</item>
+ <item>0.0040</item>
+ <item>0.0</item>
+ <item>442/100</item>
+ <item>0/1</item>
+ <item>0</item>
+ <item>1970:01:17</item>
+ <item>53/1,50/1,423/100</item>
+ <item>N</item>
+ <item>10/1,41/1,4506/100</item>
+ <item>E</item>
+ <item />
+ <item>18:08:10</item>
+ <item>337</item>
+ <item>600</item>
+ <item>800</item>
+ <item>1</item>
+ <item />
+ </array>
+</resources>
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java
index 11d9070..9be7004 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java
@@ -50,6 +50,7 @@
addMediaScannerUnitTests(suite);
addCameraUnitTests(suite);
addImageReaderTests(suite);
+ addExifInterfaceTests(suite);
return suite;
}
@@ -59,10 +60,7 @@
}
private void addCameraUnitTests(TestSuite suite) {
- suite.addTestSuite(CameraUtilsDecoratorTest.class);
- suite.addTestSuite(CameraUtilsRuntimeExceptionTest.class);
suite.addTestSuite(CameraUtilsUncheckedThrowTest.class);
- suite.addTestSuite(CameraUtilsBinderDecoratorTest.class);
suite.addTestSuite(CameraUtilsTypeReferenceTest.class);
suite.addTestSuite(CameraMetadataTest.class);
}
@@ -109,4 +107,8 @@
private void addMediaScannerUnitTests(TestSuite suite) {
suite.addTestSuite(MediaInserterTest.class);
}
+
+ private void addExifInterfaceTests(TestSuite suite) {
+ suite.addTestSuite(ExifInterfaceTest.class);
+ }
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
index 6f74203..9a0946e 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
@@ -19,16 +19,16 @@
import android.hardware.CameraInfo;
import android.hardware.ICamera;
import android.hardware.ICameraClient;
+import android.hardware.ICameraService;
import android.hardware.ICameraServiceListener;
import android.hardware.camera2.ICameraDeviceCallbacks;
import android.hardware.camera2.ICameraDeviceUser;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.impl.CaptureResultExtras;
-import android.hardware.camera2.utils.BinderHolder;
-import android.hardware.camera2.utils.CameraBinderDecorator;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
+import android.os.ServiceSpecificException;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
@@ -84,14 +84,7 @@
public void testCameraInfo() throws Exception {
for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
- CameraInfo info = new CameraInfo();
- info.info.facing = -1;
- info.info.orientation = -1;
-
- assertTrue(
- "Camera service returned info for camera " + cameraId,
- mUtils.getCameraService().getCameraInfo(cameraId, info) ==
- CameraBinderTestUtils.NO_ERROR);
+ CameraInfo info = mUtils.getCameraService().getCameraInfo(cameraId);
assertTrue("Facing was not set for camera " + cameraId, info.info.facing != -1);
assertTrue("Orientation was not set for camera " + cameraId,
info.info.orientation != -1);
@@ -105,20 +98,17 @@
public void testGetLegacyParameters() throws Exception {
for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
- String[] parameters = new String[1];
- assertEquals("Camera service returned parameters for camera " + cameraId,
- CameraBinderTestUtils.NO_ERROR,
- mUtils.getCameraService().getLegacyParameters(cameraId, /*out*/parameters));
- assertNotNull(parameters[0]);
+ String parameters = mUtils.getCameraService().getLegacyParameters(cameraId);
+ assertNotNull(parameters);
assertTrue("Parameters should have at least one character in it",
- parameters[0].length() > 0);
+ parameters.length() > 0);
- int end = parameters[0].length();
+ int end = parameters.length();
if (end > MAX_PARAMETERS_LENGTH) {
end = MAX_PARAMETERS_LENGTH;
}
- Log.v(TAG, "Camera " + cameraId + " parameters: " + parameters[0].substring(0, end));
+ Log.v(TAG, "Camera " + cameraId + " parameters: " + parameters.substring(0, end));
}
}
@@ -127,14 +117,8 @@
public void testSupportsCamera2Api() throws Exception {
for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
- int res = mUtils.getCameraService().supportsCameraApi(cameraId, API_VERSION_2);
+ boolean supports = mUtils.getCameraService().supportsCameraApi(cameraId, API_VERSION_2);
- if (res != CameraBinderTestUtils.NO_ERROR && res != -android.system.OsConstants.EOPNOTSUPP) {
- fail("Camera service returned bad value when queried if it supports camera2 api: "
- + res + " for camera ID " + cameraId);
- }
-
- boolean supports = res == CameraBinderTestUtils.NO_ERROR;
Log.v(TAG, "Camera " + cameraId + " supports api2: " + supports);
}
}
@@ -144,10 +128,10 @@
public void testSupportsCamera1Api() throws Exception {
for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
- int res = mUtils.getCameraService().supportsCameraApi(cameraId, API_VERSION_1);
- assertEquals(
- "Camera service returned bad value when queried if it supports camera1 api: "
- + res + " for camera ID " + cameraId, CameraBinderTestUtils.NO_ERROR, res);
+ boolean supports = mUtils.getCameraService().supportsCameraApi(cameraId, API_VERSION_1);
+ assertTrue(
+ "Camera service returned false when queried if it supports camera1 api " +
+ " for camera ID " + cameraId, supports);
}
}
@@ -169,11 +153,10 @@
String clientPackageName = getContext().getPackageName();
- BinderHolder holder = new BinderHolder();
- CameraBinderDecorator.newInstance(mUtils.getCameraService())
+ ICamera cameraUser = mUtils.getCameraService()
.connect(dummyCallbacks, cameraId, clientPackageName,
- CameraBinderTestUtils.USE_CALLING_UID, holder);
- ICamera cameraUser = ICamera.Stub.asInterface(holder.getBinder());
+ ICameraService.USE_CALLING_UID,
+ ICameraService.USE_CALLING_PID);
assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
Log.v(TAG, String.format("Camera %s connected", cameraId));
@@ -191,14 +174,11 @@
String clientPackageName = getContext().getPackageName();
- BinderHolder holder = new BinderHolder();
-
try {
- CameraBinderDecorator.newInstance(mUtils.getCameraService())
+ cameraUser = mUtils.getCameraService()
.connectLegacy(dummyCallbacks, cameraId, CAMERA_HAL_API_VERSION_1_0,
- clientPackageName,
- CameraBinderTestUtils.USE_CALLING_UID, holder);
- cameraUser = ICamera.Stub.asInterface(holder.getBinder());
+ clientPackageName,
+ ICameraService.USE_CALLING_UID);
assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
Log.v(TAG, String.format("Camera %s connected as HAL1 legacy device", cameraId));
@@ -284,11 +264,11 @@
String clientPackageName = getContext().getPackageName();
- BinderHolder holder = new BinderHolder();
- CameraBinderDecorator.newInstance(mUtils.getCameraService())
- .connectDevice(dummyCallbacks, cameraId,
- clientPackageName, CameraBinderTestUtils.USE_CALLING_UID, holder);
- ICameraDeviceUser cameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
+ ICameraDeviceUser cameraUser =
+ mUtils.getCameraService().connectDevice(
+ dummyCallbacks, cameraId,
+ clientPackageName,
+ ICameraService.USE_CALLING_UID);
assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
Log.v(TAG, String.format("Camera %s connected", cameraId));
@@ -323,27 +303,33 @@
ICameraServiceListener listener = new DummyCameraServiceListener();
- assertTrue(
- "Listener was removed before added",
- mUtils.getCameraService().removeListener(listener) ==
- CameraBinderTestUtils.BAD_VALUE);
+ try {
+ mUtils.getCameraService().removeListener(listener);
+ fail("Listener was removed before added");
+ } catch (ServiceSpecificException e) {
+ assertEquals("Listener was removed before added",
+ e.errorCode, ICameraService.ERROR_ILLEGAL_ARGUMENT);
+ }
- assertTrue("Listener was not added",
- mUtils.getCameraService().addListener(listener) ==
- CameraBinderTestUtils.NO_ERROR);
- assertTrue(
- "Listener was wrongly added again",
- mUtils.getCameraService().addListener(listener) ==
- CameraBinderTestUtils.ALREADY_EXISTS);
+ mUtils.getCameraService().addListener(listener);
- assertTrue(
- "Listener was not removed",
- mUtils.getCameraService().removeListener(listener) ==
- CameraBinderTestUtils.NO_ERROR);
- assertTrue(
- "Listener was wrongly removed again",
- mUtils.getCameraService().removeListener(listener) ==
- CameraBinderTestUtils.BAD_VALUE);
+ try {
+ mUtils.getCameraService().addListener(listener);
+ fail("Listener was wrongly added again");
+ } catch (ServiceSpecificException e) {
+ assertEquals("Listener was wrongly added again",
+ e.errorCode, ICameraService.ERROR_ALREADY_EXISTS);
+ }
+
+ mUtils.getCameraService().removeListener(listener);
+
+ try {
+ mUtils.getCameraService().removeListener(listener);
+ fail("Listener was wrongly removed twice");
+ } catch (ServiceSpecificException e) {
+ assertEquals("Listener was wrongly removed twice",
+ e.errorCode, ICameraService.ERROR_ILLEGAL_ARGUMENT);
+ }
}
}
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTestUtils.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTestUtils.java
index 5c4b23b..38fc49f 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTestUtils.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTestUtils.java
@@ -18,10 +18,6 @@
static final String CAMERA_SERVICE_BINDER_NAME = "media.camera";
- protected static final int USE_CALLING_UID = -1;
- protected static final int BAD_VALUE = -EINVAL;
- protected static final int INVALID_OPERATION = -ENOSYS;
- protected static final int ALREADY_EXISTS = -EEXIST;
public static final int NO_ERROR = 0;
private final Context mContext;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
index d71b44b..5c1d8a7 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -18,6 +18,7 @@
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
+import android.hardware.ICameraService;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
@@ -27,12 +28,13 @@
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.impl.CaptureResultExtras;
import android.hardware.camera2.params.OutputConfiguration;
-import android.hardware.camera2.utils.BinderHolder;
+import android.hardware.camera2.utils.SubmitInfo;
import android.media.Image;
import android.media.ImageReader;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.RemoteException;
+import android.os.ServiceSpecificException;
import android.os.SystemClock;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
@@ -164,11 +166,10 @@
}
private CaptureRequest.Builder createDefaultBuilder(boolean needStream) throws Exception {
- CameraMetadataNative metadata = new CameraMetadataNative();
+ CameraMetadataNative metadata = null;
assertTrue(metadata.isEmpty());
- int status = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW, /* out */metadata);
- assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+ metadata = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW);
assertFalse(metadata.isEmpty());
CaptureRequest.Builder request = new CaptureRequest.Builder(metadata, /*reprocess*/false,
@@ -183,12 +184,13 @@
return request;
}
- private int submitCameraRequest(CaptureRequest request, boolean streaming) throws Exception {
- int requestId = mCameraUser.submitRequest(request, streaming, null);
+ private SubmitInfo submitCameraRequest(CaptureRequest request, boolean streaming) throws Exception {
+ SubmitInfo requestInfo = mCameraUser.submitRequest(request, streaming);
assertTrue(
- "Request IDs should be non-negative (expected: >= 0, actual: " + requestId + ")",
- requestId >= 0);
- return requestId;
+ "Request IDs should be non-negative (expected: >= 0, actual: " +
+ requestInfo.getRequestId() + ")",
+ requestInfo.getRequestId() >= 0);
+ return requestInfo;
}
@Override
@@ -214,10 +216,8 @@
mMockCb = spy(dummyCallbacks);
- BinderHolder holder = new BinderHolder();
- mUtils.getCameraService().connectDevice(mMockCb, mCameraId,
- clientPackageName, CameraBinderTestUtils.USE_CALLING_UID, holder);
- mCameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
+ mCameraUser = mUtils.getCameraService().connectDevice(mMockCb, mCameraId,
+ clientPackageName, ICameraService.USE_CALLING_UID);
assertNotNull(String.format("Camera %s was null", mCameraId), mCameraUser);
mHandlerThread = new HandlerThread(TAG);
mHandlerThread.start();
@@ -238,11 +238,10 @@
@SmallTest
public void testCreateDefaultRequest() throws Exception {
- CameraMetadataNative metadata = new CameraMetadataNative();
+ CameraMetadataNative metadata = null;
assertTrue(metadata.isEmpty());
- int status = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW, /* out */metadata);
- assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+ metadata = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW);
assertFalse(metadata.isEmpty());
}
@@ -252,18 +251,28 @@
int streamId = mCameraUser.createStream(mOutputConfiguration);
assertEquals(0, streamId);
- assertEquals(CameraBinderTestUtils.ALREADY_EXISTS,
- mCameraUser.createStream(mOutputConfiguration));
+ try {
+ mCameraUser.createStream(mOutputConfiguration);
+ fail("Creating same stream twice");
+ } catch (ServiceSpecificException e) {
+ assertEquals("Creating same stream twice",
+ e.errorCode, ICameraService.ERROR_ALREADY_EXISTS);
+ }
- assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId));
+ mCameraUser.deleteStream(streamId);
}
@SmallTest
public void testDeleteInvalidStream() throws Exception {
- assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(-1));
- assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(0));
- assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(1));
- assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(0xC0FFEE));
+ int[] badStreams = { -1, 0, 1, 0xC0FFEE };
+ for (int badStream : badStreams) {
+ try {
+ mCameraUser.deleteStream(badStream);
+ fail("Allowed bad stream delete");
+ } catch (ServiceSpecificException e) {
+ assertEquals(e.errorCode, ICameraService.ERROR_ILLEGAL_ARGUMENT);
+ }
+ }
}
@SmallTest
@@ -273,8 +282,13 @@
int streamId = mCameraUser.createStream(mOutputConfiguration);
assertEquals(0, streamId);
- assertEquals(CameraBinderTestUtils.ALREADY_EXISTS,
- mCameraUser.createStream(mOutputConfiguration));
+ try {
+ mCameraUser.createStream(mOutputConfiguration);
+ fail("Created same stream twice");
+ } catch (ServiceSpecificException e) {
+ assertEquals("Created same stream twice",
+ ICameraService.ERROR_ALREADY_EXISTS, e.errorCode);
+ }
// Create second stream with a different surface.
SurfaceTexture surfaceTexture = new SurfaceTexture(/* ignored */0);
@@ -286,8 +300,8 @@
assertEquals(1, streamId2);
// Clean up streams
- assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId));
- assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId2));
+ mCameraUser.deleteStream(streamId);
+ mCameraUser.deleteStream(streamId2);
}
@SmallTest
@@ -295,16 +309,25 @@
CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */false);
CaptureRequest request1 = builder.build();
- int status = mCameraUser.submitRequest(request1, /* streaming */false, null);
- assertEquals("Expected submitRequest to return BAD_VALUE " +
- "since we had 0 surface targets set.", CameraBinderTestUtils.BAD_VALUE, status);
+ try {
+ SubmitInfo requestInfo = mCameraUser.submitRequest(request1, /* streaming */false);
+ fail("Exception expected");
+ } catch(ServiceSpecificException e) {
+ assertEquals("Expected submitRequest to throw ServiceSpecificException with BAD_VALUE " +
+ "since we had 0 surface targets set.", ICameraService.ERROR_ILLEGAL_ARGUMENT,
+ e.errorCode);
+ }
builder.addTarget(mSurface);
CaptureRequest request2 = builder.build();
- status = mCameraUser.submitRequest(request2, /* streaming */false, null);
- assertEquals("Expected submitRequest to return BAD_VALUE since " +
- "the target surface wasn't registered with createStream.",
- CameraBinderTestUtils.BAD_VALUE, status);
+ try {
+ SubmitInfo requestInfo = mCameraUser.submitRequest(request2, /* streaming */false);
+ fail("Exception expected");
+ } catch(ServiceSpecificException e) {
+ assertEquals("Expected submitRequest to throw ILLEGAL_ARGUMENT " +
+ "ServiceSpecificException since the target wasn't registered with createStream.",
+ ICameraService.ERROR_ILLEGAL_ARGUMENT, e.errorCode);
+ }
}
@SmallTest
@@ -314,9 +337,10 @@
CaptureRequest request = builder.build();
// Submit valid request twice.
- int requestId1 = submitCameraRequest(request, /* streaming */false);
- int requestId2 = submitCameraRequest(request, /* streaming */false);
- assertNotSame("Request IDs should be unique for multiple requests", requestId1, requestId2);
+ SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo2 = submitCameraRequest(request, /* streaming */false);
+ assertNotSame("Request IDs should be unique for multiple requests",
+ requestInfo1.getRequestId(), requestInfo2.getRequestId());
}
@@ -329,32 +353,35 @@
// Submit valid request once (non-streaming), and another time
// (streaming)
- int requestId1 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);
- int requestIdStreaming = submitCameraRequest(request, /* streaming */true);
- assertNotSame("Request IDs should be unique for multiple requests", requestId1,
- requestIdStreaming);
+ SubmitInfo requestInfoStreaming = submitCameraRequest(request, /* streaming */true);
+ assertNotSame("Request IDs should be unique for multiple requests",
+ requestInfo1.getRequestId(),
+ requestInfoStreaming.getRequestId());
- int status = mCameraUser.cancelRequest(-1, null);
- assertEquals("Invalid request IDs should not be cancellable",
- CameraBinderTestUtils.BAD_VALUE, status);
+ try {
+ long lastFrameNumber = mCameraUser.cancelRequest(-1);
+ fail("Expected exception");
+ } catch (ServiceSpecificException e) {
+ assertEquals("Invalid request IDs should not be cancellable",
+ ICameraService.ERROR_ILLEGAL_ARGUMENT, e.errorCode);
+ }
- status = mCameraUser.cancelRequest(requestId1, null);
- assertEquals("Non-streaming request IDs should not be cancellable",
- CameraBinderTestUtils.BAD_VALUE, status);
+ try {
+ long lastFrameNumber = mCameraUser.cancelRequest(requestInfo1.getRequestId());
+ fail("Expected exception");
+ } catch (ServiceSpecificException e) {
+ assertEquals("Non-streaming request IDs should not be cancellable",
+ ICameraService.ERROR_ILLEGAL_ARGUMENT, e.errorCode);
+ }
- status = mCameraUser.cancelRequest(requestIdStreaming, null);
- assertEquals("Streaming request IDs should be cancellable", CameraBinderTestUtils.NO_ERROR,
- status);
-
+ long lastFrameNumber = mCameraUser.cancelRequest(requestInfoStreaming.getRequestId());
}
@SmallTest
public void testCameraInfo() throws RemoteException {
- CameraMetadataNative info = new CameraMetadataNative();
-
- int status = mCameraUser.getCameraInfo(/*out*/info);
- assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+ CameraMetadataNative info = mCameraUser.getCameraInfo();
assertFalse(info.isEmpty());
assertNotNull(info.get(CameraCharacteristics.SCALER_AVAILABLE_FORMATS));
@@ -362,10 +389,7 @@
@SmallTest
public void testCameraCharacteristics() throws RemoteException {
- CameraMetadataNative info = new CameraMetadataNative();
-
- int status = mUtils.getCameraService().getCameraCharacteristics(mCameraId, /*out*/info);
- assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+ CameraMetadataNative info = mUtils.getCameraService().getCameraCharacteristics(mCameraId);
assertFalse(info.isEmpty());
assertNotNull(info.get(CameraCharacteristics.SCALER_AVAILABLE_FORMATS));
@@ -374,18 +398,19 @@
@SmallTest
public void testWaitUntilIdle() throws Exception {
CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */true);
- int requestIdStreaming = submitCameraRequest(builder.build(), /* streaming */true);
+ SubmitInfo requestInfoStreaming = submitCameraRequest(builder.build(), /* streaming */true);
// Test Bad case first: waitUntilIdle when there is active repeating request
- int status = mCameraUser.waitUntilIdle();
- assertEquals("waitUntilIdle is invalid operation when there is active repeating request",
- CameraBinderTestUtils.INVALID_OPERATION, status);
+ try {
+ mCameraUser.waitUntilIdle();
+ } catch (ServiceSpecificException e) {
+ assertEquals("waitUntilIdle is invalid operation when there is active repeating request",
+ ICameraService.ERROR_INVALID_OPERATION, e.errorCode);
+ }
// Test good case, waitUntilIdle when there is no active repeating request
- status = mCameraUser.cancelRequest(requestIdStreaming, null);
- assertEquals(CameraBinderTestUtils.NO_ERROR, status);
- status = mCameraUser.waitUntilIdle();
- assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+ long lastFrameNumber = mCameraUser.cancelRequest(requestInfoStreaming.getRequestId());
+ mCameraUser.waitUntilIdle();
}
@SmallTest
@@ -411,12 +436,12 @@
ArgumentCaptor<Long> timestamps = ArgumentCaptor.forClass(Long.class);
// Test both single request and streaming request.
- int requestId1 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);
verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).times(1)).onCaptureStarted(
any(CaptureResultExtras.class),
anyLong());
- int streamingId = submitCameraRequest(request, /* streaming */true);
+ SubmitInfo streamingInfo = submitCameraRequest(request, /* streaming */true);
verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).atLeast(NUM_CALLBACKS_CHECKED))
.onCaptureStarted(
any(CaptureResultExtras.class),
@@ -436,22 +461,22 @@
CaptureRequest request = createDefaultBuilder(/* needStream */true).build();
// Try streaming
- int streamingId = submitCameraRequest(request, /* streaming */true);
+ SubmitInfo streamingInfo = submitCameraRequest(request, /* streaming */true);
// Wait a bit to fill up the queue
SystemClock.sleep(WAIT_FOR_WORK_MS);
// Cancel and make sure we eventually quiesce
- status = mCameraUser.cancelRequest(streamingId, null);
+ long lastFrameNumber = mCameraUser.cancelRequest(streamingInfo.getRequestId());
verify(mMockCb, timeout(WAIT_FOR_IDLE_TIMEOUT_MS).times(1)).onDeviceIdle();
// Submit a few capture requests
- int requestId1 = submitCameraRequest(request, /* streaming */false);
- int requestId2 = submitCameraRequest(request, /* streaming */false);
- int requestId3 = submitCameraRequest(request, /* streaming */false);
- int requestId4 = submitCameraRequest(request, /* streaming */false);
- int requestId5 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo2 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo3 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo4 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo5 = submitCameraRequest(request, /* streaming */false);
// And wait for more idle
verify(mMockCb, timeout(WAIT_FOR_IDLE_TIMEOUT_MS).times(2)).onDeviceIdle();
@@ -463,38 +488,34 @@
int status;
// Initial flush should work
- status = mCameraUser.flush(null);
- assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+ long lastFrameNumber = mCameraUser.flush();
// Then set up a stream
CaptureRequest request = createDefaultBuilder(/* needStream */true).build();
// Flush should still be a no-op, really
- status = mCameraUser.flush(null);
- assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+ lastFrameNumber = mCameraUser.flush();
// Submit a few capture requests
- int requestId1 = submitCameraRequest(request, /* streaming */false);
- int requestId2 = submitCameraRequest(request, /* streaming */false);
- int requestId3 = submitCameraRequest(request, /* streaming */false);
- int requestId4 = submitCameraRequest(request, /* streaming */false);
- int requestId5 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo2 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo3 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo4 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo5 = submitCameraRequest(request, /* streaming */false);
// Then flush and wait for idle
- status = mCameraUser.flush(null);
- assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+ lastFrameNumber = mCameraUser.flush();
verify(mMockCb, timeout(WAIT_FOR_FLUSH_TIMEOUT_MS).times(1)).onDeviceIdle();
// Now a streaming request
- int streamingId = submitCameraRequest(request, /* streaming */true);
+ SubmitInfo streamingInfo = submitCameraRequest(request, /* streaming */true);
// Wait a bit to fill up the queue
SystemClock.sleep(WAIT_FOR_WORK_MS);
// Then flush and wait for the idle callback
- status = mCameraUser.flush(null);
- assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+ lastFrameNumber = mCameraUser.flush();
verify(mMockCb, timeout(WAIT_FOR_FLUSH_TIMEOUT_MS).times(2)).onDeviceIdle();
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsBinderDecoratorTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsBinderDecoratorTest.java
deleted file mode 100644
index 33c6388..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsBinderDecoratorTest.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.mediaframeworktest.unit;
-
-import android.hardware.camera2.CameraAccessException;
-import android.hardware.camera2.utils.CameraBinderDecorator;
-import android.hardware.camera2.utils.CameraRuntimeException;
-import android.os.DeadObjectException;
-import android.os.RemoteException;
-import android.os.TransactionTooLargeException;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import static org.mockito.Mockito.*;
-import static android.hardware.camera2.utils.CameraBinderDecorator.*;
-import static android.hardware.camera2.CameraAccessException.*;
-import static android.system.OsConstants.*;
-
-import junit.framework.Assert;
-
-public class CameraUtilsBinderDecoratorTest extends junit.framework.TestCase {
-
- private interface ICameraBinderStereotype {
-
- double doNothing();
-
- // int is a 'status_t'
- int doSomethingPositive();
-
- int doSomethingNoError();
-
- int doSomethingPermissionDenied();
-
- int doSomethingAlreadyExists();
-
- int doSomethingBadValue();
-
- int doSomethingDeadObject() throws CameraRuntimeException;
-
- int doSomethingBadPolicy() throws CameraRuntimeException;
-
- int doSomethingDeviceBusy() throws CameraRuntimeException;
-
- int doSomethingNoSuchDevice() throws CameraRuntimeException;
-
- int doSomethingUnknownErrorCode();
-
- int doSomethingThrowDeadObjectException() throws RemoteException;
-
- int doSomethingThrowTransactionTooLargeException() throws RemoteException;
- }
-
- private static final double SOME_ARBITRARY_DOUBLE = 1.0;
- private static final int SOME_ARBITRARY_POSITIVE_INT = 5;
- private static final int SOME_ARBITRARY_NEGATIVE_INT = -0xC0FFEE;
-
- @SmallTest
- public void testStereotypes() {
-
- ICameraBinderStereotype mock = mock(ICameraBinderStereotype.class);
- try {
- when(mock.doNothing()).thenReturn(SOME_ARBITRARY_DOUBLE);
- when(mock.doSomethingPositive()).thenReturn(SOME_ARBITRARY_POSITIVE_INT);
- when(mock.doSomethingNoError()).thenReturn(NO_ERROR);
- when(mock.doSomethingPermissionDenied()).thenReturn(PERMISSION_DENIED);
- when(mock.doSomethingAlreadyExists()).thenReturn(ALREADY_EXISTS);
- when(mock.doSomethingBadValue()).thenReturn(BAD_VALUE);
- when(mock.doSomethingDeadObject()).thenReturn(DEAD_OBJECT);
- when(mock.doSomethingBadPolicy()).thenReturn(-EACCES);
- when(mock.doSomethingDeviceBusy()).thenReturn(-EBUSY);
- when(mock.doSomethingNoSuchDevice()).thenReturn(-ENODEV);
- when(mock.doSomethingUnknownErrorCode()).thenReturn(SOME_ARBITRARY_NEGATIVE_INT);
- when(mock.doSomethingThrowDeadObjectException()).thenThrow(new DeadObjectException());
- when(mock.doSomethingThrowTransactionTooLargeException()).thenThrow(
- new TransactionTooLargeException());
- } catch (RemoteException e) {
- Assert.fail("Unreachable");
- }
-
- ICameraBinderStereotype decoratedMock = CameraBinderDecorator.newInstance(mock);
-
- // ignored by decorator because return type is double, not int
- assertEquals(SOME_ARBITRARY_DOUBLE, decoratedMock.doNothing());
-
- // pass through for positive values
- assertEquals(SOME_ARBITRARY_POSITIVE_INT, decoratedMock.doSomethingPositive());
-
- // pass through NO_ERROR
- assertEquals(NO_ERROR, decoratedMock.doSomethingNoError());
-
- try {
- decoratedMock.doSomethingPermissionDenied();
- Assert.fail("Should've thrown SecurityException");
- } catch (SecurityException e) {
- }
-
- assertEquals(ALREADY_EXISTS, decoratedMock.doSomethingAlreadyExists());
-
- try {
- decoratedMock.doSomethingBadValue();
- Assert.fail("Should've thrown IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- }
-
- try {
- decoratedMock.doSomethingDeadObject();
- Assert.fail("Should've thrown CameraRuntimeException");
- } catch (CameraRuntimeException e) {
- assertEquals(CAMERA_DISCONNECTED, e.getReason());
- }
-
- try {
- decoratedMock.doSomethingBadPolicy();
- Assert.fail("Should've thrown CameraRuntimeException");
- } catch (CameraRuntimeException e) {
- assertEquals(CAMERA_DISABLED, e.getReason());
- }
-
- try {
- decoratedMock.doSomethingDeviceBusy();
- Assert.fail("Should've thrown CameraRuntimeException");
- } catch (CameraRuntimeException e) {
- assertEquals(CAMERA_IN_USE, e.getReason());
- }
-
- try {
- decoratedMock.doSomethingNoSuchDevice();
- Assert.fail("Should've thrown CameraRuntimeException");
- } catch (CameraRuntimeException e) {
- assertEquals(CAMERA_DISCONNECTED, e.getReason());
- }
-
- try {
- decoratedMock.doSomethingUnknownErrorCode();
- Assert.fail("Should've thrown UnsupportedOperationException");
- } catch (UnsupportedOperationException e) {
- assertEquals(String.format("Unknown error %d",
- SOME_ARBITRARY_NEGATIVE_INT), e.getMessage());
- }
-
- try {
- decoratedMock.doSomethingThrowDeadObjectException();
- Assert.fail("Should've thrown CameraRuntimeException");
- } catch (CameraRuntimeException e) {
- assertEquals(CAMERA_DISCONNECTED, e.getReason());
- } catch (RemoteException e) {
- Assert.fail("Should not throw a DeadObjectException directly, but rethrow");
- }
-
- try {
- decoratedMock.doSomethingThrowTransactionTooLargeException();
- Assert.fail("Should've thrown UnsupportedOperationException");
- } catch (UnsupportedOperationException e) {
- assertTrue(e.getCause() instanceof TransactionTooLargeException);
- } catch (RemoteException e) {
- Assert.fail("Should not throw a TransactionTooLargeException directly, but rethrow");
- }
- }
-
-}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsDecoratorTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsDecoratorTest.java
deleted file mode 100644
index c3b6006..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsDecoratorTest.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.mediaframeworktest.unit;
-
-import android.test.suitebuilder.annotation.SmallTest;
-import android.hardware.camera2.utils.*;
-import android.hardware.camera2.utils.Decorator.DecoratorListener;
-
-import junit.framework.Assert;
-
-import java.lang.reflect.Method;
-
-/**
- * adb shell am instrument -e class 'com.android.mediaframeworktest.unit.CameraUtilsDecoratorTest' \
- * -w com.android.mediaframeworktest/.MediaFrameworkUnitTestRunner
- */
-public class CameraUtilsDecoratorTest extends junit.framework.TestCase {
- private DummyListener mDummyListener;
- private DummyInterface mIface;
-
- @Override
- public void setUp() {
- mDummyListener = new DummyListener();
- mIface = Decorator.newInstance(new DummyImpl(), mDummyListener);
- }
-
- interface DummyInterface {
- int addValues(int x, int y, int z);
-
- void raiseException() throws Exception;
-
- void raiseUnsupportedOperationException() throws UnsupportedOperationException;
- }
-
- class DummyImpl implements DummyInterface {
- @Override
- public int addValues(int x, int y, int z) {
- return x + y + z;
- }
-
- @Override
- public void raiseException() throws Exception {
- throw new Exception("Test exception");
- }
-
- @Override
- public void raiseUnsupportedOperationException() throws UnsupportedOperationException {
- throw new UnsupportedOperationException("Test exception");
- }
- }
-
- class DummyListener implements DecoratorListener {
-
- public boolean beforeCalled = false;
- public boolean afterCalled = false;
- public boolean catchCalled = false;
- public boolean finallyCalled = false;
- public Object resultValue = null;
-
- public boolean raiseException = false;
-
- @Override
- public void onBeforeInvocation(Method m, Object[] args) {
- beforeCalled = true;
- }
-
- @Override
- public void onAfterInvocation(Method m, Object[] args, Object result) {
- afterCalled = true;
- resultValue = result;
-
- if (raiseException) {
- throw new UnsupportedOperationException("Test exception");
- }
- }
-
- @Override
- public boolean onCatchException(Method m, Object[] args, Throwable t) {
- catchCalled = true;
- return false;
- }
-
- @Override
- public void onFinally(Method m, Object[] args) {
- finallyCalled = true;
- }
-
- };
-
- @SmallTest
- public void testDecorator() {
-
- // TODO rewrite this using mocks
-
- assertTrue(mIface.addValues(1, 2, 3) == 6);
- assertTrue(mDummyListener.beforeCalled);
- assertTrue(mDummyListener.afterCalled);
-
- int resultValue = (Integer)mDummyListener.resultValue;
- assertTrue(resultValue == 6);
- assertTrue(mDummyListener.finallyCalled);
- assertFalse(mDummyListener.catchCalled);
- }
-
- @SmallTest
- public void testDecoratorExceptions() {
-
- boolean gotExceptions = false;
- try {
- mIface.raiseException();
- } catch (Exception e) {
- gotExceptions = true;
- assertTrue(e.getMessage() == "Test exception");
- }
- assertTrue(gotExceptions);
- assertTrue(mDummyListener.beforeCalled);
- assertFalse(mDummyListener.afterCalled);
- assertTrue(mDummyListener.catchCalled);
- assertTrue(mDummyListener.finallyCalled);
- }
-
- @SmallTest
- public void testDecoratorUnsupportedOperationException() {
-
- boolean gotExceptions = false;
- try {
- mIface.raiseUnsupportedOperationException();
- } catch (UnsupportedOperationException e) {
- gotExceptions = true;
- assertTrue(e.getMessage() == "Test exception");
- }
- assertTrue(gotExceptions);
- assertTrue(mDummyListener.beforeCalled);
- assertFalse(mDummyListener.afterCalled);
- assertTrue(mDummyListener.catchCalled);
- assertTrue(mDummyListener.finallyCalled);
- }
-
- @SmallTest
- public void testDecoratorRaisesException() {
-
- boolean gotExceptions = false;
- try {
- mDummyListener.raiseException = true;
- mIface.addValues(1, 2, 3);
- Assert.fail("unreachable");
- } catch (UnsupportedOperationException e) {
- gotExceptions = true;
- assertTrue(e.getMessage() == "Test exception");
- }
- assertTrue(gotExceptions);
- assertTrue(mDummyListener.beforeCalled);
- assertTrue(mDummyListener.afterCalled);
- assertFalse(mDummyListener.catchCalled);
- assertTrue(mDummyListener.finallyCalled);
- }
-}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsRuntimeExceptionTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsRuntimeExceptionTest.java
deleted file mode 100644
index 02c9f2a..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsRuntimeExceptionTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.mediaframeworktest.unit;
-
-import android.hardware.camera2.CameraAccessException;
-import android.hardware.camera2.utils.CameraRuntimeException;
-import android.hardware.camera2.utils.UncheckedThrow;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.Assert;
-
-public class CameraUtilsRuntimeExceptionTest extends junit.framework.TestCase {
-
- @SmallTest
- public void testCameraRuntimeException1() {
- try {
- CameraRuntimeException runtimeExc = new CameraRuntimeException(12345);
- throw runtimeExc.asChecked();
- } catch (CameraAccessException e) {
- assertEquals(12345, e.getReason());
- assertNull(e.getMessage());
- assertNull(e.getCause());
- }
- }
-
- @SmallTest
- public void testCameraRuntimeException2() {
- try {
- CameraRuntimeException runtimeExc = new CameraRuntimeException(12345, "Hello");
- throw runtimeExc.asChecked();
- } catch (CameraAccessException e) {
- assertEquals(12345, e.getReason());
- assertEquals("Hello", e.getMessage());
- assertNull(e.getCause());
- }
- }
-
- @SmallTest
- public void testCameraRuntimeException3() {
- Throwable cause = new IllegalStateException("For great justice");
- try {
- CameraRuntimeException runtimeExc = new CameraRuntimeException(12345, cause);
- throw runtimeExc.asChecked();
- } catch (CameraAccessException e) {
- assertEquals(12345, e.getReason());
- assertNull(e.getMessage());
- assertEquals(cause, e.getCause());
- }
- }
-
- @SmallTest
- public void testCameraRuntimeException4() {
- Throwable cause = new IllegalStateException("For great justice");
- try {
- CameraRuntimeException runtimeExc = new CameraRuntimeException(12345, "Hello", cause);
- throw runtimeExc.asChecked();
- } catch (CameraAccessException e) {
- assertEquals(12345, e.getReason());
- assertEquals("Hello", e.getMessage());
- assertEquals(cause, e.getCause());
- }
- }
-}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
new file mode 100644
index 0000000..1c80746
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import com.android.mediaframeworktest.R;
+
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.media.ExifInterface;
+import android.os.Environment;
+import android.os.ParcelFileDescriptor;
+import android.test.AndroidTestCase;
+import android.util.Log;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.lang.reflect.Type;
+
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+
+public class ExifInterfaceTest extends AndroidTestCase {
+ private static final String TAG = ExifInterface.class.getSimpleName();
+ private static final boolean VERBOSE = false; // lots of logging
+
+ private static final double DIFFERENCE_TOLERANCE = .005;
+ private static final int BUFFER_SIZE = 32768;
+
+ // List of files.
+ private static final String EXIF_BYTE_ORDER_II_JPEG = "ExifByteOrderII.jpg";
+ private static final String EXIF_BYTE_ORDER_MM_JPEG = "ExifByteOrderMM.jpg";
+ private static final String LG_G4_ISO_800_DNG = "lg_g4_iso_800.dng";
+ private static final int[] IMAGE_RESOURCES = new int[] {
+ R.raw.image_exif_byte_order_ii, R.raw.image_exif_byte_order_mm, R.raw.lg_g4_iso_800 };
+ private static final String[] IMAGE_FILENAMES = new String[] {
+ EXIF_BYTE_ORDER_II_JPEG, EXIF_BYTE_ORDER_MM_JPEG, LG_G4_ISO_800_DNG };
+
+ private static final String[] EXIF_TAGS = {
+ ExifInterface.TAG_MAKE,
+ ExifInterface.TAG_MODEL,
+ ExifInterface.TAG_APERTURE,
+ ExifInterface.TAG_DATETIME,
+ ExifInterface.TAG_EXPOSURE_TIME,
+ ExifInterface.TAG_FLASH,
+ ExifInterface.TAG_FOCAL_LENGTH,
+ ExifInterface.TAG_GPS_ALTITUDE,
+ ExifInterface.TAG_GPS_ALTITUDE_REF,
+ ExifInterface.TAG_GPS_DATESTAMP,
+ ExifInterface.TAG_GPS_LATITUDE,
+ ExifInterface.TAG_GPS_LATITUDE_REF,
+ ExifInterface.TAG_GPS_LONGITUDE,
+ ExifInterface.TAG_GPS_LONGITUDE_REF,
+ ExifInterface.TAG_GPS_PROCESSING_METHOD,
+ ExifInterface.TAG_GPS_TIMESTAMP,
+ ExifInterface.TAG_IMAGE_LENGTH,
+ ExifInterface.TAG_IMAGE_WIDTH,
+ ExifInterface.TAG_ISO,
+ ExifInterface.TAG_ORIENTATION,
+ ExifInterface.TAG_WHITE_BALANCE
+ };
+
+ private static class ExpectedValue {
+ // Thumbnail information.
+ public final boolean hasThumbnail;
+ public final int thumbnailWidth;
+ public final int thumbnailHeight;
+
+ // GPS information.
+ public final boolean hasLatLong;
+ public final float latitude;
+ public final float longitude;
+ public final float altitude;
+
+ // Values.
+ public final String make;
+ public final String model;
+ public final float aperture;
+ public final String datetime;
+ public final float exposureTime;
+ public final float flash;
+ public final String focalLength;
+ public final String gpsAltitude;
+ public final String gpsAltitudeRef;
+ public final String gpsDatestamp;
+ public final String gpsLatitude;
+ public final String gpsLatitudeRef;
+ public final String gpsLongitude;
+ public final String gpsLongitudeRef;
+ public final String gpsProcessingMethod;
+ public final String gpsTimestamp;
+ public final String imageLength;
+ public final String imageWidth;
+ public final String iso;
+ public final String whiteBalance;
+ public final String orientation;
+
+ private static String getString(TypedArray typedArray, int index) {
+ String stringValue = typedArray.getString(index);
+ if (stringValue == null || stringValue.equals("")) {
+ return null;
+ }
+ return stringValue.trim();
+ }
+
+ public ExpectedValue(TypedArray typedArray) {
+ // Reads thumbnail information.
+ hasThumbnail = typedArray.getBoolean(0, false);
+ thumbnailWidth = typedArray.getInt(1, 0);
+ thumbnailHeight = typedArray.getInt(2, 0);
+
+ // Reads GPS information.
+ hasLatLong = typedArray.getBoolean(3, false);
+ latitude = typedArray.getFloat(4, 0f);
+ longitude = typedArray.getFloat(5, 0f);
+ altitude = typedArray.getFloat(6, 0f);
+
+ // Read values.
+ make = getString(typedArray, 7);
+ model = getString(typedArray, 8);
+ aperture = typedArray.getFloat(9, 0f);
+ datetime = getString(typedArray, 10);
+ exposureTime = typedArray.getFloat(11, 0f);
+ flash = typedArray.getFloat(12, 0f);
+ focalLength = getString(typedArray, 13);
+ gpsAltitude = getString(typedArray, 14);
+ gpsAltitudeRef = getString(typedArray, 15);
+ gpsDatestamp = getString(typedArray, 16);
+ gpsLatitude = getString(typedArray, 17);
+ gpsLatitudeRef = getString(typedArray, 18);
+ gpsLongitude = getString(typedArray, 19);
+ gpsLongitudeRef = getString(typedArray, 20);
+ gpsProcessingMethod = getString(typedArray, 21);
+ gpsTimestamp = getString(typedArray, 22);
+ imageLength = getString(typedArray, 23);
+ imageWidth = getString(typedArray, 24);
+ iso = getString(typedArray, 25);
+ orientation = getString(typedArray, 26);
+ whiteBalance = getString(typedArray, 27);
+
+ typedArray.recycle();
+ }
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ byte[] buffer = new byte[BUFFER_SIZE];
+
+ for (int i = 0; i < IMAGE_RESOURCES.length; ++i) {
+ String outputPath = new File(Environment.getExternalStorageDirectory(),
+ IMAGE_FILENAMES[i]).getAbsolutePath();
+ try (InputStream inputStream = getContext().getResources().openRawResource(
+ IMAGE_RESOURCES[i])) {
+ try (FileOutputStream outputStream = new FileOutputStream(outputPath)) {
+ Streams.copy(inputStream, outputStream);
+ }
+ }
+ }
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ for (int i = 0; i < IMAGE_RESOURCES.length; ++i) {
+ String imageFilePath = new File(Environment.getExternalStorageDirectory(),
+ IMAGE_FILENAMES[i]).getAbsolutePath();
+ File imageFile = new File(imageFilePath);
+ if (imageFile.exists()) {
+ imageFile.delete();
+ }
+ }
+
+ super.tearDown();
+ }
+
+ private void printExifTagsAndValues(String fileName, ExifInterface exifInterface) {
+ // Prints thumbnail information.
+ if (exifInterface.hasThumbnail()) {
+ byte[] thumbnailBytes = exifInterface.getThumbnail();
+ if (thumbnailBytes != null) {
+ Log.v(TAG, fileName + " Thumbnail size = " + thumbnailBytes.length);
+ Bitmap bitmap = BitmapFactory.decodeByteArray(
+ thumbnailBytes, 0, thumbnailBytes.length);
+ if (bitmap == null) {
+ Log.e(TAG, fileName + " Corrupted thumbnail!");
+ } else {
+ Log.v(TAG, fileName + " Thumbnail size: " + bitmap.getWidth() + ", "
+ + bitmap.getHeight());
+ }
+ } else {
+ Log.e(TAG, fileName + " Corrupted image (no thumbnail)");
+ }
+ } else {
+ if (exifInterface.getThumbnail() != null) {
+ Log.e(TAG, fileName + " Corrupted image (a thumbnail exists)");
+ } else {
+ Log.v(TAG, fileName + " No thumbnail");
+ }
+ }
+
+ // Prints GPS information.
+ Log.v(TAG, fileName + " Altitude = " + exifInterface.getAltitude(.0));
+
+ float[] latLong = new float[2];
+ if (exifInterface.getLatLong(latLong)) {
+ Log.v(TAG, fileName + " Latitude = " + latLong[0]);
+ Log.v(TAG, fileName + " Longitude = " + latLong[1]);
+ } else {
+ Log.v(TAG, fileName + "No latlong data");
+ }
+
+ // Prints values.
+ for (String tagKey : EXIF_TAGS) {
+ String tagValue = exifInterface.getAttribute(tagKey);
+ Log.v(TAG, fileName + "Key{" + tagKey + "} = '" + tagValue + "'");
+ }
+ }
+
+ private void compareFloatTag(ExifInterface exifInterface, String tag, float expectedValue) {
+ String stringValue = exifInterface.getAttribute(tag);
+ float floatValue = 0f;
+
+ if (stringValue != null) {
+ floatValue = Float.parseFloat(stringValue);
+ }
+
+ assertEquals(expectedValue, floatValue, DIFFERENCE_TOLERANCE);
+ }
+
+ private void compareStringTag(ExifInterface exifInterface, String tag, String expectedValue) {
+ String stringValue = exifInterface.getAttribute(tag);
+ if (stringValue != null) {
+ stringValue = stringValue.trim();
+ }
+
+ assertEquals(expectedValue, stringValue);
+ }
+
+ private void compareWithExpectedValue(ExifInterface exifInterface,
+ ExpectedValue expectedValue) {
+ // Checks a thumbnail image.
+ assertEquals(expectedValue.hasThumbnail, exifInterface.hasThumbnail());
+ if (expectedValue.hasThumbnail) {
+ byte[] thumbnailBytes = exifInterface.getThumbnail();
+ assertNotNull(thumbnailBytes);
+ Bitmap thumbnailBitmap =
+ BitmapFactory.decodeByteArray(thumbnailBytes, 0, thumbnailBytes.length);
+ assertNotNull(thumbnailBitmap);
+ assertEquals(expectedValue.thumbnailWidth, thumbnailBitmap.getWidth());
+ assertEquals(expectedValue.thumbnailHeight, thumbnailBitmap.getHeight());
+ } else {
+ assertNull(exifInterface.getThumbnail());
+ }
+
+ // Checks GPS information.
+ float[] latLong = new float[2];
+ assertEquals(expectedValue.hasLatLong, exifInterface.getLatLong(latLong));
+ if (expectedValue.hasLatLong) {
+ assertEquals(expectedValue.latitude, latLong[0], DIFFERENCE_TOLERANCE);
+ assertEquals(expectedValue.longitude, latLong[1], DIFFERENCE_TOLERANCE);
+ }
+ assertEquals(expectedValue.altitude, exifInterface.getAltitude(.0), DIFFERENCE_TOLERANCE);
+
+ // Checks values.
+ compareStringTag(exifInterface, ExifInterface.TAG_MAKE, expectedValue.make);
+ compareStringTag(exifInterface, ExifInterface.TAG_MODEL, expectedValue.model);
+ compareFloatTag(exifInterface, ExifInterface.TAG_APERTURE, expectedValue.aperture);
+ compareStringTag(exifInterface, ExifInterface.TAG_DATETIME, expectedValue.datetime);
+ compareFloatTag(exifInterface, ExifInterface.TAG_EXPOSURE_TIME, expectedValue.exposureTime);
+ compareFloatTag(exifInterface, ExifInterface.TAG_FLASH, expectedValue.flash);
+ compareStringTag(exifInterface, ExifInterface.TAG_FOCAL_LENGTH, expectedValue.focalLength);
+ compareStringTag(exifInterface, ExifInterface.TAG_GPS_ALTITUDE, expectedValue.gpsAltitude);
+ compareStringTag(exifInterface, ExifInterface.TAG_GPS_ALTITUDE_REF,
+ expectedValue.gpsAltitudeRef);
+ compareStringTag(exifInterface, ExifInterface.TAG_GPS_DATESTAMP,
+ expectedValue.gpsDatestamp);
+ compareStringTag(exifInterface, ExifInterface.TAG_GPS_LATITUDE, expectedValue.gpsLatitude);
+ compareStringTag(exifInterface, ExifInterface.TAG_GPS_LATITUDE_REF,
+ expectedValue.gpsLatitudeRef);
+ compareStringTag(exifInterface, ExifInterface.TAG_GPS_LONGITUDE,
+ expectedValue.gpsLongitude);
+ compareStringTag(exifInterface, ExifInterface.TAG_GPS_LONGITUDE_REF,
+ expectedValue.gpsLongitudeRef);
+ compareStringTag(exifInterface, ExifInterface.TAG_GPS_PROCESSING_METHOD,
+ expectedValue.gpsProcessingMethod);
+ compareStringTag(exifInterface, ExifInterface.TAG_GPS_TIMESTAMP,
+ expectedValue.gpsTimestamp);
+ compareStringTag(exifInterface, ExifInterface.TAG_IMAGE_LENGTH, expectedValue.imageLength);
+ compareStringTag(exifInterface, ExifInterface.TAG_IMAGE_WIDTH, expectedValue.imageWidth);
+ compareStringTag(exifInterface, ExifInterface.TAG_ISO, expectedValue.iso);
+ compareStringTag(exifInterface, ExifInterface.TAG_ORIENTATION, expectedValue.orientation);
+ compareStringTag(exifInterface, ExifInterface.TAG_WHITE_BALANCE,
+ expectedValue.whiteBalance);
+ }
+
+ private void testExifInterfaceForJpeg(String fileName, int typedArrayResourceId)
+ throws IOException {
+ ExpectedValue expectedValue = new ExpectedValue(
+ getContext().getResources().obtainTypedArray(typedArrayResourceId));
+ File imageFile = new File(Environment.getExternalStorageDirectory(), fileName);
+
+ // Created via path.
+ ExifInterface exifInterface = new ExifInterface(imageFile.getAbsolutePath());
+ if (VERBOSE) {
+ printExifTagsAndValues(fileName, exifInterface);
+ }
+ compareWithExpectedValue(exifInterface, expectedValue);
+
+ // Created via InputStream.
+ FileInputStream in = null;
+ try {
+ in = new FileInputStream(imageFile.getAbsolutePath());
+ exifInterface = new ExifInterface(in);
+ if (VERBOSE) {
+ printExifTagsAndValues(fileName, exifInterface);
+ }
+ compareWithExpectedValue(exifInterface, expectedValue);
+ } finally {
+ IoUtils.closeQuietly(in);
+ }
+
+ // Created via FileDescriptor.
+ try {
+ FileDescriptor fd = Os.open(imageFile.getAbsolutePath(), OsConstants.O_RDONLY, 0600);
+ exifInterface = new ExifInterface(fd);
+ if (VERBOSE) {
+ printExifTagsAndValues(fileName, exifInterface);
+ }
+ compareWithExpectedValue(exifInterface, expectedValue);
+ } catch (ErrnoException e) {
+ e.rethrowAsIOException();
+ }
+
+ // Test for saving attributes.
+ try {
+ FileDescriptor fd = Os.open(imageFile.getAbsolutePath(), OsConstants.O_RDWR, 0600);
+ exifInterface = new ExifInterface(fd);
+ exifInterface.saveAttributes();
+ exifInterface = new ExifInterface(fd);
+ if (VERBOSE) {
+ printExifTagsAndValues(fileName, exifInterface);
+ }
+ compareWithExpectedValue(exifInterface, expectedValue);
+ } catch (ErrnoException e) {
+ e.rethrowAsIOException();
+ }
+
+ // Test for modifying one attribute.
+ exifInterface = new ExifInterface(imageFile.getAbsolutePath());
+ exifInterface.setAttribute(ExifInterface.TAG_MAKE, "abc");
+ exifInterface.saveAttributes();
+ exifInterface = new ExifInterface(imageFile.getAbsolutePath());
+ if (VERBOSE) {
+ printExifTagsAndValues(fileName, exifInterface);
+ }
+ assertEquals("abc", exifInterface.getAttribute(ExifInterface.TAG_MAKE));
+ }
+
+ private void testExifInterfaceForRaw(String fileName, int typedArrayResourceId)
+ throws IOException {
+ ExpectedValue expectedValue = new ExpectedValue(
+ getContext().getResources().obtainTypedArray(typedArrayResourceId));
+ File imageFile = new File(Environment.getExternalStorageDirectory(), fileName);
+
+ // Created via path.
+ ExifInterface exifInterface = new ExifInterface(imageFile.getAbsolutePath());
+ if (VERBOSE) {
+ printExifTagsAndValues(fileName, exifInterface);
+ }
+ compareWithExpectedValue(exifInterface, expectedValue);
+
+ // Created via FileDescriptor.
+ FileInputStream in = null;
+ try {
+ in = new FileInputStream(imageFile);
+ exifInterface = new ExifInterface(in.getFD());
+ if (VERBOSE) {
+ printExifTagsAndValues(fileName, exifInterface);
+ }
+ compareWithExpectedValue(exifInterface, expectedValue);
+ } finally {
+ IoUtils.closeQuietly(in);
+ }
+ }
+
+ public void testReadExifDataFromExifByteOrderIIJpeg() throws Throwable {
+ testExifInterfaceForJpeg(EXIF_BYTE_ORDER_II_JPEG, R.array.exifbyteorderii_jpg);
+ }
+
+ public void testReadExifDataFromExifByteOrderMMJpeg() throws Throwable {
+ testExifInterfaceForJpeg(EXIF_BYTE_ORDER_MM_JPEG, R.array.exifbyteordermm_jpg);
+ }
+
+ public void testReadExifDataFromLgG4Iso800Dng() throws Throwable {
+ testExifInterfaceForRaw(LG_G4_ISO_800_DNG, R.array.lg_g4_iso_800_dng);
+ }
+}
diff --git a/opengl/java/android/opengl/GLES30.java b/opengl/java/android/opengl/GLES30.java
index 342ffa4..74181c5 100644
--- a/opengl/java/android/opengl/GLES30.java
+++ b/opengl/java/android/opengl/GLES30.java
@@ -889,7 +889,10 @@
);
// C function void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name )
-
+ /**
+ * @deprecated
+ * Use the version that takes a ByteBuffer as the last argument, or the versions that return a String.
+ * */
public static native void glGetTransformFeedbackVarying(
int program,
int index,
@@ -902,6 +905,18 @@
// C function void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name )
+ public static native void glGetTransformFeedbackVarying(
+ int program,
+ int index,
+ int bufsize,
+ java.nio.IntBuffer length,
+ java.nio.IntBuffer size,
+ java.nio.IntBuffer type,
+ java.nio.ByteBuffer name
+ );
+
+ // C function void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name )
+
public static native String glGetTransformFeedbackVarying(
int program,
int index,
@@ -1791,4 +1806,16 @@
java.nio.IntBuffer params
);
+ // C function void glReadPixels ( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint offset )
+
+ public static native void glReadPixels(
+ int x,
+ int y,
+ int width,
+ int height,
+ int format,
+ int type,
+ int offset
+ );
+
}
diff --git a/packages/DocumentsUI/Android.mk b/packages/DocumentsUI/Android.mk
index 1a4e3eb..d5e48b5 100644
--- a/packages/DocumentsUI/Android.mk
+++ b/packages/DocumentsUI/Android.mk
@@ -8,6 +8,7 @@
LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
# The design lib requires that the client package use appcompat themes.
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v7-appcompat
+LOCAL_STATIC_JAVA_LIBRARIES += android-support-v13
# Supplies material design components, e.g. Snackbar.
LOCAL_STATIC_JAVA_LIBRARIES += android-support-design
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v7-recyclerview
@@ -29,9 +30,12 @@
--extra-packages android.support.design \
--extra-packages android.support.v7.recyclerview
+LOCAL_JACK_FLAGS := \
+ -D jack.assert.policy=enable \
+ -D jack.optimization.inner-class.accessors=true
+
LOCAL_PACKAGE_NAME := DocumentsUI
LOCAL_CERTIFICATE := platform
include $(BUILD_PACKAGE)
-
-include $(LOCAL_PATH)/tests/Android.mk
+include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index 58e7709..637e06e 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -1,6 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.documentsui">
+ <uses-permission android:name="android.permission.GET_APP_GRANTED_URI_PERMISSIONS" />
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS" />
<uses-permission android:name="android.permission.REMOVE_TASKS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
diff --git a/packages/DocumentsUI/perf-tests/Android.mk b/packages/DocumentsUI/perf-tests/Android.mk
new file mode 100644
index 0000000..11c163b
--- /dev/null
+++ b/packages/DocumentsUI/perf-tests/Android.mk
@@ -0,0 +1,22 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+#LOCAL_SDK_VERSION := current
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+ $(call all-java-files-under, ../tests/src/com/android/documentsui/bots) \
+ ../tests/src/com/android/documentsui/ActivityTest.java \
+ ../tests/src/com/android/documentsui/DocumentsProviderHelper.java \
+ ../tests/src/com/android/documentsui/StubProvider.java
+
+LOCAL_JAVA_LIBRARIES := android-support-v4 android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ub-uiautomator
+
+LOCAL_PACKAGE_NAME := DocumentsUIPerfTests
+LOCAL_INSTRUMENTATION_FOR := DocumentsUI
+
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
+
diff --git a/packages/DocumentsUI/perf-tests/AndroidManifest.xml b/packages/DocumentsUI/perf-tests/AndroidManifest.xml
new file mode 100644
index 0000000..97353e7
--- /dev/null
+++ b/packages/DocumentsUI/perf-tests/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.documentsui.perftests">
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ <provider
+ android:name="com.android.documentsui.StressProvider"
+ android:authorities="com.android.documentsui.stressprovider"
+ android:exported="true"
+ android:grantUriPermissions="true"
+ android:permission="android.permission.MANAGE_DOCUMENTS"
+ android:enabled="true">
+ <intent-filter>
+ <action android:name="android.content.action.DOCUMENTS_PROVIDER" />
+ </intent-filter>
+ </provider>
+ </application>
+
+ <instrumentation android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.documentsui"
+ android:label="Performance tests for DocumentsUI" />
+
+</manifest>
diff --git a/packages/DocumentsUI/perf-tests/src/com/android/documentsui/FilesActivityPerfTest.java b/packages/DocumentsUI/perf-tests/src/com/android/documentsui/FilesActivityPerfTest.java
new file mode 100644
index 0000000..bf056f1
--- /dev/null
+++ b/packages/DocumentsUI/perf-tests/src/com/android/documentsui/FilesActivityPerfTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import static com.android.documentsui.StressProvider.DEFAULT_AUTHORITY;
+import static com.android.documentsui.StressProvider.STRESS_ROOT_0_ID;
+import static com.android.documentsui.StressProvider.STRESS_ROOT_1_ID;
+
+import android.app.Activity;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+import android.view.KeyEvent;
+
+import com.android.documentsui.model.RootInfo;
+import com.android.documentsui.EventListener;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+
+@LargeTest
+public class FilesActivityPerfTest extends ActivityTest<FilesActivity> {
+
+ // Constants starting with KEY_ are used to report metrics to APCT.
+ private static final String KEY_FILES_LISTED_PERFORMANCE_FIRST =
+ "files-listed-performance-first";
+
+ private static final String KEY_FILES_LISTED_PERFORMANCE_MEDIAN =
+ "files-listed-performance-median";
+
+ private static final String TESTED_URI =
+ "content://com.android.documentsui.stressprovider/document/STRESS_ROOT_1_DOC";
+
+ private static final int NUM_MEASUREMENTS = 10;
+
+ public FilesActivityPerfTest() {
+ super(FilesActivity.class);
+ }
+
+ @Override
+ protected RootInfo getInitialRoot() {
+ return rootDir0;
+ }
+
+ @Override
+ protected String getTestingProviderAuthority() {
+ return DEFAULT_AUTHORITY;
+ }
+
+ @Override
+ protected void setupTestingRoots() throws RemoteException {
+ rootDir0 = mDocsHelper.getRoot(STRESS_ROOT_0_ID);
+ rootDir1 = mDocsHelper.getRoot(STRESS_ROOT_1_ID);
+ }
+
+ @Override
+ public void initTestFiles() throws RemoteException {
+ // Nothing to create, already done by StressProvider.
+ }
+
+ public void testFilesListedPerformance() throws Exception {
+ final BaseActivity activity = getActivity();
+
+ final List<Long> measurements = new ArrayList<Long>();
+ EventListener listener;
+ for (int i = 0; i < 10; i++) {
+ final CountDownLatch signal = new CountDownLatch(1);
+ listener = new EventListener() {
+ @Override
+ public void onDirectoryNavigated(Uri uri) {
+ if (uri != null && TESTED_URI.equals(uri.toString())) {
+ mStartTime = System.currentTimeMillis();
+ } else {
+ mStartTime = -1;
+ }
+ }
+
+ @Override
+ public void onDirectoryLoaded(Uri uri) {
+ if (uri == null || !TESTED_URI.equals(uri.toString())) {
+ return;
+ }
+ assertTrue(mStartTime != -1);
+ getInstrumentation().waitForIdle(new Runnable() {
+ @Override
+ public void run() {
+ assertTrue(mStartTime != -1);
+ measurements.add(System.currentTimeMillis() - mStartTime);
+ signal.countDown();
+ }
+ });
+ }
+
+ private long mStartTime = -1;
+ };
+
+ try {
+ activity.addEventListener(listener);
+ bots.roots.openRoot(STRESS_ROOT_1_ID);
+ signal.await();
+ } finally {
+ activity.removeEventListener(listener);
+ }
+
+ assertEquals(i + 1, measurements.size());
+
+ // Go back to the empty root.
+ bots.roots.openRoot(STRESS_ROOT_0_ID);
+ }
+
+ assertEquals(NUM_MEASUREMENTS, measurements.size());
+
+ final Bundle status = new Bundle();
+ status.putDouble(KEY_FILES_LISTED_PERFORMANCE_FIRST, measurements.get(0));
+
+ final Long[] rawMeasurements = measurements.toArray(new Long[NUM_MEASUREMENTS]);
+ Arrays.sort(rawMeasurements);
+
+ final long median = rawMeasurements[NUM_MEASUREMENTS / 2 - 1];
+ status.putDouble(KEY_FILES_LISTED_PERFORMANCE_MEDIAN, median);
+
+ getInstrumentation().sendStatus(Activity.RESULT_OK, status);
+ }
+}
diff --git a/packages/DocumentsUI/perf-tests/src/com/android/documentsui/StressProvider.java b/packages/DocumentsUI/perf-tests/src/com/android/documentsui/StressProvider.java
new file mode 100644
index 0000000..1bc802a
--- /dev/null
+++ b/packages/DocumentsUI/perf-tests/src/com/android/documentsui/StressProvider.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import android.content.Context;
+import android.content.pm.ProviderInfo;
+import android.database.Cursor;
+import android.database.MatrixCursor.RowBuilder;
+import android.database.MatrixCursor;
+import android.os.CancellationSignal;
+import android.os.FileUtils;
+import android.os.ParcelFileDescriptor;
+import android.provider.DocumentsContract.Document;
+import android.provider.DocumentsContract.Root;
+import android.provider.DocumentsContract;
+import android.provider.DocumentsProvider;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * Provider with thousands of files for testing loading time of directories in DocumentsUI.
+ * It doesn't support any file operations.
+ */
+public class StressProvider extends DocumentsProvider {
+
+ public static final String DEFAULT_AUTHORITY = "com.android.documentsui.stressprovider";
+
+ // Empty root.
+ public static final String STRESS_ROOT_0_ID = "STRESS_ROOT_0";
+
+ // Root with thousands of items.
+ public static final String STRESS_ROOT_1_ID = "STRESS_ROOT_1";
+
+ private static final String STRESS_ROOT_0_DOC_ID = "STRESS_ROOT_0_DOC";
+ private static final String STRESS_ROOT_1_DOC_ID = "STRESS_ROOT_1_DOC";
+
+ private static final String[] DEFAULT_ROOT_PROJECTION = new String[] {
+ Root.COLUMN_ROOT_ID, Root.COLUMN_FLAGS, Root.COLUMN_TITLE, Root.COLUMN_DOCUMENT_ID,
+ Root.COLUMN_AVAILABLE_BYTES
+ };
+ private static final String[] DEFAULT_DOCUMENT_PROJECTION = new String[] {
+ Document.COLUMN_DOCUMENT_ID, Document.COLUMN_MIME_TYPE, Document.COLUMN_DISPLAY_NAME,
+ Document.COLUMN_LAST_MODIFIED, Document.COLUMN_FLAGS, Document.COLUMN_SIZE,
+ };
+
+ private String mAuthority = DEFAULT_AUTHORITY;
+ private ArrayList<String> mIds = new ArrayList<>();
+
+ @Override
+ public void attachInfo(Context context, ProviderInfo info) {
+ mAuthority = info.authority;
+ super.attachInfo(context, info);
+ }
+
+ @Override
+ public boolean onCreate() {
+ mIds = new ArrayList();
+ for (int i = 0; i < 10000; i++) {
+ mIds.add(createRandomId(i));
+ }
+ mIds.add(STRESS_ROOT_0_DOC_ID);
+ mIds.add(STRESS_ROOT_1_DOC_ID);
+ return true;
+ }
+
+ @Override
+ public Cursor queryRoots(String[] projection) throws FileNotFoundException {
+ final MatrixCursor result = new MatrixCursor(DEFAULT_ROOT_PROJECTION);
+ includeRoot(result, STRESS_ROOT_0_ID, STRESS_ROOT_0_DOC_ID);
+ includeRoot(result, STRESS_ROOT_1_ID, STRESS_ROOT_1_DOC_ID);
+ return result;
+ }
+
+ @Override
+ public Cursor queryDocument(String documentId, String[] projection)
+ throws FileNotFoundException {
+ final MatrixCursor result = new MatrixCursor(DEFAULT_DOCUMENT_PROJECTION);
+ includeDocument(result, documentId);
+ return result;
+ }
+
+ @Override
+ public Cursor queryChildDocuments(String parentDocumentId, String[] projection, String sortOrder)
+ throws FileNotFoundException {
+ final MatrixCursor result = new MatrixCursor(DEFAULT_DOCUMENT_PROJECTION);
+ if (STRESS_ROOT_1_DOC_ID.equals(parentDocumentId)) {
+ for (String id : mIds) {
+ includeDocument(result, id);
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public ParcelFileDescriptor openDocument(String docId, String mode, CancellationSignal signal)
+ throws FileNotFoundException {
+ throw new UnsupportedOperationException();
+ }
+
+ private void includeRoot(MatrixCursor result, String rootId, String docId) {
+ final RowBuilder row = result.newRow();
+ row.add(Root.COLUMN_ROOT_ID, rootId);
+ row.add(Root.COLUMN_FLAGS, 0);
+ row.add(Root.COLUMN_TITLE, rootId);
+ row.add(Root.COLUMN_DOCUMENT_ID, docId);
+ }
+
+ private void includeDocument(MatrixCursor result, String id) {
+ final RowBuilder row = result.newRow();
+ row.add(Document.COLUMN_DOCUMENT_ID, id);
+ row.add(Document.COLUMN_DISPLAY_NAME, id);
+ row.add(Document.COLUMN_SIZE, 0);
+ row.add(Document.COLUMN_MIME_TYPE, DocumentsContract.Document.MIME_TYPE_DIR);
+ row.add(Document.COLUMN_FLAGS, 0);
+ row.add(Document.COLUMN_LAST_MODIFIED, null);
+ }
+
+ private static String getDocumentIdForFile(File file) {
+ return file.getAbsolutePath();
+ }
+
+ private String createRandomId(int index) {
+ final Random random = new Random(index);
+ final StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < 20; i++) {
+ builder.append((char) (random.nextInt(96) + 32));
+ }
+ builder.append(index); // Append a number to guarantee uniqueness.
+ return builder.toString();
+ }
+}
diff --git a/packages/DocumentsUI/res/drawable/ic_breadcrumb_arrow_down.xml b/packages/DocumentsUI/res/drawable/ic_breadcrumb_arrow_down.xml
new file mode 100644
index 0000000..199a308
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable/ic_breadcrumb_arrow_down.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<rotate xmlns:android="http://schemas.android.com/apk/res/android"
+ android:fromDegrees="90"
+ android:toDegrees="90"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:drawable="@drawable/ic_breadcrumb_arrow">
+</rotate>
\ No newline at end of file
diff --git a/packages/DocumentsUI/res/drawable/ic_sd_storage.xml b/packages/DocumentsUI/res/drawable/ic_sd_storage.xml
index b0f3cc3..5aeebbb 100644
--- a/packages/DocumentsUI/res/drawable/ic_sd_storage.xml
+++ b/packages/DocumentsUI/res/drawable/ic_sd_storage.xml
@@ -14,8 +14,8 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
+ android:width="24dp"
+ android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
diff --git a/packages/DocumentsUI/res/drawable/ic_usb_storage.xml b/packages/DocumentsUI/res/drawable/ic_usb_storage.xml
new file mode 100644
index 0000000..2a8d024
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable/ic_usb_storage.xml
@@ -0,0 +1,24 @@
+<!--
+Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M15 7v4h1v2h-3V5h2l-3,-4,-3 4h2v8H8v-2.07c.7,-.37 1.2,-1.08 1.2,-1.93 0,-1.21,-.99,-2.2,-2.2,-2.2,-1.21 0,-2.2.99,-2.2 2.2 0 .85.5 1.56 1.2 1.93V13c0 1.11.89 2 2 2h3v3.05c-.71.37,-1.2 1.1,-1.2 1.95 0 1.22.99 2.2 2.2 2.2 1.21 0 2.2,-.98 2.2,-2.2 0,-.85,-.49,-1.58,-1.2,-1.95V15h3c1.11 0 2,-.89 2,-2v-2h1V7h-4z"/>
+</vector>
diff --git a/packages/DocumentsUI/res/layout/dialog_delete_confirmation.xml b/packages/DocumentsUI/res/layout/dialog_delete_confirmation.xml
new file mode 100644
index 0000000..990ce0b
--- /dev/null
+++ b/packages/DocumentsUI/res/layout/dialog_delete_confirmation.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingTop="30dp"
+ android:gravity="center"
+ android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+ android:textColor="@*android:color/primary_text_default_material_light">
+</TextView>
diff --git a/packages/DocumentsUI/res/layout/drawer_layout.xml b/packages/DocumentsUI/res/layout/drawer_layout.xml
index e3def05..b65c5a0 100644
--- a/packages/DocumentsUI/res/layout/drawer_layout.xml
+++ b/packages/DocumentsUI/res/layout/drawer_layout.xml
@@ -46,6 +46,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
+ android:popupTheme="?actionBarPopupTheme"
+ android:background="@android:color/transparent"
android:overlapAnchor="true" />
</com.android.documentsui.DocumentsToolbar>
@@ -61,7 +63,7 @@
android:layout_gravity="start"
android:orientation="vertical"
android:elevation="16dp"
- android:background="@color/window_background">
+ android:background="@color/drawer_background">
<Toolbar
android:id="@+id/roots_toolbar"
diff --git a/packages/DocumentsUI/res/layout/fixed_layout.xml b/packages/DocumentsUI/res/layout/fixed_layout.xml
index 84a928d..deb0894 100644
--- a/packages/DocumentsUI/res/layout/fixed_layout.xml
+++ b/packages/DocumentsUI/res/layout/fixed_layout.xml
@@ -44,6 +44,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
+ android:popupTheme="?actionBarPopupTheme"
+ android:background="@android:color/transparent"
android:overlapAnchor="true" />
</com.android.documentsui.DocumentsToolbar>
diff --git a/packages/DocumentsUI/res/layout/fragment_directory.xml b/packages/DocumentsUI/res/layout/fragment_directory.xml
index 0d336f9..03c6a83 100644
--- a/packages/DocumentsUI/res/layout/fragment_directory.xml
+++ b/packages/DocumentsUI/res/layout/fragment_directory.xml
@@ -17,7 +17,7 @@
<com.android.documentsui.DirectoryView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@color/window_background"
+ android:background="@color/directory_background"
android:outlineProvider="bounds"
android:elevation="4dp"
android:orientation="vertical">
@@ -45,7 +45,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- android:background="@color/window_background"
+ android:background="@color/directory_background"
android:focusable="true"
android:focusableInTouchMode="true"
android:visibility="gone">
diff --git a/packages/DocumentsUI/res/layout/item_dir_grid.xml b/packages/DocumentsUI/res/layout/item_dir_grid.xml
index b0331be..a4f06d1 100644
--- a/packages/DocumentsUI/res/layout/item_dir_grid.xml
+++ b/packages/DocumentsUI/res/layout/item_dir_grid.xml
@@ -20,7 +20,7 @@
android:layout_height="wrap_content"
android:layout_margin="@dimen/grid_item_margin"
android:background="@color/item_doc_background"
- android:elevation="5dp"
+ android:elevation="@dimen/grid_item_elevation"
android:focusable="true" >
<LinearLayout
@@ -62,7 +62,7 @@
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:ellipsize="middle"
+ android:ellipsize="end"
android:singleLine="true"
android:textAlignment="viewStart"
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
diff --git a/packages/DocumentsUI/res/layout/item_doc_grid.xml b/packages/DocumentsUI/res/layout/item_doc_grid.xml
index dd02d1c..af1703f 100644
--- a/packages/DocumentsUI/res/layout/item_doc_grid.xml
+++ b/packages/DocumentsUI/res/layout/item_doc_grid.xml
@@ -19,7 +19,7 @@
android:layout_height="wrap_content"
android:layout_margin="@dimen/grid_item_margin"
android:background="@color/item_doc_background"
- android:elevation="5dp"
+ android:elevation="@dimen/grid_item_elevation"
android:focusable="true">
<!-- Main item thumbnail. Comprised of two overlapping images, the
@@ -90,7 +90,7 @@
android:layout_alignParentTop="true"
android:layout_toEndOf="@id/icon_mime_sm"
android:singleLine="true"
- android:ellipsize="middle"
+ android:ellipsize="end"
android:textAlignment="viewStart"
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
android:textColor="@*android:color/primary_text_default_material_light" />
diff --git a/packages/DocumentsUI/res/layout/item_doc_list.xml b/packages/DocumentsUI/res/layout/item_doc_list.xml
index 8d98377..29f65e09 100644
--- a/packages/DocumentsUI/res/layout/item_doc_list.xml
+++ b/packages/DocumentsUI/res/layout/item_doc_list.xml
@@ -73,14 +73,15 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:orientation="vertical" >
+ android:orientation="vertical"
+ android:layout_gravity="center_vertical" >
<TextView
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
- android:ellipsize="middle"
+ android:ellipsize="end"
android:singleLine="true"
android:textAlignment="viewStart"
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
diff --git a/packages/DocumentsUI/res/layout/item_root.xml b/packages/DocumentsUI/res/layout/item_root.xml
index ff80d07..816cb8a 100644
--- a/packages/DocumentsUI/res/layout/item_root.xml
+++ b/packages/DocumentsUI/res/layout/item_root.xml
@@ -27,8 +27,6 @@
<FrameLayout
android:layout_width="@dimen/icon_size"
android:layout_height="@dimen/icon_size"
- android:layout_marginStart="@dimen/root_icon_margin"
- android:layout_marginEnd="@dimen/root_icon_margin"
android:duplicateParentState="true">
<ImageView
@@ -55,7 +53,7 @@
android:singleLine="true"
android:ellipsize="end"
android:textAlignment="viewStart"
- android:textAppearance="@android:style/TextAppearance.Material.Body1"
+ android:textAppearance="@android:style/TextAppearance.Material.Menu"
android:textColor="@color/item_root_primary_text" />
<TextView
@@ -65,7 +63,7 @@
android:singleLine="true"
android:ellipsize="end"
android:textAlignment="viewStart"
- android:textAppearance="@android:style/TextAppearance.Material.Body1"
+ android:textAppearance="@android:style/TextAppearance.Material.Caption"
android:textColor="@color/item_root_primary_text" />
</LinearLayout>
diff --git a/packages/DocumentsUI/res/layout/item_subdir.xml b/packages/DocumentsUI/res/layout/item_subdir.xml
index 821432d..ffe4afe 100644
--- a/packages/DocumentsUI/res/layout/item_subdir.xml
+++ b/packages/DocumentsUI/res/layout/item_subdir.xml
@@ -24,23 +24,13 @@
android:orientation="horizontal"
android:baselineAligned="false">
- <ImageView
- android:id="@+id/subdir"
- android:layout_width="24dp"
- android:layout_height="24dp"
- android:paddingEnd="8dp"
- android:scaleType="centerInside"
- android:visibility="gone"
- android:src="@drawable/ic_subdirectory_arrow"
- android:contentDescription="@null" />
-
<TextView
android:id="@android:id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
- android:ellipsize="middle"
+ android:ellipsize="end"
android:textAlignment="viewStart"
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
android:textColor="?android:attr/textColorPrimary" />
diff --git a/packages/DocumentsUI/res/layout/item_subdir_title.xml b/packages/DocumentsUI/res/layout/item_subdir_title.xml
index 4c839d0..8d0d807 100644
--- a/packages/DocumentsUI/res/layout/item_subdir_title.xml
+++ b/packages/DocumentsUI/res/layout/item_subdir_title.xml
@@ -26,8 +26,9 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
- android:ellipsize="middle"
+ android:ellipsize="end"
android:textAlignment="viewStart"
+ android:drawablePadding="12dp"
+ android:drawableRight="@drawable/ic_breadcrumb_arrow_down"
android:textAppearance="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title" />
-
</LinearLayout>
diff --git a/packages/DocumentsUI/res/layout/single_pane_layout.xml b/packages/DocumentsUI/res/layout/single_pane_layout.xml
index 235d22d..7b7e229 100644
--- a/packages/DocumentsUI/res/layout/single_pane_layout.xml
+++ b/packages/DocumentsUI/res/layout/single_pane_layout.xml
@@ -43,6 +43,8 @@
android:id="@+id/stack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:popupTheme="?actionBarPopupTheme"
+ android:background="@android:color/transparent"
android:layout_marginStart="4dp"
android:overlapAnchor="true" />
diff --git a/packages/DocumentsUI/res/menu/activity.xml b/packages/DocumentsUI/res/menu/activity.xml
index 73571af..79f6fa9 100644
--- a/packages/DocumentsUI/res/menu/activity.xml
+++ b/packages/DocumentsUI/res/menu/activity.xml
@@ -84,10 +84,6 @@
android:showAsAction="never"
android:visible="false" />
<item
- android:id="@+id/menu_advanced"
- android:showAsAction="never"
- android:visible="false" />
- <item
android:id="@+id/menu_settings"
android:title="@string/menu_settings"
android:showAsAction="never"
diff --git a/packages/DocumentsUI/res/values-af/config.xml b/packages/DocumentsUI/res/values-af/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-af/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-af/strings.xml b/packages/DocumentsUI/res/values-af/strings.xml
index b8bc289..8846b62 100644
--- a/packages/DocumentsUI/res/values-af/strings.xml
+++ b/packages/DocumentsUI/res/values-af/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Deel via"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kopieer tans lêers"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Skuif tans lêers"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Vee tans lêers uit"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> oor"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Kopieer tans <xliff:g id="COUNT_1">%1$d</xliff:g> lêers.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sommige lêers is omgeskakel"</string>
<string name="allow" msgid="7225948811296386551">"Laat toe"</string>
<string name="deny" msgid="2081879885755434506">"Weier"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Vee lêers uit?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Is jy seker jy wil <xliff:g id="COUNT_1">%1$d</xliff:g> lêers uitvee?</item>
+ <item quantity="one">Is jy seker jy wil <xliff:g id="COUNT_0">%1$d</xliff:g> lêer uitvee?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-am/config.xml b/packages/DocumentsUI/res/values-am/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-am/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-am/strings.xml b/packages/DocumentsUI/res/values-am/strings.xml
index f28c433..6f975da 100644
--- a/packages/DocumentsUI/res/values-am/strings.xml
+++ b/packages/DocumentsUI/res/values-am/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"በሚከተለው በኩል ያጋሩ"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"ፋይሎች በመገልበጥ ላይ"</string>
<string name="move_notification_title" msgid="6193835179777284805">"ፋይሎችን በመውሰድ ላይ"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"ፋይሎችን በመሰረዝ ላይ"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> ቀርቷል"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ፋይሎች በመቅዳት ላይ።</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"አንዳንድ ፋይሎች ተለውጠዋል"</string>
<string name="allow" msgid="7225948811296386551">"ይፍቀዱ"</string>
<string name="deny" msgid="2081879885755434506">"ያስተባብሉ"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"ፋይሎች ይሰረዙ?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">እርግጠኛ ነዎት <xliff:g id="COUNT_1">%1$d</xliff:g> ፋይሎችን መሰረዝ ይፈልጋሉ?</item>
+ <item quantity="other">እርግጠኛ ነዎት <xliff:g id="COUNT_1">%1$d</xliff:g> ፋይሎችን መሰረዝ ይፈልጋሉ?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-ar/config.xml b/packages/DocumentsUI/res/values-ar/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ar/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ar/strings.xml b/packages/DocumentsUI/res/values-ar/strings.xml
index c19e406..79c2c6a 100644
--- a/packages/DocumentsUI/res/values-ar/strings.xml
+++ b/packages/DocumentsUI/res/values-ar/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"مشاركة عبر"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"جارٍ نسخ الملفات"</string>
<string name="move_notification_title" msgid="6193835179777284805">"نقل الملفات"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"جارٍ حذف الملفات"</string>
<string name="copy_remaining" msgid="6283790937387975095">"المدة المتبقية: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="zero">جارٍ نسخ <xliff:g id="COUNT_1">%1$d</xliff:g> ملفات.</item>
@@ -139,4 +140,13 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"تم تحويل بعض الملفات"</string>
<string name="allow" msgid="7225948811296386551">"السماح"</string>
<string name="deny" msgid="2081879885755434506">"رفض"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"هل تريد حذف الملفات؟"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="zero">هل تريد بالتأكيد حذف <xliff:g id="COUNT_1">%1$d</xliff:g> ملف؟</item>
+ <item quantity="two">هل تريد بالتأكيد حذف ملفين (<xliff:g id="COUNT_1">%1$d</xliff:g>)؟</item>
+ <item quantity="few">هل تريد بالتأكيد حذف <xliff:g id="COUNT_1">%1$d</xliff:g> ملفات؟</item>
+ <item quantity="many">هل تريد بالتأكيد حذف <xliff:g id="COUNT_1">%1$d</xliff:g> ملفًا؟</item>
+ <item quantity="other">هل تريد بالتأكيد حذف <xliff:g id="COUNT_1">%1$d</xliff:g> ملف؟</item>
+ <item quantity="one">هل تريد بالتأكيد حذف <xliff:g id="COUNT_0">%1$d</xliff:g> ملف؟</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-az-rAZ/config.xml b/packages/DocumentsUI/res/values-az-rAZ/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-az-rAZ/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-az-rAZ/strings.xml b/packages/DocumentsUI/res/values-az-rAZ/strings.xml
index dc9a390..8ba9036 100644
--- a/packages/DocumentsUI/res/values-az-rAZ/strings.xml
+++ b/packages/DocumentsUI/res/values-az-rAZ/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Bunun vasitəsilə paylaş:"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Fayllar kopyalanır"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Fayllar köçürülür"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Fayllar silinir"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> qalıb"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> fayl kopyalanır.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Bəzi fayllar konvertasiya edilib"</string>
<string name="allow" msgid="7225948811296386551">"İcazə verin"</string>
<string name="deny" msgid="2081879885755434506">"Rədd et"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Fayllar silinsin?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> faylı silmək istədiyinizə əminsiniz?</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> faylı silmək istədiyinizə əminsiniz?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-b+sr+Latn/config.xml b/packages/DocumentsUI/res/values-b+sr+Latn/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-b+sr+Latn/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml b/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
index 1e1a2f7..ea4485b 100644
--- a/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Delite preko"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kopiranje datoteka"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Datoteke se premeštaju"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Datoteke se brišu"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Još <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Kopiranje <xliff:g id="COUNT_1">%1$d</xliff:g> datoteke.</item>
@@ -118,4 +119,10 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Neke datoteke su konvertovane"</string>
<string name="allow" msgid="7225948811296386551">"Dozvoli"</string>
<string name="deny" msgid="2081879885755434506">"Odbij"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Želite li da izbrišete datoteke?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Želite li stvarno da izbrišete <xliff:g id="COUNT_1">%1$d</xliff:g> datoteku?</item>
+ <item quantity="few">Želite li stvarno da izbrišete <xliff:g id="COUNT_1">%1$d</xliff:g> datoteke?</item>
+ <item quantity="other">Želite li stvarno da izbrišete <xliff:g id="COUNT_1">%1$d</xliff:g> datoteka?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-bg/config.xml b/packages/DocumentsUI/res/values-bg/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-bg/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-bg/strings.xml b/packages/DocumentsUI/res/values-bg/strings.xml
index 4a6d499..66af887 100644
--- a/packages/DocumentsUI/res/values-bg/strings.xml
+++ b/packages/DocumentsUI/res/values-bg/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Споделяне чрез"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Файловете се копират"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Файловете се преместват"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Изтриване на файлове"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Оставащо време: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Копират се <xliff:g id="COUNT_1">%1$d</xliff:g> файла.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Някои файлове бяха преобразувани"</string>
<string name="allow" msgid="7225948811296386551">"Разрешаване"</string>
<string name="deny" msgid="2081879885755434506">"Отказване"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Да се изтрият ли файловете?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Наистина ли искате да изтриете <xliff:g id="COUNT_1">%1$d</xliff:g> файла?</item>
+ <item quantity="one">Наистина ли искате да изтриете <xliff:g id="COUNT_0">%1$d</xliff:g> файл?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-bn-rBD/config.xml b/packages/DocumentsUI/res/values-bn-rBD/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-bn-rBD/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-bn-rBD/strings.xml b/packages/DocumentsUI/res/values-bn-rBD/strings.xml
index f53cfa8..6bbe95b 100644
--- a/packages/DocumentsUI/res/values-bn-rBD/strings.xml
+++ b/packages/DocumentsUI/res/values-bn-rBD/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"এর মাধ্যমে শেয়ার করুন"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"ফাইলগুলি অনুলিপি করা হচ্ছে"</string>
<string name="move_notification_title" msgid="6193835179777284805">"ফাইলগুলি সরানো হচ্ছে"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"ফাইলগুলি মোছা হচ্ছে"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> বাকি"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g>টি ফাইল অনুলিপি করা হচ্ছে৷</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"কিছু ফাইল রূপান্তরিত হয়েছে"</string>
<string name="allow" msgid="7225948811296386551">"অনুমতি দিন"</string>
<string name="deny" msgid="2081879885755434506">"আস্বীকার করুন"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"ফাইলগুলি মুছবেন?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">আপনি কি <xliff:g id="COUNT_1">%1$d</xliff:g>টি ফাইল মোছার বিষয়ে নিশ্চিত?</item>
+ <item quantity="other">আপনি কি <xliff:g id="COUNT_1">%1$d</xliff:g>টি ফাইল মোছার বিষয়ে নিশ্চিত?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-bs-rBA/strings.xml b/packages/DocumentsUI/res/values-bs-rBA/strings.xml
index d315166..9f5f932 100644
--- a/packages/DocumentsUI/res/values-bs-rBA/strings.xml
+++ b/packages/DocumentsUI/res/values-bs-rBA/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Podijeli preko"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kopiraju se fajlovi"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Premještanje fajlova"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Brisanje fajlova"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Još <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Kopira se <xliff:g id="COUNT_1">%1$d</xliff:g> fajl.</item>
@@ -118,4 +119,10 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Neke od datoteka su pretvorene"</string>
<string name="allow" msgid="7225948811296386551">"Dozvoli"</string>
<string name="deny" msgid="2081879885755434506">"Odbijte"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Zaista želite obrisati fajlove?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one"> Jeste li sigurni da želite izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> fajl?</item>
+ <item quantity="few"> Jeste li sigurni da želite izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> fajla?</item>
+ <item quantity="other"> Jeste li sigurni da želite izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> fajlova?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-ca/config.xml b/packages/DocumentsUI/res/values-ca/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ca/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ca/strings.xml b/packages/DocumentsUI/res/values-ca/strings.xml
index 96bfbb7..2b136f1 100644
--- a/packages/DocumentsUI/res/values-ca/strings.xml
+++ b/packages/DocumentsUI/res/values-ca/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Comparteix mitjançant"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"S\'estan copiant fitxers"</string>
<string name="move_notification_title" msgid="6193835179777284805">"S\'estan movent fitxers"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Suprimint els fitxers"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Temps restant: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">S\'estan copiant <xliff:g id="COUNT_1">%1$d</xliff:g> fitxers.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"S\'han convertit alguns fitxers"</string>
<string name="allow" msgid="7225948811296386551">"Permet"</string>
<string name="deny" msgid="2081879885755434506">"Denega"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Vols suprimir els fitxers?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Confirmes que vols suprimir <xliff:g id="COUNT_1">%1$d</xliff:g> fitxers?</item>
+ <item quantity="one">Confirmes que vols suprimir <xliff:g id="COUNT_0">%1$d</xliff:g> fitxer?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-cs/config.xml b/packages/DocumentsUI/res/values-cs/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-cs/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-cs/strings.xml b/packages/DocumentsUI/res/values-cs/strings.xml
index a6e79b6..7196c6a 100644
--- a/packages/DocumentsUI/res/values-cs/strings.xml
+++ b/packages/DocumentsUI/res/values-cs/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Sdílet pomocí"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kopírování souborů"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Přesouvání souborů"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Mazání souborů"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Zbývající čas: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="few">Kopírování <xliff:g id="COUNT_1">%1$d</xliff:g> souborů</item>
@@ -125,4 +126,11 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Některé soubory byly převedeny"</string>
<string name="allow" msgid="7225948811296386551">"Povolit"</string>
<string name="deny" msgid="2081879885755434506">"Odepřít"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Smazat soubory?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="few">Opravdu chcete smazat <xliff:g id="COUNT_1">%1$d</xliff:g> soubory?</item>
+ <item quantity="many">Opravdu chcete smazat <xliff:g id="COUNT_1">%1$d</xliff:g> souboru?</item>
+ <item quantity="other">Opravdu chcete smazat <xliff:g id="COUNT_1">%1$d</xliff:g> souborů?</item>
+ <item quantity="one">Opravdu chcete smazat <xliff:g id="COUNT_0">%1$d</xliff:g> soubor?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-da/config.xml b/packages/DocumentsUI/res/values-da/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-da/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-da/strings.xml b/packages/DocumentsUI/res/values-da/strings.xml
index a0b7c1f..ab9271c 100644
--- a/packages/DocumentsUI/res/values-da/strings.xml
+++ b/packages/DocumentsUI/res/values-da/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Del via"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kopierer filer"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Flytter filer"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Filerne slettes"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> tilbage"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Kopierer <xliff:g id="COUNT_1">%1$d</xliff:g> filer.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Nogle filer er konverteret"</string>
<string name="allow" msgid="7225948811296386551">"Tillad"</string>
<string name="deny" msgid="2081879885755434506">"Afvis"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Vil du slette filerne?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Er du sikker på, at du vil slette <xliff:g id="COUNT_1">%1$d</xliff:g> fil?</item>
+ <item quantity="other">Er du sikker på, at du vil slette <xliff:g id="COUNT_1">%1$d</xliff:g> filer?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-de/config.xml b/packages/DocumentsUI/res/values-de/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-de/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-de/strings.xml b/packages/DocumentsUI/res/values-de/strings.xml
index 2d968fe..8c06c7f 100644
--- a/packages/DocumentsUI/res/values-de/strings.xml
+++ b/packages/DocumentsUI/res/values-de/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Teilen über"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Dateien werden kopiert"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Dateien werden verschoben"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Dateien werden gelöscht"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Noch <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> Dateien werden kopiert.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Einige Dateien wurden konvertiert"</string>
<string name="allow" msgid="7225948811296386551">"Zulassen"</string>
<string name="deny" msgid="2081879885755434506">"Ablehnen"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Dateien löschen?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Möchtest du wirklich <xliff:g id="COUNT_1">%1$d</xliff:g> Dateien löschen?</item>
+ <item quantity="one">Möchtest du wirklich <xliff:g id="COUNT_0">%1$d</xliff:g> Datei löschen?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-el/config.xml b/packages/DocumentsUI/res/values-el/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-el/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-el/strings.xml b/packages/DocumentsUI/res/values-el/strings.xml
index 6c9896d..1752a29 100644
--- a/packages/DocumentsUI/res/values-el/strings.xml
+++ b/packages/DocumentsUI/res/values-el/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Κοινή χρήση μέσω"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Αντιγραφή αρχείων"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Μετακίνηση αρχείων"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Διαγραφή αρχείων"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Απομένουν <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Αντιγραφή <xliff:g id="COUNT_1">%1$d</xliff:g> αρχείων.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Ορισμένα αρχεία μετατράπηκαν"</string>
<string name="allow" msgid="7225948811296386551">"Να επιτρέπεται"</string>
<string name="deny" msgid="2081879885755434506">"Άρνηση"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Διαγραφή αρχείων;"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Είστε βέβαιοι ότι θέλετε να διαγράψετε <xliff:g id="COUNT_1">%1$d</xliff:g> αρχεία;</item>
+ <item quantity="one">Είστε βέβαιοι ότι θέλετε να διαγράψετε <xliff:g id="COUNT_0">%1$d</xliff:g> αρχείο;</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-en-rAU/config.xml b/packages/DocumentsUI/res/values-en-rAU/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-en-rAU/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-en-rAU/strings.xml b/packages/DocumentsUI/res/values-en-rAU/strings.xml
index 5bc4f59..82c5557 100644
--- a/packages/DocumentsUI/res/values-en-rAU/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rAU/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Share via"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Copying files"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Moving files"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Deleting files"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> left"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Copying <xliff:g id="COUNT_1">%1$d</xliff:g> files.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Some files were converted"</string>
<string name="allow" msgid="7225948811296386551">"Allow"</string>
<string name="deny" msgid="2081879885755434506">"Deny"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Delete files?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Are you sure you want to delete <xliff:g id="COUNT_1">%1$d</xliff:g> files?</item>
+ <item quantity="one">Are you sure you want to delete <xliff:g id="COUNT_0">%1$d</xliff:g> file?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-en-rGB/config.xml b/packages/DocumentsUI/res/values-en-rGB/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-en-rGB/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-en-rGB/strings.xml b/packages/DocumentsUI/res/values-en-rGB/strings.xml
index 5bc4f59..82c5557 100644
--- a/packages/DocumentsUI/res/values-en-rGB/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rGB/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Share via"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Copying files"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Moving files"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Deleting files"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> left"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Copying <xliff:g id="COUNT_1">%1$d</xliff:g> files.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Some files were converted"</string>
<string name="allow" msgid="7225948811296386551">"Allow"</string>
<string name="deny" msgid="2081879885755434506">"Deny"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Delete files?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Are you sure you want to delete <xliff:g id="COUNT_1">%1$d</xliff:g> files?</item>
+ <item quantity="one">Are you sure you want to delete <xliff:g id="COUNT_0">%1$d</xliff:g> file?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-en-rIN/config.xml b/packages/DocumentsUI/res/values-en-rIN/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-en-rIN/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-en-rIN/strings.xml b/packages/DocumentsUI/res/values-en-rIN/strings.xml
index 5bc4f59..82c5557 100644
--- a/packages/DocumentsUI/res/values-en-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rIN/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Share via"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Copying files"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Moving files"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Deleting files"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> left"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Copying <xliff:g id="COUNT_1">%1$d</xliff:g> files.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Some files were converted"</string>
<string name="allow" msgid="7225948811296386551">"Allow"</string>
<string name="deny" msgid="2081879885755434506">"Deny"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Delete files?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Are you sure you want to delete <xliff:g id="COUNT_1">%1$d</xliff:g> files?</item>
+ <item quantity="one">Are you sure you want to delete <xliff:g id="COUNT_0">%1$d</xliff:g> file?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-es-rUS/config.xml b/packages/DocumentsUI/res/values-es-rUS/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-es-rUS/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-es-rUS/strings.xml b/packages/DocumentsUI/res/values-es-rUS/strings.xml
index e212053..1ba7c2d 100644
--- a/packages/DocumentsUI/res/values-es-rUS/strings.xml
+++ b/packages/DocumentsUI/res/values-es-rUS/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Compartir mediante"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Copiando archivos"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Moviendo archivos"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Borrando los archivos"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Faltan <xliff:g id="DURATION">%s</xliff:g>."</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Copiando <xliff:g id="COUNT_1">%1$d</xliff:g> archivos</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Se convirtieron algunos archivos"</string>
<string name="allow" msgid="7225948811296386551">"Permitir"</string>
<string name="deny" msgid="2081879885755434506">"Denegar"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"¿Quieres borrar los archivos?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">¿Confirmas que quieres borrar <xliff:g id="COUNT_1">%1$d</xliff:g> archivos?</item>
+ <item quantity="one">¿Confirmas que quieres borrar <xliff:g id="COUNT_0">%1$d</xliff:g> archivo?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-es/config.xml b/packages/DocumentsUI/res/values-es/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-es/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-es/strings.xml b/packages/DocumentsUI/res/values-es/strings.xml
index 28f3fd0..0c1f2dd 100644
--- a/packages/DocumentsUI/res/values-es/strings.xml
+++ b/packages/DocumentsUI/res/values-es/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Compartir a través de"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Copiando archivos"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Moviendo archivos"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Eliminando archivos"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Tiempo restante: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Copiando <xliff:g id="COUNT_1">%1$d</xliff:g> archivos.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Se han convertido algunos archivos"</string>
<string name="allow" msgid="7225948811296386551">"Permitir"</string>
<string name="deny" msgid="2081879885755434506">"Denegar"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"¿Eliminar archivos?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">¿Seguro que quieres eliminar <xliff:g id="COUNT_1">%1$d</xliff:g> archivos?</item>
+ <item quantity="one">¿Seguro que quieres eliminar <xliff:g id="COUNT_0">%1$d</xliff:g> archivo?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-et-rEE/config.xml b/packages/DocumentsUI/res/values-et-rEE/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-et-rEE/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-et-rEE/strings.xml b/packages/DocumentsUI/res/values-et-rEE/strings.xml
index d8d6bea..13a4bfa 100644
--- a/packages/DocumentsUI/res/values-et-rEE/strings.xml
+++ b/packages/DocumentsUI/res/values-et-rEE/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Jagage teenusega"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Failide kopeerimine"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Failide teisaldamine"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Failide kustutamine"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Jäänud on <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> faili kopeerimine.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Mõned failid teisendati"</string>
<string name="allow" msgid="7225948811296386551">"Luba"</string>
<string name="deny" msgid="2081879885755434506">"Keela"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Kas kustutada failid?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Kas soovite kindlasti <xliff:g id="COUNT_1">%1$d</xliff:g> faili kustutada?</item>
+ <item quantity="one">Kas soovite kindlasti <xliff:g id="COUNT_0">%1$d</xliff:g> faili kustutada?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-eu-rES/config.xml b/packages/DocumentsUI/res/values-eu-rES/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-eu-rES/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-eu-rES/strings.xml b/packages/DocumentsUI/res/values-eu-rES/strings.xml
index a8f3517..c66bae4 100644
--- a/packages/DocumentsUI/res/values-eu-rES/strings.xml
+++ b/packages/DocumentsUI/res/values-eu-rES/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Partekatu honen bidez:"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Fitxategiak kopiatzen"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Fitxategiak mugitzea"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Fitxategiak ezabatzea"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Falta den denbora: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> fitxategi kopiatzen.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Artxibo batzuk bihurtu dira"</string>
<string name="allow" msgid="7225948811296386551">"Onartu"</string>
<string name="deny" msgid="2081879885755434506">"Ukatu"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Fitxategiak ezabatu nahi dituzu?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Ziur <xliff:g id="COUNT_1">%1$d</xliff:g> fitxategi ezabatu nahi dituzula?</item>
+ <item quantity="one">Ziur <xliff:g id="COUNT_0">%1$d</xliff:g> fitxategi ezabatu nahi duzula?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-fa/config.xml b/packages/DocumentsUI/res/values-fa/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-fa/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-fa/strings.xml b/packages/DocumentsUI/res/values-fa/strings.xml
index 3b3d559..997eea8 100644
--- a/packages/DocumentsUI/res/values-fa/strings.xml
+++ b/packages/DocumentsUI/res/values-fa/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"اشتراکگذاری از طریق"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"در حال کپی کردن فایلها"</string>
<string name="move_notification_title" msgid="6193835179777284805">"درحال انتقال فایلها"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"در حال حذف فایلها"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> باقیمانده"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">در حال کپی کردن <xliff:g id="COUNT_1">%1$d</xliff:g> فایل.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"بعضی از فایلها تبدیل شدند"</string>
<string name="allow" msgid="7225948811296386551">"ارزیابیشده"</string>
<string name="deny" msgid="2081879885755434506">"اجازه ندارد"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"فایلها حذف شوند؟"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">مطمئنید میخواهید <xliff:g id="COUNT_1">%1$d</xliff:g> فایل را حذف کنید؟</item>
+ <item quantity="other">مطمئنید میخواهید <xliff:g id="COUNT_1">%1$d</xliff:g> فایل را حذف کنید؟</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-fi/config.xml b/packages/DocumentsUI/res/values-fi/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-fi/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-fi/strings.xml b/packages/DocumentsUI/res/values-fi/strings.xml
index 14513bd..1dfbe15 100644
--- a/packages/DocumentsUI/res/values-fi/strings.xml
+++ b/packages/DocumentsUI/res/values-fi/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Jaa sovelluksessa"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kopioidaan tiedostoja"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Siirretään tiedostoja"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Poistetaan tiedostoja"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> jäljellä"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Kopioidaan <xliff:g id="COUNT_1">%1$d</xliff:g> tiedostoa.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Joitakin tiedostoja muunnettiin."</string>
<string name="allow" msgid="7225948811296386551">"Salli"</string>
<string name="deny" msgid="2081879885755434506">"Kiellä"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Poistetaanko tiedostot?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Haluatko varmasti poistaa <xliff:g id="COUNT_1">%1$d</xliff:g> tiedostoa?</item>
+ <item quantity="one">Haluatko varmasti poistaa <xliff:g id="COUNT_0">%1$d</xliff:g> tiedoston?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-fr-rCA/config.xml b/packages/DocumentsUI/res/values-fr-rCA/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-fr-rCA/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-fr-rCA/strings.xml b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
index 0d35f4a..08dacac 100644
--- a/packages/DocumentsUI/res/values-fr-rCA/strings.xml
+++ b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Partager par"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Copie de fichiers..."</string>
<string name="move_notification_title" msgid="6193835179777284805">"Déplacement des fichiers"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Suppression des fichiers"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Durée restante : <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Copier de <xliff:g id="COUNT_1">%1$d</xliff:g> fichier en cours.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Certains fichiers ont été convertis"</string>
<string name="allow" msgid="7225948811296386551">"Autoriser"</string>
<string name="deny" msgid="2081879885755434506">"Refuser"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Supprimer les fichiers?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Voulez-vous vraiment supprimer <xliff:g id="COUNT_1">%1$d</xliff:g> fichier?</item>
+ <item quantity="other">Voulez-vous vraiment supprimer <xliff:g id="COUNT_1">%1$d</xliff:g> fichiers?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-fr/config.xml b/packages/DocumentsUI/res/values-fr/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-fr/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-fr/strings.xml b/packages/DocumentsUI/res/values-fr/strings.xml
index 7ed98bb..6378191 100644
--- a/packages/DocumentsUI/res/values-fr/strings.xml
+++ b/packages/DocumentsUI/res/values-fr/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Partager via"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Copie de fichiers en cours"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Déplacement de fichiers"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Suppression des fichiers…"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Temps restant : <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Copie de <xliff:g id="COUNT_1">%1$d</xliff:g> fichier en cours…</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Certains fichiers ont été convertis"</string>
<string name="allow" msgid="7225948811296386551">"Autoriser"</string>
<string name="deny" msgid="2081879885755434506">"Refuser"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Supprimer les fichiers ?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Voulez-vous vraiment supprimer <xliff:g id="COUNT_1">%1$d</xliff:g> fichier ?</item>
+ <item quantity="other">Voulez-vous vraiment supprimer <xliff:g id="COUNT_1">%1$d</xliff:g> fichiers ?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-gl-rES/config.xml b/packages/DocumentsUI/res/values-gl-rES/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-gl-rES/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-gl-rES/strings.xml b/packages/DocumentsUI/res/values-gl-rES/strings.xml
index 645eb04..79cc70f 100644
--- a/packages/DocumentsUI/res/values-gl-rES/strings.xml
+++ b/packages/DocumentsUI/res/values-gl-rES/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Compartir a través de"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Copiando ficheiros"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Mover ficheiros"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Eliminando ficheiros"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Tempo restante: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Copiando <xliff:g id="COUNT_1">%1$d</xliff:g> ficheiros.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Convertéronse algúns ficheiros"</string>
<string name="allow" msgid="7225948811296386551">"Permitir"</string>
<string name="deny" msgid="2081879885755434506">"Rexeitar"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Queres eliminar os ficheiros?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Seguro que queres eliminar <xliff:g id="COUNT_1">%1$d</xliff:g> ficheiros?</item>
+ <item quantity="one">Seguro que queres eliminar <xliff:g id="COUNT_0">%1$d</xliff:g> ficheiro?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-gu-rIN/config.xml b/packages/DocumentsUI/res/values-gu-rIN/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-gu-rIN/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-gu-rIN/strings.xml b/packages/DocumentsUI/res/values-gu-rIN/strings.xml
index 927906a..11519a1 100644
--- a/packages/DocumentsUI/res/values-gu-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-gu-rIN/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"આના દ્વારા શેર કરો"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"ફાઇલો કૉપિ કરી રહ્યાં છે"</string>
<string name="move_notification_title" msgid="6193835179777284805">"ફાઇલો ખસેડી રહ્યાં છે"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"ફાઇલોને કાઢી નાખી રહ્યાં છે"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> બાકી"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ફાઇલો કૉપિ કરી રહ્યાં છે.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"કેટલીક ફાઇલો રૂપાંતરિત કરી હતી"</string>
<string name="allow" msgid="7225948811296386551">"મંજૂરી આપો"</string>
<string name="deny" msgid="2081879885755434506">"નકારો"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"ફાઇલોને કાઢી નાખીએ?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">શું તમે ખરેખર <xliff:g id="COUNT_1">%1$d</xliff:g> ફાઇલને કાઢી નાખવા માગો છો?</item>
+ <item quantity="other">શું તમે ખરેખર <xliff:g id="COUNT_1">%1$d</xliff:g> ફાઇલને કાઢી નાખવા માગો છો?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-hi/config.xml b/packages/DocumentsUI/res/values-hi/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-hi/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-hi/strings.xml b/packages/DocumentsUI/res/values-hi/strings.xml
index f947d3d..dcb7805 100644
--- a/packages/DocumentsUI/res/values-hi/strings.xml
+++ b/packages/DocumentsUI/res/values-hi/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"इसके द्वारा साझा करें"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"फ़ाइलें कॉपी हो रही हैं"</string>
<string name="move_notification_title" msgid="6193835179777284805">"फाइलें ले जाई जा रही हैं"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"फ़ाइलें हटाई जा रही हैं"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> शेष"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> फ़ाइलें कॉपी की जा रही हैं.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"कुछ फ़ाइलें रूपांतरित हो गई थीं"</string>
<string name="allow" msgid="7225948811296386551">"अनुमति दें"</string>
<string name="deny" msgid="2081879885755434506">"अस्वीकारें"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"फ़ाइलें हटाएं?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">क्या आप वाकई <xliff:g id="COUNT_1">%1$d</xliff:g> फ़ाइलें हटाना चाहते हैं?</item>
+ <item quantity="other">क्या आप वाकई <xliff:g id="COUNT_1">%1$d</xliff:g> फ़ाइलें हटाना चाहते हैं?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-hr/config.xml b/packages/DocumentsUI/res/values-hr/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-hr/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-hr/strings.xml b/packages/DocumentsUI/res/values-hr/strings.xml
index bfac527..7d9b6f0 100644
--- a/packages/DocumentsUI/res/values-hr/strings.xml
+++ b/packages/DocumentsUI/res/values-hr/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Dijeli putem"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kopiranje datoteka"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Premještanje datoteka"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Brisanje datoteka"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Još <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Kopiranje <xliff:g id="COUNT_1">%1$d</xliff:g> datoteke.</item>
@@ -118,4 +119,10 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Neke su datoteke konvertirane"</string>
<string name="allow" msgid="7225948811296386551">"Dopusti"</string>
<string name="deny" msgid="2081879885755434506">"Odbij"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Izbrisati datoteke?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Jeste li sigurni da želite izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> datoteku?</item>
+ <item quantity="few">Jeste li sigurni da želite izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> datoteke?</item>
+ <item quantity="other">Jeste li sigurni da želite izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> datoteka?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-hu/config.xml b/packages/DocumentsUI/res/values-hu/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-hu/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-hu/strings.xml b/packages/DocumentsUI/res/values-hu/strings.xml
index 220d99c..ac40f87 100644
--- a/packages/DocumentsUI/res/values-hu/strings.xml
+++ b/packages/DocumentsUI/res/values-hu/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Megosztás itt:"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Fájlok másolása"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Fájlok áthelyezése"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Fájlok törlése"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> van hátra"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> fájl másolása.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Egyes fájlokat konvertált a rendszer"</string>
<string name="allow" msgid="7225948811296386551">"Engedélyezés"</string>
<string name="deny" msgid="2081879885755434506">"Elutasítás"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Törli a fájlokat?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Biztosan töröl <xliff:g id="COUNT_1">%1$d</xliff:g> fájlt?</item>
+ <item quantity="one">Biztosan töröl <xliff:g id="COUNT_0">%1$d</xliff:g> fájlt?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-hy-rAM/config.xml b/packages/DocumentsUI/res/values-hy-rAM/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-hy-rAM/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-hy-rAM/strings.xml b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
index 4448fe4..3598934 100644
--- a/packages/DocumentsUI/res/values-hy-rAM/strings.xml
+++ b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Տարածել"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Ֆայլերի պատճենում"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Ֆայլերի տեղափոխում"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Ֆայլերը ջնջվում են"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Մնացել է <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ֆայլի պատճենում:</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Որոշ ֆայլեր փոխարկվել են"</string>
<string name="allow" msgid="7225948811296386551">"Թույլատրել"</string>
<string name="deny" msgid="2081879885755434506">"Մերժել"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Ջնջե՞լ ֆայլերը:"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Ջնջե՞լ <xliff:g id="COUNT_1">%1$d</xliff:g> ֆայլ:</item>
+ <item quantity="other">Ջնջե՞լ <xliff:g id="COUNT_1">%1$d</xliff:g> ֆայլ:</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-in/config.xml b/packages/DocumentsUI/res/values-in/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-in/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-in/strings.xml b/packages/DocumentsUI/res/values-in/strings.xml
index 4d4e810..d87fad3 100644
--- a/packages/DocumentsUI/res/values-in/strings.xml
+++ b/packages/DocumentsUI/res/values-in/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Bagikan melalui"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Menyalin file"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Memindahkan file"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Menghapus file"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> lagi"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Menyalin <xliff:g id="COUNT_1">%1$d</xliff:g> file.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Beberapa file dikonversi"</string>
<string name="allow" msgid="7225948811296386551">"Izinkan"</string>
<string name="deny" msgid="2081879885755434506">"Tolak"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Hapus file?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Yakin ingin menghapus <xliff:g id="COUNT_1">%1$d</xliff:g> file?</item>
+ <item quantity="one">Yakin ingin menghapus <xliff:g id="COUNT_0">%1$d</xliff:g> file?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-is-rIS/config.xml b/packages/DocumentsUI/res/values-is-rIS/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-is-rIS/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-is-rIS/strings.xml b/packages/DocumentsUI/res/values-is-rIS/strings.xml
index d7e4284..5b2531d 100644
--- a/packages/DocumentsUI/res/values-is-rIS/strings.xml
+++ b/packages/DocumentsUI/res/values-is-rIS/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Deila í gegnum"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Afritar skrár"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Skrár færðar"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Eyðir skrám"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> eftir"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Afritar <xliff:g id="COUNT_1">%1$d</xliff:g> skrá.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sumum skrám var umbreytt"</string>
<string name="allow" msgid="7225948811296386551">"Leyfa"</string>
<string name="deny" msgid="2081879885755434506">"Hafna"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Eyða skrám?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Ertu viss um að þú viljir eyða <xliff:g id="COUNT_1">%1$d</xliff:g> skrá?</item>
+ <item quantity="other">Ertu viss um að þú viljir eyða <xliff:g id="COUNT_1">%1$d</xliff:g> skrám?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-it/config.xml b/packages/DocumentsUI/res/values-it/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-it/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-it/strings.xml b/packages/DocumentsUI/res/values-it/strings.xml
index 373f480..4785ffc 100644
--- a/packages/DocumentsUI/res/values-it/strings.xml
+++ b/packages/DocumentsUI/res/values-it/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Condividi via"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Copia di file in corso"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Spostamento di file"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Eliminazione dei file"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> rimanenti"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Copia di <xliff:g id="COUNT_1">%1$d</xliff:g> file in corso.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alcuni file sono stati convertiti"</string>
<string name="allow" msgid="7225948811296386551">"Consenti"</string>
<string name="deny" msgid="2081879885755434506">"Nega"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Eliminare i file?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Vuoi eliminare <xliff:g id="COUNT_1">%1$d</xliff:g> file?</item>
+ <item quantity="one">Vuoi eliminare <xliff:g id="COUNT_0">%1$d</xliff:g> file?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-iw/config.xml b/packages/DocumentsUI/res/values-iw/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-iw/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-iw/strings.xml b/packages/DocumentsUI/res/values-iw/strings.xml
index 8806079..1fb81dd 100644
--- a/packages/DocumentsUI/res/values-iw/strings.xml
+++ b/packages/DocumentsUI/res/values-iw/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"שתף באמצעות"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"מעתיק קבצים"</string>
<string name="move_notification_title" msgid="6193835179777284805">"מעביר קבצים"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"מחיקת קבצים מתבצעת"</string>
<string name="copy_remaining" msgid="6283790937387975095">"זמן נותר: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="two">מעתיק <xliff:g id="COUNT_1">%1$d</xliff:g> קבצים.</item>
@@ -125,4 +126,11 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"קבצים מסוימים הומרו"</string>
<string name="allow" msgid="7225948811296386551">"אפשר"</string>
<string name="deny" msgid="2081879885755434506">"דחה"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"האם למחוק את הקבצים?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="two">האם אתה בטוח שברצונך למחוק <xliff:g id="COUNT_1">%1$d</xliff:g> קבצים?</item>
+ <item quantity="many">האם אתה בטוח שברצונך למחוק <xliff:g id="COUNT_1">%1$d</xliff:g> קבצים?</item>
+ <item quantity="other">האם אתה בטוח שברצונך למחוק <xliff:g id="COUNT_1">%1$d</xliff:g> קבצים?</item>
+ <item quantity="one">האם אתה בטוח שברצונך למחוק קובץ <xliff:g id="COUNT_0">%1$d</xliff:g>?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-ja/config.xml b/packages/DocumentsUI/res/values-ja/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ja/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ja/strings.xml b/packages/DocumentsUI/res/values-ja/strings.xml
index e0b82e5..32bc414 100644
--- a/packages/DocumentsUI/res/values-ja/strings.xml
+++ b/packages/DocumentsUI/res/values-ja/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"共有ツール"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"ファイルのコピー中"</string>
<string name="move_notification_title" msgid="6193835179777284805">"ファイルを移動中"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"ファイルを削除しています"</string>
<string name="copy_remaining" msgid="6283790937387975095">"残り<xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>個のファイルをコピーしています。</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"一部のファイルが変換されました"</string>
<string name="allow" msgid="7225948811296386551">"許可"</string>
<string name="deny" msgid="2081879885755434506">"拒否"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"ファイルを削除しますか?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> 個のファイルを削除してもよろしいですか?</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> 個のファイルを削除してもよろしいですか?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-ka-rGE/config.xml b/packages/DocumentsUI/res/values-ka-rGE/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ka-rGE/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ka-rGE/strings.xml b/packages/DocumentsUI/res/values-ka-rGE/strings.xml
index 5e1ddd3..ce32f23 100644
--- a/packages/DocumentsUI/res/values-ka-rGE/strings.xml
+++ b/packages/DocumentsUI/res/values-ka-rGE/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"გაზიარება:"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"მიმდ. ფაილების კოპირება"</string>
<string name="move_notification_title" msgid="6193835179777284805">"ფაილების გადაადგილება"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"ფაილების წაშლა…"</string>
<string name="copy_remaining" msgid="6283790937387975095">"დარჩა <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">მიმდინარეობს <xliff:g id="COUNT_1">%1$d</xliff:g> ფაილის კოპირება.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ზოგიერთი ფაილი გარდაქმნილია"</string>
<string name="allow" msgid="7225948811296386551">"უფლების მიცემა"</string>
<string name="deny" msgid="2081879885755434506">"აკრძალვა"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"გსურთ ფაილების წაშლა?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">ნამდვილად გსურთ <xliff:g id="COUNT_1">%1$d</xliff:g> ფაილის წაშლა?</item>
+ <item quantity="one">ნამდვილად გსურთ <xliff:g id="COUNT_0">%1$d</xliff:g> ფაილის წაშლა?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-kk-rKZ/config.xml b/packages/DocumentsUI/res/values-kk-rKZ/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-kk-rKZ/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
index 5b6b94d..ad10920 100644
--- a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
+++ b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Бөлісу"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Файлдарды көшіру"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Файлдар тасымалдануда"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Файлдар жойылуда"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> қалды"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> файлды көшіру.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Кейбір файлдар түрлендірілді"</string>
<string name="allow" msgid="7225948811296386551">"Рұқсат беру"</string>
<string name="deny" msgid="2081879885755434506">"Бас тарту"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Файлдарды жою керек пе?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> файлды жою керек пе?</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> файлды жою керек пе?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-km-rKH/config.xml b/packages/DocumentsUI/res/values-km-rKH/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-km-rKH/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-km-rKH/strings.xml b/packages/DocumentsUI/res/values-km-rKH/strings.xml
index 4664bd4..a084f81 100644
--- a/packages/DocumentsUI/res/values-km-rKH/strings.xml
+++ b/packages/DocumentsUI/res/values-km-rKH/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"ចែករំលែកតាម"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"កំពុងថតចម្លងឯកសារ"</string>
<string name="move_notification_title" msgid="6193835179777284805">"ផ្លាស់ទីឯកសារ"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"កំពុងលុបឯកសារ"</string>
<string name="copy_remaining" msgid="6283790937387975095">"នៅសល់ <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">កំពុងថតចម្លងឯកសារចំនួន <xliff:g id="COUNT_1">%1$d</xliff:g> ។</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ឯកសារមួយចំនួនត្រូវបានបម្លែង"</string>
<string name="allow" msgid="7225948811296386551">"អនុញ្ញាត"</string>
<string name="deny" msgid="2081879885755434506">"បដិសេធ"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"លុបឯកសារឬទេ?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">តើអ្នកប្រាកដថាអ្នកចង់លុប <xliff:g id="COUNT_1">%1$d</xliff:g> ឯកសារឬទេ?</item>
+ <item quantity="one">តើអ្នកប្រាកដថាអ្នកចង់លុប <xliff:g id="COUNT_0">%1$d</xliff:g> ឯកសារឬទេ?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-kn-rIN/config.xml b/packages/DocumentsUI/res/values-kn-rIN/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-kn-rIN/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-kn-rIN/strings.xml b/packages/DocumentsUI/res/values-kn-rIN/strings.xml
index 487a7b3..55c9697 100644
--- a/packages/DocumentsUI/res/values-kn-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-kn-rIN/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"ಈ ಮೂಲಕ ಹಂಚಿಕೊಳ್ಳಿ"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"ಫೈಲ್ಗಳನ್ನು ನಕಲಿಸಲಾಗುತ್ತಿದೆ"</string>
<string name="move_notification_title" msgid="6193835179777284805">"ಫೈಲ್ಗಳನ್ನು ಸರಿಸಲಾಗುತ್ತಿದೆ"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"ಫೈಲ್ ಅಳಿಸಲಾಗುತ್ತಿದೆ"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> ಉಳಿದಿದೆ"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one"> <xliff:g id="COUNT_1">%1$d</xliff:g> ಫೈಲ್ಗಳನ್ನು ನಕಲಿಸಲಾಗುತ್ತಿದೆ.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ಕೆಲವು ಫೈಲ್ಗಳನ್ನು ಪರಿವರ್ತಿಸಲಾಗಿದೆ"</string>
<string name="allow" msgid="7225948811296386551">"ಅನುಮತಿಸು"</string>
<string name="deny" msgid="2081879885755434506">"ನಿರಾಕರಿಸು"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"ಫೈಲ್ಗಳನ್ನು ಅಳಿಸುವುದೇ?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ಫೈಲ್ಗಳನ್ನು ಅಳಿಸಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ಫೈಲ್ಗಳನ್ನು ಅಳಿಸಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-ko/config.xml b/packages/DocumentsUI/res/values-ko/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ko/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ko/strings.xml b/packages/DocumentsUI/res/values-ko/strings.xml
index 62336c7..37642d1 100644
--- a/packages/DocumentsUI/res/values-ko/strings.xml
+++ b/packages/DocumentsUI/res/values-ko/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"공유 방법"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"파일 복사 중"</string>
<string name="move_notification_title" msgid="6193835179777284805">"파일 이동"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"파일 삭제"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> 남음"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">파일 <xliff:g id="COUNT_1">%1$d</xliff:g>개를 복사합니다.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"일부 파일이 변환되었습니다."</string>
<string name="allow" msgid="7225948811296386551">"허용"</string>
<string name="deny" msgid="2081879885755434506">"거부"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"파일을 삭제하시겠습니까?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">파일 <xliff:g id="COUNT_1">%1$d</xliff:g>개를 삭제하시겠습니까?</item>
+ <item quantity="one">파일 <xliff:g id="COUNT_0">%1$d</xliff:g>개를 삭제하시겠습니까?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-ky-rKG/config.xml b/packages/DocumentsUI/res/values-ky-rKG/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ky-rKG/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ky-rKG/strings.xml b/packages/DocumentsUI/res/values-ky-rKG/strings.xml
index f93f709..134b5b8 100644
--- a/packages/DocumentsUI/res/values-ky-rKG/strings.xml
+++ b/packages/DocumentsUI/res/values-ky-rKG/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Кийинки аркылуу бөлүшүү:"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Файлдар көчүрүлүүдө"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Файлдар жылдырылууда…"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Файлдар жок кылынууда"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> калды"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> файл көчүрүлүүдө.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Айрым файлдардын форматы өзгөртүлдү"</string>
<string name="allow" msgid="7225948811296386551">"Уруксат берүү"</string>
<string name="deny" msgid="2081879885755434506">"Жок"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Файлдар жок кылынсынбы?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Бул <xliff:g id="COUNT_1">%1$d</xliff:g> файлды чын эле жок кылгыңыз келеби?</item>
+ <item quantity="one">Бул <xliff:g id="COUNT_0">%1$d</xliff:g> файлды чын эле жок кылгыңыз келеби?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-ldrtl/dimens.xml b/packages/DocumentsUI/res/values-ldrtl/config.xml
similarity index 100%
rename from packages/DocumentsUI/res/values-ldrtl/dimens.xml
rename to packages/DocumentsUI/res/values-ldrtl/config.xml
diff --git a/packages/DocumentsUI/res/values-lo-rLA/config.xml b/packages/DocumentsUI/res/values-lo-rLA/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-lo-rLA/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-lo-rLA/strings.xml b/packages/DocumentsUI/res/values-lo-rLA/strings.xml
index 4b36057..edfca5c 100644
--- a/packages/DocumentsUI/res/values-lo-rLA/strings.xml
+++ b/packages/DocumentsUI/res/values-lo-rLA/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"ແບ່ງປັນຜ່ານ"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"ກຳລັງອັດສຳເນົາໄຟລ໌"</string>
<string name="move_notification_title" msgid="6193835179777284805">"ກຳລັງຍ້າຍໄຟລ໌"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"ກຳລັງລຶບໄຟລ໌"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> ຍັງເຫຼືອຢູ່"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">ກຳລັງອັດສຳເນົາ <xliff:g id="COUNT_1">%1$d</xliff:g> ໄຟລ໌.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ປ່ຽນແປງບາງໄຟລ໌ແລ້ວ"</string>
<string name="allow" msgid="7225948811296386551">"ອະນຸຍາດ"</string>
<string name="deny" msgid="2081879885755434506">"ປະຕິເສດ"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"ລຶບໄຟລ໌ອອກບໍ?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">ທ່ານແນ່ໃຈບໍ່ວ່າຕ້ອງການລຶບ <xliff:g id="COUNT_1">%1$d</xliff:g> ໄຟລ໌?</item>
+ <item quantity="one">ທ່ານແນ່ໃຈບໍ່ວ່າຕ້ອງການລຶບ <xliff:g id="COUNT_0">%1$d</xliff:g> ໄຟລ໌?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-lt/config.xml b/packages/DocumentsUI/res/values-lt/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-lt/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-lt/strings.xml b/packages/DocumentsUI/res/values-lt/strings.xml
index 8de09ce..194e5900 100644
--- a/packages/DocumentsUI/res/values-lt/strings.xml
+++ b/packages/DocumentsUI/res/values-lt/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Bendrinti naudojant"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kopijuojami failai"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Perkeliami failai"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Failų ištrynimas"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Liko: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Kopijuojamas <xliff:g id="COUNT_1">%1$d</xliff:g> failas.</item>
@@ -125,4 +126,11 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Kai kurie failai buvo konvertuoti"</string>
<string name="allow" msgid="7225948811296386551">"Leisti"</string>
<string name="deny" msgid="2081879885755434506">"Atmesti"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Ištrinti failus?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">]Ar tikrai norite ištrinti <xliff:g id="COUNT_1">%1$d</xliff:g> failą?</item>
+ <item quantity="few">]Ar tikrai norite ištrinti <xliff:g id="COUNT_1">%1$d</xliff:g> failus?</item>
+ <item quantity="many">]Ar tikrai norite ištrinti <xliff:g id="COUNT_1">%1$d</xliff:g> failo?</item>
+ <item quantity="other">]Ar tikrai norite ištrinti <xliff:g id="COUNT_1">%1$d</xliff:g> failų?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-lv/config.xml b/packages/DocumentsUI/res/values-lv/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-lv/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-lv/strings.xml b/packages/DocumentsUI/res/values-lv/strings.xml
index 7711941..cd4cb5e 100644
--- a/packages/DocumentsUI/res/values-lv/strings.xml
+++ b/packages/DocumentsUI/res/values-lv/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Kopīgot, izmantojot"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Notiek failu kopēšana"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Failu pārvietošana"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Notiek failu dzēšana"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Atlikušais laiks: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="zero">Notiek <xliff:g id="COUNT_1">%1$d</xliff:g> failu kopēšana.</item>
@@ -118,4 +119,10 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Daži faili tika pārveidoti."</string>
<string name="allow" msgid="7225948811296386551">"Atļaut"</string>
<string name="deny" msgid="2081879885755434506">"Noraidīt"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Vai dzēst failus?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="zero">Vai tiešām vēlaties dzēst <xliff:g id="COUNT_1">%1$d</xliff:g> failus?</item>
+ <item quantity="one">Vai tiešām vēlaties dzēst <xliff:g id="COUNT_1">%1$d</xliff:g> failu?</item>
+ <item quantity="other">Vai tiešām vēlaties dzēst <xliff:g id="COUNT_1">%1$d</xliff:g> failus?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-mk-rMK/config.xml b/packages/DocumentsUI/res/values-mk-rMK/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-mk-rMK/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-mk-rMK/strings.xml b/packages/DocumentsUI/res/values-mk-rMK/strings.xml
index 7798ea6..129119b 100644
--- a/packages/DocumentsUI/res/values-mk-rMK/strings.xml
+++ b/packages/DocumentsUI/res/values-mk-rMK/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Сподели преку"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Се копираат датотеки"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Датотеките се преместуваат"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Се бришат датотеки"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Уште <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Се копира <xliff:g id="COUNT_1">%1$d</xliff:g> датотека.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Некои датотеки беа конвертирани"</string>
<string name="allow" msgid="7225948811296386551">"Дозволи"</string>
<string name="deny" msgid="2081879885755434506">"Одбиј"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Избриши датотеки?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Дали сте сигурни дека сакате да избришете <xliff:g id="COUNT_1">%1$d</xliff:g> датотека?</item>
+ <item quantity="other">Дали сте сигурни дека сакате да избришете <xliff:g id="COUNT_1">%1$d</xliff:g> датотеки?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-ml-rIN/config.xml b/packages/DocumentsUI/res/values-ml-rIN/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ml-rIN/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ml-rIN/strings.xml b/packages/DocumentsUI/res/values-ml-rIN/strings.xml
index a9f9a46..966ddbb 100644
--- a/packages/DocumentsUI/res/values-ml-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-ml-rIN/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"ഇതുവഴി പങ്കിടുക"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"ഫയലുകൾ പകർത്തുന്നു"</string>
<string name="move_notification_title" msgid="6193835179777284805">"ഫയലുകൾ നീക്കുന്നു"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"ഫയലുകൾ ഇല്ലാതാക്കുന്നു"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> ശേഷിക്കുന്നു"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ഫയലുകൾ പകർത്തുന്നു.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ചില ഫയലുകൾ പരിവർത്തനം ചെയ്യപ്പെട്ടു"</string>
<string name="allow" msgid="7225948811296386551">"അനുവദിക്കുക"</string>
<string name="deny" msgid="2081879885755434506">"നിരസിക്കുക"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"ഫയലുകൾ ഇല്ലാതാക്കണോ?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ഫയലുകൾ ഇല്ലാതാക്കണമെന്ന് നിങ്ങൾക്ക് തീർച്ചയാണോ?</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ഫയൽ ഇല്ലാതാക്കണമെന്ന് നിങ്ങൾക്ക് തീർച്ചയാണോ?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-mn-rMN/config.xml b/packages/DocumentsUI/res/values-mn-rMN/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-mn-rMN/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-mn-rMN/strings.xml b/packages/DocumentsUI/res/values-mn-rMN/strings.xml
index 0663588..a2617f9 100644
--- a/packages/DocumentsUI/res/values-mn-rMN/strings.xml
+++ b/packages/DocumentsUI/res/values-mn-rMN/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Дараахаар дамжуулан хуваалцах"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Файлуудыг хуулж байна"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Файлыг зөөвөрлөж байна"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Эдгээр файлыг устгаж байна"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> үлдсэн"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"> <xliff:g id="COUNT_1">%1$d</xliff:g> файлуудыг хуулж байна.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Зарим файлыг хөрвүүлсэн"</string>
<string name="allow" msgid="7225948811296386551">"Зөвшөөрөх"</string>
<string name="deny" msgid="2081879885755434506">"Татгалзах"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Эдгээр файлыг устгах уу?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Та <xliff:g id="COUNT_1">%1$d</xliff:g> файлыг устгахдаа итгэлтэй байна уу?</item>
+ <item quantity="one">Та <xliff:g id="COUNT_0">%1$d</xliff:g> файлыг устгахдаа итгэлтэй байна уу?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-mr-rIN/config.xml b/packages/DocumentsUI/res/values-mr-rIN/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-mr-rIN/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-mr-rIN/strings.xml b/packages/DocumentsUI/res/values-mr-rIN/strings.xml
index 82bb882..c44b481 100644
--- a/packages/DocumentsUI/res/values-mr-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-mr-rIN/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"द्वारे सामायिक करा"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"फायली कॉपी करीत आहे"</string>
<string name="move_notification_title" msgid="6193835179777284805">"फायली हलविणे"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"फायली हटवित आहे"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> शिल्लक"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> फाईल कॉपी करीत आहे.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"काही फायली रूपांतरित केल्या होत्या"</string>
<string name="allow" msgid="7225948811296386551">"अनुमती द्या"</string>
<string name="deny" msgid="2081879885755434506">"नकार द्या"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"फायली हटवायच्या?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">आपल्याला खात्री आहे की आपण <xliff:g id="COUNT_1">%1$d</xliff:g> फाईल हटवू इच्छिता?</item>
+ <item quantity="other">आपल्याला खात्री आहे की आपण <xliff:g id="COUNT_1">%1$d</xliff:g> फायली हटवू इच्छिता?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-ms-rMY/config.xml b/packages/DocumentsUI/res/values-ms-rMY/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ms-rMY/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ms-rMY/strings.xml b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
index 64f6163..17cd348 100644
--- a/packages/DocumentsUI/res/values-ms-rMY/strings.xml
+++ b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Kongsi melalui"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Menyalin fail"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Mengalihkan fail"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Memadamkan fail"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> lagi"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Menyalin <xliff:g id="COUNT_1">%1$d</xliff:g> fail.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sesetengah fail telah ditukarkan"</string>
<string name="allow" msgid="7225948811296386551">"Benarkan"</string>
<string name="deny" msgid="2081879885755434506">"Nafi"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Padamkan fail?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Adakah anda pasti mahu memadamkan <xliff:g id="COUNT_1">%1$d</xliff:g> fail?</item>
+ <item quantity="one">Adakah anda pasti mahu memadamkan <xliff:g id="COUNT_0">%1$d</xliff:g> fail?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-my-rMM/config.xml b/packages/DocumentsUI/res/values-my-rMM/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-my-rMM/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-my-rMM/strings.xml b/packages/DocumentsUI/res/values-my-rMM/strings.xml
index 2813f2d..13392fc 100644
--- a/packages/DocumentsUI/res/values-my-rMM/strings.xml
+++ b/packages/DocumentsUI/res/values-my-rMM/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"မှ ဝေမျှပါ"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"ဖိုင်များကူယူနေသည်"</string>
<string name="move_notification_title" msgid="6193835179777284805">"ဖိုင်များ ရွှေ့နေသည်"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"ဖိုင်များကို ဖျက်နေသည်"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> ကျန်ရှိသည်"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ဖိုင်များကို ကူးယူနေသည်။</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"အချို့ဖိုင်များကို ပြောင်းလဲထားသည်"</string>
<string name="allow" msgid="7225948811296386551">"ခွင့်ပြုသည်"</string>
<string name="deny" msgid="2081879885755434506">"ငြင်းပယ်သည်"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"ဖိုင်များကို ဖျက်မလား။"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ဖိုင်များကိုဖျက်ရန် သေချာပါသလား။</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ဖိုင်ကိုဖျက်ရန် သေချာပါသလား။</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-nb/config.xml b/packages/DocumentsUI/res/values-nb/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-nb/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-nb/strings.xml b/packages/DocumentsUI/res/values-nb/strings.xml
index d79b279..d42c98e 100644
--- a/packages/DocumentsUI/res/values-nb/strings.xml
+++ b/packages/DocumentsUI/res/values-nb/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Del via"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kopierer filer"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Flytter filer"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Sletter filene"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> gjenstår"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Kopierer <xliff:g id="COUNT_1">%1$d</xliff:g> filer.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Noen filer er konvertert"</string>
<string name="allow" msgid="7225948811296386551">"Tillat"</string>
<string name="deny" msgid="2081879885755434506">"Avslå"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Vil du slette filene?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Er du sikker på at du vil slette <xliff:g id="COUNT_1">%1$d</xliff:g> filer?</item>
+ <item quantity="one">Er du sikker på at du vil slette <xliff:g id="COUNT_0">%1$d</xliff:g> fil?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-ne-rNP/config.xml b/packages/DocumentsUI/res/values-ne-rNP/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ne-rNP/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ne-rNP/strings.xml b/packages/DocumentsUI/res/values-ne-rNP/strings.xml
index 057e03f..d0bc737 100644
--- a/packages/DocumentsUI/res/values-ne-rNP/strings.xml
+++ b/packages/DocumentsUI/res/values-ne-rNP/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"माध्यमबाट साझेदारी गर्नुहोस्"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"फाइलहरू प्रतिलिपि गर्दै:"</string>
<string name="move_notification_title" msgid="6193835179777284805">"फाइलहरू सार्दै"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"फाइलहरूलाई मेट्दै"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g>बाँकी"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"> <xliff:g id="COUNT_1">%1$d</xliff:g>फाइलहरू प्रतिलिप गर्दै।</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"केही फाइलहरू परिवर्तन गरिएका थिए"</string>
<string name="allow" msgid="7225948811296386551">"अनुमति दिनुहोस्"</string>
<string name="deny" msgid="2081879885755434506">"अस्वीकार गर्नुहोस्"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"फाइलहरूलाई मेट्ने हो?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">तपाईँ निश्चित रूपमा <xliff:g id="COUNT_1">%1$d</xliff:g> फाइलहरूलाई मेट्न चाहनुहुन्छ?</item>
+ <item quantity="one">तपाईँ निश्चित रूपमा <xliff:g id="COUNT_0">%1$d</xliff:g> फाइललाई मेट्न चाहनुहुन्छ?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-nl/config.xml b/packages/DocumentsUI/res/values-nl/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-nl/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-nl/strings.xml b/packages/DocumentsUI/res/values-nl/strings.xml
index 99a9f91..257e7e4 100644
--- a/packages/DocumentsUI/res/values-nl/strings.xml
+++ b/packages/DocumentsUI/res/values-nl/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Delen via"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Bestanden kopiëren"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Bestanden verplaatsen"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Bestanden verwijderen"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> resterend"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> bestanden kopiëren.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sommige bestanden zijn geconverteerd"</string>
<string name="allow" msgid="7225948811296386551">"Toestaan"</string>
<string name="deny" msgid="2081879885755434506">"Weigeren"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Bestanden verwijderen?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Weet je zeker dat je <xliff:g id="COUNT_1">%1$d</xliff:g> bestanden wilt verwijderen?</item>
+ <item quantity="one">Weet je zeker dat je <xliff:g id="COUNT_0">%1$d</xliff:g> bestand wilt verwijderen?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-pa-rIN/config.xml b/packages/DocumentsUI/res/values-pa-rIN/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-pa-rIN/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-pa-rIN/strings.xml b/packages/DocumentsUI/res/values-pa-rIN/strings.xml
index 758a4d8..7dca3cf 100644
--- a/packages/DocumentsUI/res/values-pa-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-pa-rIN/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"ਇਸ ਰਾਹੀਂ ਸ਼ੇਅਰ ਕਰੋ"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"ਫਾਈਲਾਂ ਕਾਪੀ ਕਰ ਰਿਹਾ ਹੈ"</string>
<string name="move_notification_title" msgid="6193835179777284805">"ਫ਼ਾਈਲਾਂ ਨੂੰ ਮੂਵ ਕਰ ਰਿਹਾ ਹੈ"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"ਫ਼ਾਈਲਾਂ ਨੂੰ ਮਿਟਾਇਆ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> ਬਾਕੀ"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one"> <xliff:g id="COUNT_1">%1$d</xliff:g> ਫਾਈਲਾਂ ਕਾਪੀ ਕਰ ਰਿਹਾ ਹੈ।</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ਕੁਝ ਫ਼ਾਈਲਾਂ ਤਬਦੀਲ ਕੀਤੀਆਂ ਗਈਆਂ ਸਨ"</string>
<string name="allow" msgid="7225948811296386551">"ਆਗਿਆ ਦਿਓ"</string>
<string name="deny" msgid="2081879885755434506">"ਅਸਵੀਕਾਰ ਕਰੋ"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"ਕੀ ਫ਼ਾਈਲਾਂ ਨੂੰ ਮਿਟਾਉਣਾ ਹੈ?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">ਕੀ ਤੁਸੀਂ ਯਕੀਨੀ ਤੌਰ \'ਤੇ <xliff:g id="COUNT_1">%1$d</xliff:g> ਫ਼ਾਈਲਾਂ ਨੂੰ ਮਿਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?</item>
+ <item quantity="other">ਕੀ ਤੁਸੀਂ ਯਕੀਨੀ ਤੌਰ \'ਤੇ <xliff:g id="COUNT_1">%1$d</xliff:g> ਫ਼ਾਈਲਾਂ ਨੂੰ ਮਿਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-pl/config.xml b/packages/DocumentsUI/res/values-pl/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-pl/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-pl/strings.xml b/packages/DocumentsUI/res/values-pl/strings.xml
index 8a4d17c..d334194 100644
--- a/packages/DocumentsUI/res/values-pl/strings.xml
+++ b/packages/DocumentsUI/res/values-pl/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Udostępnij przez:"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kopiowanie plików"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Przenoszenie plików"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Usuwam pliki"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Pozostało: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="few">Kopiowanie <xliff:g id="COUNT_1">%1$d</xliff:g> plików.</item>
@@ -125,4 +126,11 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Niektóre pliki zostały przekonwertowane"</string>
<string name="allow" msgid="7225948811296386551">"Zezwól"</string>
<string name="deny" msgid="2081879885755434506">"Odmów"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Usunąć pliki?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="few">Na pewno chcesz usunąć <xliff:g id="COUNT_1">%1$d</xliff:g> pliki?</item>
+ <item quantity="many">Na pewno chcesz usunąć <xliff:g id="COUNT_1">%1$d</xliff:g> plików?</item>
+ <item quantity="other">Na pewno chcesz usunąć <xliff:g id="COUNT_1">%1$d</xliff:g> pliku?</item>
+ <item quantity="one">Na pewno chcesz usunąć <xliff:g id="COUNT_0">%1$d</xliff:g> plik?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-pt-rBR/config.xml b/packages/DocumentsUI/res/values-pt-rBR/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-pt-rBR/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-pt-rBR/strings.xml b/packages/DocumentsUI/res/values-pt-rBR/strings.xml
index 391a053..cc55006 100644
--- a/packages/DocumentsUI/res/values-pt-rBR/strings.xml
+++ b/packages/DocumentsUI/res/values-pt-rBR/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Compartilhar via"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Copiando arquivos"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Movendo arquivos"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Excluindo arquivos"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> restantes"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Copiando <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alguns arquivos foram convertidos"</string>
<string name="allow" msgid="7225948811296386551">"Permitir"</string>
<string name="deny" msgid="2081879885755434506">"Negar"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Excluir arquivos?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Tem certeza de que deseja excluir <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos?</item>
+ <item quantity="other">Tem certeza de que deseja excluir <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-pt-rPT/config.xml b/packages/DocumentsUI/res/values-pt-rPT/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-pt-rPT/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-pt-rPT/strings.xml b/packages/DocumentsUI/res/values-pt-rPT/strings.xml
index 448ddfe..1e51019 100644
--- a/packages/DocumentsUI/res/values-pt-rPT/strings.xml
+++ b/packages/DocumentsUI/res/values-pt-rPT/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Partilhar através de"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"A copiar ficheiros"</string>
<string name="move_notification_title" msgid="6193835179777284805">"A mover ficheiros"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Eliminar ficheiros"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Faltam <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">A copiar <xliff:g id="COUNT_1">%1$d</xliff:g> ficheiros.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alguns ficheiros foram convertidos"</string>
<string name="allow" msgid="7225948811296386551">"Permitir"</string>
<string name="deny" msgid="2081879885755434506">"Recusar"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Pretende eliminar ficheiros?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Tem a certeza de que pretende eliminar <xliff:g id="COUNT_1">%1$d</xliff:g> ficheiros?</item>
+ <item quantity="one">Tem a certeza de que pretende eliminar <xliff:g id="COUNT_0">%1$d</xliff:g> ficheiro?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-pt/config.xml b/packages/DocumentsUI/res/values-pt/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-pt/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-pt/strings.xml b/packages/DocumentsUI/res/values-pt/strings.xml
index 391a053..cc55006 100644
--- a/packages/DocumentsUI/res/values-pt/strings.xml
+++ b/packages/DocumentsUI/res/values-pt/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Compartilhar via"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Copiando arquivos"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Movendo arquivos"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Excluindo arquivos"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> restantes"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Copiando <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alguns arquivos foram convertidos"</string>
<string name="allow" msgid="7225948811296386551">"Permitir"</string>
<string name="deny" msgid="2081879885755434506">"Negar"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Excluir arquivos?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Tem certeza de que deseja excluir <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos?</item>
+ <item quantity="other">Tem certeza de que deseja excluir <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-ro/config.xml b/packages/DocumentsUI/res/values-ro/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ro/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ro/strings.xml b/packages/DocumentsUI/res/values-ro/strings.xml
index 565a4e9..9932bd8 100644
--- a/packages/DocumentsUI/res/values-ro/strings.xml
+++ b/packages/DocumentsUI/res/values-ro/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Trimiteți prin"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Se copiază fișierele"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Se mută fișierele"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Se șterg fișierele"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Timp rămas: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="few">Se copiază <xliff:g id="COUNT_1">%1$d</xliff:g> fișiere.</item>
@@ -117,5 +118,11 @@
<string name="rename_error" msgid="4203041674883412606">"Documentul nu a putut fi redenumit"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Unele fișiere au fost convertite"</string>
<string name="allow" msgid="7225948811296386551">"Permiteți"</string>
- <string name="deny" msgid="2081879885755434506">"Refuzaţi"</string>
+ <string name="deny" msgid="2081879885755434506">"Refuzați"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Ștergeți fișierele?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="few">Sigur doriți să ștergeți <xliff:g id="COUNT_1">%1$d</xliff:g> fișiere?</item>
+ <item quantity="other">Sigur doriți să ștergeți <xliff:g id="COUNT_1">%1$d</xliff:g> de fișiere?</item>
+ <item quantity="one">Sigur doriți să ștergeți <xliff:g id="COUNT_0">%1$d</xliff:g> fișier?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-ru/config.xml b/packages/DocumentsUI/res/values-ru/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ru/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ru/strings.xml b/packages/DocumentsUI/res/values-ru/strings.xml
index ec97840..ebddb27 100644
--- a/packages/DocumentsUI/res/values-ru/strings.xml
+++ b/packages/DocumentsUI/res/values-ru/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Поделиться"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Копирование файлов"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Перемещение файлов"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Удаление файлов…"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Осталось <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Копируется <xliff:g id="COUNT_1">%1$d</xliff:g> файл...</item>
@@ -125,4 +126,11 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Формат некоторых файлов изменен"</string>
<string name="allow" msgid="7225948811296386551">"Разрешить"</string>
<string name="deny" msgid="2081879885755434506">"Отклонить"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Удаление файлов"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Удалить <xliff:g id="COUNT_1">%1$d</xliff:g> файл?</item>
+ <item quantity="few">Удалить <xliff:g id="COUNT_1">%1$d</xliff:g> файла?</item>
+ <item quantity="many">Удалить <xliff:g id="COUNT_1">%1$d</xliff:g> файлов?</item>
+ <item quantity="other">Удалить <xliff:g id="COUNT_1">%1$d</xliff:g> файла?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-si-rLK/config.xml b/packages/DocumentsUI/res/values-si-rLK/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-si-rLK/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-si-rLK/strings.xml b/packages/DocumentsUI/res/values-si-rLK/strings.xml
index fdfabe2..ae85f32 100644
--- a/packages/DocumentsUI/res/values-si-rLK/strings.xml
+++ b/packages/DocumentsUI/res/values-si-rLK/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"හරහා බෙදාගන්න"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"ගොනු පිටපත් කරමින්"</string>
<string name="move_notification_title" msgid="6193835179777284805">"ගොනු ගෙන යාම"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"ගොනු මකමින්"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> ඉතිරියි"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">ගොනු <xliff:g id="COUNT_1">%1$d</xliff:g> ක් පිටපත් කරමින්.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"සමහර ගොනු පරිවර්තනය කරන ලදී"</string>
<string name="allow" msgid="7225948811296386551">"අවසර දෙන්න"</string>
<string name="deny" msgid="2081879885755434506">"ප්රතික්ෂේප කරන්න"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"ගොනු මකන්නද?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">ඔබට ගොනු <xliff:g id="COUNT_1">%1$d</xliff:g>ක් මැකීමට අවශ්ය බව විශ්වාසද?</item>
+ <item quantity="other">ඔබට ගොනු <xliff:g id="COUNT_1">%1$d</xliff:g>ක් මැකීමට අවශ්ය බව විශ්වාසද?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-sk/config.xml b/packages/DocumentsUI/res/values-sk/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-sk/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-sk/strings.xml b/packages/DocumentsUI/res/values-sk/strings.xml
index 4d29021..7b3c213 100644
--- a/packages/DocumentsUI/res/values-sk/strings.xml
+++ b/packages/DocumentsUI/res/values-sk/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Zdieľať"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kopírovanie súborov"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Presúvajú sa súbory"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Odstraňujú sa súbory"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Zostáva: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="few">Kopírujú sa <xliff:g id="COUNT_1">%1$d</xliff:g> súbory.</item>
@@ -125,4 +126,11 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Niektoré súbory boli konvertované"</string>
<string name="allow" msgid="7225948811296386551">"Povoliť"</string>
<string name="deny" msgid="2081879885755434506">"Zamietnuť"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Odstrániť súbory?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="few">Naozaj chcete odstrániť <xliff:g id="COUNT_1">%1$d</xliff:g> súbory?</item>
+ <item quantity="many">Naozaj chcete odstrániť <xliff:g id="COUNT_1">%1$d</xliff:g> súboru?</item>
+ <item quantity="other">Naozaj chcete odstrániť <xliff:g id="COUNT_1">%1$d</xliff:g> súborov?</item>
+ <item quantity="one">Naozaj chcete odstrániť <xliff:g id="COUNT_0">%1$d</xliff:g> súbor?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-sl/config.xml b/packages/DocumentsUI/res/values-sl/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-sl/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-sl/strings.xml b/packages/DocumentsUI/res/values-sl/strings.xml
index dc17a08..afcdb6a 100644
--- a/packages/DocumentsUI/res/values-sl/strings.xml
+++ b/packages/DocumentsUI/res/values-sl/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Deli z drugimi prek"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kopiranje datotek"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Premikanje datotek"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Brisanje datotek"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Še <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Kopiranje <xliff:g id="COUNT_1">%1$d</xliff:g> datoteke.</item>
@@ -125,4 +126,11 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Nekatere datoteke so bile pretvorjene"</string>
<string name="allow" msgid="7225948811296386551">"Dovoli"</string>
<string name="deny" msgid="2081879885755434506">"Zavrni"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Ali želite izbrisati datoteke?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Ali res želite izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> datoteko?</item>
+ <item quantity="two">Ali res želite izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> datoteki?</item>
+ <item quantity="few">Ali res želite izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> datoteke?</item>
+ <item quantity="other">Ali res želite izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> datotek?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-sq-rAL/config.xml b/packages/DocumentsUI/res/values-sq-rAL/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-sq-rAL/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-sq-rAL/strings.xml b/packages/DocumentsUI/res/values-sq-rAL/strings.xml
index 5ae1f2a..7934b16 100644
--- a/packages/DocumentsUI/res/values-sq-rAL/strings.xml
+++ b/packages/DocumentsUI/res/values-sq-rAL/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Shpërnda publikisht përmes"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Po kopjon skedarët"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Po zhvendos skedarët"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Po fshin skedarët"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> të mbetura"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Po kopjon <xliff:g id="COUNT_1">%1$d</xliff:g> skedarë.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Disa skedarë u konvertuan"</string>
<string name="allow" msgid="7225948811296386551">"Lejo"</string>
<string name="deny" msgid="2081879885755434506">"Moho"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Të fshihen skedarët?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Je i sigurt se dëshiron të fshish <xliff:g id="COUNT_1">%1$d</xliff:g> skedarë?</item>
+ <item quantity="one">Je i sigurt se dëshiron të fshish <xliff:g id="COUNT_0">%1$d</xliff:g> skedar?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-sr/config.xml b/packages/DocumentsUI/res/values-sr/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-sr/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-sr/strings.xml b/packages/DocumentsUI/res/values-sr/strings.xml
index e207c2e..7575ff8 100644
--- a/packages/DocumentsUI/res/values-sr/strings.xml
+++ b/packages/DocumentsUI/res/values-sr/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Делите преко"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Копирање датотека"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Датотеке се премештају"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Датотеке се бришу"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Још <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Копирање <xliff:g id="COUNT_1">%1$d</xliff:g> датотеке.</item>
@@ -118,4 +119,10 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Неке датотеке су конвертоване"</string>
<string name="allow" msgid="7225948811296386551">"Дозволи"</string>
<string name="deny" msgid="2081879885755434506">"Одбиј"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Желите ли да избришете датотеке?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Желите ли стварно да избришете <xliff:g id="COUNT_1">%1$d</xliff:g> датотеку?</item>
+ <item quantity="few">Желите ли стварно да избришете <xliff:g id="COUNT_1">%1$d</xliff:g> датотеке?</item>
+ <item quantity="other">Желите ли стварно да избришете <xliff:g id="COUNT_1">%1$d</xliff:g> датотека?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-sv/config.xml b/packages/DocumentsUI/res/values-sv/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-sv/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-sv/strings.xml b/packages/DocumentsUI/res/values-sv/strings.xml
index dfc42a3..97e6ab0 100644
--- a/packages/DocumentsUI/res/values-sv/strings.xml
+++ b/packages/DocumentsUI/res/values-sv/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Dela via"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kopierar filer"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Filer flyttas"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Filerna tas bort"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> återstår"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Kopierar <xliff:g id="COUNT_1">%1$d</xliff:g> filer.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Vissa filer konverterades"</string>
<string name="allow" msgid="7225948811296386551">"Tillåt"</string>
<string name="deny" msgid="2081879885755434506">"Neka"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Vill du ta bort filerna?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Vill du ta bort <xliff:g id="COUNT_1">%1$d</xliff:g> filer?</item>
+ <item quantity="one">Vill du ta bort <xliff:g id="COUNT_0">%1$d</xliff:g> fil?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-sw/config.xml b/packages/DocumentsUI/res/values-sw/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-sw/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-sw/strings.xml b/packages/DocumentsUI/res/values-sw/strings.xml
index cbdb44c..c50920b 100644
--- a/packages/DocumentsUI/res/values-sw/strings.xml
+++ b/packages/DocumentsUI/res/values-sw/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Shiriki kupitia"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Inanakili faili"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Inahamisha faili"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Inafuta faili"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Zimesalia <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Inanakili faili <xliff:g id="COUNT_1">%1$d</xliff:g>.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Baadhi ya faili zimebadilishwa muundo"</string>
<string name="allow" msgid="7225948811296386551">"Ruhusu"</string>
<string name="deny" msgid="2081879885755434506">"Kataza"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Ungependa kufuta faili?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Una uhakika kuwa ungependa kufuta faili <xliff:g id="COUNT_1">%1$d</xliff:g>?</item>
+ <item quantity="one">Una uhakika kuwa ungependa kufuta faili <xliff:g id="COUNT_0">%1$d</xliff:g>?</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/packages/DocumentsUI/res/values-sw720dp-land/config.xml
similarity index 68%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to packages/DocumentsUI/res/values-sw720dp-land/config.xml
index 31c0162..8d9526d 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/packages/DocumentsUI/res/values-sw720dp-land/config.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,9 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/system_secondary_color" />
- <corners
- android:topLeftRadius="0dp"
- android:topRightRadius="0dp" />
-</shape>
+
+<resources>
+ <bool name="always_show_summary">true</bool>
+</resources>
diff --git a/packages/DocumentsUI/res/values-sw720dp-land/dimens.xml b/packages/DocumentsUI/res/values-sw720dp-land/dimens.xml
index c9dee8d..fa11244 100644
--- a/packages/DocumentsUI/res/values-sw720dp-land/dimens.xml
+++ b/packages/DocumentsUI/res/values-sw720dp-land/dimens.xml
@@ -15,8 +15,6 @@
-->
<resources>
- <bool name="always_show_summary">true</bool>
-
<dimen name="list_item_height">64dp</dimen>
<dimen name="list_item_padding">24dp</dimen>
diff --git a/packages/DocumentsUI/res/values-sw720dp/dimens.xml b/packages/DocumentsUI/res/values-sw720dp/dimens.xml
index 2488fa2..b5d1150 100644
--- a/packages/DocumentsUI/res/values-sw720dp/dimens.xml
+++ b/packages/DocumentsUI/res/values-sw720dp/dimens.xml
@@ -18,4 +18,6 @@
<dimen name="grid_padding_horiz">16dp</dimen>
<dimen name="grid_padding_vert">16dp</dimen>
+ <dimen name="list_item_padding">24dp</dimen>
+
</resources>
diff --git a/packages/DocumentsUI/res/values-ta-rIN/config.xml b/packages/DocumentsUI/res/values-ta-rIN/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ta-rIN/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ta-rIN/strings.xml b/packages/DocumentsUI/res/values-ta-rIN/strings.xml
index 3f85a17..08dc5ba 100644
--- a/packages/DocumentsUI/res/values-ta-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-ta-rIN/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"இதன் வழியாகப் பகிர்"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"கோப்புகளை நகலெடுத்தல்"</string>
<string name="move_notification_title" msgid="6193835179777284805">"கோப்புகளை நகர்த்துதல்"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"கோப்புகளை நீக்குகிறது"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> மீதமுள்ளது"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> கோப்புகளை நகலெடுக்கிறது.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"சில கோப்புகள் மாற்றப்பட்டன"</string>
<string name="allow" msgid="7225948811296386551">"அனுமதி"</string>
<string name="deny" msgid="2081879885755434506">"நிராகரி"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"கோப்புகளை நீக்கவா?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> கோப்புகளை நிச்சயமாக நீக்கவா?</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> கோப்பை நிச்சயமாக நீக்கவா?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-te-rIN/config.xml b/packages/DocumentsUI/res/values-te-rIN/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-te-rIN/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-te-rIN/strings.xml b/packages/DocumentsUI/res/values-te-rIN/strings.xml
index 07a7e6d..ad8c840 100644
--- a/packages/DocumentsUI/res/values-te-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-te-rIN/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"దీని ద్వారా భాగస్వామ్యం చేయండి"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"ఫైల్లు కాపీ అవుతున్నాయి"</string>
<string name="move_notification_title" msgid="6193835179777284805">"ఫైల్లను తరలిస్తోంది"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"ఫైల్లను తొలగిస్తోంది"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> మిగిలి ఉంది"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ఫైల్లను కాపీ చేస్తోంది.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"కొన్ని పైల్లు మార్చబడ్డాయి"</string>
<string name="allow" msgid="7225948811296386551">"అనుమతించండి"</string>
<string name="deny" msgid="2081879885755434506">"తిరస్కరించండి"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"ఫైల్లను తొలగించాలా?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">మీరు ఖచ్చితంగా <xliff:g id="COUNT_1">%1$d</xliff:g> ఫైల్లను తొలగించాలనుకుంటున్నారా?</item>
+ <item quantity="one">మీరు ఖచ్చితంగా <xliff:g id="COUNT_0">%1$d</xliff:g> ఫైల్ను తొలగించాలనుకుంటున్నారా?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-th/config.xml b/packages/DocumentsUI/res/values-th/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-th/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-th/strings.xml b/packages/DocumentsUI/res/values-th/strings.xml
index 8562ef65..8881fcd 100644
--- a/packages/DocumentsUI/res/values-th/strings.xml
+++ b/packages/DocumentsUI/res/values-th/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"แชร์ผ่าน"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"กำลังคัดลอกไฟล์"</string>
<string name="move_notification_title" msgid="6193835179777284805">"กำลังย้ายไฟล์"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"กำลังลบไฟล์"</string>
<string name="copy_remaining" msgid="6283790937387975095">"เหลือ <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">กำลังคัดลอก <xliff:g id="COUNT_1">%1$d</xliff:g> ไฟล์</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"แปลงบางไฟล์แล้ว"</string>
<string name="allow" msgid="7225948811296386551">"อนุญาต"</string>
<string name="deny" msgid="2081879885755434506">"ปฏิเสธ"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"ลบไฟล์เหล่านี้ไหม"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">คุณแน่ใจไหมว่าต้องการลบ <xliff:g id="COUNT_1">%1$d</xliff:g> ไฟล์</item>
+ <item quantity="one">คุณแน่ใจไหมว่าต้องการลบ <xliff:g id="COUNT_0">%1$d</xliff:g> ไฟล์</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-tl/config.xml b/packages/DocumentsUI/res/values-tl/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-tl/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-tl/strings.xml b/packages/DocumentsUI/res/values-tl/strings.xml
index de0c9bd..1639425 100644
--- a/packages/DocumentsUI/res/values-tl/strings.xml
+++ b/packages/DocumentsUI/res/values-tl/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Ibahagi sa pamamagitan ng"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kinokopya ang mga file"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Inililipat ang mga file"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Pagde-delete ng mga file"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> na lang ang natitira"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Kumokopya ng <xliff:g id="COUNT_1">%1$d</xliff:g> file.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Na-convert ang ilang file"</string>
<string name="allow" msgid="7225948811296386551">"Payagan"</string>
<string name="deny" msgid="2081879885755434506">"Tanggihan"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"I-delete ang mga file?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Sigurado ka bang gusto mong i-delete ang <xliff:g id="COUNT_1">%1$d</xliff:g> file?</item>
+ <item quantity="other">Sigurado ka bang gusto mong i-delete ang <xliff:g id="COUNT_1">%1$d</xliff:g> na file?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-tr/config.xml b/packages/DocumentsUI/res/values-tr/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-tr/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-tr/strings.xml b/packages/DocumentsUI/res/values-tr/strings.xml
index c9245c6..822a9ed 100644
--- a/packages/DocumentsUI/res/values-tr/strings.xml
+++ b/packages/DocumentsUI/res/values-tr/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Şunu kullanarak paylaş:"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Dosyalar kopyalanıyor"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Dosyalar taşınıyor"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Dosyalar siliniyor"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> kaldı"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> dosya kopyalanıyor.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Bazı dosyalar dönüştürüldü"</string>
<string name="allow" msgid="7225948811296386551">"İzin Ver"</string>
<string name="deny" msgid="2081879885755434506">"Reddet"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Dosyalar silinsin mi?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> dosyayı silmek istediğinizden emin misiniz?</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> dosyayı silmek istediğinizden emin misiniz?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-uk/config.xml b/packages/DocumentsUI/res/values-uk/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-uk/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-uk/strings.xml b/packages/DocumentsUI/res/values-uk/strings.xml
index 5f2b99c..1886ca3 100644
--- a/packages/DocumentsUI/res/values-uk/strings.xml
+++ b/packages/DocumentsUI/res/values-uk/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Надіслати через"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Копіювання файлів"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Переміщення файлів"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Видалення файлів"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Залишилося <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Копіювання <xliff:g id="COUNT_1">%1$d</xliff:g> файлу.</item>
@@ -125,4 +126,11 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Деякі файли конвертовано"</string>
<string name="allow" msgid="7225948811296386551">"Дозвол."</string>
<string name="deny" msgid="2081879885755434506">"Забор."</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Видалити файли?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Видалити <xliff:g id="COUNT_1">%1$d</xliff:g> файл?</item>
+ <item quantity="few">Видалити <xliff:g id="COUNT_1">%1$d</xliff:g> файли?</item>
+ <item quantity="many">Видалити <xliff:g id="COUNT_1">%1$d</xliff:g> файлів?</item>
+ <item quantity="other">Видалити <xliff:g id="COUNT_1">%1$d</xliff:g> файлу?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-ur-rPK/config.xml b/packages/DocumentsUI/res/values-ur-rPK/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-ur-rPK/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-ur-rPK/strings.xml b/packages/DocumentsUI/res/values-ur-rPK/strings.xml
index 40831eb..82d20e3 100644
--- a/packages/DocumentsUI/res/values-ur-rPK/strings.xml
+++ b/packages/DocumentsUI/res/values-ur-rPK/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"اشتراک کریں بذریعہ"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"فائلیں کاپی ہو رہی ہیں"</string>
<string name="move_notification_title" msgid="6193835179777284805">"فائلیں منتقل ہو رہی ہیں"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"فائلیں حذف کی جا رہی ہیں"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> باقی ہے"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> فائلیں کاپی کی جا رہی ہیں۔</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"کچھ فائلوں کو تبدیل کیا گیا تھا"</string>
<string name="allow" msgid="7225948811296386551">"اجازت دیں"</string>
<string name="deny" msgid="2081879885755434506">"مسترد کریں"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"فائلوں کو حذف کریں؟"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">کیا آپ واقعی <xliff:g id="COUNT_1">%1$d</xliff:g> فائلیں حذف کرنا چاہتے ہیں؟</item>
+ <item quantity="one">کیا آپ واقعی <xliff:g id="COUNT_0">%1$d</xliff:g> فائل حذف کرنا چاہتے ہیں؟</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-uz-rUZ/config.xml b/packages/DocumentsUI/res/values-uz-rUZ/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-uz-rUZ/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
index 48fa9a6..ce43fc2 100644
--- a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
+++ b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Quyidagi orqali ulashish"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Fayllar nusxalanmoqda"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Ko‘chirib o‘tkazilmoqda"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Fayllar o‘chirilmoqda"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> qoldi"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"> <xliff:g id="COUNT_1">%1$d</xliff:g> ta fayl nusxalanmoqda</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Bir nechta fayllar o‘girildi"</string>
<string name="allow" msgid="7225948811296386551">"Ruxsat berish"</string>
<string name="deny" msgid="2081879885755434506">"Rad qilish"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Fayllar o‘chirib tashlansinmi?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ta fayl o‘chirib tashlansinmi?</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ta fayl o‘chirib tashlansinmi?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-vi/config.xml b/packages/DocumentsUI/res/values-vi/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-vi/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-vi/strings.xml b/packages/DocumentsUI/res/values-vi/strings.xml
index 66a5b73..0abb389 100644
--- a/packages/DocumentsUI/res/values-vi/strings.xml
+++ b/packages/DocumentsUI/res/values-vi/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Chia sẻ qua"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Đang sao chép tệp"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Đang di chuyển tệp"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Đang xóa tệp"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Còn <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Đang sao chép <xliff:g id="COUNT_1">%1$d</xliff:g> tệp.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Đã chuyển đổi một số tệp"</string>
<string name="allow" msgid="7225948811296386551">"Cho phép"</string>
<string name="deny" msgid="2081879885755434506">"Từ chối"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Xóa tệp?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Bạn có chắc chắn muốn xóa <xliff:g id="COUNT_1">%1$d</xliff:g> tệp không?</item>
+ <item quantity="one">Bạn có chắc chắn muốn xóa <xliff:g id="COUNT_0">%1$d</xliff:g> tệp không?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-zh-rCN/config.xml b/packages/DocumentsUI/res/values-zh-rCN/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-zh-rCN/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-zh-rCN/strings.xml b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
index bb48b0c..6e87c81 100644
--- a/packages/DocumentsUI/res/values-zh-rCN/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"分享方式"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"正在复制文件"</string>
<string name="move_notification_title" msgid="6193835179777284805">"正在移动文件"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"正在删除文件"</string>
<string name="copy_remaining" msgid="6283790937387975095">"剩余时间:<xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">正在复制 <xliff:g id="COUNT_1">%1$d</xliff:g> 个文件。</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"部分文件已转换成其他格式"</string>
<string name="allow" msgid="7225948811296386551">"允许"</string>
<string name="deny" msgid="2081879885755434506">"拒绝"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"要删除文件吗?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">您确定要删除 <xliff:g id="COUNT_1">%1$d</xliff:g> 个文件吗?</item>
+ <item quantity="one">您确定要删除 <xliff:g id="COUNT_0">%1$d</xliff:g> 个文件吗?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-zh-rHK/config.xml b/packages/DocumentsUI/res/values-zh-rHK/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-zh-rHK/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-zh-rHK/strings.xml b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
index f8d46d5..345bba4 100644
--- a/packages/DocumentsUI/res/values-zh-rHK/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"分享方式:"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"正在複製檔案"</string>
<string name="move_notification_title" msgid="6193835179777284805">"正在移動檔案"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"正在刪除檔案"</string>
<string name="copy_remaining" msgid="6283790937387975095">"剩餘 <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">正在複製 <xliff:g id="COUNT_1">%1$d</xliff:g> 個檔案。</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"部分檔案已轉換成其他格式"</string>
<string name="allow" msgid="7225948811296386551">"允許"</string>
<string name="deny" msgid="2081879885755434506">"拒絕"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"要刪除檔案嗎?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">您確定要刪除 <xliff:g id="COUNT_1">%1$d</xliff:g> 個檔案嗎?</item>
+ <item quantity="one">您確定要刪除 <xliff:g id="COUNT_0">%1$d</xliff:g> 個檔案嗎?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-zh-rTW/config.xml b/packages/DocumentsUI/res/values-zh-rTW/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-zh-rTW/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-zh-rTW/strings.xml b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
index ad77ad4..c799fb3 100644
--- a/packages/DocumentsUI/res/values-zh-rTW/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"分享方式:"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"複製檔案"</string>
<string name="move_notification_title" msgid="6193835179777284805">"正在移動檔案"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"正在刪除檔案"</string>
<string name="copy_remaining" msgid="6283790937387975095">"剩餘 <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">正在複製 <xliff:g id="COUNT_1">%1$d</xliff:g> 個檔案。</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"部分檔案已轉換成其他格式"</string>
<string name="allow" msgid="7225948811296386551">"允許"</string>
<string name="deny" msgid="2081879885755434506">"拒絕"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"要刪除檔案嗎?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">確定要刪除 <xliff:g id="COUNT_1">%1$d</xliff:g> 個檔案嗎?</item>
+ <item quantity="one">確定要刪除 <xliff:g id="COUNT_0">%1$d</xliff:g> 個檔案嗎?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-zu/config.xml b/packages/DocumentsUI/res/values-zu/config.xml
deleted file mode 100644
index 843a8aa..0000000
--- a/packages/DocumentsUI/res/values-zu/config.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
-</resources>
diff --git a/packages/DocumentsUI/res/values-zu/strings.xml b/packages/DocumentsUI/res/values-zu/strings.xml
index c49500c..eda4f7b 100644
--- a/packages/DocumentsUI/res/values-zu/strings.xml
+++ b/packages/DocumentsUI/res/values-zu/strings.xml
@@ -67,6 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Yabelana nge-"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Ikopisha amafayela"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Ihambisa amafayela"</string>
+ <string name="delete_notification_title" msgid="3329403967712437496">"Ukususa amafayela"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> okusele"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Ikopisha amafayela angu-<xliff:g id="COUNT_1">%1$d</xliff:g>.</item>
@@ -111,4 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Amanye amafayela aguqulelwe"</string>
<string name="allow" msgid="7225948811296386551">"Vumela"</string>
<string name="deny" msgid="2081879885755434506">"Yala"</string>
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Susa amafayela?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Ingabe uqinisekile ukuthi ufuna ukususa amafayela angu-<xliff:g id="COUNT_1">%1$d</xliff:g>?</item>
+ <item quantity="other">Ingabe uqinisekile ukuthi ufuna ukususa amafayela angu-<xliff:g id="COUNT_1">%1$d</xliff:g>?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values/colors.xml b/packages/DocumentsUI/res/values/colors.xml
index c868d34..3785adf 100644
--- a/packages/DocumentsUI/res/values/colors.xml
+++ b/packages/DocumentsUI/res/values/colors.xml
@@ -21,18 +21,18 @@
else that needs to manually declare a background matching the "default"
app background (e.g. the drawer overlay). -->
<color name="window_background">#fff1f1f1</color>
+ <color name="drawer_background">#fff1f1f1</color>
+ <color name="directory_background">#fff7f7f7</color>
+ <color name="item_doc_background">#fffafafa</color>
+ <color name="item_doc_background_selected">#ffe0f2f1</color>
+ <color name="menu_search_background">#ff676f74</color>
<color name="primary_dark">@*android:color/primary_dark_material_dark</color>
<color name="primary">@*android:color/material_blue_grey_900</color>
<color name="accent">@*android:color/accent_material_light</color>
+ <color name="accent_dark">@*android:color/accent_material_dark</color>
<color name="action_mode">@color/material_grey_400</color>
<color name="band_select_background">#88ffffff</color>
<color name="band_select_border">#44000000</color>
-
- <color name="item_doc_background">#fffafafa</color>
- <color name="item_doc_background_selected">#ffe0f2f1</color>
-
- <color name="menu_search_background">#ff676f74</color>
-
</resources>
diff --git a/packages/DocumentsUI/res/values/config.xml b/packages/DocumentsUI/res/values/config.xml
index e8d8c8e..8a76540 100644
--- a/packages/DocumentsUI/res/values/config.xml
+++ b/packages/DocumentsUI/res/values/config.xml
@@ -19,5 +19,7 @@
<bool name="config_defaultAdvancedDevices">false</bool>
<!-- Intentionally unset. Vendors should set this in an overlay. -->
- <string name="trusted_quick_viewer_package"></string>
+ <string name="trusted_quick_viewer_package" translatable="false"></string>
+ <bool name="list_divider_inset_left">true</bool>
+ <bool name="always_show_summary">false</bool>
</resources>
diff --git a/packages/DocumentsUI/res/values/dimens.xml b/packages/DocumentsUI/res/values/dimens.xml
index 5adb165..9fc8a73 100644
--- a/packages/DocumentsUI/res/values/dimens.xml
+++ b/packages/DocumentsUI/res/values/dimens.xml
@@ -17,37 +17,24 @@
<resources>
<dimen name="grid_container_padding">10dp</dimen>
<dimen name="list_container_padding">0dp</dimen>
-
<dimen name="icon_size">40dp</dimen>
<dimen name="root_icon_size">24dp</dimen>
<dimen name="root_icon_margin">0dp</dimen>
<dimen name="check_icon_size">30dp</dimen>
-
<dimen name="list_item_thumbnail_size">40dp</dimen>
<dimen name="grid_item_icon_size">30dp</dimen>
-
<dimen name="progress_bar_height">4dp</dimen>
-
<dimen name="grid_width">152dp</dimen>
<dimen name="grid_height">176dp</dimen>
-
<dimen name="grid_item_width">152dp</dimen>
<dimen name="grid_item_height">176dp</dimen>
<dimen name="grid_item_margin">4dp</dimen>
-
<dimen name="grid_padding_horiz">4dp</dimen>
<dimen name="grid_padding_vert">4dp</dimen>
-
<dimen name="list_item_height">72dp</dimen>
<dimen name="list_item_padding">16dp</dimen>
-
<dimen name="list_divider_inset">72dp</dimen>
- <bool name="list_divider_inset_left">true</bool>
-
- <bool name="always_show_summary">false</bool>
-
<dimen name="dir_elevation">8dp</dimen>
-
<dimen name="drag_shadow_size">120dp</dimen>
-
+ <dimen name="grid_item_elevation">2dp</dimen>
</resources>
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index b97918e..6e1b30e 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -134,6 +134,8 @@
<string name="copy_notification_title">Copying files</string>
<!-- Title of the move notification [CHAR LIMIT=24] -->
<string name="move_notification_title">Moving files</string>
+ <!-- Title of the move notification [CHAR LIMIT=24] -->
+ <string name="delete_notification_title">Deleting files</string>
<!-- Text shown on the copy notification to indicate remaining time, in minutes [CHAR LIMIT=24] -->
<string name="copy_remaining"><xliff:g id="duration" example="3 minutes">%s</xliff:g> left</string>
<!-- Toast shown when a file copy is kicked off -->
@@ -206,4 +208,9 @@
<string name="allow">Allow</string>
<!-- Text in the button asking user to deny access to a given directory. -->
<string name="deny">Deny</string>
+ <!-- Dialog text shown to users when asking if they want to delete files (a confirmation). -->
+ <plurals name="delete_confirmation_message">
+ <item quantity="one">Delete <xliff:g id="count" example="1">%1$d</xliff:g> file?</item>
+ <item quantity="other">Delete <xliff:g id="count" example="3">%1$d</xliff:g> files?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml
index f4dfd73..21bdfd9 100644
--- a/packages/DocumentsUI/res/values/styles.xml
+++ b/packages/DocumentsUI/res/values/styles.xml
@@ -29,6 +29,7 @@
<item name="android:colorPrimary">@color/primary</item>
<item name="android:colorAccent">@color/accent</item>
<item name="colorActionMode">@color/action_mode</item>
+ <item name="android:queryBackground">@color/menu_search_background</item>
<item name="android:listDivider">@*android:drawable/list_divider_material</item>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 648c79e..6efe9d1 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -22,16 +22,15 @@
import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_LEAVE;
import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_NONE;
import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_SIDE;
-import static com.android.internal.util.Preconditions.checkArgument;
import android.app.Activity;
import android.app.Fragment;
+import android.app.FragmentManager;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
-import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
@@ -40,20 +39,20 @@
import android.support.annotation.CallSuper;
import android.support.annotation.LayoutRes;
import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Spinner;
-import com.android.documentsui.SearchManager.SearchManagerListener;
+import com.android.documentsui.SearchViewManager.SearchManagerListener;
import com.android.documentsui.State.ViewMode;
import com.android.documentsui.dirlist.DirectoryFragment;
import com.android.documentsui.dirlist.Model;
import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.DocumentStack;
import com.android.documentsui.model.RootInfo;
-import com.android.internal.util.Preconditions;
import java.io.FileNotFoundException;
import java.util.ArrayList;
@@ -64,26 +63,18 @@
public abstract class BaseActivity extends Activity
implements SearchManagerListener, NavigationView.Environment {
- static final String EXTRA_STATE = "state";
-
- // See comments where this const is referenced for details.
- private static final int DRAWER_NO_FIDDLE_DELAY = 1500;
-
State mState;
RootsCache mRoots;
- SearchManager mSearchManager;
+ SearchViewManager mSearchManager;
DrawerController mDrawer;
NavigationView mNavigator;
+ List<EventListener> mEventListeners = new ArrayList<>();
private final String mTag;
@LayoutRes
private int mLayoutId;
- // Track the time we opened the drawer in response to back being pressed.
- // We use the time gap to figure out whether to close app or reopen the drawer.
- private long mDrawerLastFiddled;
-
private boolean mNavDrawerHasFocus;
public abstract void onDocumentPicked(DocumentInfo doc, Model model);
@@ -121,7 +112,7 @@
}
});
- mSearchManager = new SearchManager(this);
+ mSearchManager = new SearchViewManager(this, icicle);
DocumentsToolbar toolbar = (DocumentsToolbar) findViewById(R.id.toolbar);
setActionBar(toolbar);
@@ -141,6 +132,7 @@
boolean showMenu = super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.activity, menu);
+ mNavigator.update();
mSearchManager.install((DocumentsToolbar) findViewById(R.id.toolbar));
return showMenu;
@@ -159,7 +151,6 @@
final MenuItem sortSize = menu.findItem(R.id.menu_sort_size);
final MenuItem grid = menu.findItem(R.id.menu_grid);
final MenuItem list = menu.findItem(R.id.menu_list);
- final MenuItem advanced = menu.findItem(R.id.menu_advanced);
final MenuItem fileSize = menu.findItem(R.id.menu_file_size);
// Search uses backend ranking; no sorting, recents doesn't support sort.
@@ -171,9 +162,6 @@
grid.setVisible(mState.derivedMode != State.MODE_GRID);
list.setVisible(mState.derivedMode != State.MODE_LIST);
- advanced.setVisible(!mState.forceAdvanced);
- advanced.setTitle(LocalPreferences.getDisplayAdvancedDevices(this)
- ? R.string.menu_advanced_hide : R.string.menu_advanced_show);
fileSize.setTitle(LocalPreferences.getDisplayFileSize(this)
? R.string.menu_file_size_hide : R.string.menu_file_size_show);
@@ -188,7 +176,7 @@
private State getState(@Nullable Bundle icicle) {
if (icicle != null) {
- State state = icicle.<State>getParcelable(EXTRA_STATE);
+ State state = icicle.<State>getParcelable(Shared.EXTRA_STATE);
if (DEBUG) Log.d(mTag, "Recovered existing state object: " + state);
return state;
}
@@ -209,10 +197,6 @@
state.forceSize = intent.getBooleanExtra(DocumentsContract.EXTRA_SHOW_FILESIZE, false);
state.showSize = state.forceSize || LocalPreferences.getDisplayFileSize(this);
- state.forceAdvanced = intent.getBooleanExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, false);
- state.showAdvanced = state.forceAdvanced
- || LocalPreferences.getDisplayAdvancedDevices(this);
-
state.initAcceptMimes(intent);
state.excludedAuthorities = getExcludedAuthorities();
@@ -224,6 +208,9 @@
}
void onRootPicked(RootInfo root) {
+ // Clicking on the current root removes search
+ mSearchManager.cancelSearch();
+
// Skip refreshing if root nor directory didn't change
if (root.equals(getCurrentRoot()) && mState.stack.size() == 1) {
return;
@@ -233,7 +220,6 @@
// Clear entire backstack and start in new root
mState.onRootChanged(root);
- mSearchManager.update(root);
// Recents is always in memory, so we just load it directly.
// Otherwise we delegate loading data from disk to a task
@@ -284,10 +270,6 @@
if (dir != null) {
dir.pasteFromClipboard();
}
- return true;
-
- case R.id.menu_advanced:
- setDisplayAdvancedDevices(!LocalPreferences.getDisplayAdvancedDevices(this));
return true;
case R.id.menu_file_size:
@@ -314,6 +296,12 @@
CreateDirectoryFragment.show(getFragmentManager());
}
+ void onDirectoryCreated(DocumentInfo doc) {
+ // By default we do nothing, just let the new directory appear.
+ // DocumentsActivity auto-opens directories after creating them
+ // As that is more attuned to the "picker" use cases it supports.
+ }
+
/**
* Returns true if a directory can be created in the current location.
* @return
@@ -328,13 +316,11 @@
&& !root.isDownloads();
}
- void onDirectoryCreated(DocumentInfo doc) {
- checkArgument(doc.isDirectory());
- openContainerDocument(doc);
- }
-
void openContainerDocument(DocumentInfo doc) {
- checkArgument(doc.isContainer());
+ assert(doc.isContainer());
+
+ notifyDirectoryNavigated(doc.derivedUri);
+
mState.pushDocument(doc);
// Show an opening animation only if pressing "back" would get us back to the
// previous directory. Especially after opening a root document, pressing
@@ -364,24 +350,30 @@
invalidateOptionsMenu();
}
+ final void loadRoot(final Uri uri) {
+ new LoadRootTask(this, uri).executeOnExecutor(
+ ProviderExecutor.forAuthority(uri.getAuthority()));
+ }
+
/**
* Called when search results changed.
* Refreshes the content of the directory. It doesn't refresh elements on the action bar.
* e.g. The current directory name displayed on the action bar won't get updated.
*/
@Override
- public void onSearchChanged() {
- refreshDirectory(ANIM_NONE);
+ public void onSearchChanged(@Nullable String query) {
+ // We should not get here if root is not searchable
+ assert(canSearchRoot());
+
+ reloadSearch(query);
}
- /**
- * Called when search query changed.
- * Updates the state object.
- * @param query - New query
- */
- @Override
- public void onSearchQueryChanged(String query) {
- mState.currentSearch = query;
+ private void reloadSearch(String query) {
+ FragmentManager fm = getFragmentManager();
+ RootInfo root = getCurrentRoot();
+ DocumentInfo cwd = getCurrentDirectory();
+
+ DirectoryFragment.reloadSearch(fm, root, cwd, query);
}
final List<String> getExcludedAuthorities() {
@@ -431,13 +423,6 @@
return mState;
}
- void setDisplayAdvancedDevices(boolean display) {
- LocalPreferences.setDisplayAdvancedDevices(this, display);
- mState.showAdvanced = mState.forceAdvanced | display;
- RootsFragment.get(getFragmentManager()).onDisplayStateChanged();
- invalidateOptionsMenu();
- }
-
void setDisplayFileSize(boolean display) {
LocalPreferences.setDisplayFileSize(this, display);
mState.showSize = display;
@@ -456,7 +441,7 @@
DirectoryFragment dir = getDirectoryFragment();
if (dir != null) {
dir.onSortOrderChanged();
- };
+ }
}
/**
@@ -473,7 +458,7 @@
DirectoryFragment dir = getDirectoryFragment();
if (dir != null) {
dir.onViewModeChanged();
- };
+ }
}
public void setPending(boolean pending) {
@@ -486,7 +471,8 @@
@Override
protected void onSaveInstanceState(Bundle state) {
super.onSaveInstanceState(state);
- state.putParcelable(EXTRA_STATE, mState);
+ state.putParcelable(Shared.EXTRA_STATE, mState);
+ mSearchManager.onSaveInstanceState(state);
}
@Override
@@ -538,38 +524,18 @@
return;
}
- int size = mState.stack.size();
-
- // Do some "do what a I want" drawer fiddling, but don't
- // do it if user already hit back recently and we recently
- // did some fiddling.
- if (mDrawer.isPresent()
- && (System.currentTimeMillis() - mDrawerLastFiddled) > DRAWER_NO_FIDDLE_DELAY) {
- // Close drawer if it is open.
- if (mDrawer.isOpen()) {
- mDrawer.setOpen(false);
- mDrawerLastFiddled = System.currentTimeMillis();
- return;
- }
-
- // Open the Close drawer if it is closed and we're at the top of a root.
- if (size == 1) {
- mDrawer.setOpen(true);
- // Remember so we don't just close it again if back is pressed again.
- mDrawerLastFiddled = System.currentTimeMillis();
- return;
- }
- }
-
- if (size > 1) {
- mState.stack.pop();
- refreshCurrentRootAndDirectory(ANIM_LEAVE);
+ if (onBeforePopDir() || popDir()) {
return;
}
super.onBackPressed();
}
+ boolean onBeforePopDir() {
+ // Files app overrides this with some fancy logic.
+ return false;
+ }
+
public void onStackPicked(DocumentStack stack) {
try {
// Update the restored stack to ensure we have freshest data
@@ -603,12 +569,38 @@
return true;
}
} else if (keyCode == KeyEvent.KEYCODE_TAB) {
+ // Tab toggles focus on the navigation drawer.
toggleNavDrawerFocus();
return true;
+ } else if (keyCode == KeyEvent.KEYCODE_DEL) {
+ popDir();
+ return true;
}
return super.onKeyDown(keyCode, event);
}
+ @VisibleForTesting
+ public void addEventListener(EventListener listener) {
+ mEventListeners.add(listener);
+ }
+
+ @VisibleForTesting
+ public void removeEventListener(EventListener listener) {
+ mEventListeners.remove(listener);
+ }
+
+ public void notifyDirectoryLoaded(Uri uri) {
+ for (EventListener listener : mEventListeners) {
+ listener.onDirectoryLoaded(uri);
+ }
+ }
+
+ void notifyDirectoryNavigated(Uri uri) {
+ for (EventListener listener : mEventListeners) {
+ listener.onDirectoryNavigated(uri);
+ }
+ }
+
/**
* Toggles focus between the navigation drawer and the directory listing. If the drawer isn't
* locked, open/close it as appropriate.
@@ -641,6 +633,21 @@
}
}
+ /**
+ * Pops the top entry off the directory stack, and returns the user to the previous directory.
+ * If the directory stack only contains one item, this method does nothing.
+ *
+ * @return Whether the stack was popped.
+ */
+ private boolean popDir() {
+ if (mState.stack.size() > 1) {
+ mState.stack.pop();
+ refreshCurrentRootAndDirectory(ANIM_LEAVE);
+ return true;
+ }
+ return false;
+ }
+
private static final class PickRootTask extends PairedTask<BaseActivity, Void, DocumentInfo> {
private RootInfo mRoot;
@@ -672,7 +679,8 @@
@Override
protected RootInfo run(RootInfo... roots) {
- checkArgument(roots.length == 1);
+ assert(roots.length == 1);
+
final RootInfo currentRoot = roots[0];
final Collection<RootInfo> cachedRoots = mOwner.mRoots.getRootsBlocking();
RootInfo homeRoot = null;
@@ -685,7 +693,7 @@
return null;
}
}
- Preconditions.checkNotNull(homeRoot);
+ assert(homeRoot != null);
mHome = mOwner.getRootDocumentBlocking(homeRoot);
return homeRoot;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
index 40bd754..ebc9082 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
@@ -82,6 +82,9 @@
builder.setNegativeButton(android.R.string.cancel, null);
final AlertDialog dialog = builder.create();
+ // Workaround for the problem - virtual keyboard doesn't show on the phone.
+ Shared.ensureKeyboardPresent(context, dialog);
+
editText.setOnEditorActionListener(
new OnEditorActionListener() {
@Override
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
index b0542b9..d2e918c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
@@ -53,19 +53,21 @@
private final RootInfo mRoot;
private final Uri mUri;
private final int mUserSortOrder;
+ private final boolean mSearchMode;
private DocumentInfo mDoc;
private CancellationSignal mSignal;
private DirectoryResult mResult;
public DirectoryLoader(Context context, int type, RootInfo root, DocumentInfo doc, Uri uri,
- int userSortOrder) {
+ int userSortOrder, boolean inSearchMode) {
super(context, ProviderExecutor.forAuthority(root.authority));
mType = type;
mRoot = root;
mUri = uri;
mUserSortOrder = userSortOrder;
mDoc = doc;
+ mSearchMode = inSearchMode;
}
@Override
@@ -81,9 +83,10 @@
final String authority = mUri.getAuthority();
final DirectoryResult result = new DirectoryResult();
+ result.doc = mDoc;
// Use default document when searching
- if (mType == DirectoryFragment.TYPE_SEARCH) {
+ if (mSearchMode) {
final Uri docUri = DocumentsContract.buildDocumentUri(
mRoot.authority, mRoot.documentId);
try {
@@ -106,7 +109,7 @@
}
// Search always uses ranking from provider
- if (mType == DirectoryFragment.TYPE_SEARCH) {
+ if (mSearchMode) {
result.sortOrder = State.SORT_ORDER_UNKNOWN;
}
@@ -127,7 +130,7 @@
cursor = new RootCursorWrapper(mUri.getAuthority(), mRoot.rootId, cursor, -1);
- if (mType == DirectoryFragment.TYPE_SEARCH) {
+ if (mSearchMode) {
// Filter directories out of search results, for now
cursor = new FilteringCursorWrapper(cursor, null, SEARCH_REJECT_MIMES);
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryResult.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryResult.java
index 22e438a..6268643 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryResult.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryResult.java
@@ -22,12 +22,15 @@
import android.content.ContentProviderClient;
import android.database.Cursor;
+import com.android.documentsui.model.DocumentInfo;
+
import libcore.io.IoUtils;
public class DirectoryResult implements AutoCloseable {
ContentProviderClient client;
public Cursor cursor;
public Exception exception;
+ public DocumentInfo doc;
public int sortOrder = SORT_ORDER_UNKNOWN;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentClipper.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentClipper.java
index b3c2846..15bfc3b 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentClipper.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentClipper.java
@@ -28,7 +28,6 @@
import android.util.Log;
import com.android.documentsui.model.DocumentInfo;
-import com.android.internal.util.Preconditions;
import libcore.io.IoUtils;
@@ -85,7 +84,7 @@
* This should be run from inside an AsyncTask.
*/
public List<DocumentInfo> getDocumentsFromClipData(ClipData clipData) {
- Preconditions.checkNotNull(clipData);
+ assert(clipData != null);
final List<DocumentInfo> srcDocs = new ArrayList<>();
int count = clipData.getItemCount();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index ec7dde9..12a4186 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -94,13 +94,27 @@
RootsFragment.show(getFragmentManager(), null);
}
- if (!mState.restored) {
- // In this case, we set the activity title in AsyncTask.onPostExecute(). To prevent
- // talkback from reading aloud the default title, we clear it here.
- setTitle("");
- new RestoreStackTask(this).execute();
- } else {
+ if (mState.restored) {
refreshCurrentRootAndDirectory(ANIM_NONE);
+ } else {
+ // We set the activity title in AsyncTask.onPostExecute().
+ // To prevent talkback from reading aloud the default title, we clear it here.
+ setTitle("");
+
+ // As a matter of policy we don't load the last used stack for the copy
+ // destination picker (user is already in Files app).
+ // Concensus was that the experice was too confusing.
+ // In all other cases, where the user is visiting us from another app
+ // we restore the stack as last used from that app.
+ if (mState.action == ACTION_PICK_COPY_DESTINATION) {
+ if (DEBUG) Log.d(TAG, "Launching directly into Home directory.");
+ Uri homeUri = DocumentsContract.buildHomeUri();
+ new LoadRootTask(this, homeUri).executeOnExecutor(
+ ProviderExecutor.forAuthority(homeUri.getAuthority()));
+ } else {
+ if (DEBUG) Log.d(TAG, "Attempting to load last used stack for calling package.");
+ new LoadLastUsedStackTask(this).execute();
+ }
}
}
@@ -290,13 +304,8 @@
mState.derivedMode = visualMimes ? State.MODE_GRID : State.MODE_LIST;
}
} else {
- if (mSearchManager.isSearching()) {
- // Ongoing search
- DirectoryFragment.showSearch(fm, root, mState.currentSearch, anim);
- } else {
// Normal boring directory
DirectoryFragment.showDirectory(fm, root, cwd, anim);
- }
}
// Forget any replacement target
@@ -321,6 +330,12 @@
.executeOnExecutor(getExecutorForCurrentDirectory());
}
+ @Override
+ void onDirectoryCreated(DocumentInfo doc) {
+ assert(doc.isDirectory());
+ openContainerDocument(doc);
+ }
+
void onSaveRequested(String mimeType, String displayName) {
new CreateFinishTask(this, mimeType, displayName)
.executeOnExecutor(getExecutorForCurrentDirectory());
@@ -441,16 +456,19 @@
}
/**
- * Restores the stack from Recents for the specified package.
+ * Loads the last used path (stack) from Recents (history).
+ * The path selected is based on the calling package name. So the last
+ * path for an app like Gmail can be different than the last path
+ * for an app like DropBox.
*/
- private static final class RestoreStackTask
+ private static final class LoadLastUsedStackTask
extends PairedTask<DocumentsActivity, Void, Void> {
private volatile boolean mRestoredStack;
private volatile boolean mExternal;
private State mState;
- public RestoreStackTask(DocumentsActivity activity) {
+ public LoadLastUsedStackTask(DocumentsActivity activity) {
super(activity);
mState = activity.mState;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java
index f7a45e2..2f784cb 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java
@@ -39,7 +39,6 @@
import com.android.documentsui.dirlist.Model;
import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.RootInfo;
-import com.android.internal.util.Preconditions;
import java.util.Arrays;
import java.util.List;
@@ -69,7 +68,7 @@
// talkback from reading aloud the default title, we clear it here.
setTitle("");
final Uri rootUri = getIntent().getData();
- new RestoreRootTask(this, rootUri).executeOnExecutor(getExecutorForCurrentDirectory());
+ new LoadRootTask(this, rootUri).executeOnExecutor(getExecutorForCurrentDirectory());
} else {
refreshCurrentRootAndDirectory(ANIM_NONE);
}
@@ -99,12 +98,10 @@
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
- final MenuItem advanced = menu.findItem(R.id.menu_advanced);
final MenuItem createDir = menu.findItem(R.id.menu_create_dir);
final MenuItem pasteFromCb = menu.findItem(R.id.menu_paste_from_clipboard);
final MenuItem fileSize = menu.findItem(R.id.menu_file_size);
- advanced.setVisible(false);
createDir.setVisible(false);
pasteFromCb.setEnabled(false);
fileSize.setVisible(false);
@@ -119,22 +116,20 @@
final RootInfo root = getCurrentRoot();
final DocumentInfo cwd = getCurrentDirectory();
+ assert(!mSearchManager.isSearching());
+
// If started in manage roots mode, there has to be a cwd (i.e. the root dir of the managed
// root).
- Preconditions.checkNotNull(cwd);
+ assert(cwd != null);
- if (mState.currentSearch != null) {
- // Ongoing search
- DirectoryFragment.showSearch(fm, root, mState.currentSearch, anim);
- } else {
- // Normal boring directory
- DirectoryFragment.showDirectory(fm, root, cwd, anim);
- }
+ // Normal boring directory
+ DirectoryFragment.showDirectory(fm, root, cwd, anim);
}
@Override
public void onDocumentPicked(DocumentInfo doc, Model model) {
- Preconditions.checkArgument(!doc.isDirectory());
+ assert(!doc.isDirectory());
+
// First try managing the document; we expect manager to filter
// based on authority, so we don't grant.
final Intent manage = new Intent(DocumentsContract.ACTION_MANAGE_DOCUMENT);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java b/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
index bcf69c4..9fceff5 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
@@ -16,8 +16,6 @@
package com.android.documentsui;
-import static com.android.internal.util.Preconditions.checkArgument;
-
import android.app.Activity;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.widget.DrawerLayout;
@@ -83,7 +81,7 @@
DrawerLayout layout, View drawer, ActionBarDrawerToggle toggle,
Toolbar drawerToolbar) {
mToolbar = drawerToolbar;
- checkArgument(layout != null);
+ assert(layout != null);
mLayout = layout;
mDrawer = drawer;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/EventListener.java b/packages/DocumentsUI/src/com/android/documentsui/EventListener.java
new file mode 100644
index 0000000..c15e9a6
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/EventListener.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import android.net.Uri;
+import android.support.annotation.Nullable;
+
+public interface EventListener {
+ /**
+ * @param uri Uri navigated to. If recents, then null.
+ */
+ void onDirectoryNavigated(@Nullable Uri uri);
+
+ /**
+ * @param uri Uri of the loaded directory. If recents, then null.
+ */
+ void onDirectoryLoaded(@Nullable Uri uri);
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index c0faba3..c17be06 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -19,8 +19,6 @@
import static com.android.documentsui.OperationDialogFragment.DIALOG_TYPE_UNKNOWN;
import static com.android.documentsui.Shared.DEBUG;
import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_NONE;
-import static com.android.internal.util.Preconditions.checkArgument;
-import static com.android.internal.util.Preconditions.checkState;
import android.app.Activity;
import android.app.FragmentManager;
@@ -33,7 +31,6 @@
import android.os.Bundle;
import android.os.Parcelable;
import android.provider.DocumentsContract;
-import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.util.Log;
import android.view.KeyEvent;
@@ -63,6 +60,12 @@
public static final String TAG = "FilesActivity";
+ // See comments where this const is referenced for details.
+ private static final int DRAWER_NO_FIDDLE_DELAY = 1500;
+
+ // Track the time we opened the drawer in response to back being pressed.
+ // We use the time gap to figure out whether to close app or reopen the drawer.
+ private long mDrawerLastFiddled;
private DocumentClipper mClipper;
public FilesActivity() {
@@ -82,7 +85,6 @@
if (mState.restored) {
if (DEBUG) Log.d(TAG, "Stack already resolved for uri: " + intent.getData());
- refreshCurrentRootAndDirectory(ANIM_NONE);
} else if (!mState.stack.isEmpty()) {
// If a non-empty stack is present in our state it was read (presumably)
// from EXTRA_STACK intent extra. In this case, we'll skip other means of
@@ -93,25 +95,23 @@
// Launch URIs support sensible activity management, but don't specify a real
// content target.
if (DEBUG) Log.d(TAG, "Launching with non-empty stack.");
- checkState(uri == null || uri.getAuthority() == null ||
+ assert(uri == null || uri.getAuthority() == null ||
LauncherActivity.isLaunchUri(uri));
refreshCurrentRootAndDirectory(ANIM_NONE);
} else if (intent.getAction() == Intent.ACTION_VIEW) {
- checkArgument(uri != null);
+ assert(uri != null);
new OpenUriForViewTask(this).executeOnExecutor(
ProviderExecutor.forAuthority(uri.getAuthority()), uri);
} else if (DocumentsContract.isRootUri(this, uri)) {
if (DEBUG) Log.d(TAG, "Launching with root URI.");
// If we've got a specific root to display, restore that root using a dedicated
// authority. That way a misbehaving provider won't result in an ANR.
- new RestoreRootTask(this, uri).executeOnExecutor(
- ProviderExecutor.forAuthority(uri.getAuthority()));
+ loadRoot(uri);
} else {
if (DEBUG) Log.d(TAG, "Launching into Home directory.");
// If all else fails, try to load "Home" directory.
final Uri homeUri = DocumentsContract.buildHomeUri();
- new RestoreRootTask(this, homeUri).executeOnExecutor(
- ProviderExecutor.forAuthority(homeUri.getAuthority()));
+ loadRoot(homeUri);
}
final @DialogType int dialogType = intent.getIntExtra(
@@ -141,7 +141,7 @@
state.allowMultiple = true;
// Options specific to the DocumentsActivity.
- checkArgument(!intent.hasExtra(Intent.EXTRA_LOCAL_ONLY));
+ assert(!intent.hasExtra(Intent.EXTRA_LOCAL_ONLY));
final DocumentStack stack = intent.getParcelableExtra(Shared.EXTRA_STACK);
if (stack != null) {
@@ -210,7 +210,7 @@
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_create_dir:
- checkState(canCreateDirectory());
+ assert(canCreateDirectory());
showCreateDirectoryDialog();
return true;
case R.id.menu_new_window:
@@ -248,16 +248,13 @@
final RootInfo root = getCurrentRoot();
final DocumentInfo cwd = getCurrentDirectory();
+ assert(!mSearchManager.isSearching());
+
if (cwd == null) {
DirectoryFragment.showRecentsOpen(fm, anim);
} else {
- if (mState.currentSearch != null) {
- // Ongoing search
- DirectoryFragment.showSearch(fm, root, mState.currentSearch, anim);
- } else {
- // Normal boring directory
- DirectoryFragment.showDirectory(fm, root, cwd, anim);
- }
+ // Normal boring directory
+ DirectoryFragment.showDirectory(fm, root, cwd, anim);
}
}
@@ -345,6 +342,34 @@
}
}
+ // Do some "do what a I want" drawer fiddling, but don't
+ // do it if user already hit back recently and we recently
+ // did some fiddling.
+ @Override
+ boolean onBeforePopDir() {
+ int size = mState.stack.size();
+
+ if (mDrawer.isPresent()
+ && (System.currentTimeMillis() - mDrawerLastFiddled) > DRAWER_NO_FIDDLE_DELAY) {
+ // Close drawer if it is open.
+ if (mDrawer.isOpen()) {
+ mDrawer.setOpen(false);
+ mDrawerLastFiddled = System.currentTimeMillis();
+ return true;
+ }
+
+ // Open the Close drawer if it is closed and we're at the top of a root.
+ if (size == 1) {
+ mDrawer.setOpen(true);
+ // Remember so we don't just close it again if back is pressed again.
+ mDrawerLastFiddled = System.currentTimeMillis();
+ return true;
+ }
+ }
+
+ return false;
+ }
+
// Turns out only DocumentsActivity was ever calling saveStackBlocking.
// There may be a case where we want to contribute entries from
// Behavior here in FilesActivity, but it isn't yet obvious.
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RestoreRootTask.java b/packages/DocumentsUI/src/com/android/documentsui/LoadRootTask.java
similarity index 90%
rename from packages/DocumentsUI/src/com/android/documentsui/RestoreRootTask.java
rename to packages/DocumentsUI/src/com/android/documentsui/LoadRootTask.java
index 9048b9d..c5d359b 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RestoreRootTask.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/LoadRootTask.java
@@ -22,12 +22,12 @@
import com.android.documentsui.model.RootInfo;
-final class RestoreRootTask extends PairedTask<BaseActivity, Void, RootInfo> {
+final class LoadRootTask extends PairedTask<BaseActivity, Void, RootInfo> {
private static final String TAG = "RestoreRootTask";
private final Uri mRootUri;
- public RestoreRootTask(BaseActivity activity, Uri rootUri) {
+ public LoadRootTask(BaseActivity activity, Uri rootUri) {
super(activity);
mRootUri = rootUri;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
index 4bffc49..c7c61c3 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
@@ -17,7 +17,6 @@
package com.android.documentsui;
import static com.android.documentsui.State.MODE_UNKNOWN;
-import static com.android.internal.util.Preconditions.checkArgument;
import android.content.Context;
import android.preference.PreferenceManager;
@@ -26,17 +25,9 @@
import com.android.documentsui.model.RootInfo;
public class LocalPreferences {
- private static final String KEY_ADVANCED_DEVICES = "advancedDevices";
private static final String KEY_FILE_SIZE = "fileSize";
private static final String ROOT_VIEW_MODE_PREFIX = "rootViewMode-";
- public static boolean getDisplayAdvancedDevices(Context context) {
- boolean defaultAdvanced = context.getResources()
- .getBoolean(R.bool.config_defaultAdvancedDevices);
- return PreferenceManager.getDefaultSharedPreferences(context)
- .getBoolean(KEY_ADVANCED_DEVICES, defaultAdvanced);
- }
-
public static boolean getDisplayFileSize(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context)
.getBoolean(KEY_FILE_SIZE, false);
@@ -48,18 +39,14 @@
.getInt(createKey(root), fallback);
}
- public static void setDisplayAdvancedDevices(Context context, boolean display) {
- PreferenceManager.getDefaultSharedPreferences(context).edit()
- .putBoolean(KEY_ADVANCED_DEVICES, display).apply();
- }
-
public static void setDisplayFileSize(Context context, boolean display) {
PreferenceManager.getDefaultSharedPreferences(context).edit()
.putBoolean(KEY_FILE_SIZE, display).apply();
}
public static void setViewMode(Context context, RootInfo root, @ViewMode int viewMode) {
- checkArgument(viewMode != MODE_UNKNOWN);
+ assert(viewMode != MODE_UNKNOWN);
+
PreferenceManager.getDefaultSharedPreferences(context).edit()
.putInt(createKey(root), viewMode).apply();
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
index 172282a..dcaea15 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
@@ -16,11 +16,12 @@
package com.android.documentsui;
+import static android.os.Environment.STANDARD_DIRECTORIES;
import static com.android.documentsui.Shared.DEBUG;
-import static com.android.internal.util.Preconditions.checkArgument;
-
import android.annotation.IntDef;
import android.annotation.Nullable;
+import android.annotation.StringDef;
+import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
@@ -33,6 +34,7 @@
import com.android.documentsui.services.FileOperationService;
import com.android.documentsui.services.FileOperationService.OpType;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -64,23 +66,23 @@
// Indices for bucketing roots in the roots histogram. "Other" is the catch-all index for any
// root that is not explicitly recognized by the Metrics code (see {@link
- // #getSanitizedRootIndex}). Apps are also bucketed in this histogram using negative indices
- // (see below).
+ // #getSanitizedRootIndex}). Apps are also bucketed in this histogram.
// Do not change or rearrange these values, that will break historical data. Only add to the end
// of the list.
- private static final int ROOT_NONE = 0;
- private static final int ROOT_OTHER = 1;
- private static final int ROOT_AUDIO = 2;
- private static final int ROOT_DEVICE_STORAGE = 3;
- private static final int ROOT_DOWNLOADS = 4;
- private static final int ROOT_HOME = 5;
- private static final int ROOT_IMAGES = 6;
- private static final int ROOT_RECENTS = 7;
- private static final int ROOT_VIDEOS = 8;
- private static final int ROOT_MTP = 9;
+ // Do not use negative numbers or zero; clearcut only handles positive integers.
+ private static final int ROOT_NONE = 1;
+ private static final int ROOT_OTHER = 2;
+ private static final int ROOT_AUDIO = 3;
+ private static final int ROOT_DEVICE_STORAGE = 4;
+ private static final int ROOT_DOWNLOADS = 5;
+ private static final int ROOT_HOME = 6;
+ private static final int ROOT_IMAGES = 7;
+ private static final int ROOT_RECENTS = 8;
+ private static final int ROOT_VIDEOS = 9;
+ private static final int ROOT_MTP = 10;
// Apps aren't really "roots", but they are treated as such in the roots fragment UI and so they
- // are logged analogously to roots. Use negative numbers to identify apps.
- private static final int ROOT_THIRD_PARTY_APP = -1;
+ // are logged analogously to roots.
+ private static final int ROOT_THIRD_PARTY_APP = 100;
@IntDef(flag = true, value = {
ROOT_NONE,
@@ -99,19 +101,21 @@
public @interface Root {}
// Indices for bucketing mime types.
- private static final int MIME_OTHER = -2; // anything not enumerated below
- private static final int MIME_NONE = -1; // null mime
- private static final int MIME_ANY = 0; // */*
- private static final int MIME_APPLICATION = 1; // application/*
- private static final int MIME_AUDIO = 2; // audio/*
- private static final int MIME_IMAGE = 3; // image/*
- private static final int MIME_MESSAGE = 4; // message/*
- private static final int MIME_MULTIPART = 5; // multipart/*
- private static final int MIME_TEXT = 6; // text/*
- private static final int MIME_VIDEO = 7; // video/*
+ // Do not change or rearrange these values, that will break historical data. Only add to the end
+ // of the list.
+ // Do not use negative numbers or zero; clearcut only handles positive integers.
+ private static final int MIME_NONE = 1; // null mime
+ private static final int MIME_ANY = 2; // */*
+ private static final int MIME_APPLICATION = 3; // application/*
+ private static final int MIME_AUDIO = 4; // audio/*
+ private static final int MIME_IMAGE = 5; // image/*
+ private static final int MIME_MESSAGE = 6; // message/*
+ private static final int MIME_MULTIPART = 7; // multipart/*
+ private static final int MIME_TEXT = 8; // text/*
+ private static final int MIME_VIDEO = 9; // video/*
+ private static final int MIME_OTHER = 10; // anything not enumerated below
@IntDef(flag = true, value = {
- MIME_OTHER,
MIME_NONE,
MIME_ANY,
MIME_APPLICATION,
@@ -120,25 +124,29 @@
MIME_MESSAGE,
MIME_MULTIPART,
MIME_TEXT,
- MIME_VIDEO
+ MIME_VIDEO,
+ MIME_OTHER
})
@Retention(RetentionPolicy.SOURCE)
public @interface Mime {}
// Codes representing different kinds of file operations. These are used for bucketing
// operations in the COUNT_FILEOP_{SYSTEM|EXTERNAL} histograms.
- private static final int FILEOP_OTHER = 0; // any file operation not listed below
- private static final int FILEOP_COPY_INTRA_PROVIDER = 1; // Copy within a provider
- private static final int FILEOP_COPY_SYSTEM_PROVIDER = 2; // Copy to a system provider.
- private static final int FILEOP_COPY_EXTERNAL_PROVIDER = 3; // Copy to a 3rd-party provider.
- private static final int FILEOP_MOVE_INTRA_PROVIDER = 4; // Move within a provider.
- private static final int FILEOP_MOVE_SYSTEM_PROVIDER = 5; // Move to a system provider.
- private static final int FILEOP_MOVE_EXTERNAL_PROVIDER = 6; // Move to a 3rd-party provider.
- private static final int FILEOP_DELETE = 7;
- private static final int FILEOP_OTHER_ERROR = -1;
- private static final int FILEOP_COPY_ERROR = -2;
- private static final int FILEOP_MOVE_ERROR = -3;
- private static final int FILEOP_DELETE_ERROR = -4;
+ // Do not change or rearrange these values, that will break historical data. Only add to the
+ // list.
+ // Do not use negative numbers or zero; clearcut only handles positive integers.
+ private static final int FILEOP_OTHER = 1; // any file operation not listed below
+ private static final int FILEOP_COPY_INTRA_PROVIDER = 2; // Copy within a provider
+ private static final int FILEOP_COPY_SYSTEM_PROVIDER = 3; // Copy to a system provider.
+ private static final int FILEOP_COPY_EXTERNAL_PROVIDER = 4; // Copy to a 3rd-party provider.
+ private static final int FILEOP_MOVE_INTRA_PROVIDER = 5; // Move within a provider.
+ private static final int FILEOP_MOVE_SYSTEM_PROVIDER = 6; // Move to a system provider.
+ private static final int FILEOP_MOVE_EXTERNAL_PROVIDER = 7; // Move to a 3rd-party provider.
+ private static final int FILEOP_DELETE = 8;
+ private static final int FILEOP_OTHER_ERROR = 100;
+ private static final int FILEOP_DELETE_ERROR = 101;
+ private static final int FILEOP_MOVE_ERROR = 102;
+ private static final int FILEOP_COPY_ERROR = 103;
@IntDef(flag = true, value = {
FILEOP_OTHER,
@@ -157,6 +165,52 @@
@Retention(RetentionPolicy.SOURCE)
public @interface FileOp {}
+ // Codes representing different kinds of file operations. These are used for bucketing
+ // operations in the COUNT_FILEOP_CANCELED histogram.
+ // Do not change or rearrange these values, that will break historical data. Only add to the
+ // list.
+ // Do not use negative numbers or zero; clearcut only handles positive integers.
+ private static final int OPERATION_UNKNOWN = 1;
+ private static final int OPERATION_COPY = 2;
+ private static final int OPERATION_MOVE = 3;
+ private static final int OPERATION_DELETE= 4;
+
+ @IntDef(flag = true, value = {
+ OPERATION_UNKNOWN,
+ OPERATION_COPY,
+ OPERATION_MOVE,
+ OPERATION_DELETE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface MetricsOpType {}
+
+ // Codes representing different launch actions. These are used for bucketing stats in the
+ // COUNT_LAUNCH_ACTION histogram.
+ // Do not change or rearrange these values, that will break historical data. Only add to the
+ // list.
+ // Do not use negative numbers or zero; clearcut only handles positive integers.
+ private static final int ACTION_OTHER = 1;
+ private static final int ACTION_OPEN = 2;
+ private static final int ACTION_CREATE = 3;
+ private static final int ACTION_GET_CONTENT = 4;
+ private static final int ACTION_OPEN_TREE = 5;
+ private static final int ACTION_MANAGE = 6;
+ private static final int ACTION_BROWSE = 7;
+ private static final int ACTION_PICK_COPY_DESTINATION = 8;
+
+ @IntDef(flag = true, value = {
+ ACTION_OTHER,
+ ACTION_OPEN,
+ ACTION_CREATE,
+ ACTION_GET_CONTENT,
+ ACTION_OPEN_TREE,
+ ACTION_MANAGE,
+ ACTION_BROWSE,
+ ACTION_PICK_COPY_DESTINATION
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface MetricsAction {}
+
// Codes representing different provider types. Used for sorting file operations when logging.
private static final int PROVIDER_INTRA = 0;
private static final int PROVIDER_SYSTEM = 1;
@@ -179,7 +233,7 @@
*/
public static void logActivityLaunch(Context context, State state, Intent intent) {
// Log the launch action.
- logHistogram(context, COUNT_LAUNCH_ACTION, state.action);
+ logHistogram(context, COUNT_LAUNCH_ACTION, toMetricsAction(state.action));
// Then log auxiliary data (roots/mime types) associated with some actions.
Uri uri = intent.getData();
switch (state.action) {
@@ -300,7 +354,7 @@
* @param operationType
*/
public static void logFileOperationCancelled(Context context, @OpType int operationType) {
- logHistogram(context, COUNT_FILEOP_CANCELED, operationType);
+ logHistogram(context, COUNT_FILEOP_CANCELED, toMetricsOpType(operationType));
}
private static void logInterProviderFileOps(
@@ -311,7 +365,7 @@
if (operationType == FileOperationService.OPERATION_DELETE) {
logHistogram(context, histogram, FILEOP_DELETE);
} else {
- checkArgument(dst != null);
+ assert(dst != null);
@Provider int providerType =
isSystemProvider(dst.authority) ? PROVIDER_SYSTEM : PROVIDER_EXTERNAL;
logHistogram(context, histogram, getOpCode(operationType, providerType));
@@ -325,6 +379,84 @@
logHistogram(context, histogram, getOpCode(operationType, PROVIDER_INTRA));
}
+ // Types for logInvalidScopedAccessRequest
+ public static final String SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS =
+ "scoped_directory_access_invalid_args";
+ public static final String SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY =
+ "scoped_directory_access_invalid_dir";
+ public static final String SCOPED_DIRECTORY_ACCESS_ERROR =
+ "scoped_directory_access_error";
+
+ @StringDef(value = {
+ SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS,
+ SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY,
+ SCOPED_DIRECTORY_ACCESS_ERROR
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface InvalidScopedAccess{}
+
+ public static void logInvalidScopedAccessRequest(Context context,
+ @InvalidScopedAccess String type) {
+ MetricsLogger.count(context, type, 1);
+ switch (type) {
+ case SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS:
+ case SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY:
+ case SCOPED_DIRECTORY_ACCESS_ERROR:
+ MetricsLogger.count(context, type, 1);
+ break;
+ default:
+ Log.wtf(TAG, "invalid InvalidScopedAccess: " + type);
+ }
+ }
+
+ // Types for logValidScopedAccessRequest
+ public static final int SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED = 0;
+ public static final int SCOPED_DIRECTORY_ACCESS_GRANTED = 1;
+ public static final int SCOPED_DIRECTORY_ACCESS_DENIED = 2;
+
+ @IntDef(flag = true, value = {
+ SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED,
+ SCOPED_DIRECTORY_ACCESS_GRANTED,
+ SCOPED_DIRECTORY_ACCESS_DENIED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ScopedAccessGrant {}
+
+ public static void logValidScopedAccessRequest(Activity activity, String directory,
+ @ScopedAccessGrant int type) {
+ int index = -1;
+ for (int i = 0; i < STANDARD_DIRECTORIES.length; i++) {
+ if (STANDARD_DIRECTORIES[i].equals(directory)) {
+ index = i;
+ break;
+ }
+ }
+ final String packageName = activity.getCallingPackage();
+ switch (type) {
+ case SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED:
+ MetricsLogger.action(activity,
+ MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_PACKAGE,
+ packageName);
+ MetricsLogger.action(activity,
+ MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_FOLDER, index);
+ break;
+ case SCOPED_DIRECTORY_ACCESS_GRANTED:
+ MetricsLogger.action(activity,
+ MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_PACKAGE, packageName);
+ MetricsLogger.action(activity,
+ MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_FOLDER, index);
+ break;
+ case SCOPED_DIRECTORY_ACCESS_DENIED:
+ MetricsLogger.action(activity,
+ MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_PACKAGE, packageName);
+ MetricsLogger.action(activity,
+ MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_FOLDER, index);
+ break;
+ default:
+ Log.wtf(TAG, "invalid ScopedAccessGrant: " + type);
+ }
+ }
+
/**
* Internal method for making a MetricsLogger.count call. Increments the given counter by 1.
*
@@ -483,6 +615,44 @@
}
/**
+ * Maps FileOperationService OpType values, to MetricsOpType values.
+ */
+ private static @MetricsOpType int toMetricsOpType(@OpType int operation) {
+ switch (operation) {
+ case FileOperationService.OPERATION_COPY:
+ return OPERATION_COPY;
+ case FileOperationService.OPERATION_MOVE:
+ return OPERATION_MOVE;
+ case FileOperationService.OPERATION_DELETE:
+ return OPERATION_DELETE;
+ case FileOperationService.OPERATION_UNKNOWN:
+ default:
+ return OPERATION_UNKNOWN;
+ }
+ }
+
+ private static @MetricsAction int toMetricsAction(int action) {
+ switch(action) {
+ case State.ACTION_OPEN:
+ return ACTION_OPEN;
+ case State.ACTION_CREATE:
+ return ACTION_CREATE;
+ case State.ACTION_GET_CONTENT:
+ return ACTION_GET_CONTENT;
+ case State.ACTION_OPEN_TREE:
+ return ACTION_OPEN_TREE;
+ case State.ACTION_MANAGE:
+ return ACTION_MANAGE;
+ case State.ACTION_BROWSE:
+ return ACTION_BROWSE;
+ case State.ACTION_PICK_COPY_DESTINATION:
+ return ACTION_PICK_COPY_DESTINATION;
+ default:
+ return ACTION_OTHER;
+ }
+ }
+
+ /**
* Count the given src documents and provide a tally of how many come from the same provider as
* the dst document (if a dst is provided), how many come from system providers, and how many
* come from external 3rd-party providers.
diff --git a/packages/DocumentsUI/src/com/android/documentsui/NavigationView.java b/packages/DocumentsUI/src/com/android/documentsui/NavigationView.java
index 4cba135..c520204 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/NavigationView.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/NavigationView.java
@@ -220,17 +220,14 @@
.inflate(R.layout.item_subdir, parent, false);
}
- final ImageView subdir = (ImageView) convertView.findViewById(R.id.subdir);
final TextView title = (TextView) convertView.findViewById(android.R.id.title);
final DocumentInfo doc = getItem(position);
if (position == 0) {
final RootInfo root = mEnv.getCurrentRoot();
title.setText(root.title);
- subdir.setVisibility(View.GONE);
} else {
title.setText(doc.displayName);
- subdir.setVisibility(View.VISIBLE);
}
return convertView;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java b/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
index 025faea..dc529ce 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
@@ -17,11 +17,21 @@
package com.android.documentsui;
import static android.os.Environment.isStandardDirectory;
+import static android.os.Environment.STANDARD_DIRECTORIES;
import static android.os.storage.StorageVolume.EXTRA_DIRECTORY_NAME;
import static android.os.storage.StorageVolume.EXTRA_STORAGE_VOLUME;
import static com.android.documentsui.Shared.DEBUG;
+import static com.android.documentsui.Metrics.logInvalidScopedAccessRequest;
+import static com.android.documentsui.Metrics.logValidScopedAccessRequest;
+import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED;
+import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_DENIED;
+import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_ERROR;
+import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_GRANTED;
+import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS;
+import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY;
import android.app.Activity;
+import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
@@ -33,6 +43,7 @@
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
+import android.content.UriPermission;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
@@ -62,6 +73,8 @@
private static final String EXTRA_APP_LABEL = "com.android.documentsui.APP_LABEL";
private static final String EXTRA_VOLUME_LABEL = "com.android.documentsui.VOLUME_LABEL";
+ private ContentProviderClient mExternalStorageClient;
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -69,6 +82,7 @@
final Intent intent = getIntent();
if (intent == null) {
if (DEBUG) Log.d(TAG, "missing intent");
+ logInvalidScopedAccessRequest(this, SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS);
setResult(RESULT_CANCELED);
finish();
return;
@@ -78,12 +92,14 @@
if (DEBUG)
Log.d(TAG, "extra " + EXTRA_STORAGE_VOLUME + " is not a StorageVolume: "
+ storageVolume);
+ logInvalidScopedAccessRequest(this, SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS);
setResult(RESULT_CANCELED);
finish();
return;
}
final String directoryName = intent.getStringExtra(EXTRA_DIRECTORY_NAME);
if (directoryName == null) {
+ logInvalidScopedAccessRequest(this, SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS);
if (DEBUG) Log.d(TAG, "missing extra " + EXTRA_DIRECTORY_NAME + " on " + intent);
setResult(RESULT_CANCELED);
finish();
@@ -98,12 +114,20 @@
}
}
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (mExternalStorageClient != null) {
+ mExternalStorageClient.close();
+ }
+ }
+
/**
* Validates the given path (volume + directory) and display the appropriate dialog asking the
* user to grant access to it.
*/
- private static boolean showFragment(Activity activity, int userId, StorageVolume storageVolume,
- String directoryName) {
+ private static boolean showFragment(OpenExternalDirectoryActivity activity, int userId,
+ StorageVolume storageVolume, String directoryName) {
if (DEBUG)
Log.d(TAG, "showFragment() for volume " + storageVolume.dump() + ", directory "
+ directoryName + ", and user " + userId);
@@ -113,6 +137,7 @@
} catch (IOException e) {
Log.e(TAG, "Could not get canonical file for volume " + storageVolume.dump()
+ " and directory " + directoryName);
+ logInvalidScopedAccessRequest(activity, SCOPED_DIRECTORY_ACCESS_ERROR);
return false;
}
final StorageManager sm =
@@ -126,10 +151,11 @@
if (DEBUG)
Log.d(TAG, "Directory '" + directory + "' is not standard (full path: '"
+ file.getAbsolutePath() + "')");
+ logInvalidScopedAccessRequest(activity, SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY);
return false;
}
- // Gets volume label and converted path
+ // Gets volume label and converted path.
String volumeLabel = null;
final List<VolumeInfo> volumes = sm.getVolumes();
if (DEBUG) Log.d(TAG, "Number of volumes: " + volumes.size());
@@ -143,14 +169,27 @@
break;
}
}
+
+ // Checks if the user has granted the permission already.
+ final Intent intent = getIntentForExistingPermission(activity, file);
+ if (intent != null) {
+ logValidScopedAccessRequest(activity, directory,
+ SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED);
+ activity.setResult(RESULT_OK, intent);
+ activity.finish();
+ return true;
+ }
+
if (volumeLabel == null) {
Log.e(TAG, "Could not get volume for " + file);
+ logInvalidScopedAccessRequest(activity, SCOPED_DIRECTORY_ACCESS_ERROR);
return false;
}
// Gets the package label.
final String appLabel = getAppLabel(activity);
if (appLabel == null) {
+ // Error already logged.
return false;
}
@@ -177,6 +216,7 @@
try {
return pm.getApplicationLabel(pm.getApplicationInfo(packageName, 0)).toString();
} catch (NameNotFoundException e) {
+ logInvalidScopedAccessRequest(activity, SCOPED_DIRECTORY_ACCESS_ERROR);
Log.w(TAG, "Could not get label for package " + packageName);
return null;
}
@@ -196,7 +236,7 @@
return volume.isVisibleForWrite(userId) && root.equals(path);
}
- private static Intent createGrantedUriPermissionsIntent(ContentProviderClient provider,
+ private static Uri getGrantedUriPermission(Context context, ContentProviderClient provider,
File file) {
// Calls ExternalStorageProvider to get the doc id for the file
final Bundle bundle;
@@ -204,11 +244,13 @@
bundle = provider.call("getDocIdForFileCreateNewDir", file.getPath(), null);
} catch (RemoteException e) {
Log.e(TAG, "Did not get doc id from External Storage provider for " + file, e);
+ logInvalidScopedAccessRequest(context, SCOPED_DIRECTORY_ACCESS_ERROR);
return null;
}
final String docId = bundle == null ? null : bundle.getString("DOC_ID");
if (docId == null) {
Log.e(TAG, "Did not get doc id from External Storage provider for " + file);
+ logInvalidScopedAccessRequest(context, SCOPED_DIRECTORY_ACCESS_ERROR);
return null;
}
Log.d(TAG, "doc id for " + file + ": " + docId);
@@ -218,8 +260,17 @@
Log.e(TAG, "Could not get URI for doc id " + docId);
return null;
}
-
if (DEBUG) Log.d(TAG, "URI for " + file + ": " + uri);
+ return uri;
+ }
+
+ private static Intent createGrantedUriPermissionsIntent(Context context,
+ ContentProviderClient provider, File file) {
+ final Uri uri = getGrantedUriPermission(context, provider, file);
+ return createGrantedUriPermissionsIntent(uri);
+ }
+
+ private static Intent createGrantedUriPermissionsIntent(Uri uri) {
final Intent intent = new Intent();
intent.setData(uri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
@@ -229,13 +280,32 @@
return intent;
}
+ private static Intent getIntentForExistingPermission(OpenExternalDirectoryActivity activity,
+ File file) {
+ final String packageName = activity.getCallingPackage();
+ final Uri grantedUri =
+ getGrantedUriPermission(activity, activity.getExternalStorageClient(), file);
+ if (DEBUG)
+ Log.d(TAG, "checking if " + packageName + " already has permission for " + grantedUri);
+ final ActivityManager am =
+ (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
+ for (UriPermission uriPermission : am.getGrantedUriPermissions(packageName).getList()) {
+ final Uri uri = uriPermission.getUri();
+ if (uri.equals(grantedUri)) {
+ if (DEBUG) Log.d(TAG, packageName + " already has permission: " + uriPermission);
+ return createGrantedUriPermissionsIntent(uri);
+ }
+ }
+ if (DEBUG) Log.d(TAG, packageName + " does not have permission for " + grantedUri);
+ return null;
+ }
+
public static class OpenExternalDirectoryDialogFragment extends DialogFragment {
private File mFile;
private String mVolumeLabel;
private String mAppLabel;
- private ContentProviderClient mExternalStorageClient;
- private ContentResolver mResolver;
+ private OpenExternalDirectoryActivity mActivity;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -245,21 +315,13 @@
mFile = new File(args.getString(EXTRA_FILE));
mVolumeLabel = args.getString(EXTRA_VOLUME_LABEL);
mAppLabel = args.getString(EXTRA_APP_LABEL);
- mResolver = getContext().getContentResolver();
}
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- if (mExternalStorageClient != null) {
- mExternalStorageClient.close();
- }
+ mActivity = (OpenExternalDirectoryActivity) getActivity();
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
- final String folder = mFile.getName();
+ final String directory = mFile.getName();
final Activity activity = getActivity();
final OnClickListener listener = new OnClickListener() {
@@ -267,12 +329,16 @@
public void onClick(DialogInterface dialog, int which) {
Intent intent = null;
if (which == DialogInterface.BUTTON_POSITIVE) {
- intent = createGrantedUriPermissionsIntent(getExternalStorageClient(),
- mFile);
+ intent = createGrantedUriPermissionsIntent(mActivity,
+ mActivity.getExternalStorageClient(), mFile);
}
if (which == DialogInterface.BUTTON_NEGATIVE || intent == null) {
+ logValidScopedAccessRequest(activity, directory,
+ SCOPED_DIRECTORY_ACCESS_DENIED);
activity.setResult(RESULT_CANCELED);
} else {
+ logValidScopedAccessRequest(activity, directory,
+ SCOPED_DIRECTORY_ACCESS_GRANTED);
activity.setResult(RESULT_OK, intent);
}
activity.finish();
@@ -281,7 +347,7 @@
final CharSequence message = TextUtils
.expandTemplate(
- getText(R.string.open_external_dialog_request), mAppLabel, folder,
+ getText(R.string.open_external_dialog_request), mAppLabel, directory,
mVolumeLabel);
return new AlertDialog.Builder(activity, R.style.AlertDialogTheme)
.setMessage(message)
@@ -294,16 +360,17 @@
public void onCancel(DialogInterface dialog) {
super.onCancel(dialog);
final Activity activity = getActivity();
+ logValidScopedAccessRequest(activity, mFile.getName(), SCOPED_DIRECTORY_ACCESS_DENIED);
activity.setResult(RESULT_CANCELED);
activity.finish();
}
+ }
- private synchronized ContentProviderClient getExternalStorageClient() {
- if (mExternalStorageClient == null) {
- mExternalStorageClient =
- mResolver.acquireContentProviderClient(EXTERNAL_STORAGE_AUTH);
- }
- return mExternalStorageClient;
+ private synchronized ContentProviderClient getExternalStorageClient() {
+ if (mExternalStorageClient == null) {
+ mExternalStorageClient =
+ getContentResolver().acquireContentProviderClient(EXTERNAL_STORAGE_AUTH);
}
+ return mExternalStorageClient;
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/OperationDialogFragment.java b/packages/DocumentsUI/src/com/android/documentsui/OperationDialogFragment.java
index 85cc12b..2cef8d3 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/OperationDialogFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/OperationDialogFragment.java
@@ -16,9 +16,6 @@
package com.android.documentsui;
-import static com.android.documentsui.services.FileOperationService.OpType;
-import static com.android.internal.util.Preconditions.checkArgument;
-
import android.annotation.IntDef;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -32,13 +29,11 @@
import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.DocumentStack;
import com.android.documentsui.services.FileOperationService;
-import com.android.documentsui.services.FileOperations;
-import com.android.documentsui.services.Job;
+import com.android.documentsui.services.FileOperationService.OpType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
-import java.util.List;
/**
* Alert dialog for operation dialogs.
@@ -114,7 +109,7 @@
final StringBuilder list = new StringBuilder("<p>");
for (DocumentInfo documentInfo : srcList) {
- list.append(String.format("• %s<br>", documentInfo.displayName));
+ list.append(String.format("• %s<br>", Html.escapeHtml(documentInfo.displayName)));
}
list.append("</p>");
builder.setMessage(Html.fromHtml(String.format(messageFormat, list.toString())));
diff --git a/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java b/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java
index 32543c8..933506c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java
@@ -19,7 +19,6 @@
import static com.android.documentsui.services.FileOperationService.OPERATION_DELETE;
import static com.android.documentsui.services.FileOperationService.OPERATION_MOVE;
import static com.android.documentsui.services.FileOperationService.OPERATION_UNKNOWN;
-import static com.android.internal.util.Preconditions.checkArgument;
import android.app.Activity;
import android.app.Fragment;
@@ -101,7 +100,8 @@
*/
public void setPickTarget(
int action, @OpType int copyOperationSubType, DocumentInfo pickTarget) {
- checkArgument(copyOperationSubType != OPERATION_DELETE);
+ assert(copyOperationSubType != OPERATION_DELETE);
+
mAction = action;
mCopyOperationSubType = copyOperationSubType;
mPickTarget = pickTarget;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java b/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java
index b0e332f..8145edc 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java
@@ -19,7 +19,6 @@
import android.os.AsyncTask;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.Preconditions;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -85,7 +84,7 @@
private Executor mNonPreemptingExecutor = new Executor() {
@Override
public void execute(Runnable command) {
- Preconditions.checkNotNull(command);
+ assert(command != null);
mQueue.add(command);
}
};
@@ -93,7 +92,7 @@
@Override
public void execute(Runnable command) {
preempt();
- Preconditions.checkNotNull(command);
+ assert(command != null);
mQueue.add(command);
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsLoader.java
similarity index 92%
rename from packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
rename to packages/DocumentsUI/src/com/android/documentsui/RecentsLoader.java
index 0ee54e6..cebc9b0 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsLoader.java
@@ -31,12 +31,12 @@
import android.os.Bundle;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
-import android.provider.DocumentsContract.Root;
import android.text.format.DateUtils;
import android.util.Log;
import com.android.documentsui.model.RootInfo;
import com.android.internal.annotations.GuardedBy;
+
import com.google.common.util.concurrent.AbstractFuture;
import libcore.io.IoUtils;
@@ -52,7 +52,7 @@
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
-public class RecentLoader extends AsyncTaskLoader<DirectoryResult> {
+public class RecentsLoader extends AsyncTaskLoader<DirectoryResult> {
// TODO: clean up cursor ownership so background thread doesn't traverse
// previously returned cursors for filtering/sorting; this currently races
// with the UI thread.
@@ -80,7 +80,7 @@
private final State mState;
@GuardedBy("mTasks")
- private final HashMap<RootInfo, RecentTask> mTasks = new HashMap<>();
+ private final HashMap<RootInfo, RecentsTask> mTasks = new HashMap<>();
private final int mSortOrder = State.SORT_ORDER_LAST_MODIFIED;
@@ -89,69 +89,7 @@
private DirectoryResult mResult;
- // TODO: create better transfer of ownership around cursor to ensure its
- // closed in all edge cases.
-
- public class RecentTask extends AbstractFuture<Cursor> implements Runnable, Closeable {
- public final String authority;
- public final String rootId;
-
- private Cursor mWithRoot;
-
- public RecentTask(String authority, String rootId) {
- this.authority = authority;
- this.rootId = rootId;
- }
-
- @Override
- public void run() {
- if (isCancelled()) return;
-
- try {
- mQueryPermits.acquire();
- } catch (InterruptedException e) {
- return;
- }
-
- try {
- runInternal();
- } finally {
- mQueryPermits.release();
- }
- }
-
- public void runInternal() {
- ContentProviderClient client = null;
- try {
- client = DocumentsApplication.acquireUnstableProviderOrThrow(
- getContext().getContentResolver(), authority);
-
- final Uri uri = DocumentsContract.buildRecentDocumentsUri(authority, rootId);
- final Cursor cursor = client.query(
- uri, null, null, null, DirectoryLoader.getQuerySortOrder(mSortOrder));
- mWithRoot = new RootCursorWrapper(authority, rootId, cursor, MAX_DOCS_FROM_ROOT);
-
- } catch (Exception e) {
- Log.w(TAG, "Failed to load " + authority + ", " + rootId, e);
- } finally {
- ContentProviderClient.releaseQuietly(client);
- }
-
- set(mWithRoot);
-
- mFirstPassLatch.countDown();
- if (mFirstPassDone) {
- onContentChanged();
- }
- }
-
- @Override
- public void close() throws IOException {
- IoUtils.closeQuietly(mWithRoot);
- }
- }
-
- public RecentLoader(Context context, RootsCache roots, State state) {
+ public RecentsLoader(Context context, RootsCache roots, State state) {
super(context);
mRoots = roots;
mState = state;
@@ -178,14 +116,13 @@
final Collection<RootInfo> roots = mRoots.getMatchingRootsBlocking(mState);
for (RootInfo root : roots) {
- if ((root.flags & Root.FLAG_SUPPORTS_RECENTS) != 0) {
- final RecentTask task = new RecentTask(root.authority, root.rootId);
- mTasks.put(root, task);
+ if (root.supportsRecents()) {
+ mTasks.put(root, new RecentsTask(root.authority, root.rootId));
}
}
mFirstPassLatch = new CountDownLatch(mTasks.size());
- for (RecentTask task : mTasks.values()) {
+ for (RecentsTask task : mTasks.values()) {
ProviderExecutor.forAuthority(task.authority).execute(task);
}
@@ -202,7 +139,7 @@
// Collect all finished tasks
boolean allDone = true;
List<Cursor> cursors = new ArrayList<>();
- for (RecentTask task : mTasks.values()) {
+ for (RecentsTask task : mTasks.values()) {
if (task.isDone()) {
try {
final Cursor cursor = task.get();
@@ -303,7 +240,7 @@
onStopLoading();
synchronized (mTasks) {
- for (RecentTask task : mTasks.values()) {
+ for (RecentsTask task : mTasks.values()) {
IoUtils.closeQuietly(task);
}
}
@@ -311,4 +248,66 @@
IoUtils.closeQuietly(mResult);
mResult = null;
}
+
+ // TODO: create better transfer of ownership around cursor to ensure its
+ // closed in all edge cases.
+
+ public class RecentsTask extends AbstractFuture<Cursor> implements Runnable, Closeable {
+ public final String authority;
+ public final String rootId;
+
+ private Cursor mWithRoot;
+
+ public RecentsTask(String authority, String rootId) {
+ this.authority = authority;
+ this.rootId = rootId;
+ }
+
+ @Override
+ public void run() {
+ if (isCancelled()) return;
+
+ try {
+ mQueryPermits.acquire();
+ } catch (InterruptedException e) {
+ return;
+ }
+
+ try {
+ runInternal();
+ } finally {
+ mQueryPermits.release();
+ }
+ }
+
+ public void runInternal() {
+ ContentProviderClient client = null;
+ try {
+ client = DocumentsApplication.acquireUnstableProviderOrThrow(
+ getContext().getContentResolver(), authority);
+
+ final Uri uri = DocumentsContract.buildRecentDocumentsUri(authority, rootId);
+ final Cursor cursor = client.query(
+ uri, null, null, null, DirectoryLoader.getQuerySortOrder(mSortOrder));
+ mWithRoot = new RootCursorWrapper(authority, rootId, cursor, MAX_DOCS_FROM_ROOT);
+
+ } catch (Exception e) {
+ Log.w(TAG, "Failed to load " + authority + ", " + rootId, e);
+ } finally {
+ ContentProviderClient.releaseQuietly(client);
+ }
+
+ set(mWithRoot);
+
+ mFirstPassLatch.countDown();
+ if (mFirstPassDone) {
+ onContentChanged();
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ IoUtils.closeQuietly(mWithRoot);
+ }
+ }
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
index 92ffb93..e1b1c09 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
@@ -95,6 +95,7 @@
public static final String PACKAGE_NAME = "package_name";
public static final String STACK = "stack";
public static final String TIMESTAMP = "timestamp";
+ // Indicates handler was an external app, like photos.
public static final String EXTERNAL = "external";
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index fd96391..2b7294a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -17,7 +17,6 @@
package com.android.documentsui;
import static com.android.documentsui.Shared.DEBUG;
-import static com.android.documentsui.Shared.TAG;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
@@ -62,6 +61,8 @@
public static final Uri sNotificationUri = Uri.parse(
"content://com.android.documentsui.roots/");
+ private static final String TAG = "RootsCache";
+
private final Context mContext;
private final ContentObserver mObserver;
private OnCacheUpdateListener mCacheUpdateListener;
@@ -85,15 +86,14 @@
// Create a new anonymous "Recents" RootInfo. It's a faker.
mRecentsRoot = new RootInfo() {{
- // Special root for recents
- authority = null;
- rootId = null;
- derivedIcon = R.drawable.ic_root_recent;
- derivedType = RootInfo.TYPE_RECENTS;
- flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_IS_CHILD;
- title = mContext.getString(R.string.root_recent);
- availableBytes = -1;
- }};
+ // Special root for recents
+ derivedIcon = R.drawable.ic_root_recent;
+ derivedType = RootInfo.TYPE_RECENTS;
+ flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_IS_CHILD
+ | Root.FLAG_SUPPORTS_CREATE;
+ title = mContext.getString(R.string.root_recent);
+ availableBytes = -1;
+ }};
}
private class RootsChangedObserver extends ContentObserver {
@@ -116,6 +116,22 @@
* Gather roots from all known storage providers.
*/
public void updateAsync() {
+
+ // NOTE: This method is called when the UI language changes.
+ // For that reason we upadte our RecentsRoot to reflect
+ // the current language.
+ mRecentsRoot.title = mContext.getString(R.string.root_recent);
+
+ // Nothing else about the root should ever change.
+ assert(mRecentsRoot.authority == null);
+ assert(mRecentsRoot.rootId == null);
+ assert(mRecentsRoot.derivedIcon == R.drawable.ic_root_recent);
+ assert(mRecentsRoot.derivedType == RootInfo.TYPE_RECENTS);
+ assert(mRecentsRoot.flags == (Root.FLAG_LOCAL_ONLY
+ | Root.FLAG_SUPPORTS_IS_CHILD
+ | Root.FLAG_SUPPORTS_CREATE));
+ assert(mRecentsRoot.availableBytes == -1);
+
new UpdateTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
@@ -402,44 +418,64 @@
static List<RootInfo> getMatchingRoots(Collection<RootInfo> roots, State state) {
final List<RootInfo> matching = new ArrayList<>();
for (RootInfo root : roots) {
- // Exclude read-only devices when creating
- if (state.action == State.ACTION_CREATE && !root.supportsCreate()) continue;
- if (state.action == State.ACTION_PICK_COPY_DESTINATION
- && !root.supportsCreate()) continue;
- // Exclude roots that don't support directory picking
- if (state.action == State.ACTION_OPEN_TREE && !root.supportsChildren()) continue;
- // Exclude advanced devices when not requested
- if (!state.showAdvanced && root.isAdvanced()) continue;
- // Exclude non-local devices when local only
- if (state.localOnly && !root.isLocalOnly()) continue;
- // Exclude downloads roots that don't support directory creation
- // TODO: Add flag to check the root supports directory creation or not.
- if (state.directoryCopy && !root.supportsChildren()) continue;
- // Only show empty roots when creating, or in browse mode.
- if (root.isEmpty() && (state.action == State.ACTION_OPEN
- || state.action == State.ACTION_GET_CONTENT)) {
- if (DEBUG) Log.i(TAG, "Skipping empty root: " + root);
+ if (DEBUG) Log.d(TAG, "Evaluating " + root);
+
+ if (state.action == State.ACTION_CREATE && !root.supportsCreate()) {
+ if (DEBUG) Log.d(TAG, "Excluding read-only root because: ACTION_CREATE.");
continue;
}
- // Only include roots that serve requested content
+ if (state.action == State.ACTION_PICK_COPY_DESTINATION
+ && !root.supportsCreate()) {
+ if (DEBUG) Log.d(
+ TAG, "Excluding read-only root because: ACTION_PICK_COPY_DESTINATION.");
+ continue;
+ }
+
+ if (state.action == State.ACTION_OPEN_TREE && !root.supportsChildren()) {
+ if (DEBUG) Log.d(
+ TAG, "Excluding root !supportsChildren because: ACTION_OPEN_TREE.");
+ continue;
+ }
+
+ if (state.localOnly && !root.isLocalOnly()) {
+ if (DEBUG) Log.d(TAG, "Excluding root because: unwanted non-local device.");
+ continue;
+ }
+
+ if (state.directoryCopy && root.isDownloads()) {
+ if (DEBUG) Log.d(
+ TAG, "Excluding downloads root because: unsupported directory copy.");
+ continue;
+ }
+
+ if (state.action == State.ACTION_OPEN && root.isEmpty()) {
+ if (DEBUG) Log.d(TAG, "Excluding empty root because: ACTION_OPEN.");
+ continue;
+ }
+
+ if (state.action == State.ACTION_GET_CONTENT && root.isEmpty()) {
+ if (DEBUG) Log.d(TAG, "Excluding empty root because: ACTION_GET_CONTENT.");
+ continue;
+ }
+
final boolean overlap =
MimePredicate.mimeMatches(root.derivedMimeTypes, state.acceptMimes) ||
MimePredicate.mimeMatches(state.acceptMimes, root.derivedMimeTypes);
if (!overlap) {
- continue;
- }
-
- // Exclude roots from the calling package.
- if (state.excludedAuthorities.contains(root.authority)) {
if (DEBUG) Log.d(
- TAG, "Excluding root " + root.authority + " from calling package.");
+ TAG, "Excluding root because: unsupported content types > "
+ + state.acceptMimes);
continue;
}
- if (DEBUG) Log.d(
- TAG, "Including root " + root + " in roots list.");
+ if (state.excludedAuthorities.contains(root.authority)) {
+ if (DEBUG) Log.d(TAG, "Excluding root because: owned by calling package.");
+ continue;
+ }
+
+ if (DEBUG) Log.d(TAG, "Including " + root);
matching.add(root);
}
return matching;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index f908eeb..9f83c04 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -45,7 +45,6 @@
import android.widget.ListView;
import android.widget.TextView;
-import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.RootInfo;
import java.util.ArrayList;
@@ -403,17 +402,7 @@
public static class RootComparator implements Comparator<RootItem> {
@Override
public int compare(RootItem lhs, RootItem rhs) {
- // Sort by root type, then title, then summary.
- int score = lhs.root.derivedType - rhs.root.derivedType;
- if (score != 0) {
- return score;
- }
- score = DocumentInfo.compareToIgnoreCaseNullable(lhs.root.title, rhs.root.title);
- if (score != 0) {
- return score;
- }
-
- return DocumentInfo.compareToIgnoreCaseNullable(lhs.root.summary, rhs.root.summary);
+ return lhs.root.compareTo(rhs.root);
}
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/SearchManager.java b/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java
similarity index 77%
rename from packages/DocumentsUI/src/com/android/documentsui/SearchManager.java
rename to packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java
index 69f54c7..63dc2ee 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/SearchManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java
@@ -16,6 +16,8 @@
package com.android.documentsui;
+import android.annotation.Nullable;
+import android.os.Bundle;
import android.provider.DocumentsContract.Root;
import android.text.TextUtils;
import android.util.Log;
@@ -31,28 +33,27 @@
/**
* Manages searching UI behavior.
*/
-final class SearchManager implements
+final class SearchViewManager implements
SearchView.OnCloseListener, OnQueryTextListener, OnClickListener, OnFocusChangeListener {
public interface SearchManagerListener {
- void onSearchChanged();
-
- void onSearchQueryChanged(String query);
+ void onSearchChanged(@Nullable String query);
}
public static final String TAG = "SearchManger";
private SearchManagerListener mListener;
- private String currentSearch;
private boolean mSearchExpanded;
+ private String mCurrentSearch;
private boolean mIgnoreNextClose;
private DocumentsToolbar mActionBar;
private MenuItem mMenu;
private SearchView mView;
- public SearchManager(SearchManagerListener listener) {
+ public SearchViewManager(SearchManagerListener listener, @Nullable Bundle savedState) {
mListener = listener;
+ mCurrentSearch = savedState != null ? savedState.getString(Shared.EXTRA_QUERY) : null;
}
public void setSearchMangerListener(SearchManagerListener listener) {
@@ -60,7 +61,8 @@
}
public void install(DocumentsToolbar actionBar) {
- assert (mActionBar == null);
+ // assert(mActionBar == null);
+
mActionBar = actionBar;
mMenu = actionBar.getSearchMenu();
mView = (SearchView) mMenu.getActionView();
@@ -69,6 +71,8 @@
mView.setOnCloseListener(this);
mView.setOnSearchClickListener(this);
mView.setOnQueryTextFocusChangeListener(this);
+
+ restoreSearch();
}
/**
@@ -80,12 +84,12 @@
return;
}
- if (currentSearch != null) {
+ if (mCurrentSearch != null) {
mMenu.expandActionView();
mView.setIconified(false);
mView.clearFocus();
- mView.setQuery(currentSearch, false);
+ mView.setQuery(mCurrentSearch, false);
} else {
mView.clearFocus();
if (!mView.isIconified()) {
@@ -108,13 +112,11 @@
return;
}
- mMenu.setVisible(visible);
if (!visible) {
- currentSearch = null;
- if (mListener != null) {
- mListener.onSearchQueryChanged(currentSearch);
- }
+ mCurrentSearch = null;
}
+
+ mMenu.setVisible(visible);
}
/**
@@ -133,8 +135,21 @@
return false;
}
+ private void restoreSearch() {
+ if (isSearching()) {
+ onSearchExpanded();
+ mView.setIconified(false);
+ mView.setQuery(mCurrentSearch, false);
+ mView.clearFocus();
+ }
+ }
+
+ private void onSearchExpanded() {
+ mSearchExpanded = true;
+ }
+
boolean isSearching() {
- return currentSearch != null;
+ return mCurrentSearch != null;
}
boolean isExpanded() {
@@ -142,6 +157,14 @@
}
/**
+ * Called when owning activity is saving state to be used to restore state during creation.
+ * @param state Bundle to save state too
+ */
+ public void onSaveInstanceState(Bundle state) {
+ state.putString(Shared.EXTRA_QUERY, mCurrentSearch);
+ }
+
+ /**
* Clears the search. Clears the SearchView background color. Triggers refreshing of the
* directory content.
* @return True if the default behavior of clearing/dismissing SearchView should be overridden.
@@ -155,15 +178,11 @@
return false;
}
- mView.setBackgroundColor(
- mView.getResources().getColor(android.R.color.transparent, null));
-
// Refresh the directory if a search was done
- if (currentSearch != null) {
- currentSearch = null;
+ if (mCurrentSearch != null) {
+ mCurrentSearch = null;
if (mListener != null) {
- mListener.onSearchQueryChanged(currentSearch);
- mListener.onSearchChanged();
+ mListener.onSearchChanged(mCurrentSearch);
}
}
return false;
@@ -176,18 +195,15 @@
*/
@Override
public void onClick(View v) {
- mSearchExpanded = true;
- mView.setBackgroundColor(
- mView.getResources().getColor(R.color.menu_search_background, null));
+ onSearchExpanded();
}
@Override
public boolean onQueryTextSubmit(String query) {
- currentSearch = query;
+ mCurrentSearch = query;
mView.clearFocus();
if (mListener != null) {
- mListener.onSearchQueryChanged(currentSearch);
- mListener.onSearchChanged();
+ mListener.onSearchChanged(mCurrentSearch);
}
return true;
}
@@ -195,7 +211,7 @@
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
- if (currentSearch == null) {
+ if (mCurrentSearch == null) {
mView.setIconified(true);
} else if (TextUtils.isEmpty(mView.getQuery())) {
cancelSearch();
@@ -207,4 +223,9 @@
public boolean onQueryTextChange(String newText) {
return false;
}
+
+ String getCurrentSearch() {
+ return mCurrentSearch;
+ }
+
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
index 22cb25a..26900a7 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
@@ -17,14 +17,24 @@
package com.android.documentsui;
import android.content.Context;
+import android.content.res.Configuration;
+import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.format.Time;
+import android.view.WindowManager;
+import android.app.AlertDialog;
+import java.text.Collator;
import java.util.ArrayList;
import java.util.List;
/** @hide */
public final class Shared {
+
+ public static final String TAG = "Documents";
+
+ public static final boolean DEBUG = true;
+
/** Intent action name to pick a copy destination. */
public static final String ACTION_PICK_COPY_DESTINATION =
"com.android.documentsui.PICK_COPY_DESTINATION";
@@ -34,12 +44,62 @@
* specifies if the destination directory needs to create new directory or not.
*/
public static final String EXTRA_DIRECTORY_COPY = "com.android.documentsui.DIRECTORY_COPY";
-
- public static final boolean DEBUG = true;
- public static final String TAG = "Documents";
public static final String EXTRA_STACK = "com.android.documentsui.STACK";
/**
+ * Extra flag used to store query of type String in the bundle.
+ */
+ public static final String EXTRA_QUERY = "query";
+
+ /**
+ * Extra flag used to store state of type State in the bundle.
+ */
+ public static final String EXTRA_STATE = "state";
+
+ /**
+ * Extra flag used to store type of DirectoryFragment's type ResultType type in the bundle.
+ */
+ public static final String EXTRA_TYPE = "type";
+
+ /**
+ * Extra flag used to store root of type RootInfo in the bundle.
+ */
+ public static final String EXTRA_ROOT = "root";
+
+ /**
+ * Extra flag used to store document of DocumentInfo type in the bundle.
+ */
+ public static final String EXTRA_DOC = "document";
+
+ /**
+ * Extra flag used to store DirectoryFragment's selection of Selection type in the bundle.
+ */
+ public static final String EXTRA_SELECTION = "selection";
+
+ /**
+ * Extra flag used to store DirectoryFragment's search mode of boolean type in the bundle.
+ */
+ public static final String EXTRA_SEARCH_MODE = "searchMode";
+
+ /**
+ * Extra flag used to store DirectoryFragment's ignore state of boolean type in the bundle.
+ */
+ public static final String EXTRA_IGNORE_STATE = "ignoreState";
+
+
+ /**
+ * String prefix used to indicate the document is a directory.
+ */
+ public static final char DIR_PREFIX = '\001';
+
+ private static final Collator sCollator;
+
+ static {
+ sCollator = Collator.getInstance();
+ sCollator.setStrength(Collator.SECONDARY);
+ }
+
+ /**
* Generates a formatted quantity string.
*/
public static final String getQuantityString(Context context, int resourceId, int quantity) {
@@ -76,4 +136,37 @@
? (ArrayList<T>) list
: new ArrayList<T>(list);
}
+
+ /**
+ * Compare two strings against each other using system default collator in a
+ * case-insensitive mode. Clusters strings prefixed with {@link DIR_PREFIX}
+ * before other items.
+ */
+ public static int compareToIgnoreCaseNullable(String lhs, String rhs) {
+ final boolean leftEmpty = TextUtils.isEmpty(lhs);
+ final boolean rightEmpty = TextUtils.isEmpty(rhs);
+
+ if (leftEmpty && rightEmpty) return 0;
+ if (leftEmpty) return -1;
+ if (rightEmpty) return 1;
+
+ final boolean leftDir = (lhs.charAt(0) == DIR_PREFIX);
+ final boolean rightDir = (rhs.charAt(0) == DIR_PREFIX);
+
+ if (leftDir && !rightDir) return -1;
+ if (rightDir && !leftDir) return 1;
+
+ return sCollator.compare(lhs, rhs);
+ }
+
+ public static boolean isHardwareKeyboardAvailable(Context context) {
+ return context.getResources().getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS;
+ }
+
+ public static void ensureKeyboardPresent(Context context, AlertDialog dialog) {
+ if (!isHardwareKeyboardAvailable(context)) {
+ dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
+ }
+ }
+
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Snackbars.java b/packages/DocumentsUI/src/com/android/documentsui/Snackbars.java
index 48c1a73..b4d7971 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Snackbars.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Snackbars.java
@@ -16,8 +16,6 @@
package com.android.documentsui;
-import static com.android.internal.util.Preconditions.checkNotNull;
-
import android.app.Activity;
import android.support.design.widget.Snackbar;
import android.view.View;
@@ -26,12 +24,13 @@
private Snackbars() {}
public static final Snackbar makeSnackbar(Activity activity, int messageId, int duration) {
- return Snackbars.makeSnackbar(activity, activity.getResources().getText(messageId), duration);
+ return Snackbars.makeSnackbar(
+ activity, activity.getResources().getText(messageId), duration);
}
- public static final Snackbar makeSnackbar(Activity activity, CharSequence message, int duration)
- {
- final View view = checkNotNull(activity.findViewById(R.id.coordinator_layout));
+ public static final Snackbar makeSnackbar(
+ Activity activity, CharSequence message, int duration) {
+ final View view = activity.findViewById(R.id.coordinator_layout);
return Snackbar.make(view, message, duration);
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/State.java b/packages/DocumentsUI/src/com/android/documentsui/State.java
index 0948ab1..4f460b4 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/State.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/State.java
@@ -82,8 +82,6 @@
public boolean forceSize;
public boolean showSize;
public boolean localOnly;
- public boolean forceAdvanced;
- public boolean showAdvanced;
public boolean restored;
// Indicates that a copy operation (or move) includes a directory.
@@ -105,9 +103,6 @@
private boolean mInitialRootChanged;
private boolean mInitialDocChanged;
- /** Currently active search, overriding any stack. */
- public String currentSearch;
-
/** Instance state for every shown directory */
public HashMap<String, SparseArray<Parcelable>> dirState = new HashMap<>();
@@ -160,11 +155,13 @@
mStackTouched = true;
}
+ // This will return true even when the initial location is set.
+ // To get a read on if the user has changed something, use #hasInitialLocationChanged.
public boolean hasLocationChanged() {
return mStackTouched;
}
- public boolean initialLocationHasChanged() {
+ public boolean hasInitialLocationChanged() {
return mInitialRootChanged || mInitialDocChanged;
}
@@ -182,11 +179,8 @@
out.writeInt(forceSize ? 1 : 0);
out.writeInt(showSize ? 1 : 0);
out.writeInt(localOnly ? 1 : 0);
- out.writeInt(forceAdvanced ? 1 : 0);
- out.writeInt(showAdvanced ? 1 : 0);
out.writeInt(restored ? 1 : 0);
DurableUtils.writeToParcel(out, stack);
- out.writeString(currentSearch);
out.writeMap(dirState);
out.writeParcelable(selectedDocuments, 0);
out.writeList(selectedDocumentsForCopy);
@@ -213,11 +207,8 @@
state.forceSize = in.readInt() != 0;
state.showSize = in.readInt() != 0;
state.localOnly = in.readInt() != 0;
- state.forceAdvanced = in.readInt() != 0;
- state.showAdvanced = in.readInt() != 0;
state.restored = in.readInt() != 0;
DurableUtils.readFromParcel(in, state.stack);
- state.currentSearch = in.readString();
in.readMap(state.dirState, loader);
state.selectedDocuments = in.readParcelable(loader);
in.readList(state.selectedDocumentsForCopy, loader);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index 236fa94..83838d3 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -23,21 +23,19 @@
import static com.android.documentsui.State.SORT_ORDER_UNKNOWN;
import static com.android.documentsui.model.DocumentInfo.getCursorInt;
import static com.android.documentsui.model.DocumentInfo.getCursorString;
-import static com.android.internal.util.Preconditions.checkNotNull;
-import static com.android.internal.util.Preconditions.checkState;
-import static com.google.common.base.Preconditions.checkArgument;
import android.annotation.IntDef;
import android.annotation.StringRes;
import android.app.Activity;
import android.app.ActivityManager;
+import android.app.AlertDialog;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.ClipData;
-import android.content.ContentResolver;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
@@ -52,6 +50,7 @@
import android.provider.DocumentsContract.Document;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
+import android.support.v13.view.DragStartHelper;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.GridLayoutManager.SpanSizeLookup;
import android.support.v7.widget.RecyclerView;
@@ -72,7 +71,6 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewParent;
import android.widget.ImageView;
import android.widget.TextView;
@@ -88,7 +86,7 @@
import com.android.documentsui.MessageBar;
import com.android.documentsui.MimePredicate;
import com.android.documentsui.R;
-import com.android.documentsui.RecentLoader;
+import com.android.documentsui.RecentsLoader;
import com.android.documentsui.RootsCache;
import com.android.documentsui.Shared;
import com.android.documentsui.Snackbars;
@@ -109,23 +107,31 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
/**
* Display the documents inside a single directory.
*/
-public class DirectoryFragment extends Fragment implements DocumentsAdapter.Environment {
+public class DirectoryFragment extends Fragment
+ implements DocumentsAdapter.Environment, LoaderCallbacks<DirectoryResult> {
@IntDef(flag = true, value = {
TYPE_NORMAL,
- TYPE_SEARCH,
TYPE_RECENT_OPEN
})
@Retention(RetentionPolicy.SOURCE)
public @interface ResultType {}
public static final int TYPE_NORMAL = 1;
- public static final int TYPE_SEARCH = 2;
- public static final int TYPE_RECENT_OPEN = 3;
+ public static final int TYPE_RECENT_OPEN = 2;
+ @IntDef(flag = true, value = {
+ ANIM_NONE,
+ ANIM_SIDE,
+ ANIM_LEAVE,
+ ANIM_ENTER
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AnimationType {}
public static final int ANIM_NONE = 1;
public static final int ANIM_SIDE = 2;
public static final int ANIM_LEAVE = 3;
@@ -138,19 +144,8 @@
public @interface RequestCode {}
public static final int REQUEST_COPY_DESTINATION = 1;
- static final boolean DEBUG_ENABLE_DND = true;
-
private static final String TAG = "DirectoryFragment";
private static final int LOADER_ID = 42;
- private static final int DELETE_UNDO_TIMEOUT = 5000;
- private static final int DELETE_JOB_DELAY = 5500;
- private static final int EMPTY_REVEAL_DURATION = 250;
-
- private static final String EXTRA_TYPE = "type";
- private static final String EXTRA_ROOT = "root";
- private static final String EXTRA_DOC = "doc";
- private static final String EXTRA_QUERY = "query";
- private static final String EXTRA_IGNORE_STATE = "ignoreState";
private Model mModel;
private MultiSelectManager mSelectionManager;
@@ -164,30 +159,36 @@
private RecyclerView mRecView;
private ListeningGestureDetector mGestureDetector;
- private @ResultType int mType = TYPE_NORMAL;
private String mStateKey;
private int mLastSortOrder = SORT_ORDER_UNKNOWN;
private DocumentsAdapter mAdapter;
- private LoaderCallbacks<DirectoryResult> mCallbacks;
private FragmentTuner mTuner;
private DocumentClipper mClipper;
private GridLayoutManager mLayout;
private int mColumnCount = 1; // This will get updated when layout changes.
+ private LayoutInflater mInflater;
private MessageBar mMessageBar;
private View mProgressBar;
+ // Directory fragment state is defined by: root, document, query, type, selection
+ private @ResultType int mType = TYPE_NORMAL;
+ private RootInfo mRoot;
+ private DocumentInfo mDocument;
+ private String mQuery = null;
+ private Selection mSelection = null;
+ private boolean mSearchMode = false;
+
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ mInflater = inflater;
final View view = inflater.inflate(R.layout.fragment_directory, container, false);
mMessageBar = MessageBar.create(getChildFragmentManager());
mProgressBar = view.findViewById(R.id.progressbar);
-
mEmptyView = view.findViewById(android.R.id.empty);
-
mRecView = (RecyclerView) view.findViewById(R.id.dir_list);
mRecView.setRecyclerListener(
new RecyclerListener() {
@@ -199,17 +200,16 @@
mRecView.setItemAnimator(new DirectoryItemAnimator(getActivity()));
- // TODO: Add a divider between views (which might use RecyclerView.ItemDecoration).
- if (DEBUG_ENABLE_DND) {
- setupDragAndDropOnDirectoryView(mRecView);
- }
+ // Make the recycler and the empty views responsive to drop events.
+ mRecView.setOnDragListener(mOnDragListener);
+ mEmptyView.setOnDragListener(mOnDragListener);
return view;
}
@Override
public void onDestroyView() {
- super.onDestroyView();
+ mSelectionManager.clearSelection();
// Cancel any outstanding thumbnail requests
final int count = mRecView.getChildCount();
@@ -217,6 +217,8 @@
final View view = mRecView.getChildAt(i);
cancelThumbnailTask(view);
}
+
+ super.onDestroyView();
}
@Override
@@ -226,9 +228,16 @@
final Context context = getActivity();
final State state = getDisplayState();
- final RootInfo root = getArguments().getParcelable(EXTRA_ROOT);
- final DocumentInfo doc = getArguments().getParcelable(EXTRA_DOC);
- mStateKey = buildStateKey(root, doc);
+ // Read arguments when object created for the first time.
+ // Restore state if fragment recreated.
+ Bundle args = savedInstanceState == null ? getArguments() : savedInstanceState;
+ mRoot = args.getParcelable(Shared.EXTRA_ROOT);
+ mDocument = args.getParcelable(Shared.EXTRA_DOC);
+ mStateKey = buildStateKey(mRoot, mDocument);
+ mQuery = args.getString(Shared.EXTRA_QUERY);
+ mType = args.getInt(Shared.EXTRA_TYPE);
+ mSelection = args.getParcelable(Shared.EXTRA_SELECTION);
+ mSearchMode = args.getBoolean(Shared.EXTRA_SEARCH_MODE);
mIconHelper = new IconHelper(context, MODE_GRID);
@@ -244,17 +253,11 @@
}
mRecView.setLayoutManager(mLayout);
- mGestureDetector = new ListeningGestureDetector(this.getContext(), new GestureListener());
+ mGestureDetector =
+ new ListeningGestureDetector(this.getContext(), mDragHelper, new GestureListener());
mRecView.addOnItemTouchListener(mGestureDetector);
- // final here because we'll manually bump the listener iwhen we had an initial selection,
- // but only after the model is fully loaded.
- final SelectionModeListener selectionListener = new SelectionModeListener();
- final Selection initialSelection = state.selectedDocuments.hasDirectoryKey(mStateKey)
- ? state.selectedDocuments
- : null;
-
// TODO: instead of inserting the view into the constructor, extract listener-creation code
// and set the listener on the view after the fact. Then the view doesn't need to be passed
// into the selection manager.
@@ -264,18 +267,16 @@
state.allowMultiple
? MultiSelectManager.MODE_MULTIPLE
: MultiSelectManager.MODE_SINGLE,
- initialSelection);
+ null);
- mSelectionManager.addCallback(selectionListener);
-
- // Make sure this is done after the RecyclerView is set up.
- mFocusManager = new FocusManager(mRecView);
+ mSelectionManager.addCallback(new SelectionModeListener());
mModel = new Model();
mModel.addUpdateListener(mAdapter);
mModel.addUpdateListener(mModelUpdateListener);
- mType = getArguments().getInt(EXTRA_TYPE);
+ // Make sure this is done after the RecyclerView is set up.
+ mFocusManager = new FocusManager(context, mRecView, mModel);
mTuner = FragmentTuner.pick(getContext(), state);
mClipper = new DocumentClipper(context);
@@ -286,7 +287,7 @@
hideGridTitles = MimePredicate.mimeMatches(
MimePredicate.VISUAL_MIMES, state.acceptMimes);
} else {
- hideGridTitles = (doc != null) && doc.isGridTitlesHidden();
+ hideGridTitles = (mDocument != null) && mDocument.isGridTitlesHidden();
}
GridDocumentHolder.setHideTitles(hideGridTitles);
@@ -295,86 +296,23 @@
boolean svelte = am.isLowRamDevice() && (mType == TYPE_RECENT_OPEN);
mIconHelper.setThumbnailsEnabled(!svelte);
- mCallbacks = new LoaderCallbacks<DirectoryResult>() {
- @Override
- public Loader<DirectoryResult> onCreateLoader(int id, Bundle args) {
- final String query = getArguments().getString(EXTRA_QUERY);
-
- Uri contentsUri;
- switch (mType) {
- case TYPE_NORMAL:
- contentsUri = DocumentsContract.buildChildDocumentsUri(
- doc.authority, doc.documentId);
- if (state.action == ACTION_MANAGE) {
- contentsUri = DocumentsContract.setManageMode(contentsUri);
- }
- return new DirectoryLoader(
- context, mType, root, doc, contentsUri, state.userSortOrder);
- case TYPE_SEARCH:
- contentsUri = DocumentsContract.buildSearchDocumentsUri(
- root.authority, root.rootId, query);
- if (state.action == ACTION_MANAGE) {
- contentsUri = DocumentsContract.setManageMode(contentsUri);
- }
- return new DirectoryLoader(
- context, mType, root, doc, contentsUri, state.userSortOrder);
- case TYPE_RECENT_OPEN:
- final RootsCache roots = DocumentsApplication.getRootsCache(context);
- return new RecentLoader(context, roots, state);
- default:
- throw new IllegalStateException("Unknown type " + mType);
- }
- }
-
- @Override
- public void onLoadFinished(Loader<DirectoryResult> loader, DirectoryResult result) {
- if (!isAdded()) return;
-
- mModel.update(result);
- state.derivedSortOrder = result.sortOrder;
-
- updateDisplayState();
-
- if (initialSelection != null) {
- selectionListener.onSelectionChanged();
- }
-
- // Restore any previous instance state
- final SparseArray<Parcelable> container = state.dirState.remove(mStateKey);
- if (container != null && !getArguments().getBoolean(EXTRA_IGNORE_STATE, false)) {
- getView().restoreHierarchyState(container);
- } else if (mLastSortOrder != state.derivedSortOrder) {
- // The derived sort order takes the user sort order into account, but applies
- // directory-specific defaults when the user doesn't explicitly set the sort
- // order. Scroll to the top if the sort order actually changed.
- mRecView.smoothScrollToPosition(0);
- }
-
- mLastSortOrder = state.derivedSortOrder;
-
- mTuner.onModelLoaded(mModel, mType);
- }
-
- @Override
- public void onLoaderReset(Loader<DirectoryResult> loader) {
- mModel.update(null);
- }
- };
-
// Kick off loader at least once
- getLoaderManager().restartLoader(LOADER_ID, null, mCallbacks);
+ getLoaderManager().restartLoader(LOADER_ID, null, this);
}
@Override
public void onSaveInstanceState(Bundle outState) {
- State state = getDisplayState();
- if (mSelectionManager.hasSelection()) {
- mSelectionManager.getSelection(state.selectedDocuments);
- state.selectedDocuments.setDirectoryKey(mStateKey);
- if (!state.selectedDocuments.isEmpty()) {
- if (DEBUG) Log.d(TAG, "Persisted selection: " + state.selectedDocuments);
- }
- }
+ super.onSaveInstanceState(outState);
+
+ mSelectionManager.getSelection(mSelection);
+
+ outState.putInt(Shared.EXTRA_TYPE, mType);
+ outState.putParcelable(Shared.EXTRA_ROOT, mRoot);
+ outState.putParcelable(Shared.EXTRA_DOC, mDocument);
+ outState.putString(Shared.EXTRA_QUERY, mQuery);
+ outState.putParcelable(Shared.EXTRA_SELECTION, mSelection);
+ outState.putBoolean(Shared.EXTRA_SEARCH_MODE, mSearchMode);
+
}
@Override
@@ -419,7 +357,9 @@
private boolean handleViewItem(String id) {
final Cursor cursor = mModel.getItem(id);
- checkNotNull(cursor, "Cursor cannot be null.");
+
+ assert(cursor != null);
+
final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
if (mTuner.isDocumentEnabled(docMimeType, docFlags)) {
@@ -449,7 +389,7 @@
public void onSortOrderChanged() {
// Sort order is implemented as a sorting wrapper around directory
// results. So when sort order changes, we force a reload of the directory.
- getLoaderManager().restartLoader(LOADER_ID, null, mCallbacks);
+ getLoaderManager().restartLoader(LOADER_ID, null, this);
}
public void onViewModeChanged() {
@@ -490,7 +430,8 @@
int cellMargin = 2 * getResources().getDimensionPixelSize(R.dimen.grid_item_margin);
int viewPadding = mRecView.getPaddingLeft() + mRecView.getPaddingRight();
- checkState(mRecView.getWidth() > 0);
+ assert(mRecView.getWidth() > 0);
+
int columnCount = Math.max(1,
(mRecView.getWidth() - viewPadding) / (cellWidth + cellMargin));
@@ -531,7 +472,9 @@
public boolean onBeforeItemStateChange(String modelId, boolean selected) {
if (selected) {
final Cursor cursor = mModel.getItem(modelId);
- checkNotNull(cursor, "Cursor cannot be null.");
+
+ assert(cursor != null);
+
final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
return mTuner.canSelectType(docMimeType, docFlags);
@@ -552,7 +495,8 @@
// triggered on "silent" selection updates (i.e. we might be reacting to unfinalized
// selection changes here)
final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
- if ((docFlags & Document.FLAG_SUPPORTS_DELETE) == 0) {
+ if ((docFlags & Document.FLAG_SUPPORTS_DELETE) == 0
+ && (docFlags & Document.FLAG_SUPPORTS_DELETE) == 0) {
mNoDeleteCount += selected ? 1 : -1;
}
if ((docFlags & Document.FLAG_SUPPORTS_RENAME) != 0) {
@@ -623,7 +567,7 @@
}
private void updateActionMenu() {
- checkNotNull(mMenu);
+ assert(mMenu != null);
// Delegate update logic to our owning action, since specialized logic is desired.
mTuner.updateActionMenu(mMenu, mType, canDeleteSelection(), canRenameSelection());
@@ -758,51 +702,47 @@
}
private void deleteDocuments(final Selection selected) {
+ assert(!selected.isEmpty());
- checkArgument(!selected.isEmpty());
final DocumentInfo srcParent = getDisplayState().stack.peek();
new GetDocumentsTask() {
@Override
- void onDocumentsReady(List<DocumentInfo> docs) {
- // Hide the files in the UI.
- final SparseArray<String> hidden = mAdapter.hide(selected.getAll());
+ void onDocumentsReady(final List<DocumentInfo> docs) {
- checkState(DELETE_JOB_DELAY > DELETE_UNDO_TIMEOUT);
- String operationId = FileOperations.delete(
- getActivity(), docs, srcParent, getDisplayState().stack,
- DELETE_JOB_DELAY);
- showDeleteSnackbar(hidden, operationId);
- }
- }.execute(selected);
- }
+ TextView message =
+ (TextView) mInflater.inflate(R.layout.dialog_delete_confirmation, null);
+ message.setText(
+ Shared.getQuantityString(
+ getActivity(),
+ R.plurals.delete_confirmation_message,
+ docs.size()));
- private void showDeleteSnackbar(final SparseArray<String> hidden, final String jobId) {
-
- Context context = getActivity();
- String message = Shared.getQuantityString(context, R.plurals.deleting, hidden.size());
-
- // Show a snackbar informing the user that files will be deleted, and give them an option to
- // cancel.
- final Activity activity = getActivity();
- Snackbars.makeSnackbar(activity, message, DELETE_UNDO_TIMEOUT)
- .setAction(
- R.string.undo,
- new View.OnClickListener() {
- @Override
- public void onClick(View view) {}
- })
- .setCallback(
- new Snackbar.Callback() {
- @Override
- public void onDismissed(Snackbar snackbar, int event) {
- if (event == Snackbar.Callback.DISMISS_EVENT_ACTION) {
- // If the delete was cancelled, just unhide the files.
- FileOperations.cancel(activity, jobId);
- mAdapter.unhide(hidden);
- }
+ // This "insta-hides" files that are being deleted, because
+ // the delete operation may be not execute immediately (it
+ // may be queued up on the FileOperationService.)
+ // To hide the files locally, we call the hide method on the adapter
+ // ...which a live object...cannot be parceled.
+ // For that reason, for now, we implement this dialog NOT
+ // as a fragment (which can survive rotation and have its own state),
+ // but as a simple runtime dialog. So rotating a device with an
+ // active delete dialog...results in that dialog disappearing.
+ // We can do better, but don't have cycles for it now.
+ new AlertDialog.Builder(getActivity())
+ .setView(message)
+ .setPositiveButton(
+ android.R.string.yes,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ // Hide the files in the UI.
+ mAdapter.hide(selected.getAll());
+ FileOperations.delete(
+ getActivity(), docs, srcParent, getDisplayState().stack);
}
})
- .show();
+ .setNegativeButton(android.R.string.no, null)
+ .show();
+ }
+ }.execute(selected);
}
private void transferDocuments(final Selection selected, final @OpType int mode) {
@@ -854,7 +794,7 @@
private void renameDocuments(Selection selected) {
// Batch renaming not supported
// Rename option is only available in menu when 1 document selected
- checkArgument(selected.size() == 1);
+ assert(selected.size() == 1);
new GetDocumentsTask() {
@Override
@@ -872,9 +812,7 @@
@Override
public void onBindDocumentHolder(DocumentHolder holder, Cursor cursor) {
- if (DEBUG_ENABLE_DND) {
- setupDragAndDropOnDocumentView(holder.itemView, cursor);
- }
+ setupDragAndDropOnDocumentView(holder.itemView, cursor);
}
@Override
@@ -969,7 +907,8 @@
}
private void copyFromClipData(final ClipData clipData, final DocumentInfo destination) {
- checkNotNull(clipData);
+ assert(clipData != null);
+
new AsyncTask<Void, Void, List<DocumentInfo>>() {
@Override
@@ -1011,25 +950,6 @@
FileOperations.copy(getActivity(), docs, tmpStack);
}
- private ClipData getClipDataFromDocuments(List<DocumentInfo> docs) {
- Context context = getActivity();
- final ContentResolver resolver = context.getContentResolver();
- ClipData clipData = null;
- for (DocumentInfo doc : docs) {
- final Uri uri = DocumentsContract.buildDocumentUri(doc.authority, doc.documentId);
- if (clipData == null) {
- // TODO: figure out what this string should be.
- // Currently it is not displayed anywhere in the UI, but this might change.
- final String label = "";
- clipData = ClipData.newUri(resolver, label, uri);
- } else {
- // TODO: update list of mime types in ClipData.
- clipData.addItem(new ClipData.Item(uri));
- }
- }
- return clipData;
- }
-
public void copySelectedToClipboard() {
Selection selection = mSelectionManager.getSelection(new Selection());
if (!selection.isEmpty()) {
@@ -1039,7 +959,7 @@
}
void copySelectionToClipboard(Selection selection) {
- checkArgument(!selection.isEmpty());
+ assert(!selection.isEmpty());
new GetDocumentsTask() {
@Override
void onDocumentsReady(List<DocumentInfo> docs) {
@@ -1071,8 +991,8 @@
return false;
}
- // Can't copy folders to roots that don't support children.
- if (!root.supportsChildren()) {
+ // Can't copy folders to downloads, because we don't show folders there.
+ if (!root.isDownloads()) {
for (DocumentInfo docs : files) {
if (docs.isDirectory()) {
return false;
@@ -1098,11 +1018,6 @@
mFocusManager.restoreLastFocus();
}
- private void setupDragAndDropOnDirectoryView(View view) {
- // Listen for drops on non-directory items and empty space.
- view.setOnDragListener(mOnDragListener);
- }
-
private void setupDragAndDropOnDocumentView(View view, Cursor cursor) {
final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
if (Document.MIME_TYPE_DIR.equals(docMimeType)) {
@@ -1111,7 +1026,8 @@
view.setOnDragListener(mOnDragListener);
}
- view.setOnLongClickListener(mLongClickListener);
+ // Make all items draggable.
+ view.setOnLongClickListener(mDragHelper);
}
private View.OnDragListener mOnDragListener = new View.OnDragListener() {
@@ -1122,28 +1038,66 @@
// TODO: Check if the event contains droppable data.
return true;
- // TODO: Highlight potential drop target directory?
// TODO: Expand drop target directory on hover?
case DragEvent.ACTION_DRAG_ENTERED:
- case DragEvent.ACTION_DRAG_LOCATION:
+ setDropTargetHighlight(v, true);
+ return true;
case DragEvent.ACTION_DRAG_EXITED:
+ setDropTargetHighlight(v, false);
+ return true;
+
+ case DragEvent.ACTION_DRAG_LOCATION:
+ return true;
+
case DragEvent.ACTION_DRAG_ENDED:
+ if (event.getResult()) {
+ // Exit selection mode if the drop was handled.
+ mSelectionManager.clearSelection();
+ }
return true;
case DragEvent.ACTION_DROP:
- String dstId = getModelId(v);
- DocumentInfo dstDir = null;
- if (dstId != null) {
- Cursor dstCursor = mModel.getItem(dstId);
- checkNotNull(dstCursor, "Cursor cannot be null.");
- dstDir = DocumentInfo.fromDirectoryCursor(dstCursor);
- // TODO: Do not drop into the directory where the documents came from.
+ // After a drop event, always stop highlighting the target.
+ setDropTargetHighlight(v, false);
+ // Don't copy from the cwd into the cwd. Note: this currently doesn't work for
+ // multi-window drag, because localState isn't carried over from one process to
+ // another.
+ Object src = event.getLocalState();
+ DocumentInfo dst = getDestination(v);
+ if (Objects.equals(src, dst)) {
+ return false;
}
- copyFromClipData(event.getClipData(), dstDir);
+ copyFromClipData(event.getClipData(), dst);
return true;
}
return false;
}
+
+ private DocumentInfo getDestination(View v) {
+ String id = getModelId(v);
+ if (id != null) {
+ Cursor dstCursor = mModel.getItem(id);
+ assert(dstCursor != null);
+ return DocumentInfo.fromDirectoryCursor(dstCursor);
+ }
+
+ if (v == mRecView || v == mEmptyView) {
+ return getDisplayState().stack.peek();
+ }
+
+ return null;
+ }
+
+ private void setDropTargetHighlight(View v, boolean highlight) {
+ // Note: use exact comparison - this code is searching for views which are children of
+ // the RecyclerView instance in the UI.
+ if (v.getParent() == mRecView) {
+ RecyclerView.ViewHolder vh = mRecView.getChildViewHolder(v);
+ if (vh instanceof DocumentHolder) {
+ ((DocumentHolder) vh).setHighlighted(highlight);
+ }
+ }
+ }
};
/**
@@ -1169,21 +1123,14 @@
* a document item view.
*/
private String getModelId(View view) {
- while (true) {
- if (view.getLayoutParams() instanceof RecyclerView.LayoutParams) {
- RecyclerView.ViewHolder vh = mRecView.getChildViewHolder(view);
- if (vh instanceof DocumentHolder) {
- return ((DocumentHolder) vh).modelId;
- } else {
- return null;
- }
+ View itemView = mRecView.findContainingItemView(view);
+ if (itemView != null) {
+ RecyclerView.ViewHolder vh = mRecView.getChildViewHolder(itemView);
+ if (vh instanceof DocumentHolder) {
+ return ((DocumentHolder) vh).modelId;
}
- ViewParent parent = view.getParent();
- if (parent == null || !(parent instanceof View)) {
- return null;
- }
- view = (View) parent;
}
+ return null;
}
private List<DocumentInfo> getDraggableDocuments(View currentItemView) {
@@ -1203,10 +1150,11 @@
}
final Cursor cursor = mModel.getItem(modelId);
- checkNotNull(cursor, "Cursor cannot be null.");
- final DocumentInfo doc = DocumentInfo.fromDirectoryCursor(cursor);
- return Lists.newArrayList(doc);
+ assert(cursor != null);
+
+ return Lists.newArrayList(
+ DocumentInfo.fromDirectoryCursor(cursor));
}
private Drawable getDragShadowIcon(List<DocumentInfo> docs) {
@@ -1296,6 +1244,11 @@
return false;
}
+ // Ignore tab key events. Those should be handled by the top-level key handler.
+ if (keyCode == KeyEvent.KEYCODE_TAB) {
+ return false;
+ }
+
if (mFocusManager.handleKey(doc, keyCode, event)) {
// Handle range selection adjustments. Extending the selection will adjust the
// bounds of the in-progress range selection. Each time an unshifted navigation
@@ -1342,7 +1295,7 @@
mProgressBar.setVisibility(model.isLoading() ? View.VISIBLE : View.GONE);
if (model.isEmpty()) {
- if (getDisplayState().currentSearch != null) {
+ if (mSearchMode) {
showNoResults(getDisplayState().stack.root);
} else {
showEmptyDirectory();
@@ -1351,6 +1304,11 @@
showDirectory();
mAdapter.notifyDataSetChanged();
}
+
+ if (!model.isLoading()) {
+ ((BaseActivity) getActivity()).notifyDirectoryLoaded(
+ model.doc != null ? model.doc.derivedUri : null);
+ }
}
@Override
@@ -1359,18 +1317,18 @@
}
}
- private View.OnLongClickListener mLongClickListener = new View.OnLongClickListener() {
+ private DragStartHelper mDragHelper = new DragStartHelper(null) {
@Override
- public boolean onLongClick(View v) {
- if (mGestureDetector.mouseSpawnedLastEvent()) {
+ protected boolean onDragStart(View v) {
+ if (isSelected(getModelId(v))) {
List<DocumentInfo> docs = getDraggableDocuments(v);
if (docs.isEmpty()) {
return false;
}
- v.startDrag(
- getClipDataFromDocuments(docs),
+ v.startDragAndDrop(
+ mClipper.getClipDataForDocuments(docs),
new DrawableShadowBuilder(getDragShadowIcon(docs)),
- null,
+ getDisplayState().stack.peek(),
View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_GLOBAL_URI_READ |
View.DRAG_FLAG_GLOBAL_URI_WRITE
);
@@ -1388,9 +1346,12 @@
implements OnItemTouchListener {
private int mLastTool = -1;
+ private DragStartHelper mDragHelper;
- public ListeningGestureDetector(Context context, GestureListener listener) {
+ public ListeningGestureDetector(
+ Context context, DragStartHelper dragHelper, GestureListener listener) {
super(context, listener);
+ mDragHelper = dragHelper;
setOnDoubleTapListener(listener);
}
@@ -1405,12 +1366,27 @@
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
mLastTool = e.getToolType(0);
- onTouchEvent(e); // bounce this forward to our detecty heart
+
+ // Detect drag events. When a drag is detected, intercept the rest of the gesture.
+ View itemView = rv.findChildViewUnder(e.getX(), e.getY());
+ if (itemView != null && mDragHelper.handleTouch(itemView, e)) {
+ return true;
+ }
+ // Forward unhandled events to the GestureDetector.
+ onTouchEvent(e);
+
return false;
}
@Override
- public void onTouchEvent(RecyclerView rv, MotionEvent e) {}
+ public void onTouchEvent(RecyclerView rv, MotionEvent e) {
+ View itemView = rv.findChildViewUnder(e.getX(), e.getY());
+ mDragHelper.handleTouch(itemView, e);
+ // Note: even though this event is being handled as part of a drag gesture, continue
+ // forwarding to the GestureDetector. The detector needs to see the entire cluster of
+ // events in order to properly interpret gestures.
+ onTouchEvent(e);
+ }
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {}
@@ -1468,32 +1444,51 @@
public static void showDirectory(
FragmentManager fm, RootInfo root, DocumentInfo doc, int anim) {
- show(fm, TYPE_NORMAL, root, doc, null, anim);
- }
-
- public static void showSearch(FragmentManager fm, RootInfo root, String query, int anim) {
- show(fm, TYPE_SEARCH, root, null, query, anim);
+ create(fm, TYPE_NORMAL, root, doc, null, anim);
}
public static void showRecentsOpen(FragmentManager fm, int anim) {
- show(fm, TYPE_RECENT_OPEN, null, null, null, anim);
+ create(fm, TYPE_RECENT_OPEN, null, null, null, anim);
}
- private static void show(FragmentManager fm, int type, RootInfo root, DocumentInfo doc,
+ public static void reloadSearch(FragmentManager fm, RootInfo root, DocumentInfo doc,
+ String query) {
+ DirectoryFragment df = get(fm);
+
+ df.mQuery = query;
+ df.mRoot = root;
+ df.mDocument = doc;
+ df.mSearchMode = query != null;
+ df.getLoaderManager().restartLoader(LOADER_ID, null, df);
+ }
+
+ public static void reload(FragmentManager fm, int type, RootInfo root, DocumentInfo doc,
+ String query) {
+ DirectoryFragment df = get(fm);
+ df.mType = type;
+ df.mQuery = query;
+ df.mRoot = root;
+ df.mDocument = doc;
+ df.mSearchMode = query != null;
+ df.getLoaderManager().restartLoader(LOADER_ID, null, df);
+ }
+
+ public static void create(FragmentManager fm, int type, RootInfo root, DocumentInfo doc,
String query, int anim) {
final Bundle args = new Bundle();
- args.putInt(EXTRA_TYPE, type);
- args.putParcelable(EXTRA_ROOT, root);
- args.putParcelable(EXTRA_DOC, doc);
- args.putString(EXTRA_QUERY, query);
+ args.putInt(Shared.EXTRA_TYPE, type);
+ args.putParcelable(Shared.EXTRA_ROOT, root);
+ args.putParcelable(Shared.EXTRA_DOC, doc);
+ args.putString(Shared.EXTRA_QUERY, query);
+ args.putParcelable(Shared.EXTRA_SELECTION, new Selection());
final FragmentTransaction ft = fm.beginTransaction();
switch (anim) {
case ANIM_SIDE:
- args.putBoolean(EXTRA_IGNORE_STATE, true);
+ args.putBoolean(Shared.EXTRA_IGNORE_STATE, true);
break;
case ANIM_ENTER:
- args.putBoolean(EXTRA_IGNORE_STATE, true);
+ args.putBoolean(Shared.EXTRA_IGNORE_STATE, true);
ft.setCustomAnimations(R.animator.dir_enter, R.animator.dir_frozen);
break;
case ANIM_LEAVE:
@@ -1504,7 +1499,7 @@
final DirectoryFragment fragment = new DirectoryFragment();
fragment.setArguments(args);
- ft.replace(R.id.container_directory, fragment);
+ ft.replace(getFragmentId(), fragment);
ft.commitAllowingStateLoss();
}
@@ -1518,9 +1513,78 @@
public static @Nullable DirectoryFragment get(FragmentManager fm) {
// TODO: deal with multiple directories shown at once
- Fragment fragment = fm.findFragmentById(R.id.container_directory);
+ Fragment fragment = fm.findFragmentById(getFragmentId());
return fragment instanceof DirectoryFragment
? (DirectoryFragment) fragment
: null;
}
-}
+
+ private static int getFragmentId() {
+ return R.id.container_directory;
+ }
+
+ @Override
+ public Loader<DirectoryResult> onCreateLoader(int id, Bundle args) {
+ Context context = getActivity();
+ State state = getDisplayState();
+
+ Uri contentsUri;
+ switch (mType) {
+ case TYPE_NORMAL:
+ contentsUri = mSearchMode ? DocumentsContract.buildSearchDocumentsUri(
+ mRoot.authority, mRoot.rootId, mQuery)
+ : DocumentsContract.buildChildDocumentsUri(
+ mDocument.authority, mDocument.documentId);
+ if (state.action == ACTION_MANAGE) {
+ contentsUri = DocumentsContract.setManageMode(contentsUri);
+ }
+ return new DirectoryLoader(
+ context, mType, mRoot, mDocument, contentsUri, state.userSortOrder,
+ mSearchMode);
+ case TYPE_RECENT_OPEN:
+ final RootsCache roots = DocumentsApplication.getRootsCache(context);
+ return new RecentsLoader(context, roots, state);
+ default:
+ throw new IllegalStateException("Unknown type " + mType);
+ }
+ }
+
+ @Override
+ public void onLoadFinished(Loader<DirectoryResult> loader, DirectoryResult result) {
+ if (!isAdded()) return;
+
+ State state = getDisplayState();
+
+ mAdapter.notifyDataSetChanged();
+ mModel.update(result);
+
+ state.derivedSortOrder = result.sortOrder;
+
+ updateLayout(state.derivedMode);
+
+ if (mSelection != null) {
+ mSelectionManager.setItemsSelected(mSelection.toList(), true);
+ }
+
+ // Restore any previous instance state
+ final SparseArray<Parcelable> container = state.dirState.remove(mStateKey);
+ if (container != null && !getArguments().getBoolean(Shared.EXTRA_IGNORE_STATE, false)) {
+ getView().restoreHierarchyState(container);
+ } else if (mLastSortOrder != state.derivedSortOrder) {
+ // The derived sort order takes the user sort order into account, but applies
+ // directory-specific defaults when the user doesn't explicitly set the sort
+ // order. Scroll to the top if the sort order actually changed.
+ mRecView.smoothScrollToPosition(0);
+ }
+
+ mLastSortOrder = state.derivedSortOrder;
+
+ mTuner.onModelLoaded(mModel, mType, mSearchMode);
+
+ }
+
+ @Override
+ public void onLoaderReset(Loader<DirectoryResult> loader) {
+ mModel.update(null);
+ }
+ }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
index 1bfc6e9..3b5ce87 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
@@ -16,9 +16,6 @@
package com.android.documentsui.dirlist;
-import static com.android.internal.util.Preconditions.checkNotNull;
-import static com.android.internal.util.Preconditions.checkState;
-
import android.content.Context;
import android.database.Cursor;
import android.graphics.Rect;
@@ -75,27 +72,42 @@
*/
public abstract void bind(Cursor cursor, String modelId, State state);
+ /**
+ * Makes the associated item view appear selected. Note that this merely affects the appearance
+ * of the view, it doesn't actually select the item.
+ *
+ * @param selected
+ */
public void setSelected(boolean selected) {
itemView.setActivated(selected);
itemView.setBackgroundColor(selected ? mSelectedItemColor : mDefaultItemColor);
}
+ /**
+ * Highlights the associated item view.
+ * @param highlighted
+ */
+ public void setHighlighted(boolean highlighted) {
+ itemView.setBackgroundColor(highlighted ? mSelectedItemColor : mDefaultItemColor);
+ }
+
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
// Event listener should always be set.
- checkNotNull(mEventListener);
+ assert(mEventListener != null);
+
return mEventListener.onKey(this, keyCode, event);
}
public void addEventListener(DocumentHolder.EventListener listener) {
// Just handle one for now; switch to a list if necessary.
- checkState(mEventListener == null);
+ assert(mEventListener == null);
mEventListener = listener;
}
public void addOnKeyListener(View.OnKeyListener listener) {
// Just handle one for now; switch to a list if necessary.
- checkState(mKeyListener == null);
+ assert(mKeyListener == null);
mKeyListener = listener;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentsAdapter.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentsAdapter.java
index 0930c22..0bbecf9 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentsAdapter.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentsAdapter.java
@@ -74,13 +74,6 @@
abstract public SparseArray<String> hide(String... ids);
/**
- * Unhides a set of previously hidden items.
- *
- * @param ids A sparse array of IDs from a previous call to {@link #hide}.
- */
- abstract void unhide(SparseArray<String> ids);
-
- /**
* Returns a class that yields the span size for a particular element. This is
* primarily useful in {@link SectionBreakDocumentsAdapterWrapper} where
* we adjust sizes.
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FocusManager.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FocusManager.java
index e90a447..ac05c05 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FocusManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FocusManager.java
@@ -16,13 +16,34 @@
package com.android.documentsui.dirlist;
+import static com.android.documentsui.model.DocumentInfo.getCursorString;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.SystemClock;
+import android.provider.DocumentsContract.Document;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
+import android.text.Editable;
+import android.text.Spannable;
+import android.text.method.KeyListener;
+import android.text.method.TextKeyListener;
+import android.text.method.TextKeyListener.Capitalize;
+import android.text.style.BackgroundColorSpan;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
+import android.widget.TextView;
import com.android.documentsui.Events;
+import com.android.documentsui.R;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
/**
* A class that handles navigation and focus within the DirectoryFragment.
@@ -31,15 +52,21 @@
private static final String TAG = "FocusManager";
private RecyclerView mView;
- private RecyclerView.Adapter<?> mAdapter;
+ private DocumentsAdapter mAdapter;
private GridLayoutManager mLayout;
+ private TitleSearchHelper mSearchHelper;
+ private Model mModel;
+
private int mLastFocusPosition = RecyclerView.NO_POSITION;
- public FocusManager(RecyclerView view) {
+ public FocusManager(Context context, RecyclerView view, Model model) {
mView = view;
- mAdapter = view.getAdapter();
+ mAdapter = (DocumentsAdapter) view.getAdapter();
mLayout = (GridLayoutManager) view.getLayoutManager();
+ mModel = model;
+
+ mSearchHelper = new TitleSearchHelper(context);
}
/**
@@ -52,7 +79,11 @@
* @return Whether the event was handled.
*/
public boolean handleKey(DocumentHolder doc, int keyCode, KeyEvent event) {
- boolean extendSelection = false;
+ // Search helper gets first crack, for doing type-to-focus.
+ if (mSearchHelper.handleKey(doc, keyCode, event)) {
+ return true;
+ }
+
// Translate space/shift-space into PgDn/PgUp
if (keyCode == KeyEvent.KEYCODE_SPACE) {
if (event.isShiftPressed()) {
@@ -60,8 +91,6 @@
} else {
keyCode = KeyEvent.KEYCODE_PAGE_DOWN;
}
- } else {
- extendSelection = event.isShiftPressed();
}
if (Events.isNavigationKeyCode(keyCode)) {
@@ -90,6 +119,11 @@
* Requests focus on the item that last had focus. Scrolls to that item if necessary.
*/
public void restoreLastFocus() {
+ if (mAdapter.getItemCount() == 0) {
+ // Nothing to focus.
+ return;
+ }
+
if (mLastFocusPosition != RecyclerView.NO_POSITION) {
// The system takes care of situations when a view is no longer on screen, etc,
focusItem(mLastFocusPosition);
@@ -231,12 +265,24 @@
* @param pos
*/
private void focusItem(final int pos) {
+ focusItem(pos, null);
+ }
+
+ /**
+ * Requests focus for the item in the given adapter position, scrolling the RecyclerView if
+ * necessary.
+ *
+ * @param pos
+ * @param callback A callback to call after the given item has been focused.
+ */
+ private void focusItem(final int pos, @Nullable final FocusCallback callback) {
// If the item is already in view, focus it; otherwise, scroll to it and focus it.
RecyclerView.ViewHolder vh = mView.findViewHolderForAdapterPosition(pos);
if (vh != null) {
- vh.itemView.requestFocus();
+ if (vh.itemView.requestFocus() && callback != null) {
+ callback.onFocus(vh.itemView);
+ }
} else {
- mView.smoothScrollToPosition(pos);
// Set a one-time listener to request focus when the scroll has completed.
mView.addOnScrollListener(
new RecyclerView.OnScrollListener() {
@@ -247,7 +293,9 @@
RecyclerView.ViewHolder vh =
view.findViewHolderForAdapterPosition(pos);
if (vh != null) {
- vh.itemView.requestFocus();
+ if (vh.itemView.requestFocus() && callback != null) {
+ callback.onFocus(vh.itemView);
+ }
} else {
// This might happen in weird corner cases, e.g. if the user is
// scrolling while a delete operation is in progress. In that
@@ -258,6 +306,7 @@
}
}
});
+ mView.smoothScrollToPosition(pos);
}
}
@@ -267,4 +316,246 @@
private boolean inGridMode() {
return mLayout.getSpanCount() > 1;
}
+
+ private interface FocusCallback {
+ public void onFocus(View view);
+ }
+
+ /**
+ * A helper class for handling type-to-focus. Instantiate this class, and pass it KeyEvents via
+ * the {@link #handleKey(DocumentHolder, int, KeyEvent)} method. The class internally will build
+ * up a string from individual key events, and perform searching based on that string. When an
+ * item is found that matches the search term, that item will be focused. This class also
+ * highlights instances of the search term found in the view.
+ */
+ private class TitleSearchHelper {
+ static private final int SEARCH_TIMEOUT = 500; // ms
+
+ private final KeyListener mTextListener = new TextKeyListener(Capitalize.NONE, false);
+ private final Editable mSearchString = Editable.Factory.getInstance().newEditable("");
+ private final Highlighter mHighlighter = new Highlighter();
+ private final BackgroundColorSpan mSpan;
+
+ private List<String> mIndex;
+ private boolean mActive;
+ private Timer mTimer;
+ private KeyEvent mLastEvent;
+ private Handler mUiRunner;
+
+ public TitleSearchHelper(Context context) {
+ mSpan = new BackgroundColorSpan(context.getColor(R.color.accent_dark));
+ // Handler for running things on the main UI thread. Needed for updating the UI from a
+ // timer (see #activate, below).
+ mUiRunner = new Handler(Looper.getMainLooper());
+ }
+
+ /**
+ * Handles alphanumeric keystrokes for type-to-focus. This method builds a search term out
+ * of individual key events, and then performs a search for the given string.
+ *
+ * @param doc The document holder receiving the key event.
+ * @param keyCode
+ * @param event
+ * @return Whether the event was handled.
+ */
+ public boolean handleKey(DocumentHolder doc, int keyCode, KeyEvent event) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_ESCAPE:
+ case KeyEvent.KEYCODE_ENTER:
+ if (mActive) {
+ // These keys end any active searches.
+ endSearch();
+ return true;
+ } else {
+ // Don't handle these key events if there is no active search.
+ return false;
+ }
+ case KeyEvent.KEYCODE_SPACE:
+ // This allows users to search for files with spaces in their names, but ignores
+ // spacebar events when a text search is not active. Ignoring the spacebar
+ // event is necessary because other handlers (see FocusManager#handleKey) also
+ // listen for and handle it.
+ if (!mActive) {
+ return false;
+ }
+ }
+
+ // Navigation keys also end active searches.
+ if (Events.isNavigationKeyCode(keyCode)) {
+ endSearch();
+ // Don't handle the keycode, so navigation still occurs.
+ return false;
+ }
+
+ // Build up the search string, and perform the search.
+ boolean handled = mTextListener.onKeyDown(doc.itemView, mSearchString, keyCode, event);
+
+ // Delete is processed by the text listener, but not "handled". Check separately for it.
+ if (keyCode == KeyEvent.KEYCODE_DEL) {
+ handled = true;
+ }
+
+ if (handled) {
+ mLastEvent = event;
+ if (mSearchString.length() == 0) {
+ // Don't perform empty searches.
+ return false;
+ }
+ search();
+ }
+
+ return handled;
+ }
+
+ /**
+ * Activates the search helper, which changes its key handling and updates the search index
+ * and highlights if necessary. Call this each time the search term is updated.
+ */
+ private void search() {
+ if (!mActive) {
+ // The model listener invalidates the search index when the model changes.
+ mModel.addUpdateListener(mModelListener);
+
+ // Used to keep the current search alive until the timeout expires. If the user
+ // presses another key within that time, that keystroke is added to the current
+ // search. Otherwise, the current search ends, and subsequent keystrokes start a new
+ // search.
+ mTimer = new Timer();
+ mActive = true;
+ }
+
+ // If the search index was invalidated, rebuild it
+ if (mIndex == null) {
+ buildIndex();
+ }
+
+ // Search for the current search term.
+ // Perform case-insensitive search.
+ String searchString = mSearchString.toString().toLowerCase();
+ for (int pos = 0; pos < mIndex.size(); pos++) {
+ String title = mIndex.get(pos);
+ if (title != null && title.startsWith(searchString)) {
+ focusItem(pos, new FocusCallback() {
+ @Override
+ public void onFocus(View view) {
+ mHighlighter.applyHighlight(view);
+ // Using a timer repeat period of SEARCH_TIMEOUT/2 means the amount of
+ // time between the last keystroke and a search expiring is actually
+ // between 500 and 750 ms. A smaller timer period results in less
+ // variability but does more polling.
+ mTimer.schedule(new TimeoutTask(), 0, SEARCH_TIMEOUT / 2);
+ }
+ });
+ break;
+ }
+ }
+ }
+
+ /**
+ * Ends the current search (see {@link #search()}.
+ */
+ private void endSearch() {
+ if (mActive) {
+ mModel.removeUpdateListener(mModelListener);
+ mTimer.cancel();
+ }
+
+ mHighlighter.removeHighlight();
+
+ mIndex = null;
+ mSearchString.clear();
+ mActive = false;
+ }
+
+ /**
+ * Builds a search index for finding items by title. Queries the model and adapter, so both
+ * must be set up before calling this method.
+ */
+ private void buildIndex() {
+ int itemCount = mAdapter.getItemCount();
+ List<String> index = new ArrayList<>(itemCount);
+ for (int i = 0; i < itemCount; i++) {
+ String modelId = mAdapter.getModelId(i);
+ if (modelId != null) {
+ String title =
+ getCursorString(mModel.getItem(modelId), Document.COLUMN_DISPLAY_NAME);
+ // Perform case-insensitive search.
+ index.add(title.toLowerCase());
+ } else {
+ index.add("");
+ }
+ }
+ mIndex = index;
+ }
+
+ private Model.UpdateListener mModelListener = new Model.UpdateListener() {
+ @Override
+ public void onModelUpdate(Model model) {
+ // Invalidate the search index when the model updates.
+ mIndex = null;
+ }
+
+ @Override
+ public void onModelUpdateFailed(Exception e) {
+ // Invalidate the search index when the model updates.
+ mIndex = null;
+ }
+ };
+
+ private class TimeoutTask extends TimerTask {
+ @Override
+ public void run() {
+ long last = mLastEvent.getEventTime();
+ long now = SystemClock.uptimeMillis();
+ if ((now - last) > SEARCH_TIMEOUT) {
+ // endSearch must run on the main thread because it does UI work
+ mUiRunner.post(new Runnable() {
+ @Override
+ public void run() {
+ endSearch();
+ }
+ });
+ }
+ }
+ };
+
+ private class Highlighter {
+ private Spannable mCurrentHighlight;
+
+ /**
+ * Applies title highlights to the given view. The view must have a title field that is a
+ * spannable text field. If this condition is not met, this function does nothing.
+ *
+ * @param view
+ */
+ private void applyHighlight(View view) {
+ TextView titleView = (TextView) view.findViewById(android.R.id.title);
+ if (titleView == null) {
+ return;
+ }
+
+ CharSequence tmpText = titleView.getText();
+ if (tmpText instanceof Spannable) {
+ if (mCurrentHighlight != null) {
+ mCurrentHighlight.removeSpan(mSpan);
+ }
+ mCurrentHighlight = (Spannable) tmpText;
+ mCurrentHighlight.setSpan(
+ mSpan, 0, mSearchString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+ }
+
+ /**
+ * Removes title highlights from the given view. The view must have a title field that is a
+ * spannable text field. If this condition is not met, this function does nothing.
+ *
+ * @param view
+ */
+ private void removeHighlight() {
+ if (mCurrentHighlight != null) {
+ mCurrentHighlight.removeSpan(mSpan);
+ }
+ }
+ };
+ }
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
index a9b0fd1..f99ec85c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
@@ -16,24 +16,19 @@
package com.android.documentsui.dirlist;
-import static com.android.documentsui.Shared.DEBUG;
import static com.android.documentsui.State.ACTION_BROWSE;
import static com.android.documentsui.State.ACTION_CREATE;
import static com.android.documentsui.State.ACTION_GET_CONTENT;
import static com.android.documentsui.State.ACTION_MANAGE;
import static com.android.documentsui.State.ACTION_OPEN;
import static com.android.documentsui.State.ACTION_OPEN_TREE;
-import static com.android.internal.util.Preconditions.checkArgument;
import android.content.Context;
-import android.os.SystemProperties;
import android.provider.DocumentsContract.Document;
-import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
-import com.android.documentsui.DocumentsActivity;
-import com.android.documentsui.FilesActivity;
+import com.android.documentsui.BaseActivity;
import com.android.documentsui.Menus;
import com.android.documentsui.MimePredicate;
import com.android.documentsui.R;
@@ -66,8 +61,8 @@
}
- public abstract void updateActionMenu(Menu menu, int dirType, boolean canDelete,
- boolean canRename);
+ public abstract void updateActionMenu(
+ Menu menu, @ResultType int dirType, boolean canDelete, boolean canRename);
// Subtly different from isDocumentEnabled. The reason may be illuminated as follows.
// A folder is enabled such that it may be double clicked, even in settings
@@ -84,7 +79,7 @@
return MimePredicate.mimeMatches(mState.acceptMimes, docMimeType);
}
- abstract void onModelLoaded(Model model, @ResultType int resultType);
+ abstract void onModelLoaded(Model model, @ResultType int resultType, boolean isSearch);
/**
* Provides support for Platform specific specializations of DirectoryFragment.
@@ -140,38 +135,26 @@
}
@Override
- public void updateActionMenu(Menu menu, int dirType, boolean canDelete,
- boolean canRename) {
+ public void updateActionMenu(
+ Menu menu, @ResultType int dirType, boolean canDelete, boolean canRename) {
- boolean copyEnabled = dirType != DirectoryFragment.TYPE_RECENT_OPEN;
- boolean moveEnabled =
- SystemProperties.getBoolean("debug.documentsui.enable_move", false);
- menu.findItem(R.id.menu_copy_to_clipboard).setEnabled(copyEnabled);
-
- final MenuItem open = menu.findItem(R.id.menu_open);
- final MenuItem share = menu.findItem(R.id.menu_share);
- final MenuItem delete = menu.findItem(R.id.menu_delete);
- final MenuItem copyTo = menu.findItem(R.id.menu_copy_to);
- final MenuItem moveTo = menu.findItem(R.id.menu_move_to);
- final MenuItem rename = menu.findItem(R.id.menu_rename);
+ MenuItem open = menu.findItem(R.id.menu_open);
+ MenuItem share = menu.findItem(R.id.menu_share);
+ MenuItem delete = menu.findItem(R.id.menu_delete);
+ MenuItem rename = menu.findItem(R.id.menu_rename);
open.setVisible(true);
share.setVisible(false);
delete.setVisible(false);
- copyTo.setVisible(copyEnabled);
- copyTo.setEnabled(copyEnabled);
- moveTo.setVisible(moveEnabled);
- moveTo.setEnabled(moveEnabled);
rename.setVisible(false);
}
@Override
- void onModelLoaded(Model model, @ResultType int resultType) {
- // When launched into empty recents, show drawer
- if (resultType == DirectoryFragment.TYPE_RECENT_OPEN
- && model.isEmpty()
- && !mState.hasLocationChanged()) {
- ((DocumentsActivity) mContext).setRootsDrawerOpen(true);
+ void onModelLoaded(Model model, @ResultType int resultType, boolean isSearch) {
+ // When launched into empty root, open drawer.
+ if (model.isEmpty() && !mState.hasInitialLocationChanged() && !isSearch) {
+ // This noops on layouts without drawer, so no need to guard.
+ ((BaseActivity) mContext).setRootsDrawerOpen(true);
}
}
}
@@ -186,32 +169,29 @@
}
@Override
- public void updateActionMenu(Menu menu, int dirType, boolean canDelete,
- boolean canRename) {
- checkArgument(dirType != DirectoryFragment.TYPE_RECENT_OPEN);
+ public void updateActionMenu(
+ Menu menu, @ResultType int resultType, boolean canDelete, boolean canRename) {
+ assert(resultType != DirectoryFragment.TYPE_RECENT_OPEN);
- boolean moveEnabled =
- SystemProperties.getBoolean("debug.documentsui.enable_move", false);
- menu.findItem(R.id.menu_copy_to_clipboard).setEnabled(true);
-
- final MenuItem open = menu.findItem(R.id.menu_open);
- final MenuItem share = menu.findItem(R.id.menu_share);
- final MenuItem delete = menu.findItem(R.id.menu_delete);
- final MenuItem copyTo = menu.findItem(R.id.menu_copy_to);
- final MenuItem moveTo = menu.findItem(R.id.menu_move_to);
- final MenuItem rename = menu.findItem(R.id.menu_rename);
+ MenuItem open = menu.findItem(R.id.menu_open);
+ MenuItem delete = menu.findItem(R.id.menu_delete);
+ MenuItem copyTo = menu.findItem(R.id.menu_copy_to);
+ MenuItem moveTo = menu.findItem(R.id.menu_move_to);
+ MenuItem rename = menu.findItem(R.id.menu_rename);
+ MenuItem copy = menu.findItem(R.id.menu_copy_to_clipboard);
open.setVisible(false);
delete.setVisible(canDelete);
+ copy.setEnabled(true); // to clipboard
copyTo.setVisible(true);
copyTo.setEnabled(true);
- moveTo.setVisible(moveEnabled);
- moveTo.setEnabled(moveEnabled);
+ moveTo.setVisible(true);
+ moveTo.setEnabled(true);
rename.setVisible(false);
}
@Override
- void onModelLoaded(Model model, @ResultType int resultType) {}
+ void onModelLoaded(Model model, @ResultType int resultType, boolean isSearch) {}
}
/**
@@ -219,15 +199,13 @@
*/
private static final class FilesTuner extends FragmentTuner {
- private static final String TAG = "FilesTuner";
-
public FilesTuner(Context context, State state) {
super(context, state);
}
@Override
- public void updateActionMenu(Menu menu, int dirType, boolean canDelete,
- boolean canRename) {
+ public void updateActionMenu(
+ Menu menu, @ResultType int dirType, boolean canDelete, boolean canRename) {
MenuItem copy = menu.findItem(R.id.menu_copy_to_clipboard);
MenuItem paste = menu.findItem(R.id.menu_paste_from_clipboard);
@@ -239,31 +217,25 @@
menu.findItem(R.id.menu_share).setVisible(true);
menu.findItem(R.id.menu_delete).setVisible(canDelete);
-
menu.findItem(R.id.menu_open).setVisible(false);
menu.findItem(R.id.menu_copy_to).setVisible(true);
menu.findItem(R.id.menu_move_to).setVisible(true);
+ menu.findItem(R.id.menu_move_to).setEnabled(canDelete);
Menus.disableHiddenItems(menu, copy, paste);
}
@Override
- void onModelLoaded(Model model, @ResultType int resultType) {
- if (DEBUG) Log.d(TAG, "Handling model loaded. Has Location shcnage: " + mState.initialLocationHasChanged());
+ void onModelLoaded(Model model, @ResultType int resultType, boolean isSearch) {
// When launched into empty root, open drawer.
- if (model.isEmpty() && !mState.initialLocationHasChanged()
- && resultType != DirectoryFragment.TYPE_SEARCH) {
- if (DEBUG) Log.d(TAG, "Showing roots drawer cuz stuffs empty.");
-
+ if (model.isEmpty() && !mState.hasInitialLocationChanged() && !isSearch) {
// This noops on layouts without drawer, so no need to guard.
- ((FilesActivity) mContext).setRootsDrawerOpen(true);
+ ((BaseActivity) mContext).setRootsDrawerOpen(true);
}
- if (DEBUG) Log.d(TAG, "Donezo.");
}
}
private static boolean isDirectory(String mimeType) {
return Document.MIME_TYPE_DIR.equals(mimeType);
}
-
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java
index e672327..90b2341 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java
@@ -17,7 +17,6 @@
package com.android.documentsui.dirlist;
import static com.android.documentsui.model.DocumentInfo.getCursorString;
-import static com.android.internal.util.Preconditions.checkNotNull;
import android.content.Context;
import android.database.Cursor;
@@ -58,11 +57,12 @@
* @param state Current display state.
*/
public void bind(Cursor cursor, String modelId, State state) {
- checkNotNull(cursor, "Cursor cannot be null.");
+ assert(cursor != null);
this.modelId = modelId;
final String docDisplayName = getCursorString(cursor, Document.COLUMN_DISPLAY_NAME);
- mTitle.setText(docDisplayName);
+ mTitle.setText(docDisplayName, TextView.BufferType.SPANNABLE);
+
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java
index 055adc6a..a4bce16 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java
@@ -19,7 +19,6 @@
import static com.android.documentsui.model.DocumentInfo.getCursorInt;
import static com.android.documentsui.model.DocumentInfo.getCursorLong;
import static com.android.documentsui.model.DocumentInfo.getCursorString;
-import static com.android.internal.util.Preconditions.checkNotNull;
import android.content.Context;
import android.database.Cursor;
@@ -32,7 +31,6 @@
import android.widget.ImageView;
import android.widget.TextView;
-import com.android.documentsui.IconUtils;
import com.android.documentsui.R;
import com.android.documentsui.RootCursorWrapper;
import com.android.documentsui.Shared;
@@ -80,9 +78,9 @@
* @param state Current display state.
*/
public void bind(Cursor cursor, String modelId, State state) {
- this.modelId = modelId;
+ assert(cursor != null);
- checkNotNull(cursor, "Cursor cannot be null.");
+ this.modelId = modelId;
final String docAuthority = getCursorString(cursor, RootCursorWrapper.COLUMN_AUTHORITY);
final String docId = getCursorString(cursor, Document.COLUMN_DOCUMENT_ID);
@@ -107,7 +105,7 @@
if (mHideTitles) {
mTitle.setVisibility(View.GONE);
} else {
- mTitle.setText(docDisplayName);
+ mTitle.setText(docDisplayName, TextView.BufferType.SPANNABLE);
mTitle.setVisibility(View.VISIBLE);
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
index 8c3b53c..0831dbf 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
@@ -19,7 +19,6 @@
import static com.android.documentsui.model.DocumentInfo.getCursorInt;
import static com.android.documentsui.model.DocumentInfo.getCursorLong;
import static com.android.documentsui.model.DocumentInfo.getCursorString;
-import static com.android.internal.util.Preconditions.checkNotNull;
import android.content.Context;
import android.database.Cursor;
@@ -30,6 +29,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.documentsui.R;
@@ -39,9 +39,10 @@
final class ListDocumentHolder extends DocumentHolder {
final TextView mTitle;
- final TextView mSummary;
+ final LinearLayout mDetails; // Container of date/size/summary
final TextView mDate;
final TextView mSize;
+ final TextView mSummary;
final ImageView mIconMime;
final ImageView mIconThumb;
final ImageView mIconCheck;
@@ -51,12 +52,14 @@
super(context, parent, R.layout.item_doc_list);
mTitle = (TextView) itemView.findViewById(android.R.id.title);
- mSummary = (TextView) itemView.findViewById(android.R.id.summary);
mDate = (TextView) itemView.findViewById(R.id.date);
mSize = (TextView) itemView.findViewById(R.id.size);
+ mSummary = (TextView) itemView.findViewById(android.R.id.summary);
mIconMime = (ImageView) itemView.findViewById(R.id.icon_mime);
mIconThumb = (ImageView) itemView.findViewById(R.id.icon_thumb);
mIconCheck = (ImageView) itemView.findViewById(R.id.icon_check);
+ // Warning: mDetails view doesn't exists in layout-sw720dp-land layout
+ mDetails = (LinearLayout) itemView.findViewById(R.id.line2);
mIconHelper = iconHelper;
}
@@ -79,9 +82,9 @@
*/
@Override
public void bind(Cursor cursor, String modelId, State state) {
- this.modelId = modelId;
+ assert(cursor != null);
- checkNotNull(cursor, "Cursor cannot be null.");
+ this.modelId = modelId;
final String docAuthority = getCursorString(cursor, RootCursorWrapper.COLUMN_AUTHORITY);
final String docId = getCursorString(cursor, Document.COLUMN_DOCUMENT_ID);
@@ -92,6 +95,7 @@
final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
final String docSummary = getCursorString(cursor, Document.COLUMN_SUMMARY);
final long docSize = getCursorLong(cursor, Document.COLUMN_SIZE);
+ final boolean isDirectory = Document.MIME_TYPE_DIR.equals(docMimeType);
mIconHelper.stopLoading(mIconThumb);
@@ -103,27 +107,42 @@
final Uri uri = DocumentsContract.buildDocumentUri(docAuthority, docId);
mIconHelper.loadThumbnail(uri, docMimeType, docFlags, docIcon, mIconThumb, mIconMime, null);
- mTitle.setText(docDisplayName);
+ mTitle.setText(docDisplayName, TextView.BufferType.SPANNABLE);
mTitle.setVisibility(View.VISIBLE);
- if (docSummary != null) {
- mSummary.setText(docSummary);
- mSummary.setVisibility(View.VISIBLE);
+
+ boolean hasDetails = false;
+ if (isDirectory) {
+ // Note, we don't show any details for any directory...ever.
+ hasDetails = false;
} else {
- mSummary.setVisibility(View.INVISIBLE);
+ if (docSummary != null) {
+ hasDetails = true;
+ mSummary.setText(docSummary);
+ mSummary.setVisibility(View.VISIBLE);
+ } else {
+ mSummary.setVisibility(View.INVISIBLE);
+ }
+
+ if (docLastModified > 0) {
+ hasDetails = true;
+ mDate.setText(Shared.formatTime(mContext, docLastModified));
+ } else {
+ mDate.setText(null);
+ }
+
+ if (state.showSize && docSize > -1) {
+ hasDetails = true;
+ mSize.setVisibility(View.VISIBLE);
+ mSize.setText(Formatter.formatFileSize(mContext, docSize));
+ } else {
+ mSize.setVisibility(View.GONE);
+ }
}
- if (docLastModified == -1) {
- mDate.setText(null);
- } else {
- mDate.setText(Shared.formatTime(mContext, docLastModified));
- }
-
- if (!state.showSize || Document.MIME_TYPE_DIR.equals(docMimeType) || docSize == -1) {
- mSize.setVisibility(View.GONE);
- } else {
- mSize.setVisibility(View.VISIBLE);
- mSize.setText(Formatter.formatFileSize(mContext, docSize));
+ // mDetails view doesn't exists in layout-sw720dp-land layout
+ if (mDetails != null) {
+ mDetails.setVisibility(hasDetails ? View.VISIBLE : View.GONE);
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
index 3a45995..8170e2a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
@@ -22,11 +22,9 @@
import static com.android.documentsui.State.SORT_ORDER_SIZE;
import static com.android.documentsui.model.DocumentInfo.getCursorLong;
import static com.android.documentsui.model.DocumentInfo.getCursorString;
-import static com.android.internal.util.Preconditions.checkNotNull;
import android.database.Cursor;
import android.os.Bundle;
-import android.os.Looper;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.support.annotation.Nullable;
@@ -35,6 +33,7 @@
import com.android.documentsui.DirectoryResult;
import com.android.documentsui.RootCursorWrapper;
+import com.android.documentsui.Shared;
import com.android.documentsui.dirlist.MultiSelectManager.Selection;
import com.android.documentsui.model.DocumentInfo;
@@ -65,6 +64,7 @@
@Nullable String info;
@Nullable String error;
+ @Nullable DocumentInfo doc;
/**
* Generates a Model ID for a cursor entry that refers to a document. The Model ID is a unique
@@ -112,6 +112,7 @@
mPositions.clear();
info = null;
error = null;
+ doc = null;
mIsLoading = false;
notifyUpdateListeners();
return;
@@ -126,6 +127,7 @@
mCursor = result.cursor;
mCursorCount = mCursor.getCount();
mSortOrder = result.sortOrder;
+ doc = result.doc;
updateModelData();
@@ -170,7 +172,7 @@
final String displayName = getCursorString(
mCursor, Document.COLUMN_DISPLAY_NAME);
if (Document.MIME_TYPE_DIR.equals(mimeType)) {
- stringValues[pos] = DocumentInfo.DIR_PREFIX + displayName;
+ stringValues[pos] = Shared.DIR_PREFIX + displayName;
} else {
stringValues[pos] = displayName;
}
@@ -227,7 +229,7 @@
final String lhs = pivotValue;
final String rhs = sortKey[mid];
- final int compare = DocumentInfo.compareToIgnoreCaseNullable(lhs, rhs);
+ final int compare = Shared.compareToIgnoreCaseNullable(lhs, rhs);
if (compare < 0) {
right = mid;
@@ -380,9 +382,9 @@
final List<DocumentInfo> docs = new ArrayList<>(size);
for (String modelId: items.getAll()) {
final Cursor cursor = getItem(modelId);
- checkNotNull(cursor, "Cursor cannot be null.");
- final DocumentInfo doc = DocumentInfo.fromDirectoryCursor(cursor);
- docs.add(doc);
+ assert(cursor != null);
+
+ docs.add(DocumentInfo.fromDirectoryCursor(cursor));
}
return docs;
}
@@ -391,6 +393,10 @@
mUpdateListeners.add(listener);
}
+ void removeUpdateListener(UpdateListener listener) {
+ mUpdateListeners.remove(listener);
+ }
+
static interface UpdateListener {
/**
* Called when a successful update has occurred.
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
index 69a6711..2b07339 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
@@ -29,6 +29,7 @@
import android.view.ViewGroup;
import com.android.documentsui.State;
+
import com.google.common.collect.Sets;
import java.util.ArrayList;
@@ -181,28 +182,6 @@
}
@Override
- public void unhide(SparseArray<String> ids) {
- if (DEBUG) Log.d(TAG, "Un-iding ids: " + ids);
-
- // An ArrayList can shrink at runtime...and in fact
- // it does when we clear it completely.
- // This means we can't call add(pos, id) without
- // first checking the list size.
- List<String> oldIds = mModelIds;
- mModelIds = new ArrayList<>(oldIds.size() + ids.size());
- mModelIds.addAll(oldIds);
-
- // Finally insert the unhidden items.
- for (int i = 0; i < ids.size(); i++) {
- int pos = ids.keyAt(i);
- String id = ids.get(pos);
- mHiddenIds.remove(id);
- mModelIds.add(pos, id);
- notifyItemInserted(pos);
- }
- }
-
- @Override
public List<String> getModelIds() {
return mModelIds;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
index c8b6f85..b0cc09a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
@@ -19,9 +19,6 @@
import static com.android.documentsui.Shared.DEBUG;
import static com.android.documentsui.dirlist.ModelBackedDocumentsAdapter.ITEM_TYPE_DIRECTORY;
import static com.android.documentsui.dirlist.ModelBackedDocumentsAdapter.ITEM_TYPE_DOCUMENT;
-import static com.android.internal.util.Preconditions.checkArgument;
-import static com.android.internal.util.Preconditions.checkNotNull;
-import static com.android.internal.util.Preconditions.checkState;
import android.annotation.IntDef;
import android.graphics.Point;
@@ -134,8 +131,12 @@
@SelectionMode int mode,
@Nullable Selection initialSelection) {
- mEnvironment = checkNotNull(environment, "'environment' cannot be null.");
- mAdapter = checkNotNull(adapter, "'adapter' cannot be null.");
+ assert(environment != null);
+ assert(adapter != null);
+
+ mEnvironment = environment;
+ mAdapter = adapter;
+
mSingleSelect = mode == MODE_SINGLE;
if (initialSelection != null) {
mSelection.copyFrom(initialSelection);
@@ -168,8 +169,8 @@
@Override
public void onItemRangeRemoved(int startPosition, int itemCount) {
- checkState(startPosition >= 0);
- checkState(itemCount > 0);
+ assert(startPosition >= 0);
+ assert(itemCount > 0);
mSelection.cancelProvisionalSelection();
// Remove any disappeared IDs from the selection.
@@ -356,7 +357,8 @@
* @param modelId
*/
public void toggleSelection(String modelId) {
- checkNotNull(modelId);
+ assert(modelId != null);
+
boolean changed = false;
if (mSelection.contains(modelId)) {
changed = attemptDeselect(modelId);
@@ -389,7 +391,8 @@
* @param pos The new end position for the selection range.
*/
void snapRangeSelection(int pos) {
- checkNotNull(mRanger);
+ assert(mRanger != null);
+
mRanger.snapSelection(pos);
notifySelectionChanged();
}
@@ -436,7 +439,7 @@
* @param selected New selection state.
*/
private void updateRange(int begin, int end, boolean selected) {
- checkState(end >= begin);
+ assert(end >= begin);
for (int i = begin; i <= end; i++) {
String id = mAdapter.getModelId(i);
if (id == null) {
@@ -474,7 +477,7 @@
* @return True if the update was applied.
*/
private boolean attemptDeselect(String id) {
- checkArgument(id != null);
+ assert(id != null);
if (notifyBeforeItemStateChange(id, false)) {
mSelection.remove(id);
notifyItemStateChanged(id, false);
@@ -491,7 +494,7 @@
* @return True if the update was applied.
*/
private boolean attemptSelect(String id) {
- checkArgument(id != null);
+ assert(id != null);
boolean canSelect = notifyBeforeItemStateChange(id, true);
if (!canSelect) {
return false;
@@ -519,7 +522,7 @@
* (identified by {@code position}) changes.
*/
private void notifyItemStateChanged(String id, boolean selected) {
- checkArgument(id != null);
+ assert(id != null);
int lastListener = mCallbacks.size() - 1;
for (int i = lastListener; i > -1; i--) {
mCallbacks.get(i).onItemStateChanged(id, selected);
@@ -555,8 +558,8 @@
}
private void snapSelection(int position) {
- checkState(mRanger != null);
- checkArgument(position != RecyclerView.NO_POSITION);
+ assert(mRanger != null);
+ assert(position != RecyclerView.NO_POSITION);
if (mEnd == UNDEFINED || mEnd == mBegin) {
// Reset mEnd so it can be established in establishRange.
@@ -568,7 +571,7 @@
}
private void establishRange(int position) {
- checkState(mRanger.mEnd == UNDEFINED);
+ assert(mRanger.mEnd == UNDEFINED);
if (position == mBegin) {
mEnd = position;
@@ -584,8 +587,8 @@
}
private void reviseRange(int position) {
- checkState(mEnd != UNDEFINED);
- checkState(mBegin != mEnd);
+ assert(mEnd != UNDEFINED);
+ assert(mBegin != mEnd);
if (position == mEnd) {
if (DEBUG) Log.i(TAG, "Skipping no-op revision click on mEndRange.");
@@ -657,15 +660,22 @@
// item A is tapped (and selected), then an in-progress band select covers A then uncovers
// A, A should still be selected as it has been saved. To ensure this behavior, the saved
// selection must be tracked separately.
- private Set<String> mSelection = new HashSet<>();
- private Set<String> mProvisionalSelection = new HashSet<>();
+ private final Set<String> mSelection;
+ private final Set<String> mProvisionalSelection;
private String mDirectoryKey;
- @VisibleForTesting
- public Selection(String... ids) {
- for (int i = 0; i < ids.length; i++) {
- add(ids[i]);
- }
+ public Selection() {
+ mSelection = new HashSet<String>();
+ mProvisionalSelection = new HashSet<String>();
+ }
+
+ /**
+ * Used by CREATOR.
+ */
+ private Selection(String directoryKey, List<String> selection) {
+ mDirectoryKey = directoryKey;
+ mSelection = new HashSet<String>(selection);
+ mProvisionalSelection = new HashSet<String>();
}
/**
@@ -687,7 +697,7 @@
* Returns an unordered array of selected positions (including any
* provisional selections current in effect).
*/
- private List<String> toList() {
+ public List<String> toList() {
ArrayList<String> selection = new ArrayList<String>(mSelection);
selection.addAll(mProvisionalSelection);
return selection;
@@ -810,8 +820,11 @@
@VisibleForTesting
void copyFrom(Selection source) {
- mSelection = new HashSet<>(source.mSelection);
- mProvisionalSelection = new HashSet<>(source.mProvisionalSelection);
+ mSelection.clear();
+ mSelection.addAll(source.mSelection);
+
+ mProvisionalSelection.clear();
+ mProvisionalSelection.addAll(source.mProvisionalSelection);
}
@Override
@@ -878,6 +891,26 @@
// We don't include provisional selection since it is
// typically coupled to some other runtime state (like a band).
}
+
+ public static final ClassLoaderCreator<Selection> CREATOR =
+ new ClassLoaderCreator<Selection>() {
+ @Override
+ public Selection createFromParcel(Parcel in) {
+ return createFromParcel(in, null);
+ }
+
+ @Override
+ public Selection createFromParcel(Parcel in, ClassLoader loader) {
+ return new Selection(
+ in.readString(),
+ (ArrayList<String>) in.readArrayList(loader));
+ }
+
+ @Override
+ public Selection[] newArray(int size) {
+ return new Selection[size];
+ }
+ };
}
/**
@@ -1155,7 +1188,7 @@
* @param input
*/
private void processInputEvent(InputEvent input) {
- checkArgument(input.isMouseEvent());
+ assert(input.isMouseEvent());
if (shouldStop(input)) {
endBandSelect();
@@ -1169,7 +1202,6 @@
}
mCurrentPosition = input.getOrigin();
- mModel.resizeSelection(input.getOrigin());
scrollViewIfNecessary();
resizeBandSelectRectangle();
}
@@ -1458,6 +1490,7 @@
* top-left of the viewport would have a relative origin of (0, 0), even though its
* absolute point has a higher y-value.
*/
+ @VisibleForTesting
void resizeSelection(Point relativePointer) {
mPointer = mHelper.createAbsolutePoint(relativePointer);
updateModel();
@@ -1585,7 +1618,7 @@
private void updateSelection(Rect rect) {
int columnStart =
Collections.binarySearch(mColumnBounds, new Limits(rect.left, rect.left));
- checkState(columnStart >= 0);
+ assert(columnStart >= 0);
int columnEnd = columnStart;
for (int i = columnStart; i < mColumnBounds.size()
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/RenameDocumentFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
index 7394c12..884abbb 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
@@ -17,7 +17,6 @@
package com.android.documentsui.dirlist;
import static com.android.documentsui.Shared.TAG;
-import static com.android.internal.util.Preconditions.checkArgument;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -36,9 +35,9 @@
import android.support.design.widget.Snackbar;
import android.util.Log;
import android.view.KeyEvent;
-import android.view.inputmethod.EditorInfo;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
@@ -46,6 +45,7 @@
import com.android.documentsui.BaseActivity;
import com.android.documentsui.DocumentsApplication;
import com.android.documentsui.R;
+import com.android.documentsui.Shared;
import com.android.documentsui.Snackbars;
import com.android.documentsui.model.DocumentInfo;
@@ -55,6 +55,7 @@
public class RenameDocumentFragment extends DialogFragment {
private static final String TAG_RENAME_DOCUMENT = "rename_document";
private DocumentInfo mDocument;
+ private EditText mEditText;
public static void show(FragmentManager fm, DocumentInfo document) {
final RenameDocumentFragment dialog = new RenameDocumentFragment();
@@ -62,6 +63,11 @@
dialog.show(fm, TAG_RENAME_DOCUMENT);
}
+ /**
+ * Creates the dialog UI.
+ * @param savedInstanceState
+ * @return
+ */
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Context context = getActivity();
@@ -69,8 +75,7 @@
LayoutInflater dialogInflater = LayoutInflater.from(builder.getContext());
View view = dialogInflater.inflate(R.layout.dialog_file_name, null, false);
- final EditText editText = (EditText) view.findViewById(android.R.id.text1);
- fillWithFileName(editText, mDocument.displayName);
+ mEditText = (EditText) view.findViewById(android.R.id.text1);
builder.setTitle(R.string.menu_rename);
builder.setView(view);
@@ -79,7 +84,7 @@
new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
- renameDocuments(editText.getText().toString());
+ renameDocuments(mEditText.getText().toString());
}
});
@@ -87,7 +92,10 @@
final AlertDialog dialog = builder.create();
- editText.setOnEditorActionListener(
+ // Workaround for the problem - virtual keyboard doesn't show on the phone.
+ Shared.ensureKeyboardPresent(context, dialog);
+
+ mEditText.setOnEditorActionListener(
new OnEditorActionListener() {
@Override
public boolean onEditorAction(
@@ -95,18 +103,51 @@
if ((actionId == EditorInfo.IME_ACTION_DONE) || (event != null
&& event.getKeyCode() == KeyEvent.KEYCODE_ENTER
&& event.hasNoModifiers())) {
- renameDocuments(editText.getText().toString());
+ renameDocuments(mEditText.getText().toString());
dialog.dismiss();
return true;
}
return false;
}
});
-
return dialog;
}
/**
+ * Sets/Restores the data.
+ * @param savedInstanceState
+ * @return
+ */
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ if(savedInstanceState == null) {
+ // Fragment created for the first time, we set the text.
+ // mDocument value was set in show
+ mEditText.setText(mDocument.displayName);
+ }
+ else {
+ // Fragment restored, text was restored automatically.
+ // mDocument value needs to be restored.
+ mDocument = savedInstanceState.getParcelable(Shared.EXTRA_DOC);
+ }
+ // Do selection in both cases, because we cleared it.
+ selectFileName(mEditText);
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ // Clear selection before storing state and restore it manually,
+ // because otherwise after rotation selection is displayed with cut/copy menu visible :/
+ clearFileNameSelection(mEditText);
+
+ super.onSaveInstanceState(outState);
+
+ outState.putParcelable(Shared.EXTRA_DOC, mDocument);
+ }
+
+ /**
* Validates if string is a proper document name.
* Checks if string is not empty. More rules might be added later.
* @param docName string representing document name
@@ -120,12 +161,21 @@
* Fills text field with the file name and selects the name without extension.
*
* @param editText text field to be filled
- * @param name full name of the file
*/
- private void fillWithFileName(EditText editText, String name) {
- editText.setText(name);
- int separatorIndex = name.indexOf(".");
- editText.setSelection(0, separatorIndex == -1 ? name.length() : separatorIndex);
+ private void selectFileName(EditText editText) {
+ String text = editText.getText().toString();
+ int separatorIndex = text.indexOf(".");
+ editText.setSelection(0,
+ (separatorIndex == -1 || mDocument.isDirectory()) ? text.length() : separatorIndex);
+ }
+
+ /**
+ * Clears selection in text field.
+ *
+ * @param editText text field to be cleared.
+ */
+ private void clearFileNameSelection(EditText editText) {
+ editText.setSelection(0, 0);
}
private void renameDocuments(String newDisplayName) {
@@ -157,7 +207,7 @@
@Override
protected DocumentInfo doInBackground(DocumentInfo... document) {
- checkArgument(document.length == 1);
+ assert(document.length == 1);
final ContentResolver resolver = mActivity.getContentResolver();
ContentProviderClient client = null;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/SectionBreakDocumentsAdapterWrapper.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/SectionBreakDocumentsAdapterWrapper.java
index 2485ad9..b698059 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/SectionBreakDocumentsAdapterWrapper.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/SectionBreakDocumentsAdapterWrapper.java
@@ -16,8 +16,6 @@
package com.android.documentsui.dirlist;
-import static com.android.internal.util.Preconditions.checkArgument;
-
import android.content.Context;
import android.database.Cursor;
import android.support.v7.widget.GridLayoutManager;
@@ -171,13 +169,6 @@
}
@Override
- void unhide(SparseArray<String> ids) {
- // NOTE: We hear about these changes and adjust break position
- // in our AdapterDataObserver.
- mDelegate.unhide(ids);
- }
-
- @Override
List<String> getModelIds() {
return mDelegate.getModelIds();
}
@@ -204,12 +195,12 @@
}
public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
- checkArgument(itemCount == 1);
+ assert(itemCount == 1);
notifyItemRangeChanged(toViewPosition(positionStart), itemCount, payload);
}
public void onItemRangeInserted(int positionStart, int itemCount) {
- checkArgument(itemCount == 1);
+ assert(itemCount == 1);
if (positionStart < mBreakPosition) {
mBreakPosition++;
}
@@ -217,7 +208,7 @@
}
public void onItemRangeRemoved(int positionStart, int itemCount) {
- checkArgument(itemCount == 1);
+ assert(itemCount == 1);
if (positionStart < mBreakPosition) {
mBreakPosition--;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
index 1c696ad..d74121e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
@@ -26,7 +26,6 @@
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsProvider;
import android.support.annotation.VisibleForTesting;
-import android.text.TextUtils;
import com.android.documentsui.DocumentsApplication;
import com.android.documentsui.RootCursorWrapper;
@@ -38,7 +37,6 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.ProtocolException;
-import java.text.Collator;
import java.util.Objects;
/**
@@ -48,13 +46,6 @@
private static final int VERSION_INIT = 1;
private static final int VERSION_SPLIT_URI = 2;
- private static final Collator sCollator;
-
- static {
- sCollator = Collator.getInstance();
- sCollator.setStrength(Collator.SECONDARY);
- }
-
public String authority;
public String documentId;
public String mimeType;
@@ -216,7 +207,13 @@
return "Document{"
+ "docId=" + documentId
+ ", name=" + displayName
+ + ", isContainer=" + isContainer()
+ ", isDirectory=" + isDirectory()
+ + ", isArchive=" + isArchive()
+ + ", isVirtualDocument=" + isVirtualDocument()
+ + ", isDeleteSupported=" + isDeleteSupported()
+ + ", isCreateSupported=" + isCreateSupported()
+ + ", isRenameSupported=" + isRenameSupported()
+ "}";
}
@@ -240,6 +237,10 @@
return (flags & Document.FLAG_SUPPORTS_DELETE) != 0;
}
+ public boolean isRemoveSupported() {
+ return (flags & Document.FLAG_SUPPORTS_REMOVE) != 0;
+ }
+
public boolean isRenameSupported() {
return (flags & Document.FLAG_SUPPORTS_RENAME) != 0;
}
@@ -320,31 +321,4 @@
fnfe.initCause(t);
throw fnfe;
}
-
- /**
- * String prefix used to indicate the document is a directory.
- */
- public static final char DIR_PREFIX = '\001';
-
- /**
- * Compare two strings against each other using system default collator in a
- * case-insensitive mode. Clusters strings prefixed with {@link #DIR_PREFIX}
- * before other items.
- */
- public static int compareToIgnoreCaseNullable(String lhs, String rhs) {
- final boolean leftEmpty = TextUtils.isEmpty(lhs);
- final boolean rightEmpty = TextUtils.isEmpty(rhs);
-
- if (leftEmpty && rightEmpty) return 0;
- if (leftEmpty) return -1;
- if (rightEmpty) return 1;
-
- final boolean leftDir = (lhs.charAt(0) == DIR_PREFIX);
- final boolean rightDir = (rhs.charAt(0) == DIR_PREFIX);
-
- if (leftDir && !rightDir) return -1;
- if (rightDir && !leftDir) return 1;
-
- return sCollator.compare(lhs, rhs);
- }
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
index 8cbbb6c..3eaf10a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
@@ -16,10 +16,13 @@
package com.android.documentsui.model;
+import static com.android.documentsui.Shared.DEBUG;
+import static com.android.documentsui.Shared.compareToIgnoreCaseNullable;
import static com.android.documentsui.model.DocumentInfo.getCursorInt;
import static com.android.documentsui.model.DocumentInfo.getCursorLong;
import static com.android.documentsui.model.DocumentInfo.getCursorString;
+import android.annotation.IntDef;
import android.content.Context;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
@@ -29,6 +32,7 @@
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Root;
import android.text.TextUtils;
+import android.util.Log;
import com.android.documentsui.IconUtils;
import com.android.documentsui.R;
@@ -36,17 +40,35 @@
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.net.ProtocolException;
import java.util.Objects;
/**
* Representation of a {@link Root}.
*/
-public class RootInfo implements Durable, Parcelable {
+public class RootInfo implements Durable, Parcelable, Comparable<RootInfo> {
+
+ private static final String TAG = "RootInfo";
private static final int VERSION_INIT = 1;
private static final int VERSION_DROP_TYPE = 2;
// The values of these constants determine the sort order of various roots in the RootsFragment.
+ @IntDef(flag = true, value = {
+ TYPE_IMAGES,
+ TYPE_VIDEO,
+ TYPE_AUDIO,
+ TYPE_RECENTS,
+ TYPE_DOWNLOADS,
+ TYPE_LOCAL,
+ TYPE_MTP,
+ TYPE_SD,
+ TYPE_USB,
+ TYPE_OTHER
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface RootType {}
public static final int TYPE_IMAGES = 1;
public static final int TYPE_VIDEO = 2;
public static final int TYPE_AUDIO = 3;
@@ -54,7 +76,9 @@
public static final int TYPE_DOWNLOADS = 5;
public static final int TYPE_LOCAL = 6;
public static final int TYPE_MTP = 7;
- public static final int TYPE_OTHER = 8;
+ public static final int TYPE_SD = 8;
+ public static final int TYPE_USB = 9;
+ public static final int TYPE_OTHER = 10;
public String authority;
public String rootId;
@@ -69,7 +93,7 @@
/** Derived fields that aren't persisted */
public String[] derivedMimeTypes;
public int derivedIcon;
- public int derivedType;
+ public @RootType int derivedType;
public RootInfo() {
reset();
@@ -169,33 +193,40 @@
private void deriveFields() {
derivedMimeTypes = (mimeTypes != null) ? mimeTypes.split("\n") : null;
- // TODO: remove these special case icons
if (isHome()) {
+ derivedType = TYPE_LOCAL;
derivedIcon = R.drawable.ic_root_documents;
- derivedType = TYPE_LOCAL;
- } else if (isExternalStorage()) {
- derivedIcon = R.drawable.ic_root_smartphone;
- derivedType = TYPE_LOCAL;
- // TODO: Apply SD card icon to SD devices.
- } else if (isDownloads()) {
- derivedIcon = R.drawable.ic_root_download;
- derivedType = TYPE_DOWNLOADS;
- } else if (isImages()) {
- derivedIcon = R.drawable.ic_doc_image;
- derivedType = TYPE_IMAGES;
- } else if (isVideos()) {
- derivedIcon = R.drawable.ic_doc_video;
- derivedType = TYPE_VIDEO;
- } else if (isAudio()) {
- derivedIcon = R.drawable.ic_doc_audio;
- derivedType = TYPE_AUDIO;
- } else if (isRecents()) {
- derivedType = TYPE_RECENTS;
} else if (isMtp()) {
derivedType = TYPE_MTP;
+ derivedIcon = R.drawable.ic_usb_storage;
+ } else if (isUsb()) {
+ derivedType = TYPE_USB;
+ derivedIcon = R.drawable.ic_usb_storage;
+ } else if (isSd()) {
+ derivedType = TYPE_SD;
+ derivedIcon = R.drawable.ic_sd_storage;
+ } else if (isExternalStorage()) {
+ derivedType = TYPE_LOCAL;
+ derivedIcon = R.drawable.ic_root_smartphone;
+ } else if (isDownloads()) {
+ derivedType = TYPE_DOWNLOADS;
+ derivedIcon = R.drawable.ic_root_download;
+ } else if (isImages()) {
+ derivedType = TYPE_IMAGES;
+ derivedIcon = R.drawable.ic_doc_image;
+ } else if (isVideos()) {
+ derivedType = TYPE_VIDEO;
+ derivedIcon = R.drawable.ic_doc_video;
+ } else if (isAudio()) {
+ derivedType = TYPE_AUDIO;
+ derivedIcon = R.drawable.ic_doc_audio;
+ } else if (isRecents()) {
+ derivedType = TYPE_RECENTS;
} else {
derivedType = TYPE_OTHER;
}
+
+ if (DEBUG) Log.d(TAG, "Finished deriving fields: " + this);
}
public Uri getUri() {
@@ -241,8 +272,10 @@
}
public boolean isLibrary() {
- return derivedType == TYPE_IMAGES || derivedType == TYPE_VIDEO || derivedType == TYPE_AUDIO
- || derivedType == TYPE_RECENTS || derivedType == TYPE_DOWNLOADS;
+ return derivedType == TYPE_IMAGES
+ || derivedType == TYPE_VIDEO
+ || derivedType == TYPE_AUDIO
+ || derivedType == TYPE_RECENTS;
}
public boolean hasSettings() {
@@ -257,8 +290,12 @@
return (flags & Root.FLAG_SUPPORTS_CREATE) != 0;
}
- public boolean isAdvanced() {
- return (flags & Root.FLAG_ADVANCED) != 0;
+ public boolean supportsRecents() {
+ return (flags & Root.FLAG_SUPPORTS_RECENTS) != 0;
+ }
+
+ public boolean supportsSearch() {
+ return (flags & Root.FLAG_SUPPORTS_SEARCH) != 0;
}
public boolean isLocalOnly() {
@@ -269,6 +306,14 @@
return (flags & Root.FLAG_EMPTY) != 0;
}
+ public boolean isSd() {
+ return (flags & Root.FLAG_REMOVABLE_SD) != 0;
+ }
+
+ public boolean isUsb() {
+ return (flags & Root.FLAG_REMOVABLE_USB) != 0;
+ }
+
public Drawable loadIcon(Context context) {
if (derivedIcon != 0) {
return context.getDrawable(derivedIcon);
@@ -319,8 +364,31 @@
}
@Override
+ public int compareTo(RootInfo other) {
+ // Sort by root type, then title, then summary.
+ int score = derivedType - other.derivedType;
+ if (score != 0) {
+ return score;
+ }
+
+ score = compareToIgnoreCaseNullable(title, other.title);
+ if (score != 0) {
+ return score;
+ }
+
+ return compareToIgnoreCaseNullable(summary, other.summary);
+ }
+
+ @Override
public String toString() {
- return "Root{authority=" + authority + ", rootId=" + rootId + ", title=" + title + "}";
+ return "Root{"
+ + "authority=" + authority
+ + ", rootId=" + rootId
+ + ", title=" + title
+ + ", isUsb=" + isUsb()
+ + ", isSd=" + isSd()
+ + ", isMtp=" + isMtp()
+ + "}";
}
public String getDirectoryString() {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java b/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java
index dad8697..ad48a70 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java
@@ -29,7 +29,6 @@
import static com.android.documentsui.services.FileOperationService.EXTRA_OPERATION;
import static com.android.documentsui.services.FileOperationService.EXTRA_SRC_LIST;
import static com.android.documentsui.services.FileOperationService.OPERATION_COPY;
-import static com.google.common.base.Preconditions.checkArgument;
import android.annotation.StringRes;
import android.app.Notification;
@@ -67,12 +66,15 @@
import java.util.List;
class CopyJob extends Job {
+
private static final String TAG = "CopyJob";
- private static final int PROGRESS_INTERVAL_MILLIS = 1000;
+ private static final int PROGRESS_INTERVAL_MILLIS = 500;
+
final List<DocumentInfo> mSrcs;
final ArrayList<DocumentInfo> convertedFiles = new ArrayList<>();
private long mStartTime = -1;
+
private long mBatchSize;
private long mBytesCopied;
private long mLastNotificationTime;
@@ -92,7 +94,7 @@
String id, DocumentStack stack, List<DocumentInfo> srcs) {
super(service, appContext, listener, OPERATION_COPY, id, stack);
- checkArgument(!srcs.isEmpty());
+ assert(!srcs.isEmpty());
this.mSrcs = srcs;
}
@@ -105,7 +107,7 @@
@OpType int opType, String id, DocumentStack destination, List<DocumentInfo> srcs) {
super(service, appContext, listener, opType, id, destination);
- checkArgument(!srcs.isEmpty());
+ assert(!srcs.isEmpty());
this.mSrcs = srcs;
}
@@ -129,10 +131,19 @@
}
Notification getProgressNotification(@StringRes int msgId) {
- double completed = (double) this.mBytesCopied / mBatchSize;
- mProgressBuilder.setProgress(100, (int) (completed * 100), false);
- mProgressBuilder.setContentInfo(
- NumberFormat.getPercentInstance().format(completed));
+ if (mBatchSize >= 0) {
+ double completed = (double) this.mBytesCopied / mBatchSize;
+ mProgressBuilder.setProgress(100, (int) (completed * 100), false);
+ mProgressBuilder.setContentInfo(
+ NumberFormat.getPercentInstance().format(completed));
+ } else {
+ // If the total file size failed to compute on some files, then show
+ // an indeterminate spinner. CopyJob would most likely fail on those
+ // files while copying, but would continue with another files.
+ // Also, if the total size is 0 bytes, show an indeterminate spinner.
+ mProgressBuilder.setProgress(0, 0, true);
+ }
+
if (mRemainingTime > 0) {
mProgressBuilder.setContentText(service.getString(msgId,
DateUtils.formatDuration(mRemainingTime)));
@@ -208,11 +219,15 @@
}
@Override
- void start() throws RemoteException {
+ void start() {
mStartTime = elapsedRealtime();
- // client
- mBatchSize = calculateSize(mSrcs);
+ try {
+ mBatchSize = calculateSize(mSrcs);
+ } catch (ResourceException e) {
+ Log.w(TAG, "Failed to calculate total size. Copying without progress.");
+ mBatchSize = -1;
+ }
DocumentInfo srcInfo;
DocumentInfo dstInfo = stack.peek();
@@ -220,9 +235,13 @@
srcInfo = mSrcs.get(i);
// Guard unsupported recursive operation.
- if (dstInfo.equals(srcInfo) || isDescendentOf(srcInfo, dstInfo)) {
- onFileFailed(srcInfo,
- "Skipping recursive operation on directory " + dstInfo.derivedUri + ".");
+ try {
+ if (dstInfo.equals(srcInfo) || isDescendentOf(srcInfo, dstInfo)) {
+ throw new ResourceException("Cannot copy to itself recursively.");
+ }
+ } catch (ResourceException e) {
+ Log.e(TAG, e.toString());
+ onFileFailed(srcInfo);
continue;
}
@@ -230,7 +249,12 @@
"Copying " + srcInfo.displayName + " (" + srcInfo.derivedUri + ")"
+ " to " + dstInfo.displayName + " (" + dstInfo.derivedUri + ")");
- processDocument(srcInfo, null, dstInfo);
+ try {
+ processDocument(srcInfo, null, dstInfo);
+ } catch (ResourceException e) {
+ Log.e(TAG, e.toString());
+ onFileFailed(srcInfo);
+ }
}
Metrics.logFileOperation(service, operationType, mSrcs, dstInfo);
}
@@ -259,13 +283,12 @@
* @param src DocumentInfos for the documents to copy.
* @param srcParent DocumentInfo for the parent of the document to process.
* @param dstDirInfo The destination directory.
- * @return True on success, false on failure.
- * @throws RemoteException
+ * @throws ResourceException
*
* TODO: Stop passing srcParent, as it's not used for copy, but for move only.
*/
- boolean processDocument(DocumentInfo src, DocumentInfo srcParent,
- DocumentInfo dstDirInfo) throws RemoteException {
+ void processDocument(DocumentInfo src, DocumentInfo srcParent,
+ DocumentInfo dstDirInfo) throws ResourceException {
// TODO: When optimized copy kicks in, we'll not making any progress updates.
// For now. Local storage isn't using optimized copy.
@@ -274,22 +297,28 @@
// If not supported, then fallback to byte-by-byte copy/move.
if (src.authority.equals(dstDirInfo.authority)) {
if ((src.flags & Document.FLAG_SUPPORTS_COPY) != 0) {
- if (DocumentsContract.copyDocument(getClient(src), src.derivedUri,
- dstDirInfo.derivedUri) == null) {
- onFileFailed(src,
- "Provider side copy failed for documents: " + src.derivedUri + ".");
- return false;
+ try {
+ if (DocumentsContract.copyDocument(getClient(src), src.derivedUri,
+ dstDirInfo.derivedUri) == null) {
+ throw new ResourceException("Provider side copy failed for document %s.",
+ src.derivedUri);
+ }
+ } catch (ResourceException e) {
+ throw e;
+ } catch (RemoteException | RuntimeException e) {
+ throw new ResourceException(
+ "Provider side copy failed for document %s due to an exception.",
+ src.derivedUri, e);
}
- return true;
+ return;
}
}
// If we couldn't do an optimized copy...we fall back to vanilla byte copy.
- return byteCopyDocument(src, dstDirInfo);
+ byteCopyDocument(src, dstDirInfo);
}
- boolean byteCopyDocument(DocumentInfo src, DocumentInfo dest)
- throws RemoteException {
+ void byteCopyDocument(DocumentInfo src, DocumentInfo dest) throws ResourceException {
final String dstMimeType;
final String dstDisplayName;
@@ -297,8 +326,14 @@
// If the file is virtual, but can be converted to another format, then try to copy it
// as such format. Also, append an extension for the target mime type (if known).
if (src.isVirtualDocument()) {
- final String[] streamTypes = getContentResolver().getStreamTypes(
- src.derivedUri, "*/*");
+ String[] streamTypes = null;
+ try {
+ streamTypes = getContentResolver().getStreamTypes(src.derivedUri, "*/*");
+ } catch (RuntimeException e) {
+ throw new ResourceException(
+ "Failed to obtain streamable types for %s due to an exception.",
+ src.derivedUri, e);
+ }
if (streamTypes != null && streamTypes.length > 0) {
dstMimeType = streamTypes[0];
final String extension = MimeTypeMap.getSingleton().
@@ -306,8 +341,8 @@
dstDisplayName = src.displayName +
(extension != null ? "." + extension : src.displayName);
} else {
- onFileFailed(src, "Cannot copy virtual file. No streamable formats available.");
- return false;
+ throw new ResourceException("Cannot copy virtual file %s. No streamable formats "
+ + "available.", src.derivedUri);
}
} else {
dstMimeType = src.mimeType;
@@ -316,33 +351,35 @@
// Create the target document (either a file or a directory), then copy recursively the
// contents (bytes or children).
- final Uri dstUri = DocumentsContract.createDocument(
- getClient(dest), dest.derivedUri, dstMimeType, dstDisplayName);
+ Uri dstUri = null;
+ try {
+ dstUri = DocumentsContract.createDocument(
+ getClient(dest), dest.derivedUri, dstMimeType, dstDisplayName);
+ } catch (RemoteException | RuntimeException e) {
+ throw new ResourceException(
+ "Couldn't create destination document " + dstDisplayName + " in directory %s "
+ + "due to an exception.", dest.derivedUri, e);
+ }
if (dstUri == null) {
// If this is a directory, the entire subdir will not be copied over.
- onFileFailed(src,
- "Couldn't create destination document " + dstDisplayName
- + " in directory " + dest.displayName + ".");
- return false;
+ throw new ResourceException(
+ "Couldn't create destination document " + dstDisplayName + " in directory %s.",
+ dest.derivedUri);
}
DocumentInfo dstInfo = null;
try {
dstInfo = DocumentInfo.fromUri(getContentResolver(), dstUri);
- } catch (FileNotFoundException e) {
- onFileFailed(src,
- "Could not load DocumentInfo for newly created file: " + dstUri + ".");
- return false;
+ } catch (FileNotFoundException | RuntimeException e) {
+ throw new ResourceException("Could not load DocumentInfo for newly created file %s.",
+ dstUri);
}
- final boolean success;
if (Document.MIME_TYPE_DIR.equals(src.mimeType)) {
- success = copyDirectoryHelper(src, dstInfo);
+ copyDirectoryHelper(src, dstInfo);
} else {
- success = copyFileHelper(src, dstInfo, dstMimeType);
+ copyFileHelper(src, dstInfo, dest, dstMimeType);
}
-
- return success;
}
/**
@@ -352,11 +389,10 @@
* @param srcDir Info of the directory to copy from. The routine will copy the directory's
* contents, not the directory itself.
* @param destDir Info of the directory to copy to. Must be created beforehand.
- * @return True on success, false if some of the children failed to copy.
- * @throws RemoteException
+ * @throws ResourceException
*/
- private boolean copyDirectoryHelper(DocumentInfo srcDir, DocumentInfo destDir)
- throws RemoteException {
+ private void copyDirectoryHelper(DocumentInfo srcDir, DocumentInfo destDir)
+ throws ResourceException {
// Recurse into directories. Copy children into the new subdirectory.
final String queryColumns[] = new String[] {
Document.COLUMN_DISPLAY_NAME,
@@ -367,106 +403,143 @@
};
Cursor cursor = null;
boolean success = true;
+ // Iterate over srcs in the directory; copy to the destination directory.
+ final Uri queryUri = buildChildDocumentsUri(srcDir.authority, srcDir.documentId);
try {
- // Iterate over srcs in the directory; copy to the destination directory.
- final Uri queryUri = buildChildDocumentsUri(srcDir.authority, srcDir.documentId);
- cursor = getClient(srcDir).query(queryUri, queryColumns, null, null, null);
- while (cursor.moveToNext() && !isCanceled()) {
- DocumentInfo src = DocumentInfo.fromCursor(cursor, srcDir.authority);
- success &= processDocument(src, srcDir, destDir);
+ try {
+ cursor = getClient(srcDir).query(queryUri, queryColumns, null, null, null);
+ } catch (RemoteException | RuntimeException e) {
+ throw new ResourceException("Failed to query children of %s due to an exception.",
+ srcDir.derivedUri, e);
}
+
+ DocumentInfo src;
+ while (cursor.moveToNext() && !isCanceled()) {
+ try {
+ src = DocumentInfo.fromCursor(cursor, srcDir.authority);
+ processDocument(src, srcDir, destDir);
+ } catch (RuntimeException e) {
+ Log.e(TAG, "Failed to recursively process a file %s due to an exception."
+ .format(srcDir.derivedUri.toString()), e);
+ success = false;
+ }
+ }
+ } catch (RuntimeException e) {
+ Log.e(TAG, "Failed to copy a file %s to %s. "
+ .format(srcDir.derivedUri.toString(), destDir.derivedUri.toString()), e);
+ success = false;
} finally {
IoUtils.closeQuietly(cursor);
}
- return success;
+ if (!success) {
+ throw new RuntimeException("Some files failed to copy during a recursive "
+ + "directory copy.");
+ }
}
/**
* Handles copying a single file.
*
- * @param srcUriInfo Info of the file to copy from.
- * @param dstUriInfo Info of the *file* to copy to. Must be created beforehand.
+ * @param src Info of the file to copy from.
+ * @param dest Info of the *file* to copy to. Must be created beforehand.
+ * @param destParent Info of the parent of the destination.
* @param mimeType Mime type for the target. Can be different than source for virtual files.
- * @return True on success, false on error.
- * @throws RemoteException
+ * @throws ResourceException
*/
- private boolean copyFileHelper(DocumentInfo src, DocumentInfo dest, String mimeType)
- throws RemoteException {
+ private void copyFileHelper(DocumentInfo src, DocumentInfo dest, DocumentInfo destParent,
+ String mimeType) throws ResourceException {
CancellationSignal canceller = new CancellationSignal();
+ AssetFileDescriptor srcFileAsAsset = null;
ParcelFileDescriptor srcFile = null;
ParcelFileDescriptor dstFile = null;
InputStream in = null;
OutputStream out = null;
+ boolean success = false;
- boolean success = true;
try {
// If the file is virtual, but can be converted to another format, then try to copy it
// as such format.
if (src.isVirtualDocument()) {
- final AssetFileDescriptor srcFileAsAsset =
- getClient(src).openTypedAssetFileDescriptor(
+ try {
+ srcFileAsAsset = getClient(src).openTypedAssetFileDescriptor(
src.derivedUri, mimeType, null, canceller);
+ } catch (FileNotFoundException | RemoteException | RuntimeException e) {
+ throw new ResourceException("Failed to open a file as asset for %s due to an "
+ + "exception.", src.derivedUri, e);
+ }
srcFile = srcFileAsAsset.getParcelFileDescriptor();
- in = new AssetFileDescriptor.AutoCloseInputStream(srcFileAsAsset);
+ try {
+ in = new AssetFileDescriptor.AutoCloseInputStream(srcFileAsAsset);
+ } catch (IOException e) {
+ throw new ResourceException("Failed to open a file input stream for %s due "
+ + "an exception.", src.derivedUri, e);
+ }
} else {
- srcFile = getClient(src).openFile(src.derivedUri, "r", canceller);
+ try {
+ srcFile = getClient(src).openFile(src.derivedUri, "r", canceller);
+ } catch (FileNotFoundException | RemoteException | RuntimeException e) {
+ throw new ResourceException(
+ "Failed to open a file for %s due to an exception.", src.derivedUri, e);
+ }
in = new ParcelFileDescriptor.AutoCloseInputStream(srcFile);
}
- dstFile = getClient(dest).openFile(dest.derivedUri, "w", canceller);
+ try {
+ dstFile = getClient(dest).openFile(dest.derivedUri, "w", canceller);
+ } catch (FileNotFoundException | RemoteException | RuntimeException e) {
+ throw new ResourceException("Failed to open the destination file %s for writing "
+ + "due to an exception.", dest.derivedUri, e);
+ }
out = new ParcelFileDescriptor.AutoCloseOutputStream(dstFile);
byte[] buffer = new byte[32 * 1024];
int len;
- while ((len = in.read(buffer)) != -1) {
- if (isCanceled()) {
- if (DEBUG) Log.d(TAG, "Canceled copy mid-copy. Id:" + id);
- success = false;
- break;
+ try {
+ while ((len = in.read(buffer)) != -1) {
+ if (isCanceled()) {
+ if (DEBUG) Log.d(TAG, "Canceled copy mid-copy of: " + src.derivedUri);
+ return;
+ }
+ out.write(buffer, 0, len);
+ makeCopyProgress(len);
}
- out.write(buffer, 0, len);
- makeCopyProgress(len);
+
+ srcFile.checkError();
+ } catch (IOException e) {
+ throw new ResourceException(
+ "Failed to copy bytes from %s to %s due to an IO exception.",
+ src.derivedUri, dest.derivedUri, e);
}
- srcFile.checkError();
- } catch (IOException e) {
- success = false;
- onFileFailed(src, "Exception thrown while copying from "
- + src.derivedUri + " to " + dest.derivedUri + ".");
-
- if (dstFile != null) {
- try {
- dstFile.closeWithError(e.getMessage());
- } catch (IOException closeError) {
- Log.e(TAG, "Error closing destination", closeError);
- }
+ if (src.isVirtualDocument()) {
+ convertedFiles.add(src);
}
+
+ success = true;
} finally {
+ if (!success) {
+ if (dstFile != null) {
+ try {
+ dstFile.closeWithError("Error copying bytes.");
+ } catch (IOException closeError) {
+ Log.w(TAG, "Error closing destination.", closeError);
+ }
+ }
+
+ if (DEBUG) Log.d(TAG, "Cleaning up failed operation leftovers.");
+ canceller.cancel();
+ try {
+ deleteDocument(dest, destParent);
+ } catch (ResourceException e) {
+ Log.w(TAG, "Failed to cleanup after copy error: " + src.derivedUri, e);
+ }
+ }
+
// This also ensures the file descriptors are closed.
IoUtils.closeQuietly(in);
IoUtils.closeQuietly(out);
}
-
- if (!success) {
- if (DEBUG) Log.d(TAG, "Cleaning up failed operation leftovers.");
- canceller.cancel();
- try {
- DocumentsContract.deleteDocument(getClient(dest), dest.derivedUri);
- } catch (RemoteException e) {
- // RemoteExceptions usually signal that the connection is dead, so there's no
- // point attempting to continue. Propagate the exception up so the copy job is
- // cancelled.
- Log.w(TAG, "Failed to cleanup after copy error: " + src.derivedUri, e);
- throw e;
- }
- }
-
- if (src.isVirtualDocument() && success) {
- convertedFiles.add(src);
- }
-
- return success;
}
/**
@@ -475,16 +548,20 @@
*
* @param srcs
* @return Size in bytes.
- * @throws RemoteException
+ * @throws ResourceException
*/
- private long calculateSize(List<DocumentInfo> srcs)
- throws RemoteException {
+ private long calculateSize(List<DocumentInfo> srcs) throws ResourceException {
long result = 0;
for (DocumentInfo src : srcs) {
if (src.isDirectory()) {
// Directories need to be recursed into.
- result += calculateFileSizesRecursively(getClient(src), src.derivedUri);
+ try {
+ result += calculateFileSizesRecursively(getClient(src), src.derivedUri);
+ } catch (RemoteException e) {
+ throw new ResourceException("Failed to obtain the client for %s.",
+ src.derivedUri);
+ }
} else {
result += src.size;
}
@@ -495,10 +572,10 @@
/**
* Calculates (recursively) the cumulative size of all the files under the given directory.
*
- * @throws RemoteException
+ * @throws ResourceException
*/
private static long calculateFileSizesRecursively(
- ContentProviderClient client, Uri uri) throws RemoteException {
+ ContentProviderClient client, Uri uri) throws ResourceException {
final String authority = uri.getAuthority();
final Uri queryUri = buildChildDocumentsUri(authority, getDocumentId(uri));
final String queryColumns[] = new String[] {
@@ -524,6 +601,9 @@
result += size > 0 ? size : 0;
}
}
+ } catch (RemoteException | RuntimeException e) {
+ throw new ResourceException(
+ "Failed to calculate size for %s due to an exception.", uri, e);
} finally {
IoUtils.closeQuietly(cursor);
}
@@ -533,21 +613,22 @@
/**
* Returns true if {@code doc} is a descendant of {@code parentDoc}.
- * @throws RemoteException
+ * @throws ResourceException
*/
boolean isDescendentOf(DocumentInfo doc, DocumentInfo parent)
- throws RemoteException {
+ throws ResourceException {
if (parent.isDirectory() && doc.authority.equals(parent.authority)) {
- return isChildDocument(getClient(doc), doc.derivedUri, parent.derivedUri);
+ try {
+ return isChildDocument(getClient(doc), doc.derivedUri, parent.derivedUri);
+ } catch (RemoteException | RuntimeException e) {
+ throw new ResourceException(
+ "Failed to check if %s is a child of %s due to an exception.",
+ doc.derivedUri, parent.derivedUri, e);
+ }
}
return false;
}
- private void onFileFailed(DocumentInfo file, String msg) {
- Log.w(TAG, msg);
- onFileFailed(file);
- }
-
@Override
public String toString() {
return new StringBuilder()
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/DeleteJob.java b/packages/DocumentsUI/src/com/android/documentsui/services/DeleteJob.java
index 11c3a29..8f45162 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/DeleteJob.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/DeleteJob.java
@@ -22,7 +22,6 @@
import android.app.Notification;
import android.app.Notification.Builder;
import android.content.Context;
-import android.os.RemoteException;
import android.util.Log;
import com.android.documentsui.Metrics;
@@ -58,8 +57,8 @@
@Override
Builder createProgressBuilder() {
return super.createProgressBuilder(
- service.getString(R.string.move_notification_title),
- R.drawable.ic_menu_copy,
+ service.getString(R.string.delete_notification_title),
+ R.drawable.ic_menu_delete,
service.getString(android.R.string.cancel),
R.drawable.ic_cab_cancel);
}
@@ -81,13 +80,13 @@
}
@Override
- void start() throws RemoteException {
+ void start() {
for (DocumentInfo doc : mSrcs) {
if (DEBUG) Log.d(TAG, "Deleting document @ " + doc.derivedUri);
- // TODO: Start using mSrcParent as soon as DocumentsProvider::removeDocument() is
- // implemented.
- if (!deleteDocument(doc)) {
- Log.w(TAG, "Failed to delete document @ " + doc.derivedUri);
+ try {
+ deleteDocument(doc, mSrcParent);
+ } catch (ResourceException e) {
+ Log.e(TAG, "Failed to delete document @ " + doc.derivedUri);
onFileFailed(doc);
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/FileOperationService.java b/packages/DocumentsUI/src/com/android/documentsui/services/FileOperationService.java
index 05a3f11..580fa38 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/FileOperationService.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/FileOperationService.java
@@ -17,9 +17,6 @@
package com.android.documentsui.services;
import static com.android.documentsui.Shared.DEBUG;
-import static com.android.internal.util.Preconditions.checkArgument;
-import static com.android.internal.util.Preconditions.checkNotNull;
-import static com.android.internal.util.Preconditions.checkState;
import android.annotation.IntDef;
import android.app.NotificationManager;
@@ -136,12 +133,12 @@
String jobId = intent.getStringExtra(EXTRA_JOB_ID);
@OpType int operationType = intent.getIntExtra(EXTRA_OPERATION, OPERATION_UNKNOWN);
- checkArgument(jobId != null);
+ assert(jobId != null);
if (intent.hasExtra(EXTRA_CANCEL)) {
handleCancel(intent);
} else {
- checkArgument(operationType != OPERATION_UNKNOWN);
+ assert(operationType != OPERATION_UNKNOWN);
handleOperation(intent, serviceId, jobId, operationType);
}
@@ -173,9 +170,9 @@
mWakeLock.acquire();
}
- checkState(job != null);
+ assert(job != null);
int delay = intent.getIntExtra(EXTRA_DELAY, DEFAULT_DELAY);
- checkArgument(delay <= MAX_DELAY);
+ assert(delay <= MAX_DELAY);
if (DEBUG) Log.d(
TAG, "Scheduling job " + job.id + " to run in " + delay + " milliseconds.");
ScheduledFuture<?> future = executor.schedule(job, delay, TimeUnit.MILLISECONDS);
@@ -188,8 +185,10 @@
* @param intent The cancellation intent.
*/
private void handleCancel(Intent intent) {
- checkArgument(intent.hasExtra(EXTRA_CANCEL));
- String jobId = checkNotNull(intent.getStringExtra(EXTRA_JOB_ID));
+ assert(intent.hasExtra(EXTRA_CANCEL));
+ assert(intent.getStringExtra(EXTRA_JOB_ID) != null);
+
+ String jobId = intent.getStringExtra(EXTRA_JOB_ID);
if (DEBUG) Log.d(TAG, "handleCancel: " + jobId);
@@ -253,7 +252,8 @@
throw new UnsupportedOperationException();
}
- return checkNotNull(job);
+ assert(job != null);
+ return job;
}
@GuardedBy("mRunning")
@@ -261,7 +261,7 @@
if (DEBUG) Log.d(TAG, "deleteJob: " + job.id);
JobRecord record = mRunning.remove(job.id);
- checkArgument(record != null);
+ assert(record != null);
record.job.cleanup();
if (mRunning.isEmpty()) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/FileOperations.java b/packages/DocumentsUI/src/com/android/documentsui/services/FileOperations.java
index 9d017ee..b53e165 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/FileOperations.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/FileOperations.java
@@ -22,7 +22,6 @@
import static com.android.documentsui.Shared.asArrayList;
import static com.android.documentsui.Shared.getQuantityString;
import static com.android.documentsui.services.FileOperationService.EXTRA_CANCEL;
-import static com.android.documentsui.services.FileOperationService.EXTRA_DELAY;
import static com.android.documentsui.services.FileOperationService.EXTRA_JOB_ID;
import static com.android.documentsui.services.FileOperationService.EXTRA_OPERATION;
import static com.android.documentsui.services.FileOperationService.EXTRA_SRC_LIST;
@@ -165,19 +164,16 @@
* Use {@link #createJobId} if you don't have one handy.
* @param srcDocs A list of src files to copy.
* @param srcParent Parent of all the source documents.
- * @param delay Number of milliseconds to wait before executing the job.
* @return Id of the job.
*/
public static String delete(
Activity activity, List<DocumentInfo> srcDocs, DocumentInfo srcParent,
- DocumentStack location, int delay) {
+ DocumentStack location) {
String jobId = createJobId();
- if (DEBUG) Log.d(TAG, "Initiating 'delete' operation id " + jobId
- + " delayed by " + delay + " milliseconds.");
+ if (DEBUG) Log.d(TAG, "Initiating 'delete' operation id " + jobId + ".");
Intent intent = createBaseIntent(OPERATION_DELETE, activity, jobId, srcDocs, srcParent,
location);
- intent.putExtra(EXTRA_DELAY, delay);
activity.startService(intent);
return jobId;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/Job.java b/packages/DocumentsUI/src/com/android/documentsui/services/Job.java
index 77517ca..c723ac6 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/Job.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/Job.java
@@ -23,8 +23,6 @@
import static com.android.documentsui.services.FileOperationService.EXTRA_OPERATION;
import static com.android.documentsui.services.FileOperationService.EXTRA_SRC_LIST;
import static com.android.documentsui.services.FileOperationService.OPERATION_UNKNOWN;
-import static com.android.internal.util.Preconditions.checkArgument;
-import static com.android.internal.util.Preconditions.checkNotNull;
import android.annotation.DrawableRes;
import android.annotation.PluralsRes;
@@ -98,7 +96,7 @@
Job(Context service, Context appContext, Listener listener,
@OpType int operationType, String id, DocumentStack stack) {
- checkArgument(operationType != OPERATION_UNKNOWN);
+ assert(operationType != OPERATION_UNKNOWN);
this.service = service;
this.appContext = appContext;
@@ -116,19 +114,17 @@
listener.onStart(this);
try {
start();
- } catch (Exception e) {
- // In the case of an unmanaged failure, we still want
- // to resolve business in an orderly fashion. That'll
- // ensure the service is shut down and notifications
- // shown/closed.
- Log.e(TAG, "Operation failed due to an exception.", e);
+ } catch (RuntimeException e) {
+ // No exceptions should be thrown here, as all calls to the provider must be
+ // handled within Job implementations. However, just in case catch them here.
+ Log.e(TAG, "Operation failed due to an unhandled runtime exception.", e);
Metrics.logFileOperationErrors(service, operationType, failedFiles);
} finally {
listener.onFinished(this);
}
}
- abstract void start() throws RemoteException;
+ abstract void start();
abstract Notification getSetupNotification();
// TODO: Progress notification for deletes.
@@ -152,7 +148,8 @@
mClients.put(doc.authority, client);
}
- return checkNotNull(client);
+ assert(client != null);
+ return client;
}
final void cleanup() {
@@ -186,20 +183,25 @@
return false;
}
- final boolean deleteDocument(DocumentInfo doc) {
+ final void deleteDocument(DocumentInfo doc, DocumentInfo parent) throws ResourceException {
try {
- DocumentsContract.deleteDocument(getClient(doc), doc.derivedUri);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to delete file: " + doc.derivedUri, e);
- return false;
+ if (doc.isRemoveSupported()) {
+ DocumentsContract.removeDocument(getClient(doc), doc.derivedUri, parent.derivedUri);
+ } else if (doc.isDeleteSupported()) {
+ DocumentsContract.deleteDocument(getClient(doc), doc.derivedUri);
+ } else {
+ throw new ResourceException("Unable to delete source document as the file is " +
+ "not deletable nor removable: %s.", doc.derivedUri);
+ }
+ } catch (RemoteException | RuntimeException e) {
+ throw new ResourceException("Failed to delete file %s due to an exception.",
+ doc.derivedUri, e);
}
-
- return true; // victory dance!
}
Notification getSetupNotification(String content) {
- mProgressBuilder.setProgress(0, 0, true);
- mProgressBuilder.setContentText(content);
+ mProgressBuilder.setProgress(0, 0, true)
+ .setContentText(content);
return mProgressBuilder.build();
}
@@ -218,6 +220,7 @@
.setCategory(Notification.CATEGORY_ERROR)
.setSmallIcon(icon)
.setAutoCancel(true);
+
return errorBuilder.build();
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java b/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java
index 9b72077..dc39235 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java
@@ -21,11 +21,9 @@
import android.app.Notification;
import android.app.Notification.Builder;
import android.content.Context;
-import android.net.Uri;
import android.os.RemoteException;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
-import android.util.Log;
import com.android.documentsui.R;
import com.android.documentsui.model.DocumentInfo;
@@ -36,7 +34,6 @@
// TODO: Stop extending CopyJob.
final class MoveJob extends CopyJob {
- private static final String TAG = "MoveJob";
final DocumentInfo mSrcParent;
/**
@@ -80,8 +77,8 @@
R.plurals.move_error_notification_title, R.drawable.ic_menu_copy);
}
- boolean processDocument(DocumentInfo src, DocumentInfo srcParent, DocumentInfo dest)
- throws RemoteException {
+ void processDocument(DocumentInfo src, DocumentInfo srcParent, DocumentInfo dest)
+ throws ResourceException {
// TODO: When optimized move kicks in, we're not making any progress updates. FIX IT!
@@ -89,13 +86,19 @@
// If not supported, then fallback to byte-by-byte copy/move.
if (src.authority.equals(dest.authority)) {
if ((src.flags & Document.FLAG_SUPPORTS_MOVE) != 0) {
- if (DocumentsContract.moveDocument(getClient(src), src.derivedUri,
- srcParent != null ? srcParent.derivedUri : mSrcParent.derivedUri,
- dest.derivedUri) == null) {
- onFileFailed(src);
- return false;
+ try {
+ if (DocumentsContract.moveDocument(getClient(src), src.derivedUri,
+ srcParent != null ? srcParent.derivedUri : mSrcParent.derivedUri,
+ dest.derivedUri) == null) {
+ throw new ResourceException("Provider side move failed for document %s.",
+ src.derivedUri);
+ }
+ } catch (RuntimeException | RemoteException e) {
+ throw new ResourceException(
+ "Provider side move failed for document %s due to an exception.",
+ src.derivedUri, e);
}
- return true;
+ return;
}
}
@@ -103,16 +106,15 @@
// conversion, and the source file should not be deleted in such case (as it's a different
// file).
if (src.isVirtualDocument()) {
- Log.w(TAG, "Cannot move virtual files byte by byte.");
- onFileFailed(src);
- return false;
+ throw new ResourceException("Cannot move virtual file %s byte by byte.",
+ src.derivedUri);
}
// If we couldn't do an optimized copy...we fall back to vanilla byte copy.
- boolean copied = byteCopyDocument(src, dest);
+ byteCopyDocument(src, dest);
- // TODO: Replace deleteDocument() with removeDocument() once implemented.
- return copied && !isCanceled() && deleteDocument(src);
+ // Remove the source document.
+ deleteDocument(src, srcParent);
}
@Override
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/ResourceException.java b/packages/DocumentsUI/src/com/android/documentsui/services/ResourceException.java
new file mode 100644
index 0000000..7d3d91a
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/ResourceException.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.services;
+
+import android.net.Uri;
+
+public class ResourceException extends Exception {
+ public ResourceException(String message, Exception e) {
+ super(message, e);
+ }
+
+ public ResourceException(String message, Uri uri1, Exception e) {
+ super(String.format(message, uri1.toString()), e);
+ }
+
+ public ResourceException(String message, Uri uri1, Uri uri2, Exception e) {
+ super(String.format(message, uri1.toString(), uri2.toString()), e);
+ }
+
+ public ResourceException(String message) {
+ super(message);
+ }
+
+ public ResourceException(String message, Uri uri1) {
+ super(String.format(message, uri1.toString()));
+ }
+
+ public ResourceException(String message, Uri uri1, Uri uri2) {
+ super(message.format(uri1.toString(), uri2.toString()));
+ }
+}
diff --git a/packages/DocumentsUI/tests/Android.mk b/packages/DocumentsUI/tests/Android.mk
index b65ac98..3983f78 100644
--- a/packages/DocumentsUI/tests/Android.mk
+++ b/packages/DocumentsUI/tests/Android.mk
@@ -7,8 +7,8 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 mockito-target ub-uiautomator
+LOCAL_JAVA_LIBRARIES := android-support-v4 android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ub-uiautomator
LOCAL_PACKAGE_NAME := DocumentsUITests
LOCAL_INSTRUMENTATION_FOR := DocumentsUI
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/ActivityTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/ActivityTest.java
index 34f1120..683fd6c 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/ActivityTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/ActivityTest.java
@@ -20,22 +20,27 @@
import static com.android.documentsui.StubProvider.ROOT_0_ID;
import static com.android.documentsui.StubProvider.ROOT_1_ID;
+import android.annotation.Nullable;
import android.app.Activity;
-import android.app.Instrumentation;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.os.RemoteException;
import android.provider.DocumentsContract.Document;
-import android.support.test.uiautomator.By;
import android.support.test.uiautomator.Configurator;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObjectNotFoundException;
-import android.support.test.uiautomator.Until;
import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
import android.view.MotionEvent;
+import com.android.documentsui.BaseActivity;
+import com.android.documentsui.EventListener;
+import com.android.documentsui.bots.DirectoryListBot;
+import com.android.documentsui.bots.KeyboardBot;
+import com.android.documentsui.bots.RootsListBot;
+import com.android.documentsui.bots.UiBot;
import com.android.documentsui.model.RootInfo;
/**
@@ -56,13 +61,12 @@
public static final String fileName4 = "poodles.text";
public static final String fileNameNoRename = "NO_RENAMEfile.txt";
- public UiBot bot;
+ public Bots bots;
public UiDevice device;
public Context context;
public RootInfo rootDir0;
public RootInfo rootDir1;
-
ContentResolver mResolver;
DocumentsProviderHelper mDocsHelper;
ContentProviderClient mClient;
@@ -71,26 +75,51 @@
super(activityClass);
}
+ /*
+ * Returns the root that will be opened within the activity.
+ * By default tests are started with one of the test roots.
+ * Override the method if you want to open different root on start.
+ * @return Root that will be opened. Return null if you want to open activity's default root.
+ */
+ @Nullable
+ protected RootInfo getInitialRoot() {
+ return rootDir0;
+ }
+
+ /**
+ * Returns the authority of the testing provider begin used.
+ * By default it's StubProvider's authority.
+ * @return Authority of the provider.
+ */
+ protected String getTestingProviderAuthority() {
+ return DEFAULT_AUTHORITY;
+ }
+
+ /**
+ * Resolves testing roots.
+ */
+ protected void setupTestingRoots() throws RemoteException {
+ rootDir0 = mDocsHelper.getRoot(ROOT_0_ID);
+ rootDir1 = mDocsHelper.getRoot(ROOT_1_ID);
+ }
+
@Override
public void setUp() throws Exception {
device = UiDevice.getInstance(getInstrumentation());
// NOTE: Must be the "target" context, else security checks in content provider will fail.
context = getInstrumentation().getTargetContext();
- bot = new UiBot(device, context, TIMEOUT);
+
+ bots = new Bots(device, context, TIMEOUT);
Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_MOUSE);
- bot.revealLauncher();
mResolver = context.getContentResolver();
- mClient = mResolver.acquireUnstableContentProviderClient(DEFAULT_AUTHORITY);
- mDocsHelper = new DocumentsProviderHelper(DEFAULT_AUTHORITY, mClient);
+ mClient = mResolver.acquireUnstableContentProviderClient(getTestingProviderAuthority());
+ mDocsHelper = new DocumentsProviderHelper(getTestingProviderAuthority(), mClient);
- rootDir0 = mDocsHelper.getRoot(ROOT_0_ID);
- rootDir1 = mDocsHelper.getRoot(ROOT_1_ID);
+ setupTestingRoots();
launchActivity();
-
- bot.revealApp();
resetStorage();
}
@@ -104,6 +133,9 @@
final Intent intent = context.getPackageManager().getLaunchIntentForPackage(
UiBot.TARGET_PKG);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
+ if (getInitialRoot() != null) {
+ intent.setData(getInitialRoot().getUri());
+ }
setActivityIntent(intent);
getActivity(); // Launch the activity.
}
@@ -125,12 +157,29 @@
}
void assertDefaultContentOfTestDir0() throws UiObjectNotFoundException {
- bot.assertDocumentsCount(ROOT_0_ID, 4);
- bot.assertHasDocuments(fileName1, fileName2, dirName1, fileNameNoRename);
+ bots.directory.assertDocumentsCount(4);
+ bots.directory.assertDocumentsPresent(fileName1, fileName2, dirName1, fileNameNoRename);
}
void assertDefaultContentOfTestDir1() throws UiObjectNotFoundException {
- bot.assertDocumentsCount(ROOT_1_ID, 2);
- bot.assertHasDocuments(fileName3, fileName4);
+ bots.directory.assertDocumentsCount(2);
+ bots.directory.assertDocumentsPresent(fileName3, fileName4);
+ }
+
+ /**
+ * Handy collection of bots for working with Files app.
+ */
+ public static final class Bots {
+ public final UiBot main;
+ public final RootsListBot roots;
+ public final DirectoryListBot directory;
+ public final KeyboardBot keyboard;
+
+ private Bots(UiDevice device, Context context, int timeout) {
+ this.main = new UiBot(device, context, TIMEOUT);
+ this.roots = new RootsListBot(device, context, TIMEOUT);
+ this.directory = new DirectoryListBot(device, context, TIMEOUT);
+ this.keyboard = new KeyboardBot(device, context, TIMEOUT);
+ }
}
}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/DownloadsActivityUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/DownloadsActivityUiTest.java
index c51f927..79d7887 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/DownloadsActivityUiTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/DownloadsActivityUiTest.java
@@ -52,13 +52,13 @@
public void testWindowTitle() throws Exception {
initTestFiles();
- bot.assertWindowTitle(ROOT_0_ID);
+ bots.main.assertWindowTitle(ROOT_0_ID);
}
public void testFilesListed() throws Exception {
initTestFiles();
- bot.assertHasDocuments("file0.log", "file1.png", "file2.csv");
+ bots.directory.assertDocumentsPresent("file0.log", "file1.png", "file2.csv");
}
public void testFilesList_LiveUpdate() throws Exception {
@@ -66,30 +66,31 @@
mDocsHelper.createDocument(rootDir0, "yummers/sandwich", "Ham & Cheese.sandwich");
- bot.waitForDocument("Ham & Cheese.sandwich");
- bot.assertHasDocuments("file0.log", "file1.png", "file2.csv", "Ham & Cheese.sandwich");
+ bots.directory.waitForDocument("Ham & Cheese.sandwich");
+ bots.directory.assertDocumentsPresent(
+ "file0.log", "file1.png", "file2.csv", "Ham & Cheese.sandwich");
}
public void testDeleteDocument() throws Exception {
initTestFiles();
- bot.clickDocument("file1.png");
+ bots.directory.clickDocument("file1.png");
device.waitForIdle();
- bot.menuDelete().click();
+ bots.main.menuDelete().click();
- bot.waitForDeleteSnackbar();
- assertFalse(bot.hasDocuments("file1.png"));
+ bots.directory.waitForDeleteSnackbar();
+ bots.directory.assertDocumentsAbsent("file1.png");
- bot.waitForDeleteSnackbarGone();
- assertFalse(bot.hasDocuments("file1.png"));
+ bots.directory.waitForDeleteSnackbarGone();
+ bots.directory.assertDocumentsAbsent("file1.png");
}
public void testSupportsShare() throws Exception {
initTestFiles();
- bot.clickDocument("file1.png");
+ bots.directory.clickDocument("file1.png");
device.waitForIdle();
- assertNotNull(bot.menuShare());
+ assertNotNull(bots.main.menuShare());
}
public void testClosesOnBack() throws Exception {
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
index 95515db..498471e 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
@@ -23,6 +23,8 @@
import android.test.suitebuilder.annotation.LargeTest;
import android.view.KeyEvent;
+import com.android.documentsui.model.RootInfo;
+
@LargeTest
public class FilesActivityUiTest extends ActivityTest<FilesActivity> {
@@ -31,6 +33,11 @@
}
@Override
+ protected RootInfo getInitialRoot() {
+ return null;
+ }
+
+ @Override
public void initTestFiles() throws RemoteException {
mDocsHelper.createDocument(rootDir0, "text/plain", "file0.log");
mDocsHelper.createDocument(rootDir0, "image/png", "file1.png");
@@ -43,11 +50,11 @@
public void testRootsListed() throws Exception {
initTestFiles();
- bot.openRoot(ROOT_0_ID);
+ bots.roots.openRoot(ROOT_0_ID);
// Should also have Drive, but that requires pre-configuration of devices
// We omit for now.
- bot.assertHasRoots(
+ bots.roots.assertHasRoots(
"Images",
"Videos",
"Audio",
@@ -60,93 +67,107 @@
public void testFilesListed() throws Exception {
initTestFiles();
- bot.openRoot(ROOT_0_ID);
- bot.assertHasDocuments("file0.log", "file1.png", "file2.csv");
+ bots.roots.openRoot(ROOT_0_ID);
+ bots.directory.assertDocumentsPresent("file0.log", "file1.png", "file2.csv");
}
public void testLoadsHomeDirectoryByDefault() throws Exception {
initTestFiles();
device.waitForIdle();
- bot.assertWindowTitle("Documents");
+ bots.main.assertWindowTitle("Documents");
}
public void testRootClickSetsWindowTitle() throws Exception {
initTestFiles();
- bot.openRoot("Downloads");
- bot.assertWindowTitle("Downloads");
+ bots.roots.openRoot("Downloads");
+ bots.main.assertWindowTitle("Downloads");
}
public void testFilesList_LiveUpdate() throws Exception {
initTestFiles();
- bot.openRoot(ROOT_0_ID);
+ bots.roots.openRoot(ROOT_0_ID);
mDocsHelper.createDocument(rootDir0, "yummers/sandwich", "Ham & Cheese.sandwich");
- bot.waitForDocument("Ham & Cheese.sandwich");
- bot.assertHasDocuments("file0.log", "file1.png", "file2.csv", "Ham & Cheese.sandwich");
+ bots.directory.waitForDocument("Ham & Cheese.sandwich");
+ bots.directory.assertDocumentsPresent(
+ "file0.log", "file1.png", "file2.csv", "Ham & Cheese.sandwich");
+ }
+
+ public void testCreateDirectory() throws Exception {
+ initTestFiles();
+
+ bots.roots.openRoot(ROOT_0_ID);
+
+ bots.main.openOverflowMenu();
+ bots.main.menuNewFolder().click();
+ bots.main.setDialogText("Kung Fu Panda");
+
+ bots.keyboard.pressEnter();
+
+ bots.directory.assertDocumentsPresent("Kung Fu Panda");
}
public void testDeleteDocument() throws Exception {
initTestFiles();
- bot.openRoot(ROOT_0_ID);
+ bots.roots.openRoot(ROOT_0_ID);
- bot.clickDocument("file1.png");
+ bots.directory.clickDocument("file1.png");
device.waitForIdle();
- bot.menuDelete().click();
+ bots.main.menuDelete().click();
- bot.waitForDeleteSnackbar();
- assertFalse(bot.hasDocuments("file1.png"));
+ bots.main.findDialogOkButton().click();
- bot.waitForDeleteSnackbarGone();
- assertFalse(bot.hasDocuments("file1.png"));
+ bots.directory.assertDocumentsAbsent("file1.png");
+ }
- // Now delete from another root.
- bot.openRoot(ROOT_1_ID);
+ public void testDeleteDocument_Cancel() throws Exception {
+ initTestFiles();
- bot.clickDocument("poodles.text");
+ bots.roots.openRoot(ROOT_0_ID);
+
+ bots.directory.clickDocument("file1.png");
device.waitForIdle();
- bot.menuDelete().click();
+ bots.main.menuDelete().click();
- bot.waitForDeleteSnackbar();
- assertFalse(bot.hasDocuments("poodles.text"));
+ bots.main.findDialogCancelButton().click();
- bot.waitForDeleteSnackbarGone();
- assertFalse(bot.hasDocuments("poodles.text"));
+ bots.directory.assertDocumentsPresent("file1.png");
}
// Tests that pressing tab switches focus between the roots and directory listings.
public void testKeyboard_tab() throws Exception {
- bot.pressKey(KeyEvent.KEYCODE_TAB);
- bot.assertHasFocus("com.android.documentsui:id/roots_list");
- bot.pressKey(KeyEvent.KEYCODE_TAB);
- bot.assertHasFocus("com.android.documentsui:id/dir_list");
+ bots.main.pressKey(KeyEvent.KEYCODE_TAB);
+ bots.roots.assertHasFocus();
+ bots.main.pressKey(KeyEvent.KEYCODE_TAB);
+ bots.directory.assertHasFocus();
}
// Tests that arrow keys do not switch focus away from the dir list.
public void testKeyboard_arrowsDirList() throws Exception {
for (int i = 0; i < 10; i++) {
- bot.pressKey(KeyEvent.KEYCODE_DPAD_LEFT);
- bot.assertHasFocus("com.android.documentsui:id/dir_list");
+ bots.main.pressKey(KeyEvent.KEYCODE_DPAD_LEFT);
+ bots.directory.assertHasFocus();
}
for (int i = 0; i < 10; i++) {
- bot.pressKey(KeyEvent.KEYCODE_DPAD_RIGHT);
- bot.assertHasFocus("com.android.documentsui:id/dir_list");
+ bots.main.pressKey(KeyEvent.KEYCODE_DPAD_RIGHT);
+ bots.directory.assertHasFocus();
}
}
// Tests that arrow keys do not switch focus away from the roots list.
public void testKeyboard_arrowsRootsList() throws Exception {
- bot.pressKey(KeyEvent.KEYCODE_TAB);
+ bots.main.pressKey(KeyEvent.KEYCODE_TAB);
for (int i = 0; i < 10; i++) {
- bot.pressKey(KeyEvent.KEYCODE_DPAD_RIGHT);
- bot.assertHasFocus("com.android.documentsui:id/roots_list");
+ bots.main.pressKey(KeyEvent.KEYCODE_DPAD_RIGHT);
+ bots.roots.assertHasFocus();
}
for (int i = 0; i < 10; i++) {
- bot.pressKey(KeyEvent.KEYCODE_DPAD_LEFT);
- bot.assertHasFocus("com.android.documentsui:id/roots_list");
+ bots.main.pressKey(KeyEvent.KEYCODE_DPAD_LEFT);
+ bots.roots.assertHasFocus();
}
}
}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/RenameDocumentUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/RenameDocumentUiTest.java
index 770bc2c..5f33b32 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/RenameDocumentUiTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/RenameDocumentUiTest.java
@@ -23,8 +23,6 @@
@LargeTest
public class RenameDocumentUiTest extends ActivityTest<FilesActivity> {
- private static final String TAG = "RenamDocumentUiTest";
-
private final String newName = "kitties.log";
public RenameDocumentUiTest() {
@@ -35,125 +33,118 @@
public void setUp() throws Exception {
super.setUp();
initTestFiles();
- bot.openRoot(ROOT_0_ID);
}
public void testRenameEnabled_SingleSelection() throws Exception {
- bot.selectDocument(fileName1);
- bot.openOverflowMenu();
- bot.assertMenuEnabled(R.string.menu_rename, true);
+ bots.directory.selectDocument(fileName1);
+ bots.main.openOverflowMenu();
+ bots.main.assertMenuEnabled(R.string.menu_rename, true);
// Dismiss more options window
device.pressBack();
}
public void testNoRenameSupport_SingleSelection() throws Exception {
- bot.selectDocument(fileNameNoRename);
- bot.openOverflowMenu();
- bot.assertMenuEnabled(R.string.menu_rename, false);
+ bots.directory.selectDocument(fileNameNoRename);
+ bots.main.openOverflowMenu();
+ bots.main.assertMenuEnabled(R.string.menu_rename, false);
// Dismiss more options window
device.pressBack();
}
public void testOneHasRenameSupport_MultipleSelection() throws Exception {
- bot.selectDocument(fileName1);
- bot.selectDocument(fileNameNoRename);
- bot.openOverflowMenu();
- bot.assertMenuEnabled(R.string.menu_rename, false);
+ bots.directory.selectDocument(fileName1);
+ bots.directory.selectDocument(fileNameNoRename);
+ bots.main.openOverflowMenu();
+ bots.main.assertMenuEnabled(R.string.menu_rename, false);
// Dismiss more options window
device.pressBack();
}
public void testRenameDisabled_MultipleSelection() throws Exception {
- bot.selectDocument(fileName1);
- bot.selectDocument(fileName2);
- bot.openOverflowMenu();
- bot.assertMenuEnabled(R.string.menu_rename, false);
+ bots.directory.selectDocument(fileName1);
+ bots.directory.selectDocument(fileName2);
+ bots.main.openOverflowMenu();
+ bots.main.assertMenuEnabled(R.string.menu_rename, false);
// Dismiss more options window
device.pressBack();
}
public void testRenameFile_OkButton() throws Exception {
- bot.selectDocument(fileName1);
- bot.openOverflowMenu();
- bot.openDialog(R.string.menu_rename);
- bot.setDialogText(newName);
+ bots.directory.selectDocument(fileName1);
+ bots.main.openOverflowMenu();
+ bots.main.menuRename().click();
+ bots.main.setDialogText(newName);
device.waitForIdle(TIMEOUT);
- bot.findRenameDialogOkButton().click();
+ bots.main.findDialogOkButton().click();
device.waitForIdle(TIMEOUT);
- bot.assertDocument(fileName1, false);
- bot.assertDocument(newName, true);
- bot.assertDocumentsCount(4);
+ bots.directory.assertDocumentsAbsent(fileName1);
+ bots.directory.assertDocumentsPresent(newName);
+ bots.directory.assertDocumentsCount(4);
}
public void testRenameFile_Enter() throws Exception {
- bot.selectDocument(fileName1);
- bot.openOverflowMenu();
- bot.openDialog(R.string.menu_rename);
- bot.setDialogText(newName);
+ bots.directory.selectDocument(fileName1);
+ bots.main.openOverflowMenu();
+ bots.main.menuRename().click();
+ bots.main.setDialogText(newName);
- pressEnter();
+ bots.keyboard.pressEnter();
- bot.assertDocument(fileName1, false);
- bot.assertDocument(newName, true);
- bot.assertDocumentsCount(4);
+ bots.directory.assertDocumentsAbsent(fileName1);
+ bots.directory.assertDocumentsPresent(newName);
+ bots.directory.assertDocumentsCount(4);
}
public void testRenameFile_Cancel() throws Exception {
- bot.selectDocument(fileName1);
- bot.openOverflowMenu();
- bot.openDialog(R.string.menu_rename);
- bot.setDialogText(newName);
+ bots.directory.selectDocument(fileName1);
+ bots.main.openOverflowMenu();
+ bots.main.menuRename().click();
+ bots.main.setDialogText(newName);
device.waitForIdle(TIMEOUT);
- bot.findRenameDialogCancelButton().click();
+ bots.main.findDialogCancelButton().click();
device.waitForIdle(TIMEOUT);
- bot.assertDocument(fileName1, true);
- bot.assertDocument(newName, false);
- bot.assertDocumentsCount(4);
+ bots.directory.assertDocumentsPresent(fileName1);
+ bots.directory.assertDocumentsAbsent(newName);
+ bots.directory.assertDocumentsCount(4);
}
public void testRenameDir() throws Exception {
String oldName = "Dir1";
String newName = "Dir123";
- bot.selectDocument(oldName);
- bot.openOverflowMenu();
- bot.openDialog(R.string.menu_rename);
- bot.setDialogText(newName);
+ bots.directory.selectDocument(oldName);
+ bots.main.openOverflowMenu();
+ bots.main.menuRename().click();
+ bots.main.setDialogText(newName);
- pressEnter();
+ bots.keyboard.pressEnter();
- bot.assertDocument(oldName, false);
- bot.assertDocument(newName, true);
- bot.assertDocumentsCount(4);
+ bots.directory.assertDocumentsAbsent(oldName);
+ bots.directory.assertDocumentsPresent(newName);
+ bots.directory.assertDocumentsCount(4);
}
public void testRename_NameExists() throws Exception {
// Check that document with the new name exists
- bot.assertDocument(fileName2, true);
- bot.selectDocument(fileName1);
- bot.openOverflowMenu();
- bot.openDialog(R.string.menu_rename);
- bot.setDialogText(fileName2);
+ bots.directory.assertDocumentsPresent(fileName2);
+ bots.directory.selectDocument(fileName1);
+ bots.main.openOverflowMenu();
+ bots.main.menuRename().click();
+ bots.main.setDialogText(fileName2);
- pressEnter();
+ bots.keyboard.pressEnter();
- bot.assertSnackbar(R.string.rename_error);
- bot.assertDocument(fileName1, true);
- bot.assertDocument(fileName2, true);
- bot.assertDocumentsCount(4);
- }
-
- private void pressEnter() {
- device.waitForIdle(TIMEOUT);
- device.pressEnter();
- device.waitForIdle(TIMEOUT);
+ bots.directory.assertSnackbar(R.string.rename_error);
+ bots.directory.assertDocumentsPresent(fileName1);
+ bots.directory.assertDocumentsPresent(fileName2);
+ bots.directory.assertDocumentsCount(4);
}
}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java
index 7d3498e..e73dd8c 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java
@@ -16,6 +16,9 @@
package com.android.documentsui;
+import static com.android.documentsui.RootsCache.getMatchingRoots;
+import static com.google.common.collect.Lists.newArrayList;
+
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
@@ -28,23 +31,18 @@
@SmallTest
public class RootsCacheTest extends AndroidTestCase {
- private static RootInfo buildForMimeTypes(String... mimeTypes) {
- final RootInfo root = new RootInfo();
- root.derivedMimeTypes = mimeTypes;
- return root;
- }
+ private static RootInfo mNull = new RootInfo();
+ private static RootInfo mEmpty = buildForMimeTypes();
+ private static RootInfo mWild = buildForMimeTypes("*/*");
+ private static RootInfo mImages = buildForMimeTypes("image/*");
+ private static RootInfo mAudio = buildForMimeTypes(
+ "audio/*", "application/ogg", "application/x-flac");
+ private static RootInfo mDocs = buildForMimeTypes(
+ "application/msword", "application/vnd.ms-excel");
+ private static RootInfo mMalformed1 = buildForMimeTypes("meow");
+ private static RootInfo mMalformed2 = buildForMimeTypes("*/meow");
- private RootInfo mNull = new RootInfo();
- private RootInfo mEmpty = buildForMimeTypes();
- private RootInfo mWild = buildForMimeTypes("*/*");
- private RootInfo mImages = buildForMimeTypes("image/*");
- private RootInfo mAudio = buildForMimeTypes("audio/*", "application/ogg", "application/x-flac");
- private RootInfo mDocs = buildForMimeTypes("application/msword", "application/vnd.ms-excel");
- private RootInfo mMalformed1 = buildForMimeTypes("meow");
- private RootInfo mMalformed2 = buildForMimeTypes("*/meow");
-
- private List<RootInfo> mRoots = Lists.newArrayList(
- mNull, mWild, mEmpty, mImages, mAudio, mDocs, mMalformed1, mMalformed2);
+ private List<RootInfo> mRoots;
private State mState;
@@ -52,70 +50,86 @@
protected void setUp() throws Exception {
super.setUp();
+ mRoots = Lists.newArrayList(
+ mNull, mWild, mEmpty, mImages, mAudio, mDocs, mMalformed1, mMalformed2);
+
mState = new State();
mState.action = State.ACTION_OPEN;
- mState.showAdvanced = true;
mState.localOnly = false;
}
- public void testMatchingRootsEverything() throws Exception {
+ public void testMatchingRoots_Everything() throws Exception {
mState.acceptMimes = new String[] { "*/*" };
assertContainsExactly(
- Lists.newArrayList(mNull, mWild, mImages, mAudio, mDocs, mMalformed1, mMalformed2),
- RootsCache.getMatchingRoots(mRoots, mState));
+ newArrayList(mNull, mWild, mImages, mAudio, mDocs, mMalformed1, mMalformed2),
+ getMatchingRoots(mRoots, mState));
}
- public void testMatchingRootsPngOrWild() throws Exception {
+ public void testMatchingRoots_DirectoryCopy() throws Exception {
+ RootInfo downloads = buildForMimeTypes("*/*");
+ downloads.authority = "com.android.providers.downloads.documents";
+ mRoots.add(downloads);
+
+ mState.acceptMimes = new String[] { "*/*" };
+ mState.directoryCopy = true;
+
+ // basically we're asserting that the results don't contain downloads
+ assertContainsExactly(
+ newArrayList(mNull, mWild, mImages, mAudio, mDocs, mMalformed1, mMalformed2),
+ getMatchingRoots(mRoots, mState));
+ }
+
+ public void testMatchingRoots_PngOrWild() throws Exception {
mState.acceptMimes = new String[] { "image/png", "*/*" };
assertContainsExactly(
- Lists.newArrayList(mNull, mWild, mImages, mAudio, mDocs, mMalformed1, mMalformed2),
- RootsCache.getMatchingRoots(mRoots, mState));
+ newArrayList(mNull, mWild, mImages, mAudio, mDocs, mMalformed1, mMalformed2),
+ getMatchingRoots(mRoots, mState));
}
- public void testMatchingRootsAudioWild() throws Exception {
+ public void testMatchingRoots_AudioWild() throws Exception {
mState.acceptMimes = new String[] { "audio/*" };
assertContainsExactly(
- Lists.newArrayList(mNull, mWild, mAudio),
- RootsCache.getMatchingRoots(mRoots, mState));
+ newArrayList(mNull, mWild, mAudio),
+ getMatchingRoots(mRoots, mState));
}
- public void testMatchingRootsAudioWildOrImageWild() throws Exception {
+ public void testMatchingRoots_AudioWildOrImageWild() throws Exception {
mState.acceptMimes = new String[] { "audio/*", "image/*" };
assertContainsExactly(
- Lists.newArrayList(mNull, mWild, mAudio, mImages),
- RootsCache.getMatchingRoots(mRoots, mState));
+ newArrayList(mNull, mWild, mAudio, mImages),
+ getMatchingRoots(mRoots, mState));
}
- public void testMatchingRootsAudioSpecific() throws Exception {
+ public void testMatchingRoots_AudioSpecific() throws Exception {
mState.acceptMimes = new String[] { "audio/mpeg" };
assertContainsExactly(
- Lists.newArrayList(mNull, mWild, mAudio),
- RootsCache.getMatchingRoots(mRoots, mState));
+ newArrayList(mNull, mWild, mAudio),
+ getMatchingRoots(mRoots, mState));
}
- public void testMatchingRootsDocument() throws Exception {
+ public void testMatchingRoots_Document() throws Exception {
mState.acceptMimes = new String[] { "application/msword" };
assertContainsExactly(
- Lists.newArrayList(mNull, mWild, mDocs),
- RootsCache.getMatchingRoots(mRoots, mState));
+ newArrayList(mNull, mWild, mDocs),
+ getMatchingRoots(mRoots, mState));
}
- public void testMatchingRootsApplication() throws Exception {
+ public void testMatchingRoots_Application() throws Exception {
mState.acceptMimes = new String[] { "application/*" };
assertContainsExactly(
- Lists.newArrayList(mNull, mWild, mAudio, mDocs),
- RootsCache.getMatchingRoots(mRoots, mState));
+ newArrayList(mNull, mWild, mAudio, mDocs),
+ getMatchingRoots(mRoots, mState));
}
- public void testMatchingRootsFlacOrPng() throws Exception {
+ public void testMatchingRoots_FlacOrPng() throws Exception {
mState.acceptMimes = new String[] { "application/x-flac", "image/png" };
assertContainsExactly(
- Lists.newArrayList(mNull, mWild, mAudio, mImages),
- RootsCache.getMatchingRoots(mRoots, mState));
+ newArrayList(mNull, mWild, mAudio, mImages),
+ getMatchingRoots(mRoots, mState));
}
public void testExcludedAuthorities() throws Exception {
- final List<RootInfo> roots = Lists.newArrayList();
+ final List<RootInfo> roots = newArrayList();
// Set up some roots
for (int i = 0; i < 5; ++i) {
@@ -124,7 +138,7 @@
roots.add(root);
}
// Make some allowed authorities
- List<RootInfo> allowedRoots = Lists.newArrayList(
+ List<RootInfo> allowedRoots = newArrayList(
roots.get(0), roots.get(2), roots.get(4));
// Set up the excluded authority list
for (RootInfo root: roots) {
@@ -136,7 +150,7 @@
assertContainsExactly(
allowedRoots,
- RootsCache.getMatchingRoots(roots, mState));
+ getMatchingRoots(roots, mState));
}
private static void assertContainsExactly(List<?> expected, List<?> actual) {
@@ -145,4 +159,10 @@
assertTrue(actual.contains(o));
}
}
+
+ private static RootInfo buildForMimeTypes(String... mimeTypes) {
+ final RootInfo root = new RootInfo();
+ root.derivedMimeTypes = mimeTypes;
+ return root;
+ }
}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/RootUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsUiTest.java
similarity index 65%
rename from packages/DocumentsUI/tests/src/com/android/documentsui/RootUiTest.java
rename to packages/DocumentsUI/tests/src/com/android/documentsui/RootsUiTest.java
index 1d1d3b5..73c1c5f 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/RootUiTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsUiTest.java
@@ -17,20 +17,16 @@
package com.android.documentsui;
import static com.android.documentsui.StubProvider.ROOT_0_ID;
+import static com.android.documentsui.StubProvider.ROOT_1_ID;
-import android.support.test.uiautomator.Configurator;
-import android.support.test.uiautomator.UiObject;
-import android.support.test.uiautomator.UiObjectNotFoundException;
-import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.LargeTest;
-import android.view.MotionEvent;
@LargeTest
-public class RootUiTest extends ActivityTest<FilesActivity> {
+public class RootsUiTest extends ActivityTest<FilesActivity> {
private static final String TAG = "RootUiTest";
- public RootUiTest() {
+ public RootsUiTest() {
super(FilesActivity.class);
}
@@ -38,14 +34,22 @@
public void setUp() throws Exception {
super.setUp();
initTestFiles();
- bot.openRoot(ROOT_0_ID);
}
public void testRootTapped_GoToRootFromChildDir() throws Exception {
- bot.openDocument(dirName1);
- bot.assertWindowTitle(dirName1);
- bot.openRoot(ROOT_0_ID);
- bot.assertWindowTitle(ROOT_0_ID);
+ bots.directory.openDocument(dirName1);
+ bots.main.assertWindowTitle(dirName1);
+ bots.roots.openRoot(ROOT_0_ID);
+ bots.main.assertWindowTitle(ROOT_0_ID);
assertDefaultContentOfTestDir0();
}
+
+ public void testRootChanged_ClearSelection() throws Exception {
+ bots.directory.selectDocument(fileName1);
+ bots.main.assertInActionMode(true);
+
+ bots.roots.openRoot(ROOT_1_ID);
+ bots.main.assertInActionMode(false);
+ }
+
}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/SearchViewUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/SearchViewUiTest.java
index b8d8795..8c3fd90 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/SearchViewUiTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/SearchViewUiTest.java
@@ -24,61 +24,57 @@
@LargeTest
public class SearchViewUiTest extends ActivityTest<FilesActivity> {
- private static final String TAG = "SearchViewUiTest";
-
public SearchViewUiTest() {
super(FilesActivity.class);
}
public void testSearchView_ExpandsOnClick() throws Exception {
- bot.openSearchView();
- bot.assertSearchTextFiledAndIcon(true, false);
+ bots.main.openSearchView();
+ bots.main.assertSearchTextFiledAndIcon(true, false);
}
public void testSearchView_CollapsesOnBack() throws Exception {
- bot.openSearchView();
+ bots.main.openSearchView();
device.pressBack();
- bot.assertSearchTextFiledAndIcon(false, true);
+ bots.main.assertSearchTextFiledAndIcon(false, true);
}
public void testSearchView_ClearsTextOnBack() throws Exception {
String query = "file2";
- bot.openSearchView();
- bot.setSearchQuery(query);
+ bots.main.openSearchView();
+ bots.main.setSearchQuery(query);
device.pressBack();
- bot.assertSearchTextFiledAndIcon(false, true);
+ bots.main.assertSearchTextFiledAndIcon(false, true);
}
public void testSearch_ResultsFound() throws Exception {
initTestFiles();
- bot.openRoot(ROOT_0_ID);
assertDefaultContentOfTestDir0();
String query = "file1";
- bot.openSearchView();
- bot.setSearchQuery(query);
- bot.assertSearchTextField(true, query);
+ bots.main.openSearchView();
+ bots.main.setSearchQuery(query);
+ bots.main.assertSearchTextField(true, query);
device.pressEnter();
- bot.assertDocumentsCountOnList(true, 2);
- bot.assertHasDocuments(fileName1, fileName2);
+ bots.directory.assertDocumentsCountOnList(true, 2);
+ bots.directory.assertDocumentsPresent(fileName1, fileName2);
- bot.assertSearchTextField(false, query);
+ bots.main.assertSearchTextField(false, query);
}
public void testSearchResultsFound_ClearsOnBack() throws Exception {
initTestFiles();
- bot.openRoot(ROOT_0_ID);
assertDefaultContentOfTestDir0();
String query = fileName1;
- bot.openSearchView();
- bot.setSearchQuery(query);
+ bots.main.openSearchView();
+ bots.main.setSearchQuery(query);
device.pressEnter();
device.pressBack();
@@ -88,32 +84,30 @@
public void testSearch_NoResults() throws Exception {
initTestFiles();
- bot.openRoot(ROOT_0_ID);
assertDefaultContentOfTestDir0();
String query = "chocolate";
- bot.openSearchView();
- bot.setSearchQuery(query);
+ bots.main.openSearchView();
+ bots.main.setSearchQuery(query);
device.pressEnter();
- bot.assertDocumentsCountOnList(false, 0);
+ bots.directory.assertDocumentsCountOnList(false, 0);
device.waitForIdle();
String msg = String.valueOf(context.getString(R.string.no_results));
- bot.assertMessageTextView(String.format(msg, "TEST_ROOT_0"));
+ bots.directory.assertMessageTextView(String.format(msg, "TEST_ROOT_0"));
- bot.assertSearchTextField(false, query);
+ bots.main.assertSearchTextField(false, query);
}
public void testSearchNoResults_ClearsOnBack() throws Exception {
initTestFiles();
- bot.openRoot(ROOT_0_ID);
assertDefaultContentOfTestDir0();
String query = "chocolate";
- bot.openSearchView();
- bot.setSearchQuery(query);
+ bots.main.openSearchView();
+ bots.main.setSearchQuery(query);
device.pressEnter();
device.pressBack();
@@ -124,30 +118,29 @@
public void testSearchResultsFound_ClearsOnDirectoryChange() throws Exception {
initTestFiles();
- bot.openRoot(ROOT_0_ID);
assertDefaultContentOfTestDir0();
String query = fileName1;
- bot.openSearchView();
- bot.setSearchQuery(query);
+ bots.main.openSearchView();
+ bots.main.setSearchQuery(query);
device.pressEnter();
- bot.openRoot(ROOT_1_ID);
+ bots.roots.openRoot(ROOT_1_ID);
assertDefaultContentOfTestDir1();
- bot.openRoot(ROOT_0_ID);
+ bots.roots.openRoot(ROOT_0_ID);
assertDefaultContentOfTestDir0();
}
public void testSearchIconVisible_RootWithSearchSupport() throws Exception {
- bot.openRoot(ROOT_0_ID);
- bot.assertSearchTextFiledAndIcon(false, true);
+ bots.roots.openRoot(ROOT_0_ID);
+ bots.main.assertSearchTextFiledAndIcon(false, true);
}
public void testSearchIconHidden_RootNoSearchSupport() throws Exception {
- bot.openRoot(ROOT_1_ID);
- bot.assertSearchTextFiledAndIcon(false, false);
+ bots.roots.openRoot(ROOT_1_ID);
+ bots.main.assertSearchTextFiledAndIcon(false, false);
}
}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/UiBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/UiBot.java
deleted file mode 100644
index d2f8403..0000000
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/UiBot.java
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui;
-
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertTrue;
-import static junit.framework.Assert.assertFalse;
-
-import android.app.Activity;
-import android.content.Context;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.BySelector;
-import android.support.test.uiautomator.Configurator;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject;
-import android.support.test.uiautomator.UiObject2;
-import android.support.test.uiautomator.UiObjectNotFoundException;
-import android.support.test.uiautomator.UiScrollable;
-import android.support.test.uiautomator.UiSelector;
-import android.support.test.uiautomator.Until;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.inputmethod.InputMethodManager;
-
-import junit.framework.Assert;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-import java.util.regex.Pattern;
-
-/**
- * A test helper class that provides support for controlling DocumentsUI activities
- * programmatically, and making assertions against the state of the UI.
- */
-class UiBot {
- public static final String TARGET_PKG = "com.android.documentsui";
-
- private static final String TAG = "UiBot";
- private static final String LAUNCHER_PKG = "com.android.launcher";
-
- private static final BySelector SNACK_DELETE =
- By.desc(Pattern.compile("^Deleting [0-9]+ file.+"));
-
- private UiDevice mDevice;
- private Context mContext;
- private int mTimeout;
-
- public UiBot(UiDevice device, Context context, int timeout) {
- mDevice = device;
- mContext = context;
- mTimeout = timeout;
- }
-
- UiObject findRoot(String label) throws UiObjectNotFoundException {
- final UiSelector rootsList = new UiSelector().resourceId(
- "com.android.documentsui:id/container_roots").childSelector(
- new UiSelector().resourceId("com.android.documentsui:id/roots_list"));
-
- // We might need to expand drawer if not visible
- if (!new UiObject(rootsList).waitForExists(mTimeout)) {
- Log.d(TAG, "Failed to find roots list; trying to expand");
- final UiSelector hamburger = new UiSelector().resourceId(
- "com.android.documentsui:id/toolbar").childSelector(
- new UiSelector().className("android.widget.ImageButton").clickable(true));
- new UiObject(hamburger).click();
- }
-
- // Wait for the first list item to appear
- new UiObject(rootsList.childSelector(new UiSelector())).waitForExists(mTimeout);
-
- // Now scroll around to find our item
- new UiScrollable(rootsList).scrollIntoView(new UiSelector().text(label));
- return new UiObject(rootsList.childSelector(new UiSelector().text(label)));
- }
-
- void openRoot(String label) throws UiObjectNotFoundException {
- findRoot(label).click();
- mDevice.waitForIdle();
- }
-
- void assertWindowTitle(String expected) {
- // Turns out the title field on a window does not have
- // an id associated with it at runtime (which confuses the hell out of me)
- // In code we address this via "android.R.id.title".
- UiObject2 o = find(By.text(expected));
- // It's a bit of a conceit that we then *assert* that the title
- // is the value that we used to identify the UiObject2.
- // If the preceeding lookup fails, this'll choke with an NPE.
- // But given the issue described in the comment above, we're
- // going to do it anyway. Because we shouldn't be looking up
- // the uiobject by it's expected content :|
- assertEquals(expected, o.getText());
- }
-
- void assertHasRoots(String... labels) throws UiObjectNotFoundException {
- List<String> missing = new ArrayList<>();
- for (String label : labels) {
- if (!findRoot(label).exists()) {
- missing.add(label);
- }
- }
- if (!missing.isEmpty()) {
- Assert.fail(
- "Expected roots " + Arrays.asList(labels) + ", but missing " + missing);
- }
- }
-
- void assertMenuEnabled(int id, boolean enabled) {
- UiObject2 menu= findMenuWithName(mContext.getString(id));
- assertNotNull(menu);
- assertEquals(enabled, menu.isEnabled());
- }
-
- void assertDocumentsCount(int count) throws UiObjectNotFoundException {
- UiObject docsList = findDocumentsList();
- assertEquals(count, docsList.getChildCount());
- }
-
- void assertDocumentsCount(String dir, int count) throws UiObjectNotFoundException {
- openRoot(dir);
- UiObject docsList = findDocumentsList();
- assertEquals(count, docsList.getChildCount());
- }
-
- void assertSearchTextField(boolean isFocused, String query)
- throws UiObjectNotFoundException {
- UiObject textField = findSearchViewTextField();
- UiObject searchIcon = findSearchViewIcon();
-
- assertFalse(searchIcon.exists());
- assertTrue(textField.exists());
- assertEquals(isFocused, textField.isFocused());
- if(query != null) {
- assertEquals(query, textField.getText());
- }
- }
-
- void assertSearchTextFiledAndIcon(boolean searchTextFieldExists, boolean searchIconExists) {
- assertEquals(searchTextFieldExists, findSearchViewTextField().exists());
- assertEquals(searchIconExists, findSearchViewIcon().exists());
- }
-
- void assertHasDocuments(String... labels) throws UiObjectNotFoundException {
- List<String> missing = new ArrayList<>();
- for (String label : labels) {
- if (!findDocument(label).exists()) {
- missing.add(label);
- }
- }
- if (!missing.isEmpty()) {
- Assert.fail(
- "Expected documents " + Arrays.asList(labels) + ", but missing " + missing);
- }
- }
-
- void assertDocument(String name, boolean exists) throws UiObjectNotFoundException {
- UiObject doc = findDocument(name);
- assertEquals(exists, doc.exists());
- }
-
- void assertDocumentsCountOnList(boolean exists, int count) throws UiObjectNotFoundException {
- UiObject docsList = findDocumentsList();
- assertEquals(exists, docsList.exists());
- if(docsList.exists()) {
- assertEquals(count, docsList.getChildCount());
- }
- }
-
- void assertMessageTextView(String message) throws UiObjectNotFoundException {
- UiObject messageTextView = findMessageTextView();
- assertTrue(messageTextView.exists());
-
- String msg = String.valueOf(message);
- assertEquals(String.format(msg, "TEST_ROOT_0"), messageTextView.getText());
-
- }
- void assertSnackbar(int id) {
- assertNotNull(getSnackbar(mContext.getString(id)));
- }
-
- /**
- * Asserts that the specified view or one of its descendents has focus.
- */
- void assertHasFocus(String resourceName) {
- UiObject2 candidate = mDevice.findObject(By.res(resourceName));
- assertNotNull("Expected " + resourceName + " to have focus, but it didn't.",
- candidate.findObject(By.focused(true)));
- }
-
- void openDocument(String label) throws UiObjectNotFoundException {
- int toolType = Configurator.getInstance().getToolType();
- Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_FINGER);
- UiObject doc = findDocument(label);
- doc.click();
- Configurator.getInstance().setToolType(toolType);
- }
-
- void clickDocument(String label) throws UiObjectNotFoundException {
- findDocument(label).click();
- }
-
- void openSearchView() throws UiObjectNotFoundException {
- UiObject searchView = findSearchView();
- searchView.click();
- assertTrue(searchView.exists());
- }
-
- void setSearchQuery(String query) throws UiObjectNotFoundException {
- UiObject searchView = findSearchView();
- assertTrue(searchView.exists());
- UiObject searchTextField = findSearchViewTextField();
- searchTextField.setText(query);
- assertSearchTextField(true, query);
- }
-
- UiObject openOverflowMenu() throws UiObjectNotFoundException {
- UiObject obj = findMenuMoreOptions();
- obj.click();
- mDevice.waitForIdle(mTimeout);
- return obj;
- }
-
- void openDialog(int id) {
- UiObject2 menu= findMenuWithName(mContext.getString(id));
- assertNotNull(menu);
- assertEquals(true, menu.isEnabled());
- menu.click();
- }
-
- void setDialogText(String text) throws UiObjectNotFoundException {
- findDialogEditText().setText(text);
- }
-
- UiObject selectDocument(String label) throws UiObjectNotFoundException {
- UiObject doc = findDocument(label);
- doc.longClick();
- return doc;
- }
-
- UiObject2 getSnackbar(String message) {
- return mDevice.wait(Until.findObject(By.text(message)), mTimeout);
- }
-
- void waitForDeleteSnackbar() {
- mDevice.wait(Until.findObject(SNACK_DELETE), mTimeout);
- }
-
- void waitForDeleteSnackbarGone() {
- // wait a little longer for snackbar to go away, as it disappears after a timeout.
- mDevice.wait(Until.gone(SNACK_DELETE), mTimeout * 2);
- }
-
- void waitForDocument(String label) throws UiObjectNotFoundException {
- findDocument(label).waitForExists(mTimeout);
- }
-
- void switchViewMode() {
- UiObject2 mode = menuGridMode();
- if (mode != null) {
- mode.click();
- } else {
- menuListMode().click();
- }
- }
-
- UiObject2 menuGridMode() {
- // Note that we're using By.desc rather than By.res, because of b/25285770
- return find(By.desc("Grid view"));
- }
-
- UiObject2 menuListMode() {
- // Note that we're using By.desc rather than By.res, because of b/25285770
- return find(By.desc("List view"));
- }
-
- UiObject2 menuDelete() {
- return find(By.res("com.android.documentsui:id/menu_delete"));
- }
-
- UiObject2 menuShare() {
- return find(By.res("com.android.documentsui:id/menu_share"));
- }
-
- private UiObject2 find(BySelector selector) {
- mDevice.wait(Until.findObject(selector), mTimeout);
- return mDevice.findObject(selector);
- }
-
- private UiObject findObject(String resourceId) {
- final UiSelector object = new UiSelector().resourceId(resourceId);
- return mDevice.findObject(object);
- }
-
- private UiObject findObject(String parentResourceId, String childResourceId) {
- final UiSelector selector = new UiSelector()
- .resourceId(parentResourceId)
- .childSelector(new UiSelector().resourceId(childResourceId));
- return mDevice.findObject(selector);
- }
-
- UiObject findDocument(String label) throws UiObjectNotFoundException {
- final UiSelector docList = new UiSelector().resourceId(
- "com.android.documentsui:id/container_directory").childSelector(
- new UiSelector().resourceId("com.android.documentsui:id/dir_list"));
-
- // Wait for the first list item to appear
- new UiObject(docList.childSelector(new UiSelector())).waitForExists(mTimeout);
-
- // new UiScrollable(docList).scrollIntoView(new UiSelector().text(label));
- return mDevice.findObject(docList.childSelector(new UiSelector().text(label)));
- }
-
- boolean hasDocuments(String... labels) throws UiObjectNotFoundException {
- for (String label : labels) {
- if (!findDocument(label).exists()) {
- return false;
- }
- }
- return true;
- }
-
- UiObject findDocumentsList() {
- return findObject(
- "com.android.documentsui:id/container_directory",
- "com.android.documentsui:id/dir_list");
- }
-
- UiObject findSearchView() {
- return findObject("com.android.documentsui:id/menu_search");
- }
-
- UiObject findSearchViewTextField() {
- return findObject("com.android.documentsui:id/menu_search", "android:id/search_src_text");
- }
-
- UiObject findSearchViewIcon() {
- return findObject("com.android.documentsui:id/menu_search", "android:id/search_button");
- }
-
- UiObject findMessageTextView() {
- return findObject(
- "com.android.documentsui:id/container_directory",
- "com.android.documentsui:id/message");
- }
-
- UiObject findActionModeBar() {
- return findObject("android:id/action_mode_bar");
- }
-
- UiObject findDialogEditText() {
- return findObject("android:id/content", "android:id/text1");
- }
-
- UiObject findRenameDialogOkButton() {
- return findObject("android:id/content", "android:id/button1");
- }
-
- UiObject findRenameDialogCancelButton() {
- return findObject("android:id/content", "android:id/button2");
- }
-
- UiObject findMenuLabelWithName(String label) {
- UiSelector selector = new UiSelector().text(label);
- return mDevice.findObject(selector);
- }
-
- UiObject2 findMenuWithName(String label) {
- List<UiObject2> menuItems = mDevice.findObjects(By.clazz("android.widget.LinearLayout"));
- Iterator<UiObject2> it = menuItems.iterator();
-
- UiObject2 menuItem = null;
- while(it.hasNext()) {
- menuItem = it.next();
- UiObject2 text = menuItem.findObject(By.text(label));
- if(text != null) {
- break;
- }
- }
- return menuItem;
- }
-
- UiObject findMenuMoreOptions() {
- UiSelector selector = new UiSelector().className("android.widget.ImageButton")
- .descriptionContains("More options");
- //TODO: use the system string ? android.R.string.action_menu_overflow_description
- return mDevice.findObject(selector);
- }
-
- // Indirect way to detect the keyboard.
- boolean isKeyboardPresent() {
- InputMethodManager inputManager = (InputMethodManager) mContext
- .getSystemService(Context.INPUT_METHOD_SERVICE);
- return inputManager.isAcceptingText();
- }
-
- void dismissKeyboardIfPresent() {
- if(isKeyboardPresent()) {
- mDevice.pressBack();
- }
- }
-
- void revealLauncher() {
- mDevice.pressHome();
- mDevice.wait(Until.hasObject(By.pkg(LAUNCHER_PKG).depth(0)), mTimeout);
- }
-
- void revealApp() {
- mDevice.wait(Until.hasObject(By.pkg(TARGET_PKG).depth(0)), mTimeout);
- mDevice.waitForIdle();
- }
-
- void pressKey(int keyCode) {
- mDevice.pressKeyCode(keyCode);
- }
-}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/BaseBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/BaseBot.java
new file mode 100644
index 0000000..1d2b47f
--- /dev/null
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/BaseBot.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.bots;
+
+import static junit.framework.Assert.assertNotNull;
+
+import android.content.Context;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.UiSelector;
+import android.support.test.uiautomator.Until;
+
+/**
+ * A test helper class that provides support for controlling directory list
+ * and making assertions against the state of it.
+ */
+abstract class BaseBot {
+ final UiDevice mDevice;
+ final Context mContext;
+ final int mTimeout;
+
+ BaseBot(UiDevice device, Context context, int timeout) {
+ mDevice = device;
+ mContext = context;
+ mTimeout = timeout;
+ }
+
+ /**
+ * Asserts that the specified view or one of its descendents has focus.
+ */
+ protected void assertHasFocus(String resourceName) {
+ UiObject2 candidate = mDevice.findObject(By.res(resourceName));
+ assertNotNull("Expected " + resourceName + " to have focus, but it didn't.",
+ candidate.findObject(By.focused(true)));
+ }
+
+ protected UiObject2 find(BySelector selector) {
+ mDevice.wait(Until.findObject(selector), mTimeout);
+ return mDevice.findObject(selector);
+ }
+
+ protected UiObject findObject(String resourceId) {
+ final UiSelector object = new UiSelector().resourceId(resourceId);
+ return mDevice.findObject(object);
+ }
+
+ protected UiObject findObject(String parentResourceId, String childResourceId) {
+ final UiSelector selector = new UiSelector()
+ .resourceId(parentResourceId)
+ .childSelector(new UiSelector().resourceId(childResourceId));
+ return mDevice.findObject(selector);
+ }
+
+ protected void waitForIdle() {
+ mDevice.waitForIdle(mTimeout);
+ }
+}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/DirectoryListBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/DirectoryListBot.java
new file mode 100644
index 0000000..da9f9c3
--- /dev/null
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/DirectoryListBot.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.bots;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertTrue;
+
+import android.content.Context;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.Configurator;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.support.test.uiautomator.UiSelector;
+import android.support.test.uiautomator.Until;
+import android.view.MotionEvent;
+
+import junit.framework.Assert;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * A test helper class that provides support for controlling directory list
+ * and making assertions against the state of it.
+ */
+public class DirectoryListBot extends BaseBot {
+ private static final String DIR_LIST_ID = "com.android.documentsui:id/dir_list";
+
+ private static final BySelector SNACK_DELETE =
+ By.desc(Pattern.compile("^Deleting [0-9]+ file.+"));
+
+ public DirectoryListBot(UiDevice device, Context context, int timeout) {
+ super(device, context, timeout);
+ }
+
+ public void assertDocumentsCount(int count) throws UiObjectNotFoundException {
+ UiObject docsList = findDocumentsList();
+ assertEquals(count, docsList.getChildCount());
+ }
+
+ public void assertDocumentsPresent(String... labels) throws UiObjectNotFoundException {
+ List<String> absent = new ArrayList<>();
+ for (String label : labels) {
+ if (!findDocument(label).exists()) {
+ absent.add(label);
+ }
+ }
+ if (!absent.isEmpty()) {
+ Assert.fail("Expected documents " + Arrays.asList(labels)
+ + ", but missing " + absent);
+ }
+ }
+
+ public void assertDocumentsAbsent(String... labels) throws UiObjectNotFoundException {
+ List<String> found = new ArrayList<>();
+ for (String label : labels) {
+ if (findDocument(label).exists()) {
+ found.add(label);
+ }
+ }
+ if (!found.isEmpty()) {
+ Assert.fail("Expected documents not present" + Arrays.asList(labels)
+ + ", but present " + found);
+ }
+ }
+
+ public void assertDocumentsCountOnList(boolean exists, int count) throws UiObjectNotFoundException {
+ UiObject docsList = findDocumentsList();
+ assertEquals(exists, docsList.exists());
+ if(docsList.exists()) {
+ assertEquals(count, docsList.getChildCount());
+ }
+ }
+
+ public void assertMessageTextView(String message) throws UiObjectNotFoundException {
+ UiObject messageTextView = findMessageTextView();
+ assertTrue(messageTextView.exists());
+
+ String msg = String.valueOf(message);
+ assertEquals(String.format(msg, "TEST_ROOT_0"), messageTextView.getText());
+
+ }
+
+ private UiObject findMessageTextView() {
+ return findObject(
+ "com.android.documentsui:id/container_directory",
+ "com.android.documentsui:id/message");
+ }
+
+ public void assertSnackbar(int id) {
+ assertNotNull(getSnackbar(mContext.getString(id)));
+ }
+
+ public void openDocument(String label) throws UiObjectNotFoundException {
+ int toolType = Configurator.getInstance().getToolType();
+ Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_FINGER);
+ UiObject doc = findDocument(label);
+ doc.click();
+ Configurator.getInstance().setToolType(toolType);
+ }
+
+ public void clickDocument(String label) throws UiObjectNotFoundException {
+ findDocument(label).click();
+ }
+
+ public UiObject selectDocument(String label) throws UiObjectNotFoundException {
+ UiObject doc = findDocument(label);
+ doc.longClick();
+ return doc;
+ }
+
+ public UiObject2 getSnackbar(String message) {
+ return mDevice.wait(Until.findObject(By.text(message)), mTimeout);
+ }
+
+ public void waitForDeleteSnackbar() {
+ mDevice.wait(Until.findObject(SNACK_DELETE), mTimeout);
+ }
+
+ public void waitForDeleteSnackbarGone() {
+ // wait a little longer for snackbar to go away, as it disappears after a timeout.
+ mDevice.wait(Until.gone(SNACK_DELETE), mTimeout * 2);
+ }
+
+ public void waitForDocument(String label) throws UiObjectNotFoundException {
+ findDocument(label).waitForExists(mTimeout);
+ }
+
+ public UiObject findDocument(String label) throws UiObjectNotFoundException {
+ final UiSelector docList = new UiSelector().resourceId(
+ "com.android.documentsui:id/container_directory").childSelector(
+ new UiSelector().resourceId(DIR_LIST_ID));
+
+ // Wait for the first list item to appear
+ new UiObject(docList.childSelector(new UiSelector())).waitForExists(mTimeout);
+
+ // new UiScrollable(docList).scrollIntoView(new UiSelector().text(label));
+ return mDevice.findObject(docList.childSelector(new UiSelector().text(label)));
+ }
+
+ public boolean hasDocuments(String... labels) throws UiObjectNotFoundException {
+ for (String label : labels) {
+ if (!findDocument(label).exists()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private UiObject findDocumentsList() {
+ return findObject(
+ "com.android.documentsui:id/container_directory",
+ DIR_LIST_ID);
+ }
+
+ public void assertHasFocus() {
+ assertHasFocus(DIR_LIST_ID);
+ }
+}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/KeyboardBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/KeyboardBot.java
new file mode 100644
index 0000000..4c47cfa
--- /dev/null
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/KeyboardBot.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.bots;
+
+import android.content.Context;
+import android.support.test.uiautomator.UiDevice;
+import android.view.inputmethod.InputMethodManager;
+
+/**
+ * A test helper class that provides support for keyboard manipulation.
+ */
+public class KeyboardBot extends BaseBot {
+
+ public KeyboardBot(UiDevice device, Context context, int timeout) {
+ super(device, context, timeout);
+ }
+
+ public void dismissKeyboardIfPresent() {
+ if(isKeyboardPresent()) {
+ mDevice.pressBack();
+ }
+ }
+
+ // Indirect way to detect the keyboard.
+ private boolean isKeyboardPresent() {
+ InputMethodManager inputManager = (InputMethodManager) mContext
+ .getSystemService(Context.INPUT_METHOD_SERVICE);
+ return inputManager.isAcceptingText();
+ }
+
+ public void pressEnter() {
+ waitForIdle();
+ mDevice.pressEnter();
+ waitForIdle();
+ }
+}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/RootsListBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/RootsListBot.java
new file mode 100644
index 0000000..356fd01
--- /dev/null
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/RootsListBot.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.bots;
+
+import android.content.Context;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.support.test.uiautomator.UiScrollable;
+import android.support.test.uiautomator.UiSelector;
+import android.util.Log;
+
+import junit.framework.Assert;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A test helper class that provides support for controlling and asserting against
+ * the roots list drawer.
+ */
+public class RootsListBot extends BaseBot {
+ private static final String ROOTS_LIST_ID = "com.android.documentsui:id/roots_list";
+ private static final String TAG = "RootsListBot";
+
+ public RootsListBot(UiDevice device, Context context, int timeout) {
+ super(device, context, timeout);
+ }
+
+ private UiObject findRoot(String label) throws UiObjectNotFoundException {
+ final UiSelector rootsList = new UiSelector().resourceId(
+ "com.android.documentsui:id/container_roots").childSelector(
+ new UiSelector().resourceId(ROOTS_LIST_ID));
+
+ // We might need to expand drawer if not visible
+ if (!new UiObject(rootsList).waitForExists(mTimeout)) {
+ Log.d(TAG, "Failed to find roots list; trying to expand");
+ final UiSelector hamburger = new UiSelector().resourceId(
+ "com.android.documentsui:id/toolbar").childSelector(
+ new UiSelector().className("android.widget.ImageButton").clickable(true));
+ new UiObject(hamburger).click();
+ }
+
+ // Wait for the first list item to appear
+ new UiObject(rootsList.childSelector(new UiSelector())).waitForExists(mTimeout);
+
+ // Now scroll around to find our item
+ new UiScrollable(rootsList).scrollIntoView(new UiSelector().text(label));
+ return new UiObject(rootsList.childSelector(new UiSelector().text(label)));
+ }
+
+ public void openRoot(String label) throws UiObjectNotFoundException {
+ findRoot(label).click();
+ mDevice.waitForIdle();
+ }
+
+ public void assertHasRoots(String... labels) throws UiObjectNotFoundException {
+ List<String> missing = new ArrayList<>();
+ for (String label : labels) {
+ if (!findRoot(label).exists()) {
+ missing.add(label);
+ }
+ }
+ if (!missing.isEmpty()) {
+ Assert.fail(
+ "Expected roots " + Arrays.asList(labels) + ", but missing " + missing);
+ }
+ }
+
+ public void assertHasFocus() {
+ assertHasFocus(ROOTS_LIST_ID);
+ }
+}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/UiBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/UiBot.java
new file mode 100644
index 0000000..11f5194
--- /dev/null
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/UiBot.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.bots;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertTrue;
+
+import android.content.Context;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.support.test.uiautomator.UiSelector;
+import android.support.test.uiautomator.Until;
+
+import com.android.documentsui.R;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * A test helper class that provides support for controlling DocumentsUI activities
+ * programmatically, and making assertions against the state of the UI.
+ *
+ * <p>Support for working directly with Roots and Directory view can be found
+ * in the respective bots.
+ */
+public class UiBot extends BaseBot {
+ public static final String TARGET_PKG = "com.android.documentsui";
+ private static final String LAUNCHER_PKG = "com.android.launcher";
+
+ public UiBot(UiDevice device, Context context, int timeout) {
+ super(device, context, timeout);
+ }
+
+ public void assertWindowTitle(String expected) {
+ // Turns out the title field on a window does not have
+ // an id associated with it at runtime (which confuses the hell out of me)
+ // In code we address this via "android.R.id.title".
+ UiObject2 o = find(By.text(expected));
+ // It's a bit of a conceit that we then *assert* that the title
+ // is the value that we used to identify the UiObject2.
+ // If the preceeding lookup fails, this'll choke with an NPE.
+ // But given the issue described in the comment above, we're
+ // going to do it anyway. Because we shouldn't be looking up
+ // the uiobject by it's expected content :|
+ assertEquals(expected, o.getText());
+ }
+
+ public void assertMenuEnabled(int id, boolean enabled) {
+ UiObject2 menu= findMenuWithName(mContext.getString(id));
+ assertNotNull(menu);
+ assertEquals(enabled, menu.isEnabled());
+ }
+
+ public void assertSearchTextField(boolean isFocused, String query)
+ throws UiObjectNotFoundException {
+ UiObject textField = findSearchViewTextField();
+ UiObject searchIcon = findSearchViewIcon();
+
+ assertFalse(searchIcon.exists());
+ assertTrue(textField.exists());
+ assertEquals(isFocused, textField.isFocused());
+ if(query != null) {
+ assertEquals(query, textField.getText());
+ }
+ }
+
+ public void assertSearchTextFiledAndIcon(boolean searchTextFieldExists, boolean searchIconExists) {
+ assertEquals(searchTextFieldExists, findSearchViewTextField().exists());
+ assertEquals(searchIconExists, findSearchViewIcon().exists());
+ }
+
+ public void assertInActionMode(boolean inActionMode) {
+ UiObject actionModeBar = findActionModeBar();
+ assertEquals(inActionMode, actionModeBar.exists());
+ }
+
+ public void openSearchView() throws UiObjectNotFoundException {
+ UiObject searchView = findSearchView();
+ searchView.click();
+ assertTrue(searchView.exists());
+ }
+
+ public void setSearchQuery(String query) throws UiObjectNotFoundException {
+ UiObject searchView = findSearchView();
+ assertTrue(searchView.exists());
+ UiObject searchTextField = findSearchViewTextField();
+ searchTextField.setText(query);
+ assertSearchTextField(true, query);
+ }
+
+ public UiObject openOverflowMenu() throws UiObjectNotFoundException {
+ UiObject obj = findMenuMoreOptions();
+ obj.click();
+ mDevice.waitForIdle(mTimeout);
+ return obj;
+ }
+
+ public void setDialogText(String text) throws UiObjectNotFoundException {
+ findDialogEditText().setText(text);
+ }
+
+ void switchViewMode() {
+ UiObject2 mode = menuGridMode();
+ if (mode != null) {
+ mode.click();
+ } else {
+ menuListMode().click();
+ }
+ }
+
+ UiObject2 menuGridMode() {
+ // Note that we're using By.desc rather than By.res, because of b/25285770
+ return find(By.desc("Grid view"));
+ }
+
+ UiObject2 menuListMode() {
+ // Note that we're using By.desc rather than By.res, because of b/25285770
+ return find(By.desc("List view"));
+ }
+
+ public UiObject2 menuDelete() {
+ return find(By.res("com.android.documentsui:id/menu_delete"));
+ }
+
+ public UiObject2 menuShare() {
+ return find(By.res("com.android.documentsui:id/menu_share"));
+ }
+
+ public UiObject2 menuRename() {
+ return findMenuWithName(mContext.getString(R.string.menu_rename));
+ }
+
+ public UiObject2 menuNewFolder() {
+ return findMenuWithName(mContext.getString(R.string.menu_create_dir));
+ }
+
+ UiObject findSearchView() {
+ return findObject("com.android.documentsui:id/menu_search");
+ }
+
+ UiObject findSearchViewTextField() {
+ return findObject("com.android.documentsui:id/menu_search", "android:id/search_src_text");
+ }
+
+ UiObject findSearchViewIcon() {
+ return findObject("com.android.documentsui:id/menu_search", "android:id/search_button");
+ }
+
+ UiObject findActionModeBar() {
+ return findObject("android:id/action_mode_bar");
+ }
+
+ public UiObject findDialogEditText() {
+ return findObject("android:id/content", "android:id/text1");
+ }
+
+ public UiObject findDialogOkButton() {
+ UiObject object = findObject("android:id/content", "android:id/button1");
+ object.waitForExists(mTimeout);
+ return object;
+ }
+
+ public UiObject findDialogCancelButton() {
+ UiObject object = findObject("android:id/content", "android:id/button2");
+ object.waitForExists(mTimeout);
+ return object;
+ }
+
+ UiObject findMenuLabelWithName(String label) {
+ UiSelector selector = new UiSelector().text(label);
+ return mDevice.findObject(selector);
+ }
+
+ UiObject2 findMenuWithName(String label) {
+ List<UiObject2> menuItems = mDevice.findObjects(By.clazz("android.widget.LinearLayout"));
+ Iterator<UiObject2> it = menuItems.iterator();
+
+ UiObject2 menuItem = null;
+ while(it.hasNext()) {
+ menuItem = it.next();
+ UiObject2 text = menuItem.findObject(By.text(label));
+ if(text != null) {
+ break;
+ }
+ }
+ return menuItem;
+ }
+
+ UiObject findMenuMoreOptions() {
+ UiSelector selector = new UiSelector().className("android.widget.ImageButton")
+ .descriptionContains("More options");
+ //TODO: use the system string ? android.R.string.action_menu_overflow_description
+ return mDevice.findObject(selector);
+ }
+
+ public void pressKey(int keyCode) {
+ mDevice.pressKeyCode(keyCode);
+ }
+}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapterTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapterTest.java
index 2244be9..adc8141 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapterTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapterTest.java
@@ -73,28 +73,6 @@
assertEquals(mModel.getItemCount() - 2, mAdapter.getItemCount());
}
- // Tests that the items can be hidden and unhidden.
- public void testUnhide_ItemCount() {
- List<String> ids = mModel.getModelIds();
- SparseArray<String> hidden = mAdapter.hide(ids.toArray(new String[ids.size()]));
- mAdapter.unhide(hidden);
- assertEquals(mModel.getItemCount(), mAdapter.getItemCount());
- }
-
- // Tests that the items can be hidden and unhidden.
- public void testUnhide_PreservesOrder() {
- List<String> ids = mModel.getModelIds();
- SparseArray<String> hidden = mAdapter.hide(
- ids.get(0), ids.get(1), ids.get(5), ids.get(9));
- mAdapter.unhide(hidden);
-
- // Finally ensure the restored items are in the original order
- // by checking them against the model.
- for (int i = 0; i < mAdapter.getItemCount(); i++) {
- assertEquals(mModel.idForPosition(i), mAdapter.getModelId(i));
- }
- }
-
private final class TestEnvironment implements DocumentsAdapter.Environment {
private final Context testContext;
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java
index 83299f0..4b0bc41 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java
@@ -28,6 +28,7 @@
import com.android.documentsui.DirectoryResult;
import com.android.documentsui.RootCursorWrapper;
+import com.android.documentsui.Shared;
import com.android.documentsui.State;
import com.android.documentsui.dirlist.MultiSelectManager.Selection;
import com.android.documentsui.model.DocumentInfo;
@@ -190,7 +191,7 @@
assertEquals(ITEM_COUNT, seen.cardinality());
for (int i = 0; i < names.size()-1; ++i) {
- assertTrue(DocumentInfo.compareToIgnoreCaseNullable(names.get(i), names.get(i+1)) <= 0);
+ assertTrue(Shared.compareToIgnoreCaseNullable(names.get(i), names.get(i+1)) <= 0);
}
}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestDocumentsAdapter.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestDocumentsAdapter.java
index 267f47d..e170dbb 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestDocumentsAdapter.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestDocumentsAdapter.java
@@ -61,11 +61,6 @@
}
@Override
- void unhide(SparseArray<String> ids) {
- throw new UnsupportedOperationException();
- }
-
- @Override
public DocumentHolder onCreateViewHolder(ViewGroup parent, int viewType) {
throw new UnsupportedOperationException();
}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/services/TestJob.java b/packages/DocumentsUI/tests/src/com/android/documentsui/services/TestJob.java
index a1c6dab..9147a57 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/services/TestJob.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/services/TestJob.java
@@ -21,7 +21,6 @@
import android.app.Notification;
import android.app.Notification.Builder;
import android.content.Context;
-import android.os.RemoteException;
import com.android.documentsui.R;
import com.android.documentsui.model.DocumentInfo;
@@ -38,7 +37,7 @@
}
@Override
- void start() throws RemoteException {
+ void start() {
mStarted = true;
}
diff --git a/packages/ExternalStorageProvider/res/values-af/strings.xml b/packages/ExternalStorageProvider/res/values-af/strings.xml
index b5a159d..1de881d 100644
--- a/packages/ExternalStorageProvider/res/values-af/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-af/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Eksterne berging"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Interne berging"</string>
- <string name="root_home" msgid="7931555396767513359">"Tuis"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Dokumente"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-am/strings.xml b/packages/ExternalStorageProvider/res/values-am/strings.xml
index f4f296d..230fb06 100644
--- a/packages/ExternalStorageProvider/res/values-am/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-am/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"ውጫዊ ማከማቻ"</string>
<string name="root_internal_storage" msgid="827844243068584127">"ውስጣዊ ማከማቻ"</string>
- <string name="root_home" msgid="7931555396767513359">"መነሻ"</string>
+ <string name="root_documents" msgid="4051252304075469250">"ሰነዶች"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ar/strings.xml b/packages/ExternalStorageProvider/res/values-ar/strings.xml
index 4eee3e8..b20a056 100644
--- a/packages/ExternalStorageProvider/res/values-ar/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ar/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"وحدة تخزين خارجية"</string>
<string name="root_internal_storage" msgid="827844243068584127">"وحدة تخزين داخلية"</string>
- <string name="root_home" msgid="7931555396767513359">"الرئيسية"</string>
+ <string name="root_documents" msgid="4051252304075469250">"مستندات"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-az-rAZ/strings.xml b/packages/ExternalStorageProvider/res/values-az-rAZ/strings.xml
index f7e5f8b..cd5ba2f 100644
--- a/packages/ExternalStorageProvider/res/values-az-rAZ/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-az-rAZ/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Xarici Yaddaş"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Daxili yaddaş"</string>
- <string name="root_home" msgid="7931555396767513359">"Əsas səhifə"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Sənədlər"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-b+sr+Latn/strings.xml b/packages/ExternalStorageProvider/res/values-b+sr+Latn/strings.xml
index b280d4f..fefbc28 100644
--- a/packages/ExternalStorageProvider/res/values-b+sr+Latn/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-b+sr+Latn/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Spoljna memorija"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Interna memorija"</string>
- <string name="root_home" msgid="7931555396767513359">"Početni"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Dokumenti"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-bg/strings.xml b/packages/ExternalStorageProvider/res/values-bg/strings.xml
index 7081b17..f5dce31 100644
--- a/packages/ExternalStorageProvider/res/values-bg/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-bg/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Външно хранилище"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Вътрешно хранилище"</string>
- <string name="root_home" msgid="7931555396767513359">"Начална директория"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Документи"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-bn-rBD/strings.xml b/packages/ExternalStorageProvider/res/values-bn-rBD/strings.xml
index 842aed4..3668065 100644
--- a/packages/ExternalStorageProvider/res/values-bn-rBD/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-bn-rBD/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"বাহ্যিক সঞ্চয়স্থান"</string>
<string name="root_internal_storage" msgid="827844243068584127">"অভ্যন্তরীণ সঞ্চয়স্থান"</string>
- <string name="root_home" msgid="7931555396767513359">"হোম"</string>
+ <string name="root_documents" msgid="4051252304075469250">"দস্তাবেজগুলি"</string>
</resources>
diff --git a/packages/DocumentsUI/res/values-bs-rBA/config.xml b/packages/ExternalStorageProvider/res/values-bs-rBA/strings.xml
similarity index 69%
rename from packages/DocumentsUI/res/values-bs-rBA/config.xml
rename to packages/ExternalStorageProvider/res/values-bs-rBA/strings.xml
index 843a8aa..20177f0 100644
--- a/packages/DocumentsUI/res/values-bs-rBA/config.xml
+++ b/packages/ExternalStorageProvider/res/values-bs-rBA/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
+<!-- Copyright (C) 2013 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -16,5 +16,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="trusted_quick_viewer_package" msgid="3354383993907861267"></string>
+ <string name="app_label" msgid="7123375275748530234">"Aplikacija za vanjsku pohranu"</string>
+ <string name="root_internal_storage" msgid="827844243068584127">"Interna pohrana"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Dokumenti"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ca/strings.xml b/packages/ExternalStorageProvider/res/values-ca/strings.xml
index b3fd9f7..15e9d46 100644
--- a/packages/ExternalStorageProvider/res/values-ca/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ca/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Emmagatzematge extern"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Emmagatzematge intern"</string>
- <string name="root_home" msgid="7931555396767513359">"Inici"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Documents"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-cs/strings.xml b/packages/ExternalStorageProvider/res/values-cs/strings.xml
index 2eab596..b68a928 100644
--- a/packages/ExternalStorageProvider/res/values-cs/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-cs/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Externí úložiště"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Interní úložiště"</string>
- <string name="root_home" msgid="7931555396767513359">"Výchozí adresář"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Dokumenty"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-da/strings.xml b/packages/ExternalStorageProvider/res/values-da/strings.xml
index d008f0e..dc565ae 100644
--- a/packages/ExternalStorageProvider/res/values-da/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-da/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Ekstern lagerplads"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Intern lagerplads"</string>
- <string name="root_home" msgid="7931555396767513359">"Hjem"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Dokumenter"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-de/strings.xml b/packages/ExternalStorageProvider/res/values-de/strings.xml
index 50fc680..318634a 100644
--- a/packages/ExternalStorageProvider/res/values-de/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-de/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Externer Speicher"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Interner Speicher"</string>
- <string name="root_home" msgid="7931555396767513359">"Zuhause"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Dokumente"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-el/strings.xml b/packages/ExternalStorageProvider/res/values-el/strings.xml
index 9537afd..b3aa792 100644
--- a/packages/ExternalStorageProvider/res/values-el/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-el/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Εξωτερικός αποθηκευτικός χώρος"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Εσωτερικός αποθηκευτικός χώρος"</string>
- <string name="root_home" msgid="7931555396767513359">"Αρχική οθόνη"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Έγγραφα"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-en-rAU/strings.xml b/packages/ExternalStorageProvider/res/values-en-rAU/strings.xml
index be7aebc..f88eb9e 100644
--- a/packages/ExternalStorageProvider/res/values-en-rAU/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-en-rAU/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"External Storage"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Internal storage"</string>
- <string name="root_home" msgid="7931555396767513359">"Home"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Documents"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-en-rGB/strings.xml b/packages/ExternalStorageProvider/res/values-en-rGB/strings.xml
index be7aebc..f88eb9e 100644
--- a/packages/ExternalStorageProvider/res/values-en-rGB/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-en-rGB/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"External Storage"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Internal storage"</string>
- <string name="root_home" msgid="7931555396767513359">"Home"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Documents"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-en-rIN/strings.xml b/packages/ExternalStorageProvider/res/values-en-rIN/strings.xml
index be7aebc..f88eb9e 100644
--- a/packages/ExternalStorageProvider/res/values-en-rIN/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-en-rIN/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"External Storage"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Internal storage"</string>
- <string name="root_home" msgid="7931555396767513359">"Home"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Documents"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-es-rUS/strings.xml b/packages/ExternalStorageProvider/res/values-es-rUS/strings.xml
index 64a042d..e7e38b5 100644
--- a/packages/ExternalStorageProvider/res/values-es-rUS/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-es-rUS/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Almacenamiento externo"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Almacenamiento interno"</string>
- <string name="root_home" msgid="7931555396767513359">"Casa"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Documentos"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-es/strings.xml b/packages/ExternalStorageProvider/res/values-es/strings.xml
index d59755e..e7e38b5 100644
--- a/packages/ExternalStorageProvider/res/values-es/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-es/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Almacenamiento externo"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Almacenamiento interno"</string>
- <string name="root_home" msgid="7931555396767513359">"Inicio"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Documentos"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-et-rEE/strings.xml b/packages/ExternalStorageProvider/res/values-et-rEE/strings.xml
index 7ea2caa..6824e9d 100644
--- a/packages/ExternalStorageProvider/res/values-et-rEE/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-et-rEE/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Väline talletusruum"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Sisemine salvestusruum"</string>
- <string name="root_home" msgid="7931555396767513359">"Kodu"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Dokumendid"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-eu-rES/strings.xml b/packages/ExternalStorageProvider/res/values-eu-rES/strings.xml
index 2f94acb..5881bf2 100644
--- a/packages/ExternalStorageProvider/res/values-eu-rES/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-eu-rES/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Kanpoko memoria"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Barneko memoria"</string>
- <string name="root_home" msgid="7931555396767513359">"Etxea"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Dokumentuak"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-fa/strings.xml b/packages/ExternalStorageProvider/res/values-fa/strings.xml
index c8c49a5..9ae8a47 100644
--- a/packages/ExternalStorageProvider/res/values-fa/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-fa/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"حافظه خارجی"</string>
<string name="root_internal_storage" msgid="827844243068584127">"حافظهٔ داخلی"</string>
- <string name="root_home" msgid="7931555396767513359">"صفحه اصلی"</string>
+ <string name="root_documents" msgid="4051252304075469250">"اسناد"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-fi/strings.xml b/packages/ExternalStorageProvider/res/values-fi/strings.xml
index 660228a..9d1fbaa 100644
--- a/packages/ExternalStorageProvider/res/values-fi/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-fi/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Ulkoinen tallennustila"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Sisäinen tallennustila"</string>
- <string name="root_home" msgid="7931555396767513359">"Koti"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Dokumentit"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-fr-rCA/strings.xml b/packages/ExternalStorageProvider/res/values-fr-rCA/strings.xml
index b94682f..b3fdd48 100644
--- a/packages/ExternalStorageProvider/res/values-fr-rCA/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-fr-rCA/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Stockage externe"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Mémoire de stockage interne"</string>
- <string name="root_home" msgid="7931555396767513359">"Accueil"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Documents"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-fr/strings.xml b/packages/ExternalStorageProvider/res/values-fr/strings.xml
index 6a84bb4..b3fdd48 100644
--- a/packages/ExternalStorageProvider/res/values-fr/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-fr/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Stockage externe"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Mémoire de stockage interne"</string>
- <string name="root_home" msgid="7931555396767513359">"Répertoire de base"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Documents"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-gl-rES/strings.xml b/packages/ExternalStorageProvider/res/values-gl-rES/strings.xml
index d51eae9..780213f 100644
--- a/packages/ExternalStorageProvider/res/values-gl-rES/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-gl-rES/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Almacenamento externo"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Almacenamento interno"</string>
- <string name="root_home" msgid="7931555396767513359">"Inicio"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Documentos"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-gu-rIN/strings.xml b/packages/ExternalStorageProvider/res/values-gu-rIN/strings.xml
index 3bcc72d..ec8a0bd 100644
--- a/packages/ExternalStorageProvider/res/values-gu-rIN/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-gu-rIN/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"બાહ્ય સંગ્રહ"</string>
<string name="root_internal_storage" msgid="827844243068584127">"આંતરિક સંગ્રહ"</string>
- <string name="root_home" msgid="7931555396767513359">"હોમ"</string>
+ <string name="root_documents" msgid="4051252304075469250">"દસ્તાવેજો"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-hi/strings.xml b/packages/ExternalStorageProvider/res/values-hi/strings.xml
index 93cc712..8538081 100644
--- a/packages/ExternalStorageProvider/res/values-hi/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-hi/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"बाहरी मेमोरी"</string>
<string name="root_internal_storage" msgid="827844243068584127">"मोबाइल मेमोरी"</string>
- <string name="root_home" msgid="7931555396767513359">"होम"</string>
+ <string name="root_documents" msgid="4051252304075469250">"दस्तावेज़"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-hr/strings.xml b/packages/ExternalStorageProvider/res/values-hr/strings.xml
index c866351..a74f8e8 100644
--- a/packages/ExternalStorageProvider/res/values-hr/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-hr/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Vanjska pohrana"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Unutarnja pohrana"</string>
- <string name="root_home" msgid="7931555396767513359">"Početna"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Dokumenti"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-hu/strings.xml b/packages/ExternalStorageProvider/res/values-hu/strings.xml
index db1c7db..3f72b41 100644
--- a/packages/ExternalStorageProvider/res/values-hu/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-hu/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Külső tárhely"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Belső tárhely"</string>
- <string name="root_home" msgid="7931555396767513359">"Otthon"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Dokumentumok"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-hy-rAM/strings.xml b/packages/ExternalStorageProvider/res/values-hy-rAM/strings.xml
index 0e1de49..5360124 100644
--- a/packages/ExternalStorageProvider/res/values-hy-rAM/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-hy-rAM/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Արտաքին պահոց"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Ներքին պահոց"</string>
- <string name="root_home" msgid="7931555396767513359">"Գլխավոր էջ"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Փաստաթղթեր"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-in/strings.xml b/packages/ExternalStorageProvider/res/values-in/strings.xml
index ca7f823..42acde7 100644
--- a/packages/ExternalStorageProvider/res/values-in/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-in/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Penyimpanan Eksternal"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Penyimpanan internal"</string>
- <string name="root_home" msgid="7931555396767513359">"Rumah"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Dokumen"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-is-rIS/strings.xml b/packages/ExternalStorageProvider/res/values-is-rIS/strings.xml
index ad04002..0306165 100644
--- a/packages/ExternalStorageProvider/res/values-is-rIS/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-is-rIS/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Ytri geymsla"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Innbyggð geymsla"</string>
- <string name="root_home" msgid="7931555396767513359">"Heim"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Skjöl"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-it/strings.xml b/packages/ExternalStorageProvider/res/values-it/strings.xml
index 686ee1a..957b5ff 100644
--- a/packages/ExternalStorageProvider/res/values-it/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-it/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Archivio esterno"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Memoria interna"</string>
- <string name="root_home" msgid="7931555396767513359">"Home"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Documenti"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-iw/strings.xml b/packages/ExternalStorageProvider/res/values-iw/strings.xml
index b45fb5c..775506a 100644
--- a/packages/ExternalStorageProvider/res/values-iw/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-iw/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"אחסון חיצוני"</string>
<string name="root_internal_storage" msgid="827844243068584127">"אחסון פנימי"</string>
- <string name="root_home" msgid="7931555396767513359">"דף הבית"</string>
+ <string name="root_documents" msgid="4051252304075469250">"מסמכים"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ja/strings.xml b/packages/ExternalStorageProvider/res/values-ja/strings.xml
index 5c09bf4..188fca2 100644
--- a/packages/ExternalStorageProvider/res/values-ja/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ja/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"外部ストレージ"</string>
<string name="root_internal_storage" msgid="827844243068584127">"内部ストレージ"</string>
- <string name="root_home" msgid="7931555396767513359">"ホーム"</string>
+ <string name="root_documents" msgid="4051252304075469250">"ドキュメント"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ka-rGE/strings.xml b/packages/ExternalStorageProvider/res/values-ka-rGE/strings.xml
index c1bc5c7..cc04860 100644
--- a/packages/ExternalStorageProvider/res/values-ka-rGE/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ka-rGE/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"გარე მეხსიერება"</string>
<string name="root_internal_storage" msgid="827844243068584127">"შიდა მეხსიერება"</string>
- <string name="root_home" msgid="7931555396767513359">"მთავარი"</string>
+ <string name="root_documents" msgid="4051252304075469250">"დოკუმენტები"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-kk-rKZ/strings.xml b/packages/ExternalStorageProvider/res/values-kk-rKZ/strings.xml
index cf05782..ad49036 100644
--- a/packages/ExternalStorageProvider/res/values-kk-rKZ/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-kk-rKZ/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Сыртқы жад"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Ішкі жад"</string>
- <string name="root_home" msgid="7931555396767513359">"Негізгі бет"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Құжаттар"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-km-rKH/strings.xml b/packages/ExternalStorageProvider/res/values-km-rKH/strings.xml
index a2e926f..9cf76d4 100644
--- a/packages/ExternalStorageProvider/res/values-km-rKH/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-km-rKH/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"ឧបករណ៍ផ្ទុកខាងក្រៅ"</string>
<string name="root_internal_storage" msgid="827844243068584127">"ឧបករណ៍ផ្ទុកខាងក្នុង"</string>
- <string name="root_home" msgid="7931555396767513359">"ដើម"</string>
+ <string name="root_documents" msgid="4051252304075469250">"ឯកសារ"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-kn-rIN/strings.xml b/packages/ExternalStorageProvider/res/values-kn-rIN/strings.xml
index 1f0cfbf..e32b1d3 100644
--- a/packages/ExternalStorageProvider/res/values-kn-rIN/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-kn-rIN/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"ಬಾಹ್ಯ ಸಂಗ್ರಹಣೆ"</string>
<string name="root_internal_storage" msgid="827844243068584127">"ಆಂತರಿಕ ಸಂಗ್ರಹಣೆ"</string>
- <string name="root_home" msgid="7931555396767513359">"ಮುಖಪುಟ"</string>
+ <string name="root_documents" msgid="4051252304075469250">"ಡಾಕ್ಯುಮೆಂಟ್ಗಳು"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ko/strings.xml b/packages/ExternalStorageProvider/res/values-ko/strings.xml
index 365648d..849d37e 100644
--- a/packages/ExternalStorageProvider/res/values-ko/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ko/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"외부 저장소"</string>
<string name="root_internal_storage" msgid="827844243068584127">"내부 저장소"</string>
- <string name="root_home" msgid="7931555396767513359">"홈"</string>
+ <string name="root_documents" msgid="4051252304075469250">"문서"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ky-rKG/strings.xml b/packages/ExternalStorageProvider/res/values-ky-rKG/strings.xml
index 4a0f211..d3ccf7f1 100644
--- a/packages/ExternalStorageProvider/res/values-ky-rKG/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ky-rKG/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Тышкы сактагыч"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Ички сактагыч"</string>
- <string name="root_home" msgid="7931555396767513359">"Башкы бет"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Документтер"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-lo-rLA/strings.xml b/packages/ExternalStorageProvider/res/values-lo-rLA/strings.xml
index 9de6519..cecd9f5 100644
--- a/packages/ExternalStorageProvider/res/values-lo-rLA/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-lo-rLA/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"ບ່ອນຈັດເກັບຂໍ້ມູນພາຍນອກ"</string>
<string name="root_internal_storage" msgid="827844243068584127">"ບ່ອນຈັດເກັບຂໍ້ມູນພາຍໃນ"</string>
- <string name="root_home" msgid="7931555396767513359">"ໜ້າຫຼັກ"</string>
+ <string name="root_documents" msgid="4051252304075469250">"ເອກະສານ"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-lt/strings.xml b/packages/ExternalStorageProvider/res/values-lt/strings.xml
index 84ca2d4..240ea89 100644
--- a/packages/ExternalStorageProvider/res/values-lt/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-lt/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Išorinė atmintinė"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Vidinė atmintinė"</string>
- <string name="root_home" msgid="7931555396767513359">"Pagrindinis katalogas"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Dokumentai"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-lv/strings.xml b/packages/ExternalStorageProvider/res/values-lv/strings.xml
index 7eff0b9..d308fe8 100644
--- a/packages/ExternalStorageProvider/res/values-lv/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-lv/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Ārējā krātuve"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Iekšējā atmiņa"</string>
- <string name="root_home" msgid="7931555396767513359">"Sākumdirektorijs"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Dokumenti"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-mk-rMK/strings.xml b/packages/ExternalStorageProvider/res/values-mk-rMK/strings.xml
index fe6b753..8943d23 100644
--- a/packages/ExternalStorageProvider/res/values-mk-rMK/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-mk-rMK/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Надворешна меморија"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Внатрешна меморија"</string>
- <string name="root_home" msgid="7931555396767513359">"Почетна страница"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Документи"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ml-rIN/strings.xml b/packages/ExternalStorageProvider/res/values-ml-rIN/strings.xml
index 5369ec9..08e6dae 100644
--- a/packages/ExternalStorageProvider/res/values-ml-rIN/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ml-rIN/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"ബാഹ്യ സ്റ്റോറേജ്"</string>
<string name="root_internal_storage" msgid="827844243068584127">"ആന്തരിക സ്റ്റോറേജ്"</string>
- <string name="root_home" msgid="7931555396767513359">"വീട്"</string>
+ <string name="root_documents" msgid="4051252304075469250">"പ്രമാണങ്ങൾ"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-mn-rMN/strings.xml b/packages/ExternalStorageProvider/res/values-mn-rMN/strings.xml
index 4604f32..3d7b7f7 100644
--- a/packages/ExternalStorageProvider/res/values-mn-rMN/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-mn-rMN/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Гадаад сан"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Дотоод сан"</string>
- <string name="root_home" msgid="7931555396767513359">"Нүүр хуудас"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Документүүд"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-mr-rIN/strings.xml b/packages/ExternalStorageProvider/res/values-mr-rIN/strings.xml
index 1310b0e..a7e7fbb 100644
--- a/packages/ExternalStorageProvider/res/values-mr-rIN/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-mr-rIN/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"बाह्य संचयन"</string>
<string name="root_internal_storage" msgid="827844243068584127">"अंतर्गत संचयन"</string>
- <string name="root_home" msgid="7931555396767513359">"निवास"</string>
+ <string name="root_documents" msgid="4051252304075469250">"दस्तऐवज"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ms-rMY/strings.xml b/packages/ExternalStorageProvider/res/values-ms-rMY/strings.xml
index 007a1be..cb4d736 100644
--- a/packages/ExternalStorageProvider/res/values-ms-rMY/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ms-rMY/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Storan Luaran"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Storan dalaman"</string>
- <string name="root_home" msgid="7931555396767513359">"Rumah"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Dokumen"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-my-rMM/strings.xml b/packages/ExternalStorageProvider/res/values-my-rMM/strings.xml
index 2df9a33..dc9d684 100644
--- a/packages/ExternalStorageProvider/res/values-my-rMM/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-my-rMM/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"ပြင်ပသိုလှောင်ရာပစ္စည်း"</string>
<string name="root_internal_storage" msgid="827844243068584127">"စက်တွင်း သိုလှောင်ထားမှု"</string>
- <string name="root_home" msgid="7931555396767513359">"ပင်မ"</string>
+ <string name="root_documents" msgid="4051252304075469250">"စာရွက်စာတန်းများ"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-nb/strings.xml b/packages/ExternalStorageProvider/res/values-nb/strings.xml
index 315d932..a9ecb69 100644
--- a/packages/ExternalStorageProvider/res/values-nb/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-nb/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Ekstern lagring"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Intern lagring"</string>
- <string name="root_home" msgid="7931555396767513359">"Hjem"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Dokumenter"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ne-rNP/strings.xml b/packages/ExternalStorageProvider/res/values-ne-rNP/strings.xml
index 4a9a8cd..5294043 100644
--- a/packages/ExternalStorageProvider/res/values-ne-rNP/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ne-rNP/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"बाह्य भण्डारण"</string>
<string name="root_internal_storage" msgid="827844243068584127">"आन्तरिक भण्डारण"</string>
- <string name="root_home" msgid="7931555396767513359">"गृह"</string>
+ <string name="root_documents" msgid="4051252304075469250">"कागजातहरू"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-nl/strings.xml b/packages/ExternalStorageProvider/res/values-nl/strings.xml
index 0ae88ce..bde6166 100644
--- a/packages/ExternalStorageProvider/res/values-nl/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-nl/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Externe opslag"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Interne opslag"</string>
- <string name="root_home" msgid="7931555396767513359">"Startscherm"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Documenten"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-pa-rIN/strings.xml b/packages/ExternalStorageProvider/res/values-pa-rIN/strings.xml
index a805dd8..0e91589 100644
--- a/packages/ExternalStorageProvider/res/values-pa-rIN/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-pa-rIN/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"ਬਾਹਰੀ ਸਟੋਰੇਜ"</string>
<string name="root_internal_storage" msgid="827844243068584127">"ਅੰਦਰੂਨੀ ਸਟੋਰੇਜ"</string>
- <string name="root_home" msgid="7931555396767513359">"ਘਰ"</string>
+ <string name="root_documents" msgid="4051252304075469250">"ਦਸਤਾਵੇਜ਼"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-pl/strings.xml b/packages/ExternalStorageProvider/res/values-pl/strings.xml
index 66d83c7..6c5e7d7 100644
--- a/packages/ExternalStorageProvider/res/values-pl/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-pl/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Pamięć zewnętrzna"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Pamięć wewnętrzna"</string>
- <string name="root_home" msgid="7931555396767513359">"Katalog domowy"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Dokumenty"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-pt-rBR/strings.xml b/packages/ExternalStorageProvider/res/values-pt-rBR/strings.xml
index 958eef4..77c89b8 100644
--- a/packages/ExternalStorageProvider/res/values-pt-rBR/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-pt-rBR/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Armazenamento externo"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Armazenamento interno"</string>
- <string name="root_home" msgid="7931555396767513359">"Página inicial"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Documentos"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-pt-rPT/strings.xml b/packages/ExternalStorageProvider/res/values-pt-rPT/strings.xml
index c8865e1..77c89b8 100644
--- a/packages/ExternalStorageProvider/res/values-pt-rPT/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-pt-rPT/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Armazenamento externo"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Armazenamento interno"</string>
- <string name="root_home" msgid="7931555396767513359">"Casa"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Documentos"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-pt/strings.xml b/packages/ExternalStorageProvider/res/values-pt/strings.xml
index 958eef4..77c89b8 100644
--- a/packages/ExternalStorageProvider/res/values-pt/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-pt/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Armazenamento externo"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Armazenamento interno"</string>
- <string name="root_home" msgid="7931555396767513359">"Página inicial"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Documentos"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ro/strings.xml b/packages/ExternalStorageProvider/res/values-ro/strings.xml
index 5bb4a7c..abd0b98 100644
--- a/packages/ExternalStorageProvider/res/values-ro/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ro/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Stocare externă"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Stocare internă"</string>
- <string name="root_home" msgid="7931555396767513359">"Director principal"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Documente"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ru/strings.xml b/packages/ExternalStorageProvider/res/values-ru/strings.xml
index a651371..740272f 100644
--- a/packages/ExternalStorageProvider/res/values-ru/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ru/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Внешний накопитель"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Внутренний накопитель"</string>
- <string name="root_home" msgid="7931555396767513359">"Мои файлы"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Документы"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-si-rLK/strings.xml b/packages/ExternalStorageProvider/res/values-si-rLK/strings.xml
index 5292403..15334bb 100644
--- a/packages/ExternalStorageProvider/res/values-si-rLK/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-si-rLK/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"බාහිර ආචයනය"</string>
<string name="root_internal_storage" msgid="827844243068584127">"අභ්යන්තර ආචයනය"</string>
- <string name="root_home" msgid="7931555396767513359">"මුල් පිටුව"</string>
+ <string name="root_documents" msgid="4051252304075469250">"ලේඛන"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-sk/strings.xml b/packages/ExternalStorageProvider/res/values-sk/strings.xml
index 5157888..9be7b79 100644
--- a/packages/ExternalStorageProvider/res/values-sk/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-sk/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Externý ukladací priestor"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Interné úložisko"</string>
- <string name="root_home" msgid="7931555396767513359">"Predvolený adresár"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Dokumenty"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-sl/strings.xml b/packages/ExternalStorageProvider/res/values-sl/strings.xml
index dd2cc24..6ffa698 100644
--- a/packages/ExternalStorageProvider/res/values-sl/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-sl/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Zunanja shramba"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Notranja shramba"</string>
- <string name="root_home" msgid="7931555396767513359">"Korenska mapa"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Dokumenti"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-sq-rAL/strings.xml b/packages/ExternalStorageProvider/res/values-sq-rAL/strings.xml
index 3aafd1c..dc346ea 100644
--- a/packages/ExternalStorageProvider/res/values-sq-rAL/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-sq-rAL/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Hapësirë e jashtme ruajtjeje"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Hapësira e brendshme ruajtëse"</string>
- <string name="root_home" msgid="7931555396767513359">"Kreu"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Dokumente"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-sr/strings.xml b/packages/ExternalStorageProvider/res/values-sr/strings.xml
index 2d987ef..54238a4 100644
--- a/packages/ExternalStorageProvider/res/values-sr/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-sr/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Спољна меморија"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Интерна меморија"</string>
- <string name="root_home" msgid="7931555396767513359">"Почетни"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Документи"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-sv/strings.xml b/packages/ExternalStorageProvider/res/values-sv/strings.xml
index bc4788a..6eac11e 100644
--- a/packages/ExternalStorageProvider/res/values-sv/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-sv/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Extern lagring"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Intern lagring"</string>
- <string name="root_home" msgid="7931555396767513359">"Hem"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Dokument"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-sw/strings.xml b/packages/ExternalStorageProvider/res/values-sw/strings.xml
index dcca92a..0d0e483 100644
--- a/packages/ExternalStorageProvider/res/values-sw/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-sw/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Hifadhi ya Nje"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Hifadhi ya ndani"</string>
- <string name="root_home" msgid="7931555396767513359">"Mwanzo"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Hati"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ta-rIN/strings.xml b/packages/ExternalStorageProvider/res/values-ta-rIN/strings.xml
index b859e7a..d7bafbc 100644
--- a/packages/ExternalStorageProvider/res/values-ta-rIN/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ta-rIN/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"வெளிப்புறச் சேமிப்பிடம்"</string>
<string name="root_internal_storage" msgid="827844243068584127">"அகச் சேமிப்பிடம்"</string>
- <string name="root_home" msgid="7931555396767513359">"முகப்பு"</string>
+ <string name="root_documents" msgid="4051252304075469250">"ஆவணங்கள்"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-te-rIN/strings.xml b/packages/ExternalStorageProvider/res/values-te-rIN/strings.xml
index 934877e..800d18e 100644
--- a/packages/ExternalStorageProvider/res/values-te-rIN/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-te-rIN/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"బాహ్య నిల్వ"</string>
<string name="root_internal_storage" msgid="827844243068584127">"అంతర్గత నిల్వ"</string>
- <string name="root_home" msgid="7931555396767513359">"హోమ్"</string>
+ <string name="root_documents" msgid="4051252304075469250">"పత్రాలు"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-th/strings.xml b/packages/ExternalStorageProvider/res/values-th/strings.xml
index 957d6b7..796635e 100644
--- a/packages/ExternalStorageProvider/res/values-th/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-th/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"ที่จัดเก็บข้อมูลภายนอก"</string>
<string name="root_internal_storage" msgid="827844243068584127">"ที่จัดเก็บข้อมูลภายใน"</string>
- <string name="root_home" msgid="7931555396767513359">"Home"</string>
+ <string name="root_documents" msgid="4051252304075469250">"เอกสาร"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-tl/strings.xml b/packages/ExternalStorageProvider/res/values-tl/strings.xml
index be7aebc..529cdc2 100644
--- a/packages/ExternalStorageProvider/res/values-tl/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-tl/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"External Storage"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Internal storage"</string>
- <string name="root_home" msgid="7931555396767513359">"Home"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Mga Dokumento"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-tr/strings.xml b/packages/ExternalStorageProvider/res/values-tr/strings.xml
index 2ce1411..d6bd52a 100644
--- a/packages/ExternalStorageProvider/res/values-tr/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-tr/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Harici Depolama"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Dahili depolama"</string>
- <string name="root_home" msgid="7931555396767513359">"Ev"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Dokümanlar"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-uk/strings.xml b/packages/ExternalStorageProvider/res/values-uk/strings.xml
index 0033bca..b8206e0 100644
--- a/packages/ExternalStorageProvider/res/values-uk/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-uk/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Зовнішня пам’ять"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Внутрішня пам’ять"</string>
- <string name="root_home" msgid="7931555396767513359">"Головний екран"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Документи"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ur-rPK/strings.xml b/packages/ExternalStorageProvider/res/values-ur-rPK/strings.xml
index df46fb0..02454bc 100644
--- a/packages/ExternalStorageProvider/res/values-ur-rPK/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ur-rPK/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"بیرونی اسٹوریج"</string>
<string name="root_internal_storage" msgid="827844243068584127">"داخلی اسٹوریج"</string>
- <string name="root_home" msgid="7931555396767513359">"ہوم"</string>
+ <string name="root_documents" msgid="4051252304075469250">"دستاویزات"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-uz-rUZ/strings.xml b/packages/ExternalStorageProvider/res/values-uz-rUZ/strings.xml
index 069e137..07cc14c 100644
--- a/packages/ExternalStorageProvider/res/values-uz-rUZ/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-uz-rUZ/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Tashqi xotira"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Ichki xotira"</string>
- <string name="root_home" msgid="7931555396767513359">"Mening fayllarim"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Hujjatlar"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-vi/strings.xml b/packages/ExternalStorageProvider/res/values-vi/strings.xml
index 39e9c6c..b171c93 100644
--- a/packages/ExternalStorageProvider/res/values-vi/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-vi/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Bộ nhớ ngoài"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Bộ nhớ trong"</string>
- <string name="root_home" msgid="7931555396767513359">"Nhà riêng"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Tài liệu"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-zh-rCN/strings.xml b/packages/ExternalStorageProvider/res/values-zh-rCN/strings.xml
index ea20dce..7df77dd 100644
--- a/packages/ExternalStorageProvider/res/values-zh-rCN/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-zh-rCN/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"外部存储设备"</string>
<string name="root_internal_storage" msgid="827844243068584127">"内部存储空间"</string>
- <string name="root_home" msgid="7931555396767513359">"主目录"</string>
+ <string name="root_documents" msgid="4051252304075469250">"文档"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-zh-rHK/strings.xml b/packages/ExternalStorageProvider/res/values-zh-rHK/strings.xml
index 27f1f0a..62d8afb 100644
--- a/packages/ExternalStorageProvider/res/values-zh-rHK/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-zh-rHK/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"外部儲存空間"</string>
<string name="root_internal_storage" msgid="827844243068584127">"內部儲存空間"</string>
- <string name="root_home" msgid="7931555396767513359">"主目錄"</string>
+ <string name="root_documents" msgid="4051252304075469250">"文件"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-zh-rTW/strings.xml b/packages/ExternalStorageProvider/res/values-zh-rTW/strings.xml
index b2d764a..62d8afb 100644
--- a/packages/ExternalStorageProvider/res/values-zh-rTW/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-zh-rTW/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"外部儲存空間"</string>
<string name="root_internal_storage" msgid="827844243068584127">"內部儲存空間"</string>
- <string name="root_home" msgid="7931555396767513359">"主畫面"</string>
+ <string name="root_documents" msgid="4051252304075469250">"文件"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-zu/strings.xml b/packages/ExternalStorageProvider/res/values-zu/strings.xml
index 8a7c7df..4a0a845 100644
--- a/packages/ExternalStorageProvider/res/values-zu/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-zu/strings.xml
@@ -18,5 +18,5 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Isitoreji sangaphandle"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Isitoreji sangaphakathi"</string>
- <string name="root_home" msgid="7931555396767513359">"Ekhaya"</string>
+ <string name="root_documents" msgid="4051252304075469250">"Amadokhumenti"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 97dfd47..9a51b05 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -34,6 +34,7 @@
import android.os.ParcelFileDescriptor;
import android.os.ParcelFileDescriptor.OnCloseListener;
import android.os.UserHandle;
+import android.os.storage.DiskInfo;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.provider.DocumentsContract;
@@ -41,6 +42,7 @@
import android.provider.DocumentsContract.Root;
import android.provider.DocumentsProvider;
import android.provider.MediaStore;
+import android.provider.Settings;
import android.support.provider.DocumentArchiveHelper;
import android.text.TextUtils;
import android.util.ArrayMap;
@@ -62,6 +64,7 @@
public class ExternalStorageProvider extends DocumentsProvider {
private static final String TAG = "ExternalStorage";
+ private static final boolean DEBUG = false;
private static final boolean LOG_INOTIFY = false;
public static final String AUTHORITY = "com.android.externalstorage.documents";
@@ -136,10 +139,25 @@
if (volume.getType() == VolumeInfo.TYPE_EMULATED) {
// We currently only support a single emulated volume mounted at
// a time, and it's always considered the primary
+ if (DEBUG) Log.d(TAG, "Found primary volume: " + volume);
rootId = ROOT_ID_PRIMARY_EMULATED;
+
if (VolumeInfo.ID_EMULATED_INTERNAL.equals(volume.getId())) {
- title = getContext().getString(R.string.root_internal_storage);
+ // This is basically the user's primary device storage.
+ // Use device name for the volume since this is likely same thing
+ // the user sees when they mount their phone on another device.
+ String deviceName = Settings.Global.getString(
+ getContext().getContentResolver(), Settings.Global.DEVICE_NAME);
+
+ // Device name should always be set. In case it isn't, though,
+ // fall back to a localized "Internal Storage" string.
+ title = !TextUtils.isEmpty(deviceName)
+ ? deviceName
+ : getContext().getString(R.string.root_internal_storage);
} else {
+ // This should cover all other storage devices, like an SD card
+ // or USB OTG drive plugged in. Using getBestVolumeDescription()
+ // will give us a nice string like "Samsung SD card" or "SanDisk USB drive"
final VolumeInfo privateVol = mStorageManager.findPrivateForEmulated(volume);
title = mStorageManager.getBestVolumeDescription(privateVol);
}
@@ -167,10 +185,17 @@
root.flags = Root.FLAG_LOCAL_ONLY
| Root.FLAG_SUPPORTS_SEARCH | Root.FLAG_SUPPORTS_IS_CHILD;
+ final DiskInfo disk = volume.getDisk();
+ if (DEBUG) Log.d(TAG, "Disk for root " + rootId + " is " + disk);
+ if (disk != null && disk.isSd()) {
+ root.flags |= Root.FLAG_REMOVABLE_SD;
+ } else if (disk != null && disk.isUsb()) {
+ root.flags |= Root.FLAG_REMOVABLE_USB;
+ }
+
if (volume.isPrimary()) {
// save off the primary volume for subsequent "Home" dir initialization.
primaryVolume = volume;
- root.flags |= Root.FLAG_ADVANCED;
}
// Dunno when this would NOT be the case, but never hurts to be correct.
if (volume.isMountedWritable()) {
@@ -193,8 +218,9 @@
}
}
- // Finally, if primary storage is available we add the "Home" directory,
- // creating it as needed.
+ // Finally, if primary storage is available we add the "Documents" directory.
+ // If I recall correctly the actual directory is created on demand
+ // by calling either getPathForUser, or getInternalPathForUser.
if (primaryVolume != null && primaryVolume.isVisible()) {
final RootInfo root = new RootInfo();
root.rootId = ROOT_ID_HOME;
@@ -211,8 +237,7 @@
root.flags |= Root.FLAG_SUPPORTS_CREATE;
}
- // Create the "Home" directory on disk, but don't the localized root.title
- // since the directories shouldn't be localized.
+ // Create the "Documents" directory on disk (don't use the localized title).
root.visiblePath = new File(
primaryVolume.getPathForUser(userId), Environment.DIRECTORY_DOCUMENTS);
root.path = new File(
@@ -391,6 +416,10 @@
if (mArchiveHelper.isArchivedDocument(docId)) {
return mArchiveHelper.isChildDocument(parentDocId, docId);
}
+ // Archives do not contain regular files.
+ if (mArchiveHelper.isArchivedDocument(parentDocId)) {
+ return false;
+ }
final File parent = getFileForDocId(parentDocId).getCanonicalFile();
final File doc = getFileForDocId(docId).getCanonicalFile();
diff --git a/packages/Keyguard/res/values-h560dp/dimens.xml b/packages/Keyguard/res/values-h560dp/dimens.xml
index 1683113..469ce52 100644
--- a/packages/Keyguard/res/values-h560dp/dimens.xml
+++ b/packages/Keyguard/res/values-h560dp/dimens.xml
@@ -16,5 +16,5 @@
-->
<resources>
- <dimen name="widget_big_font_size">96dp</dimen>
+ <dimen name="widget_big_font_size">84dp</dimen>
</resources>
\ No newline at end of file
diff --git a/packages/Keyguard/res/values-h650dp/dimens.xml b/packages/Keyguard/res/values-h650dp/dimens.xml
index 1cd2162..cb89cb4 100644
--- a/packages/Keyguard/res/values-h650dp/dimens.xml
+++ b/packages/Keyguard/res/values-h650dp/dimens.xml
@@ -16,5 +16,5 @@
-->
<resources>
- <dimen name="widget_big_font_size">100dp</dimen>
+ <dimen name="widget_big_font_size">88dp</dimen>
</resources>
\ No newline at end of file
diff --git a/packages/Keyguard/res/values-sw600dp-land/dimens.xml b/packages/Keyguard/res/values-sw600dp-land/dimens.xml
index a487644..c34012d 100644
--- a/packages/Keyguard/res/values-sw600dp-land/dimens.xml
+++ b/packages/Keyguard/res/values-sw600dp-land/dimens.xml
@@ -20,5 +20,5 @@
<resources>
<!-- Overload default clock widget parameters -->
- <dimen name="widget_big_font_size">100dp</dimen>
+ <dimen name="widget_big_font_size">88dp</dimen>
</resources>
\ No newline at end of file
diff --git a/packages/Keyguard/res/values-sw600dp/dimens.xml b/packages/Keyguard/res/values-sw600dp/dimens.xml
index b181682..a3b01b6 100644
--- a/packages/Keyguard/res/values-sw600dp/dimens.xml
+++ b/packages/Keyguard/res/values-sw600dp/dimens.xml
@@ -26,9 +26,9 @@
<dimen name="keyguard_security_view_margin">12dp</dimen>
<!-- Overload default clock widget parameters -->
- <dimen name="widget_big_font_size">125dp</dimen>
+ <dimen name="widget_big_font_size">110dp</dimen>
<dimen name="widget_label_font_size">16sp</dimen>
- <dimen name="bottom_text_spacing_digital">-16dp</dimen>
+ <dimen name="bottom_text_spacing_digital">-1dp</dimen>
<!-- EmergencyCarrierArea overlap - amount to overlap the emergency button and carrier text.
Should be 0 on devices with plenty of room (e.g. tablets) -->
diff --git a/packages/Keyguard/res/values-sw720dp/dimens.xml b/packages/Keyguard/res/values-sw720dp/dimens.xml
index 08ab791..210c7eb 100644
--- a/packages/Keyguard/res/values-sw720dp/dimens.xml
+++ b/packages/Keyguard/res/values-sw720dp/dimens.xml
@@ -24,5 +24,5 @@
<!-- Height of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) -->
<dimen name="keyguard_security_height">420dp</dimen>
- <dimen name="widget_big_font_size">138dp</dimen>
+ <dimen name="widget_big_font_size">122dp</dimen>
</resources>
diff --git a/packages/Keyguard/res/values/dimens.xml b/packages/Keyguard/res/values/dimens.xml
index 18d893a..7b952be2 100644
--- a/packages/Keyguard/res/values/dimens.xml
+++ b/packages/Keyguard/res/values/dimens.xml
@@ -39,9 +39,9 @@
<dimen name="eca_overlap">-10dip</dimen>
<!-- Default clock parameters -->
- <dimen name="bottom_text_spacing_digital">-10dp</dimen>
+ <dimen name="bottom_text_spacing_digital">-1dp</dimen>
<dimen name="widget_label_font_size">14sp</dimen>
- <dimen name="widget_big_font_size">88dp</dimen>
+ <dimen name="widget_big_font_size">78dp</dimen>
<!-- The y translation to apply at the start in appear animations. -->
<dimen name="appear_y_translation_start">32dp</dimen>
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index ec2a173..434631e 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -413,7 +413,7 @@
* @return true if the menu key should be enabled
*/
private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
- private boolean shouldEnableMenuKey() {
+ public boolean shouldEnableMenuKey() {
final Resources res = getResources();
final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen);
final boolean isTestHarness = ActivityManager.isRunningInTestHarness();
@@ -421,15 +421,6 @@
return !configDisabled || isTestHarness || fileOverride;
}
- public boolean handleMenuKey() {
- // The following enables the MENU key to work for testing automation
- if (shouldEnableMenuKey()) {
- dismiss();
- return true;
- }
- return false;
- }
-
public void setViewMediatorCallback(ViewMediatorCallback viewMediatorCallback) {
mViewMediatorCallback = viewMediatorCallback;
// Update ViewMediator with the current input method requirements
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
index cedd88d..fe98cb8 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -89,7 +89,12 @@
return true;
}
if (keyCode >= KeyEvent.KEYCODE_0 && keyCode <= KeyEvent.KEYCODE_9) {
- int number = keyCode - KeyEvent.KEYCODE_0 ;
+ int number = keyCode - KeyEvent.KEYCODE_0;
+ performNumberClick(number);
+ return true;
+ }
+ if (keyCode >= KeyEvent.KEYCODE_NUMPAD_0 && keyCode <= KeyEvent.KEYCODE_NUMPAD_9) {
+ int number = keyCode - KeyEvent.KEYCODE_NUMPAD_0;
performNumberClick(number);
return true;
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index 409f6a7..b1d42e7 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -519,6 +519,9 @@
@Override
public void showPromptReason(int reason) {
if (mCurrentSecuritySelection != SecurityMode.None) {
+ if (reason != PROMPT_REASON_NONE) {
+ Log.i(TAG, "Strong auth required, reason: " + reason);
+ }
getSecurityView(mCurrentSecuritySelection).showPromptReason(reason);
}
}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/AppFuse.java b/packages/MtpDocumentsProvider/src/com/android/mtp/AppFuse.java
index 6a98405..38435f4 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/AppFuse.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/AppFuse.java
@@ -133,6 +133,8 @@
return mCallback.readObjectBytes(inode, offset, size, mBuffer);
} catch (IOException e) {
return -OsConstants.EIO;
+ } catch (UnsupportedOperationException e) {
+ return -OsConstants.ENOTSUP;
}
}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
index 90b5c09..044a061 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
@@ -16,6 +16,8 @@
package com.android.mtp;
+import android.annotation.Nullable;
+import android.annotation.WorkerThread;
import android.content.ContentResolver;
import android.database.Cursor;
import android.mtp.MtpObjectInfo;
@@ -25,6 +27,8 @@
import android.provider.DocumentsContract;
import android.util.Log;
+import com.android.internal.util.Preconditions;
+
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
@@ -38,23 +42,136 @@
* background thread to load the rest documents and caches its result for next requests.
* TODO: Rename this class to ObjectInfoLoader
*/
-class DocumentLoader {
+class DocumentLoader implements AutoCloseable {
static final int NUM_INITIAL_ENTRIES = 10;
static final int NUM_LOADING_ENTRIES = 20;
static final int NOTIFY_PERIOD_MS = 500;
+ private final MtpDeviceRecord mDevice;
private final MtpManager mMtpManager;
private final ContentResolver mResolver;
private final MtpDatabase mDatabase;
private final TaskList mTaskList = new TaskList();
- private boolean mHasBackgroundThread = false;
+ private Thread mBackgroundThread;
- DocumentLoader(MtpManager mtpManager, ContentResolver resolver, MtpDatabase database) {
+ DocumentLoader(MtpDeviceRecord device, MtpManager mtpManager, ContentResolver resolver,
+ MtpDatabase database) {
+ mDevice = device;
mMtpManager = mtpManager;
mResolver = resolver;
mDatabase = database;
}
+ /**
+ * Queries the child documents of given parent.
+ * It loads the first NUM_INITIAL_ENTRIES of object info, then launches the background thread
+ * to load the rest.
+ */
+ synchronized Cursor queryChildDocuments(String[] columnNames, Identifier parent)
+ throws IOException {
+ Preconditions.checkArgument(parent.mDeviceId == mDevice.deviceId);
+ LoaderTask task = mTaskList.findTask(parent);
+ if (task == null) {
+ if (parent.mDocumentId == null) {
+ throw new FileNotFoundException("Parent not found.");
+ }
+ // TODO: Handle nit race around here.
+ // 1. getObjectHandles.
+ // 2. putNewDocument.
+ // 3. startAddingChildDocuemnts.
+ // 4. stopAddingChildDocuments - It removes the new document added at the step 2,
+ // because it is not updated between start/stopAddingChildDocuments.
+ task = LoaderTask.create(mDatabase, mMtpManager, mDevice.operationsSupported, parent);
+ task.fillDocuments(loadDocuments(
+ mMtpManager,
+ parent.mDeviceId,
+ task.getUnloadedObjectHandles(NUM_INITIAL_ENTRIES)));
+ } else {
+ // Once remove the existing task in order to add it to the head of the list.
+ mTaskList.remove(task);
+ }
+
+ mTaskList.addFirst(task);
+ if (task.getState() == LoaderTask.STATE_LOADING) {
+ resume();
+ }
+ return task.createCursor(mResolver, columnNames);
+ }
+
+ /**
+ * Resumes a background thread.
+ */
+ synchronized void resume() {
+ if (mBackgroundThread == null) {
+ mBackgroundThread = new BackgroundLoaderThread();
+ mBackgroundThread.start();
+ }
+ }
+
+ /**
+ * Obtains next task to be run in background thread, or release the reference to background
+ * thread.
+ *
+ * Worker thread that receives null task needs to exit.
+ */
+ @WorkerThread
+ synchronized @Nullable LoaderTask getNextTaskOrReleaseBackgroundThread() {
+ Preconditions.checkState(mBackgroundThread != null);
+
+ final LoaderTask task = mTaskList.findRunningTask();
+ if (task != null) {
+ return task;
+ }
+
+ final Identifier identifier = mDatabase.getUnmappedDocumentsParent(mDevice.deviceId);
+ if (identifier != null) {
+ final LoaderTask existingTask = mTaskList.findTask(identifier);
+ if (existingTask != null) {
+ Preconditions.checkState(existingTask.getState() != LoaderTask.STATE_LOADING);
+ mTaskList.remove(existingTask);
+ }
+ try {
+ final LoaderTask newTask = LoaderTask.create(
+ mDatabase, mMtpManager, mDevice.operationsSupported, identifier);
+ mTaskList.addFirst(newTask);
+ return newTask;
+ } catch (IOException exception) {
+ Log.e(MtpDocumentsProvider.TAG, "Failed to create a task for mapping", exception);
+ // Continue to release the background thread.
+ }
+ }
+
+ mBackgroundThread = null;
+ return null;
+ }
+
+ /**
+ * Terminates background thread.
+ */
+ @Override
+ public void close() throws InterruptedException {
+ final Thread thread;
+ synchronized (this) {
+ mTaskList.clear();
+ thread = mBackgroundThread;
+ }
+ if (thread != null) {
+ thread.interrupt();
+ thread.join();
+ }
+ }
+
+ synchronized void clearCompletedTasks() {
+ mTaskList.clearCompletedTasks();
+ }
+
+ synchronized void clearTask(Identifier parentIdentifier) {
+ mTaskList.clearTask(parentIdentifier);
+ }
+
+ /**
+ * Helper method to loads multiple object info.
+ */
private static MtpObjectInfo[] loadDocuments(MtpManager manager, int deviceId, int[] handles)
throws IOException {
final ArrayList<MtpObjectInfo> objects = new ArrayList<>();
@@ -70,78 +187,27 @@
return objects.toArray(new MtpObjectInfo[objects.size()]);
}
- synchronized Cursor queryChildDocuments(String[] columnNames, Identifier parent)
- throws IOException {
- LoaderTask task = mTaskList.findTask(parent);
- if (task == null) {
- if (parent.mDocumentId == null) {
- throw new FileNotFoundException("Parent not found.");
- }
-
- int parentHandle = parent.mObjectHandle;
- // Need to pass the special value MtpManager.OBJECT_HANDLE_ROOT_CHILDREN to
- // getObjectHandles if we would like to obtain children under the root.
- if (parent.mDocumentType == MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE) {
- parentHandle = MtpManager.OBJECT_HANDLE_ROOT_CHILDREN;
- }
- // TODO: Handle nit race around here.
- // 1. getObjectHandles.
- // 2. putNewDocument.
- // 3. startAddingChildDocuemnts.
- // 4. stopAddingChildDocuments - It removes the new document added at the step 2,
- // because it is not updated between start/stopAddingChildDocuments.
- task = new LoaderTask(mDatabase, parent, mMtpManager.getObjectHandles(
- parent.mDeviceId, parent.mStorageId, parentHandle));
- task.fillDocuments(loadDocuments(
- mMtpManager,
- parent.mDeviceId,
- task.getUnloadedObjectHandles(NUM_INITIAL_ENTRIES)));
- } else {
- // Once remove the existing task in order to add it to the head of the list.
- mTaskList.remove(task);
- }
-
- mTaskList.addFirst(task);
- if (task.getState() == LoaderTask.STATE_LOADING && !mHasBackgroundThread) {
- mHasBackgroundThread = true;
- new BackgroundLoaderThread().start();
- }
- return task.createCursor(mResolver, columnNames);
- }
-
- synchronized void clearTasks() {
- mTaskList.clear();
- }
-
- synchronized void clearCompletedTasks() {
- mTaskList.clearCompletedTasks();
- }
-
- synchronized void clearTask(Identifier parentIdentifier) {
- mTaskList.clearTask(parentIdentifier);
- }
-
+ /**
+ * Background thread to fetch object info.
+ */
private class BackgroundLoaderThread extends Thread {
+ /**
+ * Finds task that needs to be processed, then loads NUM_LOADING_ENTRIES of object info and
+ * store them to the database. If it does not find a task, exits the thread.
+ */
@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- while (true) {
- LoaderTask task;
- int deviceId;
- int[] handles;
- synchronized (DocumentLoader.this) {
- task = mTaskList.findRunningTask();
- if (task == null) {
- mHasBackgroundThread = false;
- return;
- }
- deviceId = task.mIdentifier.mDeviceId;
- handles = task.getUnloadedObjectHandles(NUM_LOADING_ENTRIES);
+ while (!Thread.interrupted()) {
+ final LoaderTask task = getNextTaskOrReleaseBackgroundThread();
+ if (task == null) {
+ return;
}
-
try {
- final MtpObjectInfo[] objectInfos =
- loadDocuments(mMtpManager, deviceId, handles);
+ final MtpObjectInfo[] objectInfos = loadDocuments(
+ mMtpManager,
+ task.mIdentifier.mDeviceId,
+ task.getUnloadedObjectHandles(NUM_LOADING_ENTRIES));
task.fillDocuments(objectInfos);
final boolean shouldNotify =
task.mLastNotified.getTime() <
@@ -157,6 +223,9 @@
}
}
+ /**
+ * Task list that has helper methods to search/clear tasks.
+ */
private static class TaskList extends LinkedList<LoaderTask> {
LoaderTask findTask(Identifier parent) {
for (int i = 0; i < size(); i++) {
@@ -197,26 +266,38 @@
}
}
+ /**
+ * Loader task.
+ * Each task is responsible for fetching child documents for the given parent document.
+ */
private static class LoaderTask {
static final int STATE_LOADING = 0;
static final int STATE_COMPLETED = 1;
static final int STATE_ERROR = 2;
final MtpDatabase mDatabase;
+ int[] mOperationsSupported;
final Identifier mIdentifier;
final int[] mObjectHandles;
Date mLastNotified;
int mNumLoaded;
Exception mError;
- LoaderTask(MtpDatabase database, Identifier identifier, int[] objectHandles) {
+ LoaderTask(MtpDatabase database, int[] operationsSupported, Identifier identifier,
+ int[] objectHandles) {
mDatabase = database;
+ mOperationsSupported = operationsSupported;
mIdentifier = identifier;
mObjectHandles = objectHandles;
mNumLoaded = 0;
mLastNotified = new Date();
}
+ /**
+ * Returns a cursor that traverses the child document of the parent document handled by the
+ * task.
+ * The returned task may have a EXTRA_LOADING flag.
+ */
Cursor createCursor(ContentResolver resolver, String[] columnNames) throws IOException {
final Bundle extras = new Bundle();
switch (getState()) {
@@ -235,6 +316,9 @@
return cursor;
}
+ /**
+ * Returns a state of the task.
+ */
int getState() {
if (mError != null) {
return STATE_ERROR;
@@ -245,6 +329,9 @@
}
}
+ /**
+ * Obtains object handles that have not been loaded yet.
+ */
int[] getUnloadedObjectHandles(int count) {
return Arrays.copyOfRange(
mObjectHandles,
@@ -252,11 +339,17 @@
Math.min(mNumLoaded + count, mObjectHandles.length));
}
+ /**
+ * Notifies a change of child list of the document.
+ */
void notify(ContentResolver resolver) {
resolver.notifyChange(createUri(), null, false);
mLastNotified = new Date();
}
+ /**
+ * Stores object information into database.
+ */
void fillDocuments(MtpObjectInfo[] objectInfoList) {
if (objectInfoList.length == 0 || getState() != STATE_LOADING) {
return;
@@ -266,7 +359,8 @@
mDatabase.getMapper().startAddingDocuments(mIdentifier.mDocumentId);
}
mDatabase.getMapper().putChildDocuments(
- mIdentifier.mDeviceId, mIdentifier.mDocumentId, objectInfoList);
+ mIdentifier.mDeviceId, mIdentifier.mDocumentId, mOperationsSupported,
+ objectInfoList);
mNumLoaded += objectInfoList.length;
if (getState() != STATE_LOADING) {
mDatabase.getMapper().stopAddingDocuments(mIdentifier.mDocumentId);
@@ -276,6 +370,9 @@
}
}
+ /**
+ * Marks the loading task as error.
+ */
void setError(Exception error) {
final int lastState = getState();
setErrorInternal(error);
@@ -298,5 +395,21 @@
return DocumentsContract.buildChildDocumentsUri(
MtpDocumentsProvider.AUTHORITY, mIdentifier.mDocumentId);
}
+
+ /**
+ * Creates a LoaderTask that loads children of the given document.
+ */
+ static LoaderTask create(MtpDatabase database, MtpManager manager,
+ int[] operationsSupported, Identifier parent)
+ throws IOException {
+ int parentHandle = parent.mObjectHandle;
+ // Need to pass the special value MtpManager.OBJECT_HANDLE_ROOT_CHILDREN to
+ // getObjectHandles if we would like to obtain children under the root.
+ if (parent.mDocumentType == MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE) {
+ parentHandle = MtpManager.OBJECT_HANDLE_ROOT_CHILDREN;
+ }
+ return new LoaderTask(database, operationsSupported, parent, manager.getObjectHandles(
+ parent.mDeviceId, parent.mStorageId, parentHandle));
+ }
}
}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java b/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
index 5e3417a..8058183 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
@@ -89,7 +89,8 @@
* @return If roots are added or removed from the database.
* @throws FileNotFoundException
*/
- synchronized boolean putStorageDocuments(String parentDocumentId, MtpRoot[] roots)
+ synchronized boolean putStorageDocuments(
+ String parentDocumentId, int[] operationsSupported, MtpRoot[] roots)
throws FileNotFoundException {
final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
database.beginTransaction();
@@ -100,7 +101,11 @@
valuesList[i] = new ContentValues();
extraValuesList[i] = new ContentValues();
MtpDatabase.getStorageDocumentValues(
- valuesList[i], extraValuesList[i], parentDocumentId, roots[i]);
+ valuesList[i],
+ extraValuesList[i],
+ parentDocumentId,
+ operationsSupported,
+ roots[i]);
}
final boolean changed = putDocuments(
parentDocumentId,
@@ -125,12 +130,14 @@
* @param documents List of document information.
* @throws FileNotFoundException
*/
- synchronized void putChildDocuments(int deviceId, String parentId, MtpObjectInfo[] documents)
+ synchronized void putChildDocuments(
+ int deviceId, String parentId, int[] operationsSupported, MtpObjectInfo[] documents)
throws FileNotFoundException {
final ContentValues[] valuesList = new ContentValues[documents.length];
for (int i = 0; i < documents.length; i++) {
valuesList[i] = new ContentValues();
- MtpDatabase.getObjectDocumentValues(valuesList[i], deviceId, parentId, documents[i]);
+ MtpDatabase.getObjectDocumentValues(
+ valuesList[i], deviceId, parentId, operationsSupported, documents[i]);
}
putDocuments(
parentId,
@@ -162,9 +169,8 @@
/**
* Starts adding new documents.
- * The methods decides mapping mode depends on if all documents under the given parent have MTP
- * identifier or not. If all the documents have MTP identifier, it uses the identifier to find
- * a corresponding existing row. Otherwise it does heuristic.
+ * It changes the direct child documents of the given document from VALID to INVALIDATED.
+ * Note that it keeps DISCONNECTED documents as they are.
*
* @param parentDocumentId Parent document ID or NULL for root documents.
* @throws FileNotFoundException
@@ -286,12 +292,16 @@
}
/**
- * Maps 'pending' document and 'invalidated' document that shares the same column of groupKey.
- * If the database does not find corresponding 'invalidated' document, it just removes
- * 'invalidated' document from the database.
+ * Stops adding documents.
+ * It handles 'invalidated' and 'disconnected' documents which we don't put corresponding
+ * documents so far.
+ * If the type adding document is 'device' or 'storage', the document may appear again
+ * afterward. The method marks such documents as 'disconnected'. If the type of adding document
+ * is 'object', it seems the documents are really removed from the remote MTP device. So the
+ * method deletes the metadata from the database.
*
* @param parentId Parent document ID or null for root documents.
- * @return Whether the methods adds or removed visible rows.
+ * @return Whether the methods changes file metadata in database.
* @throws FileNotFoundException
*/
boolean stopAddingDocuments(@Nullable String parentId) throws FileNotFoundException {
@@ -313,7 +323,9 @@
mInMappingIds.remove(parentId);
boolean changed = false;
- // Delete/disconnect all invalidated rows that cannot be mapped.
+ // Delete/disconnect all invalidated/disconnected rows that cannot be mapped.
+ // If parentIdentifier is null, added documents are devices.
+ // if parentIdentifier is DOCUMENT_TYPE_DEVICE, added documents are storages.
final boolean keepUnmatchedDocument =
parentIdentifier == null ||
parentIdentifier.mDocumentType == DOCUMENT_TYPE_DEVICE;
@@ -325,8 +337,9 @@
}
} else {
if (mDatabase.deleteDocumentsAndRootsRecursively(
- COLUMN_ROW_STATE + " = ? AND " + selection,
- DatabaseUtils.appendSelectionArgs(strings(ROW_STATE_INVALIDATED), args))) {
+ COLUMN_ROW_STATE + " IN (?, ?) AND " + selection,
+ DatabaseUtils.appendSelectionArgs(
+ strings(ROW_STATE_INVALIDATED, ROW_STATE_DISCONNECTED), args))) {
changed = true;
}
}
@@ -404,12 +417,7 @@
return null;
}
try {
- final Identifier identifier = mDatabase.createIdentifier(parentId);
- if (mDatabase.getRowState(parentId) == ROW_STATE_DISCONNECTED) {
- throw new FileNotFoundException(
- "document: " + parentId + " is in disconnected device.");
- }
- return identifier;
+ return mDatabase.createIdentifier(parentId);
} catch (FileNotFoundException error) {
mInMappingIds.remove(parentId);
throw error;
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
index 441b9a7..203d6dc 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
@@ -40,6 +40,7 @@
import com.android.internal.util.Preconditions;
import java.io.FileNotFoundException;
+import java.io.IOException;
import java.util.Objects;
/**
@@ -371,9 +372,10 @@
* @param info
* @return Document ID of added document.
*/
- String putNewDocument(int deviceId, String parentDocumentId, MtpObjectInfo info) {
+ String putNewDocument(
+ int deviceId, String parentDocumentId, int[] operationsSupported, MtpObjectInfo info) {
final ContentValues values = new ContentValues();
- getObjectDocumentValues(values, deviceId, parentDocumentId, info);
+ getObjectDocumentValues(values, deviceId, parentDocumentId, operationsSupported, info);
mDatabase.beginTransaction();
try {
final long id = mDatabase.insert(TABLE_DOCUMENTS, null, values);
@@ -406,15 +408,15 @@
COLUMN_STORAGE_ID,
COLUMN_OBJECT_HANDLE,
COLUMN_DOCUMENT_TYPE),
- SELECTION_DOCUMENT_ID,
- strings(documentId),
+ SELECTION_DOCUMENT_ID + " AND " + COLUMN_ROW_STATE + " IN (?, ?)",
+ strings(documentId, ROW_STATE_VALID, ROW_STATE_INVALIDATED),
null,
null,
null,
"1");
try {
if (cursor.getCount() == 0) {
- throw new FileNotFoundException("ID is not found.");
+ throw new FileNotFoundException("ID \"" + documentId + "\" is not found.");
} else {
cursor.moveToNext();
return new Identifier(
@@ -581,6 +583,66 @@
}
}
+ void updateObject(String documentId, int deviceId, String parentId, int[] operationsSupported,
+ MtpObjectInfo info) {
+ final ContentValues values = new ContentValues();
+ getObjectDocumentValues(values, deviceId, parentId, operationsSupported, info);
+
+ mDatabase.beginTransaction();
+ try {
+ mDatabase.update(
+ TABLE_DOCUMENTS,
+ values,
+ Document.COLUMN_DOCUMENT_ID + " = ?",
+ strings(documentId));
+ mDatabase.setTransactionSuccessful();
+ } finally {
+ mDatabase.endTransaction();
+ }
+ }
+
+ /**
+ * Obtains a document that has already mapped but has unmapped children.
+ * @param deviceId Device to find documents.
+ * @return Identifier of found document or null.
+ */
+ public @Nullable Identifier getUnmappedDocumentsParent(int deviceId) {
+ final String fromClosure =
+ TABLE_DOCUMENTS + " AS child INNER JOIN " +
+ TABLE_DOCUMENTS + " AS parent ON " +
+ "child." + COLUMN_PARENT_DOCUMENT_ID + " = " +
+ "parent." + Document.COLUMN_DOCUMENT_ID;
+ final String whereClosure =
+ "parent." + COLUMN_DEVICE_ID + " = ? AND " +
+ "parent." + COLUMN_ROW_STATE + " IN (?, ?) AND " +
+ "child." + COLUMN_ROW_STATE + " = ?";
+ try (final Cursor cursor = mDatabase.query(
+ fromClosure,
+ strings("parent." + COLUMN_DEVICE_ID,
+ "parent." + COLUMN_STORAGE_ID,
+ "parent." + COLUMN_OBJECT_HANDLE,
+ "parent." + Document.COLUMN_DOCUMENT_ID,
+ "parent." + COLUMN_DOCUMENT_TYPE),
+ whereClosure,
+ strings(deviceId, ROW_STATE_VALID, ROW_STATE_INVALIDATED,
+ ROW_STATE_DISCONNECTED),
+ null,
+ null,
+ null,
+ "1")) {
+ if (cursor.getCount() == 0) {
+ return null;
+ }
+ cursor.moveToNext();
+ return new Identifier(
+ cursor.getInt(0),
+ cursor.getInt(1),
+ cursor.getInt(2),
+ cursor.getString(3),
+ cursor.getInt(4));
+ }
+ }
+
private static class OpenHelper extends SQLiteOpenHelper {
public OpenHelper(Context context, int flags) {
super(context,
@@ -629,9 +691,7 @@
values.putNull(Document.COLUMN_SIZE);
extraValues.clear();
- extraValues.put(
- Root.COLUMN_FLAGS,
- Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE);
+ extraValues.put(Root.COLUMN_FLAGS, getRootFlags(device.operationsSupported));
extraValues.putNull(Root.COLUMN_AVAILABLE_BYTES);
extraValues.putNull(Root.COLUMN_CAPACITY_BYTES);
extraValues.put(Root.COLUMN_MIME_TYPES, "");
@@ -640,12 +700,16 @@
/**
* Gets {@link ContentValues} for the given root.
* @param values {@link ContentValues} that receives values.
+ * @param extraValues {@link ContentValues} that receives extra values for roots.
+ * @param parentDocumentId Parent document ID.
+ * @param supportedOperations Array of Operation code supported by the device.
* @param root Root to be converted {@link ContentValues}.
*/
static void getStorageDocumentValues(
ContentValues values,
ContentValues extraValues,
String parentDocumentId,
+ int[] operationsSupported,
MtpRoot root) {
values.clear();
values.put(COLUMN_DEVICE_ID, root.mDeviceId);
@@ -662,9 +726,7 @@
values.put(Document.COLUMN_FLAGS, 0);
values.put(Document.COLUMN_SIZE, root.mMaxCapacity - root.mFreeSpace);
- extraValues.put(
- Root.COLUMN_FLAGS,
- Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE);
+ extraValues.put(Root.COLUMN_FLAGS, getRootFlags(operationsSupported));
extraValues.put(Root.COLUMN_AVAILABLE_BYTES, root.mFreeSpace);
extraValues.put(Root.COLUMN_CAPACITY_BYTES, root.mMaxCapacity);
extraValues.put(Root.COLUMN_MIME_TYPES, "");
@@ -678,20 +740,10 @@
* @param info MTP object info.
*/
static void getObjectDocumentValues(
- ContentValues values, int deviceId, String parentId, MtpObjectInfo info) {
+ ContentValues values, int deviceId, String parentId, int[] operationsSupported,
+ MtpObjectInfo info) {
values.clear();
final String mimeType = getMimeType(info);
- int flag = 0;
- if (info.getProtectionStatus() == 0) {
- flag |= Document.FLAG_SUPPORTS_DELETE |
- Document.FLAG_SUPPORTS_WRITE;
- if (mimeType == Document.MIME_TYPE_DIR) {
- flag |= Document.FLAG_DIR_SUPPORTS_CREATE;
- }
- }
- if (info.getThumbCompressedSize() > 0) {
- flag |= Document.FLAG_SUPPORTS_THUMBNAIL;
- }
values.put(COLUMN_DEVICE_ID, deviceId);
values.put(COLUMN_STORAGE_ID, info.getStorageId());
values.put(COLUMN_OBJECT_HANDLE, info.getObjectHandle());
@@ -705,8 +757,10 @@
Document.COLUMN_LAST_MODIFIED,
info.getDateModified() != 0 ? info.getDateModified() : null);
values.putNull(Document.COLUMN_ICON);
- values.put(Document.COLUMN_FLAGS, flag);
- values.put(Document.COLUMN_SIZE, info.getCompressedSize());
+ values.put(Document.COLUMN_FLAGS, getDocumentFlags(
+ operationsSupported, mimeType, info.getThumbCompressedSizeLong(),
+ info.getProtectionStatus()));
+ values.put(Document.COLUMN_SIZE, info.getCompressedSizeLong());
}
private static String getMimeType(MtpObjectInfo info) {
@@ -725,6 +779,38 @@
return "application/octet-stream";
}
+ private static int getRootFlags(int[] operationsSupported) {
+ int rootFlag = Root.FLAG_SUPPORTS_IS_CHILD;
+ if (MtpDeviceRecord.isWritingSupported(operationsSupported)) {
+ rootFlag |= Root.FLAG_SUPPORTS_CREATE;
+ }
+ return rootFlag;
+ }
+
+ private static int getDocumentFlags(
+ int[] operationsSupported, String mimeType, long thumbnailSize, int protectionState) {
+ int flag = 0;
+ if (MtpDeviceRecord.isWritingSupported(operationsSupported) &&
+ protectionState == MtpConstants.PROTECTION_STATUS_NONE) {
+ flag |= Document.FLAG_SUPPORTS_WRITE;
+ }
+ if (MtpDeviceRecord.isSupported(
+ operationsSupported, MtpConstants.OPERATION_DELETE_OBJECT) &&
+ (protectionState == MtpConstants.PROTECTION_STATUS_NONE ||
+ protectionState == MtpConstants.PROTECTION_STATUS_NON_TRANSFERABLE_DATA)) {
+ flag |= Document.FLAG_SUPPORTS_DELETE;
+ }
+ if (mimeType.equals(Document.MIME_TYPE_DIR) &&
+ MtpDeviceRecord.isWritingSupported(operationsSupported) &&
+ protectionState == MtpConstants.PROTECTION_STATUS_NONE) {
+ flag |= Document.FLAG_DIR_SUPPORTS_CREATE;
+ }
+ if (thumbnailSize > 0) {
+ flag |= Document.FLAG_SUPPORTS_THUMBNAIL;
+ }
+ return flag;
+ }
+
static String[] strings(Object... args) {
final String[] results = new String[args.length];
for (int i = 0; i < args.length; i++) {
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDeviceRecord.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDeviceRecord.java
index 71716bd..393c4de 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDeviceRecord.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDeviceRecord.java
@@ -17,6 +17,7 @@
package com.android.mtp;
import android.annotation.Nullable;
+import android.mtp.MtpConstants;
class MtpDeviceRecord {
public final int deviceId;
@@ -38,4 +39,29 @@
this.operationsSupported = operationsSupported;
this.eventsSupported = eventsSupported;
}
+
+ /**
+ * Helper method to check operations/events are supported by the device or not.
+ */
+ static boolean isSupported(@Nullable int[] supportedList, int code) {
+ if (supportedList == null) {
+ return false;
+ }
+ for (int i = 0; i < supportedList.length; i++) {
+ if (supportedList[i] == code) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static boolean isPartialReadSupported(@Nullable int[] supportedList, long fileSize) {
+ return fileSize <= 0xffffffffl &&
+ isSupported(supportedList, MtpConstants.OPERATION_GET_PARTIAL_OBJECT);
+ }
+
+ static boolean isWritingSupported(@Nullable int[] supportedList) {
+ return isSupported(supportedList, MtpConstants.OPERATION_SEND_OBJECT_INFO) &&
+ isSupported(supportedList, MtpConstants.OPERATION_SEND_OBJECT);
+ }
}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index db1671d..c031f34 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
@@ -201,6 +201,7 @@
final Identifier identifier = mDatabase.createIdentifier(documentId);
try {
openDevice(identifier.mDeviceId);
+ final MtpDeviceRecord device = getDeviceToolkit(identifier.mDeviceId).mDeviceRecord;
switch (mode) {
case "r":
final long fileSize = getFileSize(documentId);
@@ -208,7 +209,8 @@
// 4GB. Fallback to non-seekable file descriptor.
// TODO: Use getPartialObject64 for MTP devices that support Android vendor
// extension.
- if (fileSize <= 0xffffffffl) {
+ if (MtpDeviceRecord.isPartialReadSupported(
+ device.operationsSupported, fileSize)) {
return mAppFuse.openFile(Integer.parseInt(documentId));
} else {
return getPipeManager(identifier).readDocument(mMtpManager, identifier);
@@ -216,8 +218,13 @@
case "w":
// TODO: Clear the parent document loader task (if exists) and call notify
// when writing is completed.
- return getPipeManager(identifier).writeDocument(
- getContext(), mMtpManager, identifier);
+ if (MtpDeviceRecord.isWritingSupported(device.operationsSupported)) {
+ return getPipeManager(identifier).writeDocument(
+ getContext(), mMtpManager, identifier, device.operationsSupported);
+ } else {
+ throw new UnsupportedOperationException(
+ "The device does not support writing operation.");
+ }
case "rw":
// TODO: Add support for "rw" mode.
throw new UnsupportedOperationException(
@@ -290,6 +297,10 @@
try {
final Identifier parentId = mDatabase.createIdentifier(parentDocumentId);
openDevice(parentId.mDeviceId);
+ final MtpDeviceRecord record = getDeviceToolkit(parentId.mDeviceId).mDeviceRecord;
+ if (!MtpDeviceRecord.isWritingSupported(record.operationsSupported)) {
+ throw new UnsupportedOperationException();
+ }
final ParcelFileDescriptor pipe[] = ParcelFileDescriptor.createReliablePipe();
pipe[0].close(); // 0 bytes for a new document.
final int formatCode = Document.MIME_TYPE_DIR.equals(mimeType) ?
@@ -305,7 +316,8 @@
final MtpObjectInfo infoWithHandle =
new MtpObjectInfo.Builder(info).setObjectHandle(objectHandle).build();
final String documentId = mDatabase.putNewDocument(
- parentId.mDeviceId, parentDocumentId, infoWithHandle);
+ parentId.mDeviceId, parentDocumentId, record.operationsSupported,
+ infoWithHandle);
getDocumentLoader(parentId).clearTask(parentId);
notifyChildDocumentsChange(parentDocumentId);
return documentId;
@@ -323,15 +335,19 @@
if (DEBUG) {
Log.d(TAG, "Open device " + deviceId);
}
- mMtpManager.openDevice(deviceId);
- mDeviceToolkits.put(
- deviceId, new DeviceToolkit(mMtpManager, mResolver, mDatabase));
+ final MtpDeviceRecord device = mMtpManager.openDevice(deviceId);
+ final DeviceToolkit toolkit =
+ new DeviceToolkit(mMtpManager, mResolver, mDatabase, device);
+ mDeviceToolkits.put(deviceId, toolkit);
mIntentSender.sendUpdateNotificationIntent();
try {
mRootScanner.resume().await();
} catch (InterruptedException error) {
Log.e(TAG, "openDevice", error);
}
+ // Resume document loader to remap disconnected document ID. Must be invoked after the
+ // root scanner resumes.
+ toolkit.mDocumentLoader.resume();
}
}
@@ -343,20 +359,15 @@
mIntentSender.sendUpdateNotificationIntent();
}
- int[] getOpenedDeviceIds() {
+ MtpDeviceRecord[] getOpenedDeviceRecordsCache() {
synchronized (mDeviceListLock) {
- return mMtpManager.getOpenedDeviceIds();
- }
- }
-
- String getDeviceName(int deviceId) throws IOException {
- synchronized (mDeviceListLock) {
- for (final MtpDeviceRecord device : mMtpManager.getDevices()) {
- if (device.deviceId == deviceId) {
- return device.name;
- }
+ final MtpDeviceRecord[] records = new MtpDeviceRecord[mDeviceToolkits.size()];
+ int i = 0;
+ for (final DeviceToolkit toolkit : mDeviceToolkits.values()) {
+ records[i] = toolkit.mDeviceRecord;
+ i++;
}
- throw new IOException("Not found the device: " + Integer.toString(deviceId));
+ return records;
}
}
@@ -387,9 +398,13 @@
public void shutdown() {
synchronized (mDeviceListLock) {
try {
- for (final int id : mMtpManager.getOpenedDeviceIds()) {
+ // Copy the opened key set because it will be modified when closing devices.
+ final Integer[] keySet =
+ mDeviceToolkits.keySet().toArray(new Integer[mDeviceToolkits.size()]);
+ for (final int id : keySet) {
closeDeviceInternal(id);
}
+ mRootScanner.pause();
} catch (InterruptedException|IOException e) {
// It should fail unit tests by throwing runtime exception.
throw new RuntimeException(e);
@@ -425,10 +440,10 @@
if (DEBUG) {
Log.d(TAG, "Close device " + deviceId);
}
- getDeviceToolkit(deviceId).mDocumentLoader.clearTasks();
+ getDeviceToolkit(deviceId).mDocumentLoader.close();
mDeviceToolkits.remove(deviceId);
mMtpManager.closeDevice(deviceId);
- if (getOpenedDeviceIds().length == 0) {
+ if (mDeviceToolkits.size() == 0) {
mRootScanner.pause();
}
}
@@ -484,10 +499,15 @@
private static class DeviceToolkit {
public final PipeManager mPipeManager;
public final DocumentLoader mDocumentLoader;
+ public final MtpDeviceRecord mDeviceRecord;
- public DeviceToolkit(MtpManager manager, ContentResolver resolver, MtpDatabase database) {
- mPipeManager = new PipeManager();
- mDocumentLoader = new DocumentLoader(manager, resolver, database);
+ public DeviceToolkit(MtpManager manager,
+ ContentResolver resolver,
+ MtpDatabase database,
+ MtpDeviceRecord record) {
+ mPipeManager = new PipeManager(database);
+ mDocumentLoader = new DocumentLoader(record, manager, resolver, database);
+ mDeviceRecord = record;
}
}
@@ -496,8 +516,13 @@
public long readObjectBytes(
int inode, long offset, long size, byte[] buffer) throws IOException {
final Identifier identifier = mDatabase.createIdentifier(Integer.toString(inode));
- return mMtpManager.getPartialObject(
- identifier.mDeviceId, identifier.mObjectHandle, offset, size, buffer);
+ final MtpDeviceRecord record = getDeviceToolkit(identifier.mDeviceId).mDeviceRecord;
+ if (MtpDeviceRecord.isPartialReadSupported(record.operationsSupported, offset)) {
+ return mMtpManager.getPartialObject(
+ identifier.mDeviceId, identifier.mObjectHandle, offset, size, buffer);
+ } else {
+ throw new UnsupportedOperationException();
+ }
}
@Override
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsService.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsService.java
index 9c4952b..9b42b78 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsService.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsService.java
@@ -67,38 +67,25 @@
*/
private boolean updateForegroundState() {
final MtpDocumentsProvider provider = MtpDocumentsProvider.getInstance();
- final int[] deviceIds = provider.getOpenedDeviceIds();
int notificationId = 0;
Notification notification = null;
// TODO: Hide notification if the device has already been removed.
- for (final int deviceId : deviceIds) {
- try {
- final String title = getResources().getString(
- R.string.accessing_notification_title,
- provider.getDeviceName(deviceIds[0]));
- final String description = getResources().getString(
- R.string.accessing_notification_description);
- notificationId = deviceId;
- notification = new Notification.Builder(this)
- .setLocalOnly(true)
- .setContentTitle(title)
- .setContentText(description)
- .setSmallIcon(com.android.internal.R.drawable.stat_sys_data_usb)
- .setCategory(Notification.CATEGORY_SYSTEM)
- .setPriority(Notification.PRIORITY_LOW)
- .build();
- mNotificationManager.notify(deviceId, notification);
- } catch (IOException exp) {
- logErrorMessage(exp);
- // If we failed to obtain device name, it looks the device is unusable.
- // Because this is the last device we opened, we should hide the notification
- // for the case.
- try {
- provider.closeDevice(deviceIds[0]);
- } catch (IOException | InterruptedException closeError) {
- logErrorMessage(closeError);
- }
- }
+ for (final MtpDeviceRecord record : provider.getOpenedDeviceRecordsCache()) {
+ final String title = getResources().getString(
+ R.string.accessing_notification_title,
+ record.name);
+ final String description = getResources().getString(
+ R.string.accessing_notification_description);
+ notificationId = record.deviceId;
+ notification = new Notification.Builder(this)
+ .setLocalOnly(true)
+ .setContentTitle(title)
+ .setContentText(description)
+ .setSmallIcon(com.android.internal.R.drawable.stat_sys_data_usb)
+ .setCategory(Notification.CATEGORY_SYSTEM)
+ .setPriority(Notification.PRIORITY_LOW)
+ .build();
+ mNotificationManager.notify(record.deviceId, notification);
}
if (notification != null) {
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
index 37dc761..1966e61 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
@@ -65,16 +65,14 @@
*/
private static final int PROTOCOL_MTP = 0;
-
private final UsbManager mManager;
- // TODO: Save and restore the set of opened device.
private final SparseArray<MtpDevice> mDevices = new SparseArray<>();
MtpManager(Context context) {
mManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
}
- synchronized void openDevice(int deviceId) throws IOException {
+ synchronized MtpDeviceRecord openDevice(int deviceId) throws IOException {
UsbDevice rawDevice = null;
for (final UsbDevice candidate : mManager.getDeviceList().values()) {
if (candidate.getDeviceId() == deviceId) {
@@ -113,6 +111,8 @@
}
mDevices.put(deviceId, device);
+
+ return createDeviceRecord(rawDevice);
}
synchronized void closeDevice(int deviceId) throws IOException {
@@ -126,45 +126,11 @@
if (!isMtpDevice(device)) {
continue;
}
- final MtpDevice mtpDevice = mDevices.get(device.getDeviceId());
- final boolean opened = mtpDevice != null;
- final String name = device.getProductName();
- MtpRoot[] roots;
- int[] operationsSupported = null;
- int[] eventsSupported = null;
- if (opened) {
- try {
- roots = getRoots(device.getDeviceId());
- } catch (IOException exp) {
- Log.e(MtpDocumentsProvider.TAG, "Failed to open device", exp);
- // If we failed to fetch roots for the device, we still returns device model
- // with an empty set of roots so that the device is shown DocumentsUI as long as
- // the device is physically connected.
- roots = new MtpRoot[0];
- }
- final MtpDeviceInfo info = mtpDevice.getDeviceInfo();
- if (info != null) {
- operationsSupported = mtpDevice.getDeviceInfo().getOperationsSupported();
- eventsSupported = mtpDevice.getDeviceInfo().getEventsSupported();
- }
- } else {
- roots = new MtpRoot[0];
- }
- devices.add(new MtpDeviceRecord(
- device.getDeviceId(), name, device.getSerialNumber(), opened, roots,
- operationsSupported, eventsSupported));
+ devices.add(createDeviceRecord(device));
}
return devices.toArray(new MtpDeviceRecord[devices.size()]);
}
- synchronized int[] getOpenedDeviceIds() {
- final int[] result = new int[mDevices.size()];
- for (int i = 0; i < result.length; i++) {
- result[i] = mDevices.keyAt(i);
- }
- return result;
- }
-
MtpObjectInfo getObjectInfo(int deviceId, int objectHandle)
throws IOException {
final MtpDevice device = getDevice(deviceId);
@@ -189,7 +155,6 @@
}
}
- @VisibleForTesting
long getPartialObject(int deviceId, int objectHandle, long offset, long size, byte[] buffer)
throws IOException {
final MtpDevice device = getDevice(deviceId);
@@ -281,6 +246,36 @@
}
}
+ private MtpDeviceRecord createDeviceRecord(UsbDevice device) {
+ final MtpDevice mtpDevice = mDevices.get(device.getDeviceId());
+ final boolean opened = mtpDevice != null;
+ final String name = device.getProductName();
+ MtpRoot[] roots;
+ int[] operationsSupported = null;
+ int[] eventsSupported = null;
+ if (opened) {
+ try {
+ roots = getRoots(device.getDeviceId());
+ } catch (IOException exp) {
+ Log.e(MtpDocumentsProvider.TAG, "Failed to open device", exp);
+ // If we failed to fetch roots for the device, we still returns device model
+ // with an empty set of roots so that the device is shown DocumentsUI as long as
+ // the device is physically connected.
+ roots = new MtpRoot[0];
+ }
+ final MtpDeviceInfo info = mtpDevice.getDeviceInfo();
+ if (info != null) {
+ operationsSupported = mtpDevice.getDeviceInfo().getOperationsSupported();
+ eventsSupported = mtpDevice.getDeviceInfo().getEventsSupported();
+ }
+ } else {
+ roots = new MtpRoot[0];
+ }
+ return new MtpDeviceRecord(
+ device.getDeviceId(), name, device.getSerialNumber(), opened, roots,
+ operationsSupported, eventsSupported);
+ }
+
static boolean isMtpDevice(UsbDevice device) {
for (int i = 0; i < device.getInterfaceCount(); i++) {
final UsbInterface usbInterface = device.getInterface(i);
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java
index 16523bc..73042c4 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java
@@ -29,12 +29,14 @@
class PipeManager {
final ExecutorService mExecutor;
+ final MtpDatabase mDatabase;
- PipeManager() {
- this(Executors.newSingleThreadExecutor());
+ PipeManager(MtpDatabase database) {
+ this(database, Executors.newSingleThreadExecutor());
}
- PipeManager(ExecutorService executor) {
+ PipeManager(MtpDatabase database, ExecutorService executor) {
+ this.mDatabase = database;
this.mExecutor = executor;
}
@@ -44,9 +46,11 @@
return task.getReadingFileDescriptor();
}
- ParcelFileDescriptor writeDocument(Context context, MtpManager model, Identifier identifier)
+ ParcelFileDescriptor writeDocument(Context context, MtpManager model, Identifier identifier,
+ int[] operationsSupported)
throws IOException {
- final Task task = new WriteDocumentTask(context, model, identifier);
+ final Task task = new WriteDocumentTask(
+ context, model, identifier, operationsSupported, mDatabase);
mExecutor.execute(task);
return task.getWritingFileDescriptor();
}
@@ -100,11 +104,19 @@
private static class WriteDocumentTask extends Task {
private final Context mContext;
+ private final MtpDatabase mDatabase;
+ private final int[] mOperationsSupported;
- WriteDocumentTask(Context context, MtpManager model, Identifier identifier)
+ WriteDocumentTask(Context context,
+ MtpManager model,
+ Identifier identifier,
+ int[] supportedOperations,
+ MtpDatabase database)
throws IOException {
super(model, identifier);
mContext = context;
+ mDatabase = database;
+ mOperationsSupported = supportedOperations;
}
@Override
@@ -112,7 +124,7 @@
File tempFile = null;
try {
// Obtain a temporary file and copy the data to it.
- tempFile = mContext.getCacheDir().createTempFile("mtp", "tmp");
+ tempFile = File.createTempFile("mtp", "tmp", mContext.getCacheDir());
try (
final FileOutputStream tempOutputStream =
new ParcelFileDescriptor.AutoCloseOutputStream(
@@ -140,12 +152,23 @@
// Create the target object info with a correct file size and upload the file.
final MtpObjectInfo targetObjectInfo =
new MtpObjectInfo.Builder(placeholderObjectInfo)
- .setCompressedSize((int) tempFile.length())
+ .setCompressedSize(tempFile.length())
.build();
final ParcelFileDescriptor tempInputDescriptor = ParcelFileDescriptor.open(
tempFile, ParcelFileDescriptor.MODE_READ_ONLY);
- mManager.createDocument(mIdentifier.mDeviceId,
- targetObjectInfo, tempInputDescriptor);
+ final int newObjectHandle = mManager.createDocument(
+ mIdentifier.mDeviceId, targetObjectInfo, tempInputDescriptor);
+
+ final MtpObjectInfo newObjectInfo = mManager.getObjectInfo(
+ mIdentifier.mDeviceId, newObjectHandle);
+ final Identifier parentIdentifier =
+ mDatabase.getParentIdentifier(mIdentifier.mDocumentId);
+ mDatabase.updateObject(
+ mIdentifier.mDocumentId,
+ mIdentifier.mDeviceId,
+ parentIdentifier.mDocumentId,
+ mOperationsSupported,
+ newObjectInfo);
} catch (IOException error) {
Log.w(MtpDocumentsProvider.TAG,
"Failed to send a file because of: " + error.getMessage());
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java b/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
index a48bf12..2f66c5c 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
@@ -26,7 +26,6 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
final class RootScanner {
@@ -56,7 +55,7 @@
final MtpDatabase mDatabase;
ExecutorService mExecutor;
- FutureTask<Void> mCurrentTask;
+ private UpdateRootsRunnable mCurrentTask;
RootScanner(
ContentResolver resolver,
@@ -84,13 +83,12 @@
mExecutor = Executors.newSingleThreadExecutor();
}
if (mCurrentTask != null) {
- // Cancel previous task.
- mCurrentTask.cancel(true);
+ // Stop previous task.
+ mCurrentTask.stop();
}
- final UpdateRootsRunnable runnable = new UpdateRootsRunnable();
- mCurrentTask = new FutureTask<Void>(runnable, null);
- mExecutor.submit(mCurrentTask);
- return runnable.mFirstScanCompleted;
+ mCurrentTask = new UpdateRootsRunnable();
+ mExecutor.execute(mCurrentTask);
+ return mCurrentTask.mFirstScanCompleted;
}
/**
@@ -112,13 +110,21 @@
* Runnable to scan roots and update the database information.
*/
private final class UpdateRootsRunnable implements Runnable {
+ /**
+ * Count down latch that specifies the runnable is stopped.
+ */
+ final CountDownLatch mStopped = new CountDownLatch(1);
+
+ /**
+ * Count down latch that specifies the first scan is completed.
+ */
final CountDownLatch mFirstScanCompleted = new CountDownLatch(1);
@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
int pollingCount = 0;
- while (true) {
+ while (mStopped.getCount() > 0) {
boolean changed = false;
// Update devices.
@@ -149,7 +155,8 @@
}
try {
mDatabase.getMapper().startAddingDocuments(documentId);
- if (mDatabase.getMapper().putStorageDocuments(documentId, device.roots)) {
+ if (mDatabase.getMapper().putStorageDocuments(
+ documentId, device.eventsSupported, device.roots)) {
changed = true;
}
if (mDatabase.getMapper().stopAddingDocuments(documentId)) {
@@ -170,12 +177,16 @@
// Use SHORT_POLLING_PERIOD for the first SHORT_POLLING_TIMES because it is
// more likely to add new root just after the device is added.
// TODO: Use short interval only for a device that is just added.
- Thread.sleep(pollingCount > SHORT_POLLING_TIMES ?
- LONG_POLLING_INTERVAL : SHORT_POLLING_INTERVAL);
+ mStopped.await(pollingCount > SHORT_POLLING_TIMES ?
+ LONG_POLLING_INTERVAL : SHORT_POLLING_INTERVAL, TimeUnit.MILLISECONDS);
} catch (InterruptedException exp) {
break;
}
}
}
+
+ void stop() {
+ mStopped.countDown();
+ }
}
}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
index 474da07..db25421 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
@@ -44,22 +44,29 @@
mDatabase.getMapper().startAddingDocuments(null);
mDatabase.getMapper().putDeviceDocument(
- new MtpDeviceRecord(1, "Device", null, true, new MtpRoot[0], null, null));
+ new MtpDeviceRecord(0, "Device", null, true, new MtpRoot[0], null, null));
mDatabase.getMapper().stopAddingDocuments(null);
mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+ mDatabase.getMapper().putStorageDocuments("1", new int[0], new MtpRoot[] {
new MtpRoot(0, 0, "Storage", 1000, 1000, "")
});
mDatabase.getMapper().stopAddingDocuments("1");
mManager = new BlockableTestMtpManager(getContext());
mResolver = new TestContentResolver();
- mLoader = new DocumentLoader(mManager, mResolver, mDatabase);
+ mLoader = new DocumentLoader(
+ new MtpDeviceRecord(
+ 0, "Device", "Key", true, new MtpRoot[0],
+ TestUtil.OPERATIONS_SUPPORTED, new int[0]),
+ mManager,
+ mResolver,
+ mDatabase);
}
@Override
- public void tearDown() {
+ public void tearDown() throws Exception {
+ mLoader.close();
mDatabase.close();
}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
index 1df7351..f9e8225 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
@@ -30,10 +30,11 @@
import static android.provider.DocumentsContract.Document.*;
import static com.android.mtp.MtpDatabase.strings;
import static com.android.mtp.MtpDatabaseConstants.*;
+import static com.android.mtp.TestUtil.OPERATIONS_SUPPORTED;
@SmallTest
public class MtpDatabaseTest extends AndroidTestCase {
- private final String[] COLUMN_NAMES = new String[] {
+ private static final String[] COLUMN_NAMES = new String[] {
DocumentsContract.Document.COLUMN_DOCUMENT_ID,
MtpDatabaseConstants.COLUMN_DEVICE_ID,
MtpDatabaseConstants.COLUMN_STORAGE_ID,
@@ -75,13 +76,10 @@
}
public void testPutSingleStorageDocuments() throws Exception {
- mDatabase.getMapper().startAddingDocuments(null);
- mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
- 0, "Device", null /* deviceKey */, true, new MtpRoot[0], null, null));
- mDatabase.getMapper().stopAddingDocuments(null);
+ addTestDevice();
mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+ mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
new MtpRoot(0, 1, "Storage", 1000, 2000, "")
});
mDatabase.getMapper().stopAddingDocuments("1");
@@ -143,7 +141,7 @@
addTestDevice();
mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+ mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
new MtpRoot(0, 1, "Storage", 1000, 2000, ""),
new MtpRoot(0, 2, "Storage", 2000, 4000, ""),
new MtpRoot(0, 3, "/@#%&<>Storage", 3000, 6000,"")
@@ -194,7 +192,7 @@
addTestStorage("1");
mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.getMapper().putChildDocuments(0, "2", new MtpObjectInfo[] {
+ mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
createDocument(101, "image.jpg", MtpConstants.FORMAT_EXIF_JPEG, 2 * 1024 * 1024),
createDocument(102, "music.mp3", MtpConstants.FORMAT_MP3, 3 * 1024 * 1024)
@@ -263,6 +261,58 @@
cursor.close();
}
+ public void testPutChildDocuments_operationsSupported() throws Exception {
+ addTestDevice();
+ addTestStorage("1");
+
+ // Put a document with empty supported operations.
+ mDatabase.getMapper().startAddingDocuments("2");
+ mDatabase.getMapper().putChildDocuments(0, "2", new int[0], new MtpObjectInfo[] {
+ createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024)
+ });
+ mDatabase.getMapper().stopAddingDocuments("2");
+
+ try (final Cursor cursor =
+ mDatabase.queryChildDocuments(strings(Document.COLUMN_FLAGS), "2")) {
+ assertEquals(1, cursor.getCount());
+ cursor.moveToNext();
+ assertEquals(0, cursor.getInt(0));
+ }
+
+ // Put a document with writable operations.
+ mDatabase.getMapper().startAddingDocuments("2");
+ mDatabase.getMapper().putChildDocuments(0, "2", new int[] {
+ MtpConstants.OPERATION_SEND_OBJECT,
+ MtpConstants.OPERATION_SEND_OBJECT_INFO,
+ }, new MtpObjectInfo[] {
+ createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024)
+ });
+ mDatabase.getMapper().stopAddingDocuments("2");
+
+ try (final Cursor cursor =
+ mDatabase.queryChildDocuments(strings(Document.COLUMN_FLAGS), "2")) {
+ assertEquals(1, cursor.getCount());
+ cursor.moveToNext();
+ assertEquals(Document.FLAG_SUPPORTS_WRITE, cursor.getInt(0));
+ }
+
+ // Put a document with deletable operations.
+ mDatabase.getMapper().startAddingDocuments("2");
+ mDatabase.getMapper().putChildDocuments(0, "2", new int[] {
+ MtpConstants.OPERATION_DELETE_OBJECT
+ }, new MtpObjectInfo[] {
+ createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024)
+ });
+ mDatabase.getMapper().stopAddingDocuments("2");
+
+ try (final Cursor cursor =
+ mDatabase.queryChildDocuments(strings(Document.COLUMN_FLAGS), "2")) {
+ assertEquals(1, cursor.getCount());
+ cursor.moveToNext();
+ assertEquals(Document.FLAG_SUPPORTS_DELETE, cursor.getInt(0));
+ }
+ }
+
public void testRestoreIdForRootDocuments() throws Exception {
final String[] columns = new String[] {
DocumentsContract.Document.COLUMN_DOCUMENT_ID,
@@ -273,7 +323,7 @@
// Add device and two storages.
addTestDevice();
mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+ mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
new MtpRoot(0, 100, "Storage A", 1000, 0, ""),
new MtpRoot(0, 101, "Storage B", 1001, 0, "")
});
@@ -304,7 +354,7 @@
// Add two storages, but one's name is different from previous one.
mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+ mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
new MtpRoot(0, 200, "Storage A", 2000, 0, ""),
new MtpRoot(0, 202, "Storage C", 2002, 0, "")
});
@@ -337,7 +387,7 @@
addTestStorage("1");
mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.getMapper().putChildDocuments(0, "2", new MtpObjectInfo[] {
+ mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
createDocument(101, "image.jpg", MtpConstants.FORMAT_EXIF_JPEG, 2 * 1024 * 1024),
createDocument(102, "music.mp3", MtpConstants.FORMAT_MP3, 3 * 1024 * 1024)
@@ -355,7 +405,7 @@
}
mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.getMapper().putChildDocuments(0, "2", new MtpObjectInfo[] {
+ mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
createDocument(203, "video.mp4", MtpConstants.FORMAT_MP4_CONTAINER, 1024),
});
@@ -398,10 +448,10 @@
mDatabase.getMapper().startAddingDocuments("1");
mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+ mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
new MtpRoot(0, 100, "Storage", 0, 0, "")
});
- mDatabase.getMapper().putStorageDocuments("2", new MtpRoot[] {
+ mDatabase.getMapper().putStorageDocuments("2", OPERATIONS_SUPPORTED, new MtpRoot[] {
new MtpRoot(1, 100, "Storage", 0, 0, "")
});
@@ -442,10 +492,10 @@
mDatabase.getMapper().startAddingDocuments("1");
mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+ mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
new MtpRoot(0, 200, "Storage", 2000, 0, "")
});
- mDatabase.getMapper().putStorageDocuments("2", new MtpRoot[] {
+ mDatabase.getMapper().putStorageDocuments("2", OPERATIONS_SUPPORTED, new MtpRoot[] {
new MtpRoot(1, 300, "Storage", 3000, 0, "")
});
mDatabase.getMapper().stopAddingDocuments("1");
@@ -488,7 +538,7 @@
addTestDevice();
addTestStorage("1");
mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.getMapper().putChildDocuments(0, "2", new MtpObjectInfo[] {
+ mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
createDocument(50, "A", MtpConstants.FORMAT_ASSOCIATION, 0),
createDocument(51, "B", MtpConstants.FORMAT_ASSOCIATION, 0),
});
@@ -497,10 +547,10 @@
// Put note.txt in each directory.
mDatabase.getMapper().startAddingDocuments("3");
mDatabase.getMapper().startAddingDocuments("4");
- mDatabase.getMapper().putChildDocuments(0, "3", new MtpObjectInfo[] {
+ mDatabase.getMapper().putChildDocuments(0, "3", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
});
- mDatabase.getMapper().putChildDocuments(0, "4", new MtpObjectInfo[] {
+ mDatabase.getMapper().putChildDocuments(0, "4", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
createDocument(101, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
});
@@ -511,7 +561,7 @@
addTestDevice();
addTestStorage("1");
mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.getMapper().putChildDocuments(0, "2", new MtpObjectInfo[] {
+ mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
createDocument(50, "A", MtpConstants.FORMAT_ASSOCIATION, 0),
createDocument(51, "B", MtpConstants.FORMAT_ASSOCIATION, 0),
});
@@ -520,10 +570,10 @@
// Add note.txt in each directory again.
mDatabase.getMapper().startAddingDocuments("3");
mDatabase.getMapper().startAddingDocuments("4");
- mDatabase.getMapper().putChildDocuments(0, "3", new MtpObjectInfo[] {
+ mDatabase.getMapper().putChildDocuments(0, "3", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
});
- mDatabase.getMapper().putChildDocuments(0, "4", new MtpObjectInfo[] {
+ mDatabase.getMapper().putChildDocuments(0, "4", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
createDocument(201, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
});
mDatabase.getMapper().stopAddingDocuments("3");
@@ -562,7 +612,7 @@
addTestDevice();
mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+ mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
new MtpRoot(0, 100, "Storage", 0, 0, ""),
});
mDatabase.getMapper().clearMapping();
@@ -576,7 +626,7 @@
}
mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+ mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
new MtpRoot(0, 200, "Storage", 2000, 0, ""),
});
mDatabase.getMapper().clearMapping();
@@ -584,7 +634,7 @@
addTestDevice();
mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+ mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
new MtpRoot(0, 300, "Storage", 3000, 0, ""),
});
mDatabase.getMapper().stopAddingDocuments("1");
@@ -625,7 +675,7 @@
// Add a device and two storages that has same name.
addTestDevice();
mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+ mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
new MtpRoot(0, 200, "Storage", 2000, 0, ""),
new MtpRoot(0, 201, "Storage", 2001, 0, ""),
});
@@ -658,13 +708,13 @@
// The client code should be able to replace existing rows with new information.
// Add one.
mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+ mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
new MtpRoot(0, 100, "Storage A", 0, 0, ""),
});
mDatabase.getMapper().stopAddingDocuments("1");
// Replace it.
mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+ mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
new MtpRoot(0, 100, "Storage B", 1000, 1000, ""),
});
mDatabase.getMapper().stopAddingDocuments("1");
@@ -703,7 +753,7 @@
// Add one.
addTestDevice();
mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+ mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
new MtpRoot(0, 100, "Storage A", 0, 0, ""),
});
mDatabase.getMapper().clearMapping();
@@ -717,11 +767,11 @@
// Add one.
mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+ mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
new MtpRoot(0, 101, "Storage B", 1000, 1000, ""),
});
// Add one more before resolving unmapped documents.
- mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+ mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
new MtpRoot(0, 102, "Storage B", 1000, 1000, ""),
});
mDatabase.getMapper().stopAddingDocuments("1");
@@ -763,7 +813,7 @@
}
mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+ mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
new MtpRoot(0, 100, "Storage A", 0, 0, "")
});
mDatabase.getMapper().stopAddingDocuments("1");
@@ -778,7 +828,7 @@
}
mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+ mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
new MtpRoot(0, 100, "Storage A", 0, 0, ""),
new MtpRoot(0, 101, "Storage B", 0, 0, "")
});
@@ -798,18 +848,15 @@
addTestDevice();
mDatabase.getMapper().startAddingDocuments("1");
- mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+ mDatabase.getMapper().putStorageDocuments("1", OPERATIONS_SUPPORTED, new MtpRoot[] {
new MtpRoot(0, 100, "Storage A", 0, 0, ""),
});
mDatabase.getMapper().stopAddingDocuments("1");
mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.getMapper().putChildDocuments(
- 0,
- "2",
- new MtpObjectInfo[] {
- createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
- });
+ mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
+ createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
+ });
mDatabase.getMapper().stopAddingDocuments("2");
assertEquals("2", mDatabase.getParentIdentifier("3").mDocumentId);
@@ -820,21 +867,15 @@
addTestStorage("1");
mDatabase.getMapper().startAddingDocuments("2");
- mDatabase.getMapper().putChildDocuments(
- 0,
- "2",
- new MtpObjectInfo[] {
- createDocument(200, "dir", MtpConstants.FORMAT_ASSOCIATION, 1024),
- });
+ mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
+ createDocument(200, "dir", MtpConstants.FORMAT_ASSOCIATION, 1024),
+ });
mDatabase.getMapper().stopAddingDocuments("2");
mDatabase.getMapper().startAddingDocuments("3");
- mDatabase.getMapper().putChildDocuments(
- 0,
- "3",
- new MtpObjectInfo[] {
- createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
- });
+ mDatabase.getMapper().putChildDocuments(0, "3", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
+ createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
+ });
mDatabase.getMapper().stopAddingDocuments("3");
mDatabase.deleteDocument("3");
@@ -863,7 +904,8 @@
assertEquals(
"3",
mDatabase.putNewDocument(
- 0, "2", createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024)));
+ 0, "2", OPERATIONS_SUPPORTED,
+ createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024)));
{
final Cursor cursor =
@@ -881,8 +923,7 @@
mDatabase.getMapper().startAddingDocuments("2");
mDatabase.putNewDocument(
- 0,
- "2",
+ 0, "2", OPERATIONS_SUPPORTED,
createDocument(201, "note.txt", MtpConstants.FORMAT_TEXT, 1024));
mDatabase.getMapper().stopAddingDocuments("2");
@@ -983,18 +1024,10 @@
}
private void addTestDevice() throws FileNotFoundException {
- mDatabase.getMapper().startAddingDocuments(null);
- mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
- 0, "Device", "device_key", /* opened is */ true, new MtpRoot[0], null,
- null));
- mDatabase.getMapper().stopAddingDocuments(null);
+ TestUtil.addTestDevice(mDatabase);
}
private void addTestStorage(String parentId) throws FileNotFoundException {
- mDatabase.getMapper().startAddingDocuments(parentId);
- mDatabase.getMapper().putStorageDocuments(parentId, new MtpRoot[] {
- new MtpRoot(0, 100, "Storage", 1024, 1024, ""),
- });
- mDatabase.getMapper().stopAddingDocuments(parentId);
+ TestUtil.addTestStorage(mDatabase, parentId);
}
}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
index 5eda9b2..3dfa4ad 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
@@ -22,6 +22,7 @@
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.os.storage.StorageManager;
+import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Root;
import android.system.Os;
import android.system.OsConstants;
@@ -37,6 +38,7 @@
import java.util.concurrent.TimeoutException;
import static com.android.mtp.MtpDatabase.strings;
+import static com.android.mtp.TestUtil.OPERATIONS_SUPPORTED;
@MediumTest
public class MtpDocumentsProviderTest extends AndroidTestCase {
@@ -76,7 +78,7 @@
2048 /* total space */,
"" /* no volume identifier */)
},
- null,
+ OPERATIONS_SUPPORTED,
null));
mProvider.resumeRootScanner();
@@ -97,7 +99,7 @@
} catch (Throwable error) {
assertTrue(error instanceof IOException);
}
- assertEquals(0, mProvider.getOpenedDeviceIds().length);
+ assertEquals(0, mProvider.getOpenedDeviceRecordsCache().length);
// Check if the following notification is the first one or not.
mMtpManager.addValidDevice(new MtpDeviceRecord(
@@ -114,7 +116,7 @@
2048 /* total space */,
"" /* no volume identifier */)
},
- null,
+ OPERATIONS_SUPPORTED,
null));
mProvider.resumeRootScanner();
mResolver.waitForNotification(ROOTS_URI, 1);
@@ -138,7 +140,7 @@
2048 /* total space */,
"" /* no volume identifier */)
},
- null,
+ OPERATIONS_SUPPORTED,
null));
mMtpManager.setObjectHandles(0, 1, -1, new int[0]);
mProvider.resumeRootScanner();
@@ -154,16 +156,16 @@
assertEquals(1, cursor.getLong(1));
}
{
- final int [] openedDevice = mProvider.getOpenedDeviceIds();
+ final MtpDeviceRecord[] openedDevice = mProvider.getOpenedDeviceRecordsCache();
assertEquals(0, openedDevice.length);
}
// Device is opened automatically when querying its children.
try (final Cursor cursor = mProvider.queryChildDocuments("1", null, null)) {}
{
- final int [] openedDevice = mProvider.getOpenedDeviceIds();
+ final MtpDeviceRecord[] openedDevice = mProvider.getOpenedDeviceRecordsCache();
assertEquals(1, openedDevice.length);
- assertEquals(0, openedDevice[0]);
+ assertEquals(0, openedDevice[0].deviceId);
}
}
@@ -183,7 +185,7 @@
2048 /* total space */,
"" /* no volume identifier */)
},
- null,
+ OPERATIONS_SUPPORTED,
null));
mMtpManager.addValidDevice(new MtpDeviceRecord(
1,
@@ -199,7 +201,7 @@
4096 /* total space */,
"Identifier B" /* no volume identifier */)
},
- null,
+ new int[0] /* No operations supported */,
null));
{
@@ -224,7 +226,7 @@
cursor.moveToNext();
cursor.moveToNext();
assertEquals("2", cursor.getString(0));
- assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
+ assertEquals(Root.FLAG_SUPPORTS_IS_CHILD, cursor.getInt(1));
assertEquals(R.drawable.ic_root_mtp, cursor.getInt(2));
assertEquals("Device B Storage B", cursor.getString(3));
assertEquals("2", cursor.getString(4));
@@ -240,7 +242,7 @@
"Device key A",
false /* unopened */,
new MtpRoot[0],
- null,
+ OPERATIONS_SUPPORTED,
null));
mMtpManager.addValidDevice(new MtpDeviceRecord(
1,
@@ -256,7 +258,7 @@
4096 /* total space */,
"Identifier B" /* no volume identifier */)
},
- null,
+ OPERATIONS_SUPPORTED,
null));
{
mProvider.openDevice(0);
@@ -410,7 +412,7 @@
assertEquals("image/jpeg", cursor.getString(1));
assertEquals("image.jpg", cursor.getString(2));
assertEquals(0, cursor.getLong(3));
- assertEquals(DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL, cursor.getInt(4));
+ assertEquals(Document.FLAG_SUPPORTS_THUMBNAIL, cursor.getInt(4));
assertEquals(1024 * 1024 * 5, cursor.getInt(5));
cursor.close();
@@ -543,14 +545,14 @@
public void testBusyDevice() throws Exception {
mMtpManager = new TestMtpManager(getContext()) {
@Override
- void openDevice(int deviceId) throws IOException {
+ MtpDeviceRecord openDevice(int deviceId) throws IOException {
throw new BusyDeviceException();
}
};
setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
mMtpManager.addValidDevice(new MtpDeviceRecord(
- 0, "Device A", null /* deviceKey */, false /* unopened */, new MtpRoot[0], null,
- null));
+ 0, "Device A", null /* deviceKey */, false /* unopened */, new MtpRoot[0],
+ OPERATIONS_SUPPORTED, null));
mProvider.resumeRootScanner();
mResolver.waitForNotification(ROOTS_URI, 1);
@@ -570,7 +572,8 @@
public void testLockedDevice() throws Exception {
setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
mMtpManager.addValidDevice(new MtpDeviceRecord(
- 0, "Device A", null, false /* unopened */, new MtpRoot[0], null, null));
+ 0, "Device A", null, false /* unopened */, new MtpRoot[0], OPERATIONS_SUPPORTED,
+ null));
mProvider.resumeRootScanner();
mResolver.waitForNotification(ROOTS_URI, 1);
@@ -587,6 +590,133 @@
}
}
+ public void testMappingDisconnectedDocuments() throws Exception {
+ setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
+ mMtpManager.addValidDevice(new MtpDeviceRecord(
+ 0,
+ "Device A",
+ "device key",
+ true /* unopened */,
+ new MtpRoot[] {
+ new MtpRoot(
+ 0 /* deviceId */,
+ 1 /* storageId */,
+ "Storage A" /* volume description */,
+ 1024 /* free space */,
+ 2048 /* total space */,
+ "" /* no volume identifier */)
+ },
+ null,
+ null));
+
+ final String[] names = strings("Directory A", "Directory B", "Directory C");
+ final int objectHandleOffset = 100;
+ for (int i = 0; i < names.length; i++) {
+ final int parentHandle = i == 0 ?
+ MtpManager.OBJECT_HANDLE_ROOT_CHILDREN : objectHandleOffset + i - 1;
+ final int objectHandle = i + objectHandleOffset;
+ mMtpManager.setObjectHandles(0, 1, parentHandle, new int[] { objectHandle });
+ mMtpManager.setObjectInfo(
+ 0,
+ new MtpObjectInfo.Builder()
+ .setName(names[i])
+ .setObjectHandle(objectHandle)
+ .setFormat(MtpConstants.FORMAT_ASSOCIATION)
+ .setStorageId(1)
+ .build());
+ }
+
+ mProvider.resumeRootScanner();
+ mResolver.waitForNotification(ROOTS_URI, 1);
+
+ final int documentIdOffset = 2;
+ for (int i = 0; i < names.length; i++) {
+ try (final Cursor cursor = mProvider.queryChildDocuments(
+ String.valueOf(documentIdOffset + i),
+ strings(Document.COLUMN_DOCUMENT_ID, Document.COLUMN_DISPLAY_NAME),
+ null)) {
+ assertEquals(1, cursor.getCount());
+ cursor.moveToNext();
+ assertEquals(String.valueOf(documentIdOffset + i + 1), cursor.getString(0));
+ assertEquals(names[i], cursor.getString(1));
+ }
+ }
+
+ mProvider.closeDevice(0);
+ mResolver.waitForNotification(ROOTS_URI, 2);
+
+ mProvider.openDevice(0);
+ mResolver.waitForNotification(ROOTS_URI, 3);
+
+ for (int i = 0; i < names.length; i++) {
+ mResolver.waitForNotification(DocumentsContract.buildChildDocumentsUri(
+ MtpDocumentsProvider.AUTHORITY,
+ String.valueOf(documentIdOffset + i)), 1);
+ try (final Cursor cursor = mProvider.queryChildDocuments(
+ String.valueOf(documentIdOffset + i),
+ strings(Document.COLUMN_DOCUMENT_ID),
+ null)) {
+ assertEquals(1, cursor.getCount());
+ cursor.moveToNext();
+ assertEquals(String.valueOf(documentIdOffset + i + 1), cursor.getString(0));
+ }
+ }
+ }
+
+ public void testCreateDocument_noWritingSupport() throws Exception {
+ setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
+ mMtpManager.addValidDevice(new MtpDeviceRecord(
+ 0, "Device A", null /* deviceKey */, false /* unopened */,
+ new MtpRoot[] {
+ new MtpRoot(
+ 0 /* deviceId */,
+ 1 /* storageId */,
+ "Storage A" /* volume description */,
+ 1024 /* free space */,
+ 2048 /* total space */,
+ "" /* no volume identifier */)
+ },
+ new int[0] /* no operations supported */, null));
+ mProvider.resumeRootScanner();
+ mResolver.waitForNotification(ROOTS_URI, 1);
+ try {
+ mProvider.createDocument("1", "text/palin", "note.txt");
+ fail();
+ } catch (UnsupportedOperationException exception) {}
+ }
+
+ public void testOpenDocument_noWritingSupport() throws Exception {
+ setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
+ mMtpManager.addValidDevice(new MtpDeviceRecord(
+ 0, "Device A", null /* deviceKey */, false /* unopened */,
+ new MtpRoot[] {
+ new MtpRoot(
+ 0 /* deviceId */,
+ 1 /* storageId */,
+ "Storage A" /* volume description */,
+ 1024 /* free space */,
+ 2048 /* total space */,
+ "" /* no volume identifier */)
+ },
+ new int[0] /* no operations supported */, null));
+ mMtpManager.setObjectHandles(
+ 0, 1, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, new int[] { 100 });
+ mMtpManager.setObjectInfo(
+ 0, new MtpObjectInfo.Builder().setObjectHandle(100).setName("note.txt").build());
+ mProvider.resumeRootScanner();
+ mResolver.waitForNotification(ROOTS_URI, 1);
+ try (final Cursor cursor = mProvider.queryChildDocuments(
+ "1", strings(Document.COLUMN_DOCUMENT_ID), null)) {
+ assertEquals(1, cursor.getCount());
+ cursor.moveToNext();
+ assertEquals("3", cursor.getString(0));
+ }
+ try {
+ mProvider.openDocument("3", "w", null);
+ fail();
+ } catch (UnsupportedOperationException exception) {}
+ }
+
private void setupProvider(int flag) {
mDatabase = new MtpDatabase(getContext(), flag);
mProvider = new MtpDocumentsProvider();
@@ -617,7 +747,7 @@
final int changeCount = mResolver.getChangeCount(ROOTS_URI);
mMtpManager.addValidDevice(
new MtpDeviceRecord(deviceId, "Device", null /* deviceKey */, false /* unopened */,
- roots, null, null));
+ roots, OPERATIONS_SUPPORTED, null));
mProvider.openDevice(deviceId);
mResolver.waitForNotification(ROOTS_URI, changeCount + 1);
return getStrings(mProvider.queryRoots(strings(DocumentsContract.Root.COLUMN_ROOT_ID)));
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
index 4dfc785..919ac39 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
@@ -16,8 +16,10 @@
package com.android.mtp;
+import android.database.Cursor;
import android.mtp.MtpObjectInfo;
import android.os.ParcelFileDescriptor;
+import android.provider.DocumentsContract.Document;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.MediumTest;
@@ -33,12 +35,14 @@
private TestMtpManager mtpManager;
private ExecutorService mExecutor;
private PipeManager mPipeManager;
+ private MtpDatabase mDatabase;
@Override
public void setUp() {
mtpManager = new TestMtpManager(getContext());
mExecutor = Executors.newSingleThreadExecutor();
- mPipeManager = new PipeManager(mExecutor);
+ mDatabase = new MtpDatabase(getContext(), MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
+ mPipeManager = new PipeManager(mDatabase, mExecutor);
}
public void testReadDocument_basic() throws Exception {
@@ -57,25 +61,35 @@
}
public void testWriteDocument_basic() throws Exception {
+ TestUtil.addTestDevice(mDatabase);
+ TestUtil.addTestStorage(mDatabase, "1");
+
+ final MtpObjectInfo info =
+ new MtpObjectInfo.Builder().setObjectHandle(1).setName("note.txt").build();
+ mDatabase.getMapper().startAddingDocuments("2");
+ mDatabase.getMapper().putChildDocuments(
+ 0, "2", TestUtil.OPERATIONS_SUPPORTED,
+ new MtpObjectInfo[] { info });
+ mDatabase.getMapper().stopAddingDocuments("2");
// Create a placeholder file which should be replaced by a real file later.
- mtpManager.setObjectInfo(0, new MtpObjectInfo.Builder()
- .setObjectHandle(1)
- .build());
+ mtpManager.setObjectInfo(0, info);
// Upload testing bytes.
final ParcelFileDescriptor descriptor = mPipeManager.writeDocument(
getContext(),
mtpManager,
- new Identifier(0, 0, 1, null, MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT));
+ new Identifier(0, 0, 1, "2", MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT),
+ TestUtil.OPERATIONS_SUPPORTED);
final ParcelFileDescriptor.AutoCloseOutputStream outputStream =
new ParcelFileDescriptor.AutoCloseOutputStream(descriptor);
outputStream.write(HELLO_BYTES, 0, HELLO_BYTES.length);
outputStream.close();
- mExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS);
+ mExecutor.shutdown();
+ assertTrue(mExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS));
// Check if the placeholder file is removed.
try {
- final MtpObjectInfo placeholderDocument = mtpManager.getObjectInfo(0, 1);
+ mtpManager.getObjectInfo(0, 1);
fail(); // The placeholder file has not been deleted.
} catch (IOException e) {
// Expected error, as the file is gone.
@@ -86,6 +100,14 @@
0, TestMtpManager.CREATED_DOCUMENT_HANDLE);
assertTrue(targetDocument != null);
+ // Confirm the object handle is updated.
+ try (final Cursor cursor = mDatabase.queryDocument(
+ "2", new String[] { MtpDatabaseConstants.COLUMN_OBJECT_HANDLE })) {
+ assertEquals(1, cursor.getCount());
+ cursor.moveToNext();
+ assertEquals(TestMtpManager.CREATED_DOCUMENT_HANDLE, cursor.getInt(0));
+ }
+
// Verify uploaded bytes.
final byte[] uploadedBytes = mtpManager.getImportFileBytes(
0, TestMtpManager.CREATED_DOCUMENT_HANDLE);
@@ -112,7 +134,8 @@
private void assertDescriptor(ParcelFileDescriptor descriptor, byte[] expectedBytes)
throws IOException, InterruptedException {
- mExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS);
+ mExecutor.shutdown();
+ assertTrue(mExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS));
try (final ParcelFileDescriptor.AutoCloseInputStream stream =
new ParcelFileDescriptor.AutoCloseInputStream(descriptor)) {
byte[] results = new byte[100];
@@ -125,7 +148,8 @@
private void assertDescriptorError(ParcelFileDescriptor descriptor)
throws InterruptedException {
- mExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS);
+ mExecutor.shutdown();
+ assertTrue(mExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS));
try {
descriptor.checkError();
fail();
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
index 4378152..5e0ee1e 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
@@ -22,6 +22,7 @@
import android.util.SparseArray;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -84,22 +85,22 @@
}
@Override
- void openDevice(int deviceId) throws IOException {
+ MtpDeviceRecord openDevice(int deviceId) throws IOException {
final MtpDeviceRecord device = mDevices.get(deviceId);
- if (device == null || device.opened) {
+ if (device == null) {
throw new IOException();
}
- mDevices.put(
- deviceId,
- new MtpDeviceRecord(
- device.deviceId, device.name, device.deviceKey, true, device.roots, null,
- null));
+ final MtpDeviceRecord record = new MtpDeviceRecord(
+ device.deviceId, device.name, device.deviceKey, true, device.roots,
+ device.operationsSupported, device.eventsSupported);
+ mDevices.put(deviceId, record);
+ return record;
}
@Override
void closeDevice(int deviceId) throws IOException {
final MtpDeviceRecord device = mDevices.get(deviceId);
- if (device == null || !device.opened) {
+ if (device == null) {
throw new IOException();
}
mDevices.put(
@@ -149,7 +150,9 @@
if (mObjectInfos.containsKey(key)) {
throw new IOException();
}
- mObjectInfos.put(key, objectInfo);
+ final MtpObjectInfo newInfo = new MtpObjectInfo.Builder(objectInfo).
+ setObjectHandle(CREATED_DOCUMENT_HANDLE).build();
+ mObjectInfos.put(key, newInfo);
if (objectInfo.getFormat() != 0x3001) {
try (final ParcelFileDescriptor.AutoCloseInputStream inputStream =
new ParcelFileDescriptor.AutoCloseInputStream(source)) {
@@ -196,19 +199,6 @@
}
@Override
- int[] getOpenedDeviceIds() {
- final int[] result = new int[mDevices.size()];
- int count = 0;
- for (int i = 0; i < mDevices.size(); i++) {
- final MtpDeviceRecord device = mDevices.valueAt(i);
- if (device.opened) {
- result[count++] = device.deviceId;
- }
- }
- return Arrays.copyOf(result, count);
- }
-
- @Override
byte[] getObject(int deviceId, int objectHandle, int expectedSize) throws IOException {
return mImportFileBytes.get(pack(deviceId, objectHandle));
}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestUtil.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestUtil.java
index ffcc088..5ceab01 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestUtil.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestUtil.java
@@ -19,20 +19,27 @@
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
+import android.mtp.MtpConstants;
import android.os.SystemClock;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Objects;
-import junit.framework.Assert;
-
/**
* Static utility methods for testing.
*/
final class TestUtil {
private TestUtil() {}
+ static final int[] OPERATIONS_SUPPORTED = new int[] {
+ MtpConstants.OPERATION_GET_PARTIAL_OBJECT,
+ MtpConstants.OPERATION_SEND_OBJECT,
+ MtpConstants.OPERATION_SEND_OBJECT_INFO,
+ MtpConstants.OPERATION_DELETE_OBJECT,
+ };
+
/**
* Requests permission for a MTP device and returns the first MTP device that has at least one
* storage.
@@ -57,6 +64,22 @@
}
}
+ static void addTestDevice(MtpDatabase database) throws FileNotFoundException {
+ database.getMapper().startAddingDocuments(null);
+ database.getMapper().putDeviceDocument(new MtpDeviceRecord(
+ 0, "Device", "device_key", /* opened is */ true, new MtpRoot[0],
+ OPERATIONS_SUPPORTED, null));
+ database.getMapper().stopAddingDocuments(null);
+ }
+
+ static void addTestStorage(MtpDatabase database, String parentId) throws FileNotFoundException {
+ database.getMapper().startAddingDocuments(parentId);
+ database.getMapper().putStorageDocuments(parentId, OPERATIONS_SUPPORTED, new MtpRoot[] {
+ new MtpRoot(0, 100, "Storage", 1024, 1024, ""),
+ });
+ database.getMapper().stopAddingDocuments(parentId);
+ }
+
private static UsbDevice findMtpDevice(
UsbManager usbManager,
MtpManager manager) throws IOException {
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
index 2ae3ec62..7a6aad6 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
@@ -16,6 +16,7 @@
package com.android.printspooler.model;
+import android.annotation.NonNull;
import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
@@ -57,6 +58,8 @@
private static final boolean DEBUG = false;
+ private static final long FORCE_CANCEL_TIMEOUT = 1000; // ms
+
private static final int STATE_INITIAL = 0;
private static final int STATE_STARTED = 1;
private static final int STATE_UPDATING = 2;
@@ -212,7 +215,7 @@
// cancellation and start over.
if (mCurrentCommand != null && (mCurrentCommand.isRunning()
|| mCurrentCommand.isPending())) {
- mCurrentCommand.cancel();
+ mCurrentCommand.cancel(false);
}
// Schedule a layout command.
@@ -233,7 +236,7 @@
// Cancel the current write as a new one is to be scheduled.
if (mCurrentCommand instanceof WriteCommand
&& (mCurrentCommand.isPending() || mCurrentCommand.isRunning())) {
- mCurrentCommand.cancel();
+ mCurrentCommand.cancel(false);
}
// Schedule a write command.
@@ -277,9 +280,9 @@
}
}
- public void cancel() {
+ public void cancel(boolean force) {
if (DEBUG) {
- Log.i(LOG_TAG, "[CALLED] cancel()");
+ Log.i(LOG_TAG, "[CALLED] cancel(" + force + ")");
}
mNextCommand = null;
@@ -290,7 +293,7 @@
mState = STATE_CANCELING;
- mCurrentCommand.cancel();
+ mCurrentCommand.cancel(force);
}
public void destroy() {
@@ -441,8 +444,9 @@
if (mCurrentCommand != null) {
if (mCurrentCommand.isPending()) {
mCurrentCommand.run();
+
+ mState = STATE_UPDATING;
}
- mState = STATE_UPDATING;
} else {
mState = STATE_UPDATED;
}
@@ -535,14 +539,17 @@
protected final CommandDoneCallback mDoneCallback;
+ private final Handler mHandler;
+
protected ICancellationSignal mCancellation;
private CharSequence mError;
private int mState = STATE_PENDING;
- public AsyncCommand(IPrintDocumentAdapter adapter, RemotePrintDocumentInfo document,
+ public AsyncCommand(Looper looper, IPrintDocumentAdapter adapter, RemotePrintDocumentInfo document,
CommandDoneCallback doneCallback) {
+ mHandler = new AsyncCommandHandler(looper);
mAdapter = adapter;
mDocument = document;
mDoneCallback = doneCallback;
@@ -556,7 +563,29 @@
return mState == STATE_CANCELED;
}
- public final void cancel() {
+ /**
+ * If a force cancel is pending, remove it. This is usually called when a command returns
+ * and thereby does not need to be canceled anymore.
+ */
+ protected void removeForceCancel() {
+ if (DEBUG) {
+ if (mHandler.hasMessages(AsyncCommandHandler.MSG_FORCE_CANCEL)) {
+ Log.i(LOG_TAG, "[FORCE CANCEL] Removed");
+ }
+ }
+
+ mHandler.removeMessages(AsyncCommandHandler.MSG_FORCE_CANCEL);
+ }
+
+ /**
+ * Cancel the current command.
+ *
+ * @param force If set, does not wait for the {@link PrintDocumentAdapter} to cancel. This
+ * should only be used if this is the last command send to the as otherwise the
+ * {@link PrintDocumentAdapter adapter} might get commands while it is still
+ * running the old one.
+ */
+ public final void cancel(boolean force) {
if (isRunning()) {
canceling();
if (mCancellation != null) {
@@ -566,14 +595,25 @@
Log.w(LOG_TAG, "Error while canceling", re);
}
}
- } else if (isCanceling()) {
- // Nothing to do
- } else {
- canceled();
-
- // Done.
- mDoneCallback.onDone();
}
+
+ if (isCanceling()) {
+ if (force) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "[FORCE CANCEL] queued");
+ }
+ mHandler.sendMessageDelayed(
+ mHandler.obtainMessage(AsyncCommandHandler.MSG_FORCE_CANCEL),
+ FORCE_CANCEL_TIMEOUT);
+ }
+
+ return;
+ }
+
+ canceled();
+
+ // Done.
+ mDoneCallback.onDone();
}
protected final void canceling() {
@@ -617,7 +657,7 @@
}
protected final void failed(CharSequence error) {
- if (mState != STATE_RUNNING) {
+ if (mState != STATE_RUNNING && mState != STATE_CANCELING) {
throw new IllegalStateException("Not running.");
}
mState = STATE_FAILED;
@@ -632,6 +672,37 @@
public CharSequence getError() {
return mError;
}
+
+ /**
+ * Handler for the async command.
+ */
+ private class AsyncCommandHandler extends Handler {
+ /** Message indicated the desire for to force cancel a command */
+ final static int MSG_FORCE_CANCEL = 0;
+
+ AsyncCommandHandler(@NonNull Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_FORCE_CANCEL:
+ if (isCanceling()) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "[FORCE CANCEL] executed");
+ }
+ failed("Command did not respond to cancellation in "
+ + FORCE_CANCEL_TIMEOUT + " ms");
+
+ mDoneCallback.onDone();
+ }
+ break;
+ default:
+ // not reached;
+ }
+ }
+ }
}
private static final class LayoutCommand extends AsyncCommand {
@@ -646,7 +717,7 @@
public LayoutCommand(Looper looper, IPrintDocumentAdapter adapter,
RemotePrintDocumentInfo document, PrintAttributes oldAttributes,
PrintAttributes newAttributes, boolean preview, CommandDoneCallback callback) {
- super(adapter, document, callback);
+ super(looper, adapter, document, callback);
mHandler = new LayoutHandler(looper);
mRemoteResultCallback = new LayoutResultCallback(mHandler);
mOldAttributes.copyFrom(oldAttributes);
@@ -795,6 +866,21 @@
@Override
public void handleMessage(Message message) {
+ // The command might have been force canceled, see
+ // AsyncCommand.AsyncCommandHandler#handleMessage
+ if (isFailed()) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "[CALLBACK] on canceled layout command");
+ }
+
+ return;
+ } else {
+ if (message.what != MSG_ON_LAYOUT_STARTED) {
+ // No need to force cancel anymore if layout finished
+ removeForceCancel();
+ }
+ }
+
switch (message.what) {
case MSG_ON_LAYOUT_STARTED: {
ICancellationSignal cancellation = (ICancellationSignal) message.obj;
@@ -882,7 +968,7 @@
public WriteCommand(Context context, Looper looper, IPrintDocumentAdapter adapter,
RemotePrintDocumentInfo document, int pageCount, PageRange[] pages,
MutexFileProvider fileProvider, CommandDoneCallback callback) {
- super(adapter, document, callback);
+ super(looper, adapter, document, callback);
mContext = context;
mHandler = new WriteHandler(looper);
mRemoteResultCallback = new WriteResultCallback(mHandler);
@@ -1052,6 +1138,21 @@
@Override
public void handleMessage(Message message) {
+ // The command might have been force canceled, see
+ // AsyncCommand.AsyncCommandHandler#handleMessage
+ if (isFailed()) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "[CALLBACK] on canceled write command");
+ }
+
+ return;
+ } else {
+ if (message.what != MSG_ON_WRITE_STARTED) {
+ // No need to force cancel anymore if write finished
+ removeForceCancel();
+ }
+ }
+
switch (message.what) {
case MSG_ON_WRITE_STARTED: {
ICancellationSignal cancellation = (ICancellationSignal) message.obj;
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 08cd0b6..4b62f24 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -320,8 +320,8 @@
if (isFinishing() || (isFinalState(mState) && !mPrintedDocument.isUpdating())) {
return;
}
- mPrintedDocument.cancel();
setState(STATE_PRINT_CANCELED);
+ mPrintedDocument.cancel(true);
doFinish();
}
}, PrintActivity.this);
@@ -731,7 +731,10 @@
// The activity is a component name, therefore it is one or none.
if (resolvedActivities.get(0).activityInfo.exported) {
- intent.putExtra(PrintService.EXTRA_PRINT_JOB_INFO, mPrintJob);
+ PrintJobInfo.Builder printJobBuilder = new PrintJobInfo.Builder(mPrintJob);
+ printJobBuilder.setPages(mSelectedPages);
+
+ intent.putExtra(PrintService.EXTRA_PRINT_JOB_INFO, printJobBuilder.build());
intent.putExtra(PrintService.EXTRA_PRINTER_INFO, printer);
intent.putExtra(PrintService.EXTRA_PRINT_DOCUMENT_INFO,
mPrintedDocument.getDocumentInfo().info);
@@ -759,10 +762,14 @@
// Take the advanced options without interpretation.
mPrintJob.setAdvancedOptions(printJobInfo.getAdvancedOptions());
- // Take copies without interpretation as the advanced print dialog
- // cannot create a print job info with invalid copies.
- mCopiesEditText.setText(String.valueOf(printJobInfo.getCopies()));
- mPrintJob.setCopies(printJobInfo.getCopies());
+ if (printJobInfo.getCopies() < 1) {
+ Log.w(LOG_TAG, "Cannot apply return value from advanced options activity. Copies " +
+ "must be 1 or more. Actual value is: " + printJobInfo.getCopies() + ". " +
+ "Ignoring.");
+ } else {
+ mCopiesEditText.setText(String.valueOf(printJobInfo.getCopies()));
+ mPrintJob.setCopies(printJobInfo.getCopies());
+ }
PrintAttributes currAttributes = mPrintJob.getAttributes();
PrintAttributes newAttributes = printJobInfo.getAttributes();
@@ -771,7 +778,7 @@
// Take the media size only if the current printer supports is.
MediaSize oldMediaSize = currAttributes.getMediaSize();
MediaSize newMediaSize = newAttributes.getMediaSize();
- if (!oldMediaSize.equals(newMediaSize)) {
+ if (newMediaSize != null && !oldMediaSize.equals(newMediaSize)) {
final int mediaSizeCount = mMediaSizeSpinnerAdapter.getCount();
MediaSize newMediaSizePortrait = newAttributes.getMediaSize().asPortrait();
for (int i = 0; i < mediaSizeCount; i++) {
@@ -1013,7 +1020,7 @@
}
private void requestCreatePdfFileOrFinish() {
- mPrintedDocument.cancel();
+ mPrintedDocument.cancel(false);
if (mCurrentPrinter == mDestinationSpinnerAdapter.getPdfPrinter()) {
startCreateDocumentActivity();
@@ -1130,7 +1137,7 @@
private void cancelPrint() {
setState(STATE_PRINT_CANCELED);
updateOptionsUi();
- mPrintedDocument.cancel();
+ mPrintedDocument.cancel(true);
doFinish();
}
@@ -1889,7 +1896,7 @@
public void onPrinterUnavailable(PrinterInfo printer) {
if (mCurrentPrinter.getId().equals(printer.getId())) {
setState(STATE_PRINTER_UNAVAILABLE);
- mPrintedDocument.cancel();
+ mPrintedDocument.cancel(false);
ensureErrorUiShown(getString(R.string.print_error_printer_unavailable),
PrintErrorFragment.ACTION_NONE);
updateOptionsUi();
diff --git a/packages/SettingsLib/res/drawable/ic_info.xml b/packages/SettingsLib/res/drawable/ic_info.xml
new file mode 100644
index 0000000..afe7e6b
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_info.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?android:attr/colorAccent">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>
+</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_settings_lock_outline.xml b/packages/SettingsLib/res/drawable/ic_settings_lock_outline.xml
deleted file mode 100644
index b3d7cf9..0000000
--- a/packages/SettingsLib/res/drawable/ic_settings_lock_outline.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="21dp"
- android:height="21dp"
- android:viewportWidth="21.0"
- android:viewportHeight="21.0"
- android:tint="?android:attr/colorAccent">
- <path
- android:fillColor="@android:color/white"
- android:pathData="M8,16c1.1,0,2-0.9,2-2s-0.9-2-2-2s-2,0.9-2,2S6.9,16,8,16zM14,7h-1V5c0-2.8-2.2-5-5-5S3,2.2,3,5v2H2C0.9,7,0,7.9,0,9v10c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V9C16,7.9,15.1,7,14,7z M4.9,5c0-1.7,1.4-3.1,3.1-3.1s3.1,1.4,3.1,3.1v2H4.9V5z M14,19H2V9h12V19z" />
-</vector>
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/packages/SettingsLib/res/layout/restricted_icon.xml
similarity index 62%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to packages/SettingsLib/res/layout/restricted_icon.xml
index 31c0162..d57fb80 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/packages/SettingsLib/res/layout/restricted_icon.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,9 +13,9 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/system_secondary_color" />
- <corners
- android:topLeftRadius="0dp"
- android:topRightRadius="0dp" />
-</shape>
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/restricted_icon"
+ android:layout_width="@dimen/restricted_icon_size"
+ android:layout_height="@dimen/restricted_icon_size"
+ android:src="@drawable/ic_info"
+ android:gravity="end|center_vertical" />
\ No newline at end of file
diff --git a/packages/SettingsLib/res/layout/restricted_switch_widget.xml b/packages/SettingsLib/res/layout/restricted_switch_widget.xml
new file mode 100644
index 0000000..6183812
--- /dev/null
+++ b/packages/SettingsLib/res/layout/restricted_switch_widget.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/restricted_icon"
+ android:layout_width="@dimen/restricted_icon_size"
+ android:layout_height="@dimen/restricted_icon_size"
+ android:src="@drawable/ic_info"
+ android:gravity="end|center_vertical" />
+ <!-- Based off frameworks/base/core/res/res/layout/preference_widget_switch.xml -->
+ <Switch xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+android:id/switch_widget"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:focusable="false"
+ android:clickable="false"
+ android:background="@null" />
+</merge>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 2ddb1e9..94e376c8 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Teks-na-spraak-uitset"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Spraaktempo"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Spoed waarteen die teks gepraat word"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Toonhoogte"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Beïnvloed die klank van die gesintetiseerde spraak"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Taal"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Gebruik stelseltaal"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Taal nie gekies nie"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Programme verplig ekstern toegelaat"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Laat enige program na ekstern geskryf word, ongeag manifeswaardes"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Verplig verstelbare groottes vir aktiwiteite"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Maak grootte van alle aktiwiteite verstelbaar vir veelvuldige vensters, ongeag manifeswaardes."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Maak die groottes van alle aktiwiteite verstelbaar vir veelvuldige vensters, ongeag manifeswaardes."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Aktiveer vormvrye-Windows"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Aktiveer steun vir eksperimentele vormvrye-Windows."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Aktiveer steun vir eksperimentele vormvrye-Windows."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Werkskerm-rugsteunwagwoord"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Volle rekenaarrugsteune word nie tans beskerm nie"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tik om die wagwoord vir volledige rekenaarrugsteune te verander of te verwyder"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktief. Tik om te wissel."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Lopende dienste"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Sien en beheer dienste wat tans loop"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Nagmodus"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Gedeaktiveer"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Altyd aan"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Outomaties"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Aktiveer multiproses-WebView"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Laat loop WebView-leweraars in \'n geïsoleerde proses."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementering"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Stel WebView-implementering"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Die gekose WebView-toepassing is gedeaktiveer, maar moet geaktiveer wees om gebruik te word. Wil jy dit aktiveer?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Die gekose WebView-toepassing is ongeldig want die lys toepassingskeuses het verouderd geraak. Die lys moet nou opgedateer word."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Skakel om na lêerenkripsie"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Skakel om …"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Lêerenkripsie is reeds uitgevoer"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Kleurregstelling"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Hierdie kenmerk is eksperimenteel en kan werkverrigting beïnvloed."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Geneutraliseer deur <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ongeveer <xliff:g id="TIME">%1$s</xliff:g> oor"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – sowat <xliff:g id="TIME">%2$s</xliff:g> oor"</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot vol"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Laai nie"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Laai nie"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Vol"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Gedeaktiveer deur administrateur"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Beheer deur administrateur"</string>
<string name="home" msgid="8263346537524314127">"Tuis"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> gelede"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> oor"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 4276bea..c605d2d 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"የፅሁፍ- ወደ- ንግግር ውፅዓት"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">" የንግግር ደረጃ"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"የተነገረበትን ፅሁፍ አፍጥን"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"ቅላፄ"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"በሲንተሲስ በተሠራው ድምፅ ላይ ተፅዕኖ ያሳድራል"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"ቋንቋ"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"የስርዓት ቋንቋ ተጠቀም"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"ቋንቋ አልተመረጠም"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"በውጫዊ ላይ ሃይል ይፈቀዳል"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"አንጸባራቂ እሴቶች ግምት ውስጥ ሳይገቡ ማንኛውም መተግበሪያ ወደ ውጫዊ ማከማቻ ለመጻፍ ብቁ ያደርጋል።"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"እንቅስቃሴዎች ዳግመኛ እንዲመጣጠኑ አስገድድ"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"የዝርዝር ሰነድ እሴቶች ምንም ይሁኑ ምን ለበርካታ መስኮቶች ሁሉንም እንቅስቃሴዎች ዳግም የሚመጣጠኑ እንዲሆኑ ያደርጋቸዋል።"</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"የዝርዝር ሰነድ እሴቶች ምንም ይሁኑ ምን ለበርካታ መስኮቶች ሁሉንም እንቅስቃሴዎች መጠናቸው የሚቀየሩ እንዲሆኑ ያደርጋቸዋል።"</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"የነጻ ቅርጽ መስኮቶችን ያንቁ"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"የሙከራ ነጻ ቅርጽ መስኮቶች ድጋፍን ያነቃል።"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"የሙከራ ነጻ መልክ መስኮቶች ድጋፍን አንቃ"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"የዴስክቶፕ መጠባበቂያ ይለፍ ቃል"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"ዴስክቶፕ ሙሉ ምትኬዎች በአሁኑ ሰዓት አልተጠበቁም"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"የዴስክቶፕ ሙሉ ምትኬዎች የይለፍ ቃሉን ለመለወጥ ወይም ለማስወገድ ነካ ያድርጉ"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"ገቢር። ለመቀያየር ነካ ያድርጉ።"</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"አሂድ አገልግሎቶች"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"በአሁኑጊዜ እየሄዱ ያሉ አገልግሎቶችን ተቆጣጠር እና እይ"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"የሌሊት ሁነታ"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"ተሰናክሏል"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"ሁልጊዜ ይበራል"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"ራስ-ሰር"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"ባለብዙ-ሂደት WebViewን አንቃ"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"የWebView ምስል ሰሪዎችን በተገለለ ሂደት ውስጥ አሂድ።"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"የWebView ትግበራ"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"የWebView ትግበራን ያዘጋጁ"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"የተመረጠው WebView ትግበራ ተሰናክሏል፣ እና ጥቅም ላይ እንዲውል መንቃት አለበት፣ ሊያነቁት ይፈልጋሉ?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"የትግበራ ምርጫዎች ዝርዝር እድገት ስላላሳየ የተመረጠው የWebView ትግበራ አይሠራም። ዝርዝሩ አሁን መዘመን አለበት።"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ወደ ፋይል ምሥጠራ ቀይር"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"ለውጥ…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ፋይል አስቀድሞ ተመስጥሯል"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"የቀለም ማስተካከያ"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ይህ ባህሪ የሙከራ ነውና አፈጻጸም ላይ ተጽዕኖ ሊኖረው ይችላል።"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"በ<xliff:g id="TITLE">%1$s</xliff:g> ተሽሯል"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"<xliff:g id="TIME">%1$s</xliff:g> ገደማ ቀርቷል"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ገደማ <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> እስከሚሞላ ድረስ"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"ባትሪ እየሞላ አይደለም"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"ኃይል እየሞላ አይደለም"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"ሙሉነው"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"በአስተዳዳሪ የተሰናከለ"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"በአስተዳዳሪ ቁጥጥር የተደረገበት"</string>
<string name="home" msgid="8263346537524314127">"መነሻ"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"ከ<xliff:g id="ID_1">%1$s</xliff:g> በፊት"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> ቀርቷል"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 67fb59c..975051a 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"إخراج تحويل النص إلى كلام"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"معدل سرعة الكلام"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"سرعة نطق الكلام"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"درجة الصوت"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"للتأثير في نبرة الكلام المُرَكَّب"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"اللغة"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"استخدام لغة النظام"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"اللغة غير محددة"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"فرض السماح للتطبيقات على الخارجي"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"تأهيل أي تطبيق بحيث تتم كتابته على سعة تخزين خارجية، بغض النظر عن قيم البيان"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"فرض إمكانية تغيير على الأنشطة"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"لتمكين تغيير حجم جميع الأنشطة لتناسب تعدد النوافذ، بغض النظر عن قيم البيان."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"تمكين تغيير حجم جميع الأنشطة لتناسب تعدد النوافذ، بغض النظر عن قيم البيان."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"تمكين النوافذ الحرة"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"لتمكين إتاحة استخدام النوافذ الحرة التجريبية."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"تمكين إتاحة استخدام النوافذ الحرة التجريبية."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"كلمة مرور احتياطية للكمبيوتر"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"النسخ الاحتياطية الكاملة لسطح المكتب غير محمية في الوقت الحالي"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"انقر لتغيير كلمة مرور النسخ الاحتياطية الكاملة لسطح المكتب أو إزالتها."</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"نشط، انقر للتبديل."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"الخدمات قيد التشغيل"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"عرض الخدمات قيد التشغيل في الوقت الحالي والتحكم فيها"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"الوضع الليلي"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"معطَّل"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"التشغيل دائمًا"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"تلقائيًا"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"تمكين عرض ويب متعدد العمليات"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"تشغيل أجهزة عرض الويب في عملية منفصلة."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"تطبيق WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"تعيين تطبيق WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"إن تنفيذ ميزة WebView التي تم اختيارها معطَّل، ويجب تمكين هذه الميزة ليتسنى استخدامها، فهل تريد تمكينها؟"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"التنفيذ الذي تم اختياره لطريقة WebView غير صالح لأن قائمة خيارات التنفيذ أصبحت قديمة. يجب أن يتم تحديث القائمة الآن."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"التحويل إلى تشفير ملفات"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"تحويل…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"تم استخدام تشفير ملفات من قبل"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"تصحيح الألوان"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"هذه الميزة تجريبية وقد تؤثر في الأداء."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"تم الاستبدال بـ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"يتبقى <xliff:g id="TIME">%1$s</xliff:g> تقريبًا"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - تبقى <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> حتى الاكتمال"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"لا يتم الشحن"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"لا يتم الشحن"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"ممتلئة"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"تم التعطيل بواسطة المشرف"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"إعدادات يتحكم فيها المشرف"</string>
<string name="home" msgid="8263346537524314127">"الشاشة الرئيسية"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"قبل <xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"يتبقى <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-az-rAZ/strings.xml b/packages/SettingsLib/res/values-az-rAZ/strings.xml
index 12b077e..3f78fa2 100644
--- a/packages/SettingsLib/res/values-az-rAZ/strings.xml
+++ b/packages/SettingsLib/res/values-az-rAZ/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Mətndən-nitqə çıxışı"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Nitq diapazonu"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Mətnin səsləndirilmə sürəti"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Pitç"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Sintez olunmuş nitqin tonuna təsir edir"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Dil"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Sistem dili işlədin"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Dil seçilməyib"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Tətbiqlərə xaricdən məcburi icazə"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Seçilmiş hər hansı tətbiqi bəyannamə dəyərlərindən aslı olmayaraq xarici yaddaşa yazılabilən edir."</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Ölçü dəyişdirmək üçün məcburi fəaliyyətlər"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Bəyannamə dəyərlərindən aslı olmayaraq bütün fəaliyyətləri çoxsaylı pəncərə üçün dəyişkən ölçülü edir."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Bəyannamə dəyərlərindən aslı olmayaraq, bütün fəaliyyətləri çoxsaylı pəncərə üçün dəyişkən ölçülü edin."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Freeform windows aktiv edin"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Sınaq üçün freeform windows aktiv edir"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Sınaq üçün freeform windows aktiv edilir."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Masaüstü rezerv parolu"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Masaüstü tam rezervlər hazırda qorunmayıblar."</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Masaüstünün tam rezerv kopyalanması üçün parolu dəyişmək və ya silmək üçün basın"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktivdir. Keçid etmək üçün basın."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"İşləyən xidmətlər"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Hazırda prosesdə olan xidmətləri görüntüləyin və onlara nəzarət edin"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Gecə rejimi"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Qeyri-aktiv"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Həmişə aktiv"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Avtomatik"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Çox prosesli WebView\'nu aktiv edin"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView rendererləri təcrid olunmuş prosesdə işlədin."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView icrası"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView icrasını ayarlayın"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Seçilmiş WebView icrası deaktiv edildi, istifadəsi üçün aktiv edilməlidir, aktivləşdirmək istəyirsiniz?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Seçilmiş WebView icrası yararsızdır cünki, icra seçimlərinin siyahısı köhnədir. Bu siyahı güncəllənməlidir."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Fayl şifrələnməsinə çevirin"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Çevirin..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Fayl artıq şifrələnib"</string>
@@ -296,7 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Rəng düzəlişi"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Bu funksiya eksperimentaldır və performansa təsir edə bilər."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> tərəfindən qəbul edilmir"</string>
- <string name="power_remaining_duration_only" msgid="4400068916452346544">"Təxminən <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string>
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Təxminən <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - təxminən <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string>
<string name="power_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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> dolana qədər"</string>
@@ -311,7 +310,7 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Doldurulmur"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Enerji doldurulmur"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Tam"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Administrator tərəfindən deaktiv edildi"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Admin tərəfindən nəzarət olunur"</string>
<string name="home" msgid="8263346537524314127">"Əsas səhifə"</string>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> əvvəl"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> qalıb"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index ae56978..a38542d 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Izlaz za pretvaranje teksta u govor"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Brzina govora"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Brzina izgovaranja teksta"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Nivo"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Utiče na ton sintetizovanog govora"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Jezik"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Koristi jezik sistema"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Jezik nije izabran"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Prinudno dozvoli aplikacije u spoljnoj"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Omogućava upisivanje svih aplikacija u spoljnu memoriju, bez obzira na vrednosti manifesta"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Prinudno omogući promenu veličine aktivnosti"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Omogućava promenu veličine svih aktivnosti za režim sa više prozora, bez obzira na vrednosti manifesta."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Omogući promenu veličine svih aktivnosti za režim sa više prozora, bez obzira na vrednosti manifesta."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Omogući prozore proizvoljnog formata"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Omogućava podršku za eksperimentalne prozore proizvoljnog formata."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Omogućite podršku za eksperimentalne prozore proizvoljnog formata."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Lozinka rezervne kopije za računar"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Rezervne kopije čitavog sistema trenutno nisu zaštićene"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Dodirnite da biste promenili ili uklonili lozinku za pravljenje rezervnih kopija čitavog sistema na računaru"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktivna. Dodirnite da biste je deaktivirali."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Pokrenute usluge"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Prikaz i kontrola trenutno pokrenutih usluga"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Noćni režim"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Onemogućeno"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Uvek uključeno"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automatski"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Omogući višeprocesni WebView"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Pokrećite WebView prikazivače u okviru izolovanog procesa."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Primena WebView-a"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Podesite primenu WebView-a"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Izabrana primena WebView-a je onemogućena, a mora da bude omogućena radi korišćenja. Želite li da je omogućite?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Izabrana primena WebView-a je nevažeća zato što je lista mogućnosti za primenu zastarela. Sada bi trebalo da ažurirate listu."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertuj u šifrovanje datoteka"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertuj..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Već se koristi šifrovanje datoteka"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korekcija boja"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova funkcija je eksperimentalna i može da utiče na performanse."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Zamenjuje ga <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Još otprilike <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo oko <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> dok se ne napuni"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Ne puni se"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ne puni se"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Puno"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Onemogućio je administrator"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kontroliše administrator"</string>
<string name="home" msgid="8263346537524314127">"Početni"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"Pre <xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"Još <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index ad0ace4..e3c8d8a 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Синтезиран говор"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Скорост на речта"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Скорост, с която се изговаря текстът"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Височина"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Отразява се на тона на синтезирания говор"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Език"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Използване на системния език"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Езикът не е избран"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Външно хран.: Принуд. разрешаване на приложенията"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Позволява прилож. да се записват във външ. хранил. независимо от стойностите в манифеста"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Възможност за преоразмеряване на активностите"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Дава възможност за преоразмеряване на всички активности в режима за няколко прозореца независимо от стойностите в манифеста."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Дава възможност за преоразмеряване на всички активности в режима за няколко прозореца независимо от стойностите в манифеста."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Активиране на прозорците в свободна форма"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Активира поддръжката за експерименталните прозорци в свободна форма."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Активиране на поддръжката за експерименталните прозорци в свободна форма."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Наст. комп.: Парола"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Понастоящем пълните резервни копия за настолен компютър не са защитени"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Докоснете, за да промените или премахнете паролата за пълни резервни копия на настолния компютър"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Активно. Докоснете, за да превключите."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Изпълнявани услуги:"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Преглед и контрол върху изпълняващите се понастоящем услуги"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Нощен режим"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Деактивирано"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Винаги включено"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Автоматично"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Многопроц. режим на WebView: Акт."</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Програми за визуализация на WebView: Изпъл. в изолиран процес."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Внедряване на WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Задаване на внедряването на WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Избраното внедряване на WebView е деактивирано и трябва да го активирате, за да се използва. Искате ли да го направите?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Избраната реализация на WebView е невалидна, тъй като списъкът с възможни реализации е остарял. Той следва да се актуализира сега."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Преобразуване към шифроване на ниво файл"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Преобразуване…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Данните вече са шифровани на ниво файл"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Корекция на цветове"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Тази функция е експериментална и може да се отрази на ефективността."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Заменено от „<xliff:g id="TITLE">%1$s</xliff:g>“"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Прибл. оставащо време: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – приблизително оставащо време: <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до пълно зареждане"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Не се зарежда"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не се зарежда"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Пълна"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Деактивирано от администратора"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Контролира се от администратор"</string>
<string name="home" msgid="8263346537524314127">"Начало"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"Преди <xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"Оставащо време: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bn-rBD/strings.xml b/packages/SettingsLib/res/values-bn-rBD/strings.xml
index 589c52e..d3c9e6b 100644
--- a/packages/SettingsLib/res/values-bn-rBD/strings.xml
+++ b/packages/SettingsLib/res/values-bn-rBD/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"লেখিত-থেকে-ভাষ্য"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"ভাষ্য হার"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"যে গতিতে পাঠ্য উচ্চারিত হয়"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"পিচ"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"সিন্থেসাইজ করা ভাষ্যের স্বরকে প্রভাবিত করে"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"ভাষা"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"সিস্টেমের ভাষা ব্যবহার করুন"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"ভাষা নির্বাচন করা নেই"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"বহিরাগততে বলপূর্বক মঞ্জুরি"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"ম্যানিফেস্ট মানগুলি নির্বিশেষে যেকোনো অ্যাপ্লিকেশানকে বাহ্যিক সঞ্চয়স্থানে লেখার উপযুক্ত বানায়"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"আকার পরিবর্তনযোগ্য করার জন্য ক্রিয়াকলাপগুলিকে জোর করুন"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"ম্যানিফেস্ট মানগুলির নির্বিশেষে মাল্টি-উইন্ডোর জন্য সমস্ত ক্রিয়াকলাপগুলিকে আকার পরিবর্তনযোগ্য করে তোলে৷"</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"ম্যানিফেস্ট মানগুলির নির্বিশেষে মাল্টি-উইন্ডোর জন্য সমস্ত ক্রিয়াকলাপগুলির আকার পরিবর্তনযোগ্য করুন৷"</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"ফ্রি-ফর্ম উইন্ডোগুলি সক্ষম করুন"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"পরীক্ষামূলক ফ্রি-ফর্ম উইন্ডোগুলির জন্য সহায়তা সক্ষম করুন৷"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"পরীক্ষামূলক ফ্রি-ফর্ম উইন্ডোগুলির জন্য সহায়তা সক্ষম করুন৷"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"ডেস্কটপ ব্যাকআপ পাসওয়ার্ড"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"ডেস্কটপ পূর্ণ ব্যাকআপ বর্তমানে সুরক্ষিত নয়"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"ডেস্কটপের সম্পূর্ণ ব্যাকআপের পাসওয়ার্ডটি পরিবর্তন করতে বা মুছে ফেলতে আলতো চাপুন"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"সক্রিয় রয়েছে৷ টগল করতে আলতো চাপুন৷"</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"এখন চলছে যে পরিষেবাগুলি"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"বর্তমান চলমান পরিষেবাগুলি দেখুন এবং নিয়ন্ত্রণ করুন"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"রাতের মোড"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"অক্ষম করা রয়েছে"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"সবসময় চালু"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"স্বয়ংক্রিয়"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"বহু-প্রক্রিয়া ওয়েবভিউ সক্ষম করুন"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"একটি বিচ্ছিন্ন প্রক্রিয়ায় ওয়েবভিউ রেন্ডারারগুলি চালান৷"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"ওয়েবভিউ প্রয়োগ"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"ওয়েবভিউ প্রয়োগ সেট করুন"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"নির্বাচিত ওয়েবভিউ প্রয়োগটি অক্ষম করা আছে এবং ব্যবহার করার জন্য অবশ্যই সক্ষম করতে হবে, আপনি কি এটিকে সক্ষম করতে চান?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"প্রয়োগ করার জন্য বেছে নেওয়া ওয়েবভিউটি অবৈধ, কারণ প্রয়োগের চয়নগুলি পুরানো হয়ে গেছে৷ এই তালিকাটিকে এখনই আপডেট করা উচিৎ৷"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ফাইল এনক্রিপশান রূপান্তর করুন"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"রূপান্তর করুন..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ফাইল ইতিমধ্যেই এনক্রিপ্ট করা রয়েছে"</string>
@@ -296,7 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"রঙ সংশোধন"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"এই বৈশিষ্ট্যটি পরীক্ষামূলক এবং এটি কার্য-সম্পাদনা প্রভাবিত করতে পারে।"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> এর দ্বারা ওভাররাইড করা হয়েছে"</string>
- <string name="power_remaining_duration_only" msgid="4400068916452346544">"প্রায় <xliff:g id="TIME">%2$s</xliff:g> বাকী আছে"</string>
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"প্রায় <xliff:g id="TIME">%1$s</xliff:g> বাকী আছে"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - আনুমানিক <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - সম্পূর্ণ হতে <xliff:g id="TIME">%2$s</xliff:g> বাকি"</string>
@@ -311,7 +310,7 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"চার্জ হচ্ছে না"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"চার্জ হচ্ছে না"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"পূর্ণ"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"প্রশাসক দ্বারা অক্ষমিত"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"প্রশাসকের দ্বারা নিয়ন্ত্রিত"</string>
<string name="home" msgid="8263346537524314127">"হোম"</string>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> আগে"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> বাকী আছে"</string>
diff --git a/packages/SettingsLib/res/values-bs-rBA/arrays.xml b/packages/SettingsLib/res/values-bs-rBA/arrays.xml
new file mode 100644
index 0000000..32b8bc5
--- /dev/null
+++ b/packages/SettingsLib/res/values-bs-rBA/arrays.xml
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+**
+** Copyright 2015 The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wifi_status">
+ <item msgid="1922181315419294640"></item>
+ <item msgid="8934131797783724664">"Skeniranje…"</item>
+ <item msgid="8513729475867537913">"Povezivanje…"</item>
+ <item msgid="515055375277271756">"Autentifikacija…"</item>
+ <item msgid="1943354004029184381">"Dobivanje IP adrese…"</item>
+ <item msgid="4221763391123233270">"Povezano"</item>
+ <item msgid="624838831631122137">"Suspendiran"</item>
+ <item msgid="7979680559596111948">"Prekidanje veze…"</item>
+ <item msgid="1634960474403853625">"Isključen"</item>
+ <item msgid="746097431216080650">"Neuspješno"</item>
+ <item msgid="6367044185730295334">"Blokirano"</item>
+ <item msgid="503942654197908005">"Privremeno izbjegavaj veze lošeg kvaliteta"</item>
+ </string-array>
+ <string-array name="wifi_status_with_ssid">
+ <item msgid="7714855332363650812"></item>
+ <item msgid="8878186979715711006">"Skeniranje…"</item>
+ <item msgid="355508996603873860">"Povezivanje na mrežu <xliff:g id="NETWORK_NAME">%1$s</xliff:g>..."</item>
+ <item msgid="554971459996405634">"Autentifikacija sa mrežom <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
+ <item msgid="7928343808033020343">"Dobivanje IP adrese iz mreže <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
+ <item msgid="8937994881315223448">"Povezan na mrežu <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</item>
+ <item msgid="1330262655415760617">"Suspendiran"</item>
+ <item msgid="7698638434317271902">"Prekidanje veze sa mrežom <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
+ <item msgid="197508606402264311">"Isključen"</item>
+ <item msgid="8578370891960825148">"Neuspješno"</item>
+ <item msgid="5660739516542454527">"Blokirano"</item>
+ <item msgid="1805837518286731242">"Privremeno izbjegavaj veze lošeg kvaliteta"</item>
+ </string-array>
+ <string-array name="hdcp_checking_titles">
+ <item msgid="441827799230089869">"Nikada ne provjeravaj"</item>
+ <item msgid="6042769699089883931">"Provjeri samo za DRM sadržaj"</item>
+ <item msgid="9174900380056846820">"Uvijek provjeri"</item>
+ </string-array>
+ <string-array name="hdcp_checking_summaries">
+ <item msgid="505558545611516707">"Nikada ne koristi HDCP provjeru"</item>
+ <item msgid="3878793616631049349">"Koristi HDCP provjeru samo za DRM sadržaj"</item>
+ <item msgid="45075631231212732">"Uvijek koristi HDCP provjeru"</item>
+ </string-array>
+ <string-array name="select_logd_size_titles">
+ <item msgid="8665206199209698501">"Isključeno"</item>
+ <item msgid="1593289376502312923">"64K"</item>
+ <item msgid="487545340236145324">"256K"</item>
+ <item msgid="2423528675294333831">"1M"</item>
+ <item msgid="180883774509476541">"4M"</item>
+ <item msgid="2803199102589126938">"16M"</item>
+ </string-array>
+ <string-array name="select_logd_size_lowram_titles">
+ <item msgid="6089470720451068364">"Isključeno"</item>
+ <item msgid="4622460333038586791">"64K"</item>
+ <item msgid="2212125625169582330">"256K"</item>
+ <item msgid="1704946766699242653">"1M"</item>
+ </string-array>
+ <string-array name="select_logd_size_summaries">
+ <item msgid="6921048829791179331">"Isključeno"</item>
+ <item msgid="2969458029344750262">"64K po međumemoriji dnevnika"</item>
+ <item msgid="1342285115665698168">"256k po međumemoriji dnevnika"</item>
+ <item msgid="1314234299552254621">"1M po međumemoriji dnevnika"</item>
+ <item msgid="3606047780792894151">"4M po međumemoriji dnevnika"</item>
+ <item msgid="5431354956856655120">"16M po međumemoriji dnevnika"</item>
+ </string-array>
+ <string-array name="window_animation_scale_entries">
+ <item msgid="8134156599370824081">"Animacija isključena"</item>
+ <item msgid="6624864048416710414">"Animacija razmjera .5x"</item>
+ <item msgid="2219332261255416635">"Animacija razmjera 1x"</item>
+ <item msgid="3544428804137048509">"Animacija razmjera 1,5x"</item>
+ <item msgid="3110710404225974514">"Animacija razmjera 2x"</item>
+ <item msgid="4402738611528318731">"Animacija razmjera 5x"</item>
+ <item msgid="6189539267968330656">"Animacija razmjera 10x"</item>
+ </string-array>
+ <string-array name="transition_animation_scale_entries">
+ <item msgid="8464255836173039442">"Animacija isključena"</item>
+ <item msgid="3375781541913316411">"Animacija razmjera .5x"</item>
+ <item msgid="1991041427801869945">"Animacija razmjera 1x"</item>
+ <item msgid="4012689927622382874">"Animacija razmjera 1,5x"</item>
+ <item msgid="3289156759925947169">"Animacija razmjera 2x"</item>
+ <item msgid="7705857441213621835">"Animacija razmjera 5x"</item>
+ <item msgid="6660750935954853365">"Animacija razmjera 10x"</item>
+ </string-array>
+ <string-array name="animator_duration_scale_entries">
+ <item msgid="6039901060648228241">"Animacija isključena"</item>
+ <item msgid="1138649021950863198">"Animacija razmjera .5x"</item>
+ <item msgid="4394388961370833040">"Animacija razmjera 1x"</item>
+ <item msgid="8125427921655194973">"Animacija razmjera 1.5x"</item>
+ <item msgid="3334024790739189573">"Animacija razmjera 2x"</item>
+ <item msgid="3170120558236848008">"Animacija razmjera 5x"</item>
+ <item msgid="1069584980746680398">"Animacija razmjera 10x"</item>
+ </string-array>
+ <string-array name="overlay_display_devices_entries">
+ <item msgid="1606809880904982133">"Nema"</item>
+ <item msgid="9033194758688161545">"480p"</item>
+ <item msgid="1025306206556583600">"480p (osiguran)"</item>
+ <item msgid="1853913333042744661">"720p"</item>
+ <item msgid="3414540279805870511">"720p (osiguran)"</item>
+ <item msgid="9039818062847141551">"1080p"</item>
+ <item msgid="4939496949750174834">"1080p (osiguran)"</item>
+ <item msgid="1833612718524903568">"4K"</item>
+ <item msgid="238303513127879234">"4K (osiguran)"</item>
+ <item msgid="3547211260846843098">"4K (povećava rezoluciju)"</item>
+ <item msgid="5411365648951414254">"4K (povećava rezoluciju, osiguran)"</item>
+ <item msgid="1311305077526792901">"720p, 1080p (dupli ekran)"</item>
+ </string-array>
+ <string-array name="enable_opengl_traces_entries">
+ <item msgid="3191973083884253830">"Nema"</item>
+ <item msgid="9089630089455370183">"Logcat"</item>
+ <item msgid="5397807424362304288">"Systrace (grafika)"</item>
+ <item msgid="1340692776955662664">"Pozovi skupinu na glGetError"</item>
+ </string-array>
+ <string-array name="show_non_rect_clip_entries">
+ <item msgid="993742912147090253">"Isključeno"</item>
+ <item msgid="675719912558941285">"Nacrtaj plavom bojom nepravougaonu oblast za isjecanje"</item>
+ <item msgid="1064373276095698656">"Označite zelenom bojom testirane komande za crtanje"</item>
+ </string-array>
+ <string-array name="track_frame_time_entries">
+ <item msgid="2193584639058893150">"Isključeno"</item>
+ <item msgid="2751513398307949636">"Na ekranu u vidu crtica"</item>
+ <item msgid="1851438178120770973">"U ADB ljuski dumpsys gfxinfo"</item>
+ </string-array>
+ <string-array name="debug_hw_overdraw_entries">
+ <item msgid="8190572633763871652">"Isključeno"</item>
+ <item msgid="7688197031296835369">"Prikaži overdraw područja"</item>
+ <item msgid="2290859360633824369">"Prikaži područja za Deuteranomaly"</item>
+ </string-array>
+ <string-array name="app_process_limit_entries">
+ <item msgid="3401625457385943795">"Standardno ograničenje"</item>
+ <item msgid="4071574792028999443">"Nema pozadinskih procesa"</item>
+ <item msgid="4810006996171705398">"Najviše 1 proces"</item>
+ <item msgid="8586370216857360863">"Najviše 2 procesa"</item>
+ <item msgid="836593137872605381">"Najviše 3 procesa"</item>
+ <item msgid="7899496259191969307">"Najviše 4 procesa"</item>
+ </string-array>
+ <string-array name="usb_configuration_titles">
+ <item msgid="488237561639712799">"Puni se"</item>
+ <item msgid="5220695614993094977">"MTP (protokol za prijenos sadržaja medija)"</item>
+ <item msgid="2086000968159047375">"PTP (protokol za prijenos slika)"</item>
+ <item msgid="7398830860950841822">"RNDIS (USB Ethernet)"</item>
+ <item msgid="1718924214939774352">"Izvor zvuka"</item>
+ <item msgid="8126315616613006284">"MIDI"</item>
+ </string-array>
+</resources>
diff --git a/packages/SettingsLib/res/values-bs-rBA/strings.xml b/packages/SettingsLib/res/values-bs-rBA/strings.xml
index 8da12cb..673b08b 100644
--- a/packages/SettingsLib/res/values-bs-rBA/strings.xml
+++ b/packages/SettingsLib/res/values-bs-rBA/strings.xml
@@ -20,130 +20,69 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for wifi_fail_to_scan (1265540342578081461) -->
- <skip />
- <!-- no translation found for wifi_security_none (7985461072596594400) -->
- <skip />
- <!-- no translation found for wifi_remembered (4955746899347821096) -->
- <skip />
- <!-- no translation found for wifi_disabled_generic (4259794910584943386) -->
- <skip />
- <!-- no translation found for wifi_disabled_network_failure (2364951338436007124) -->
- <skip />
- <!-- no translation found for wifi_disabled_wifi_failure (3081668066612876581) -->
- <skip />
- <!-- no translation found for wifi_disabled_password_failure (8659805351763133575) -->
- <skip />
- <!-- no translation found for wifi_not_in_range (1136191511238508967) -->
- <skip />
- <!-- no translation found for wifi_no_internet (9151470775868728896) -->
- <skip />
- <!-- no translation found for saved_network (4352716707126620811) -->
- <skip />
- <!-- no translation found for connected_via_wfa (3805736726317410714) -->
- <skip />
- <!-- no translation found for connected_via_passpoint (2826205693803088747) -->
- <skip />
- <!-- no translation found for available_via_passpoint (1617440946846329613) -->
- <skip />
- <!-- no translation found for wifi_connected_no_internet (3149853966840874992) -->
- <skip />
- <!-- no translation found for bluetooth_disconnected (6557104142667339895) -->
- <skip />
- <!-- no translation found for bluetooth_disconnecting (8913264760027764974) -->
- <skip />
- <!-- no translation found for bluetooth_connecting (8555009514614320497) -->
- <skip />
- <!-- no translation found for bluetooth_connected (6038755206916626419) -->
- <skip />
- <!-- no translation found for bluetooth_pairing (1426882272690346242) -->
- <skip />
- <!-- no translation found for bluetooth_connected_no_headset (2866994875046035609) -->
- <skip />
- <!-- no translation found for bluetooth_connected_no_a2dp (4576188601581440337) -->
- <skip />
- <!-- no translation found for bluetooth_connected_no_map (6504436917057479986) -->
- <skip />
- <!-- no translation found for bluetooth_connected_no_headset_no_a2dp (9195757766755553810) -->
- <skip />
- <!-- no translation found for bluetooth_profile_a2dp (2031475486179830674) -->
- <skip />
- <!-- no translation found for bluetooth_profile_headset (8658779596261212609) -->
- <skip />
- <!-- no translation found for bluetooth_profile_opp (9168139293654233697) -->
- <skip />
- <!-- no translation found for bluetooth_profile_hid (3680729023366986480) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pan (3391606497945147673) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap (5372051906968576809) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6605229608108852198) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pan_nap (8429049285027482959) -->
- <skip />
- <!-- no translation found for bluetooth_profile_map (5465271250454324383) -->
- <skip />
- <!-- no translation found for bluetooth_profile_sap (5764222021851283125) -->
- <skip />
- <!-- no translation found for bluetooth_a2dp_profile_summary_connected (963376081347721598) -->
- <skip />
- <!-- no translation found for bluetooth_headset_profile_summary_connected (7661070206715520671) -->
- <skip />
- <!-- no translation found for bluetooth_opp_profile_summary_connected (2611913495968309066) -->
- <skip />
- <!-- no translation found for bluetooth_map_profile_summary_connected (8191407438851351713) -->
- <skip />
- <!-- no translation found for bluetooth_sap_profile_summary_connected (8561765057453083838) -->
- <skip />
- <!-- no translation found for bluetooth_opp_profile_summary_not_connected (1267091356089086285) -->
- <skip />
- <!-- no translation found for bluetooth_hid_profile_summary_connected (3381760054215168689) -->
- <skip />
+ <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ne može skenirati mreže"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Nema"</string>
+ <string name="wifi_remembered" msgid="4955746899347821096">"Sačuvano"</string>
+ <string name="wifi_disabled_generic" msgid="4259794910584943386">"Onemogućeno"</string>
+ <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Greška u konfiguraciji IP-a"</string>
+ <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Greška pri povezivanju na Wi-Fi"</string>
+ <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problem pri provjeri vjerodostojnosti."</string>
+ <string name="wifi_not_in_range" msgid="1136191511238508967">"Nije u dometu"</string>
+ <string name="wifi_no_internet" msgid="9151470775868728896">"Pristup internetu nije pronađen. Neće se ponovo povezivati automatski."</string>
+ <string name="saved_network" msgid="4352716707126620811">"Sačuvao <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="connected_via_wfa" msgid="3805736726317410714">"Povezani preko Wi-Fi pomoćnika"</string>
+ <string name="connected_via_passpoint" msgid="2826205693803088747">"Povezani preko %1$s"</string>
+ <string name="available_via_passpoint" msgid="1617440946846329613">"Dostupan preko %1$s"</string>
+ <string name="wifi_connected_no_internet" msgid="3149853966840874992">"Povezano. Nema interneta"</string>
+ <string name="bluetooth_disconnected" msgid="6557104142667339895">"Isključen"</string>
+ <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Prekidanje veze…"</string>
+ <string name="bluetooth_connecting" msgid="8555009514614320497">"Povezivanje…"</string>
+ <string name="bluetooth_connected" msgid="6038755206916626419">"Povezano"</string>
+ <string name="bluetooth_pairing" msgid="1426882272690346242">"Uparivanje…"</string>
+ <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Povezano (bez telefona)"</string>
+ <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Povezano (bez medija)"</string>
+ <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Povezano (bez pristupa porukama)"</string>
+ <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Povezano (bez zvuka telefona ili medija)"</string>
+ <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Zvuk medija"</string>
+ <string name="bluetooth_profile_headset" msgid="8658779596261212609">"Zvuk telefona"</string>
+ <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Prenošenje fajla"</string>
+ <string name="bluetooth_profile_hid" msgid="3680729023366986480">"Ulazni uređaj"</string>
+ <string name="bluetooth_profile_pan" msgid="3391606497945147673">"Pristup internetu"</string>
+ <string name="bluetooth_profile_pbap" msgid="5372051906968576809">"Dijeljenje kontakta"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6605229608108852198">"Koristi za dijeljenje kontakta"</string>
+ <string name="bluetooth_profile_pan_nap" msgid="8429049285027482959">"Dijeljenje internet veze"</string>
+ <string name="bluetooth_profile_map" msgid="5465271250454324383">"Pristup poruci"</string>
+ <string name="bluetooth_profile_sap" msgid="5764222021851283125">"Pristup SIM-u"</string>
+ <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Povezano sa zvukom medija"</string>
+ <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Povezano na zvuk telefona"</string>
+ <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Povezan na server za prijenos podataka"</string>
+ <string name="bluetooth_map_profile_summary_connected" msgid="8191407438851351713">"Povezano na mapu"</string>
+ <string name="bluetooth_sap_profile_summary_connected" msgid="8561765057453083838">"Povezan na SAP"</string>
+ <string name="bluetooth_opp_profile_summary_not_connected" msgid="1267091356089086285">"Nije povezan na server za prijenos podataka"</string>
+ <string name="bluetooth_hid_profile_summary_connected" msgid="3381760054215168689">"Spojen na ulazni uređaj"</string>
<string name="bluetooth_pan_user_profile_summary_connected" msgid="4602294638909590612">"Pov. na ur. za pris. int."</string>
<string name="bluetooth_pan_nap_profile_summary_connected" msgid="1561383706411975199">"Dij. lok. int. veze s ur."</string>
- <!-- no translation found for bluetooth_pan_profile_summary_use_for (5664884523822068653) -->
- <skip />
- <!-- no translation found for bluetooth_map_profile_summary_use_for (5154200119919927434) -->
- <skip />
- <!-- no translation found for bluetooth_sap_profile_summary_use_for (7085362712786907993) -->
- <skip />
- <!-- no translation found for bluetooth_a2dp_profile_summary_use_for (4630849022250168427) -->
- <skip />
- <!-- no translation found for bluetooth_headset_profile_summary_use_for (8705753622443862627) -->
- <skip />
- <!-- no translation found for bluetooth_opp_profile_summary_use_for (1255674547144769756) -->
- <skip />
- <!-- no translation found for bluetooth_hid_profile_summary_use_for (232727040453645139) -->
- <skip />
- <!-- no translation found for bluetooth_pairing_accept (6163520056536604875) -->
- <skip />
- <!-- no translation found for bluetooth_pairing_accept_all_caps (6061699265220789149) -->
- <skip />
- <!-- no translation found for bluetooth_pairing_decline (4185420413578948140) -->
- <skip />
- <!-- no translation found for bluetooth_pairing_will_share_phonebook (4982239145676394429) -->
- <skip />
- <!-- no translation found for bluetooth_pairing_error_message (3748157733635947087) -->
- <skip />
- <!-- no translation found for bluetooth_pairing_pin_error_message (8337234855188925274) -->
- <skip />
- <!-- no translation found for bluetooth_pairing_device_down_error_message (7870998403045801381) -->
- <skip />
- <!-- no translation found for bluetooth_pairing_rejected_error_message (1648157108520832454) -->
- <skip />
- <!-- no translation found for accessibility_wifi_off (1166761729660614716) -->
- <skip />
- <!-- no translation found for accessibility_no_wifi (8834610636137374508) -->
- <skip />
- <!-- no translation found for accessibility_wifi_one_bar (4869376278894301820) -->
- <skip />
- <!-- no translation found for accessibility_wifi_two_bars (3569851234710034416) -->
- <skip />
- <!-- no translation found for accessibility_wifi_three_bars (8134185644861380311) -->
- <skip />
- <!-- no translation found for accessibility_wifi_signal_full (7061045677694702) -->
- <skip />
+ <string name="bluetooth_pan_profile_summary_use_for" msgid="5664884523822068653">"Koristi za pristup internetu"</string>
+ <string name="bluetooth_map_profile_summary_use_for" msgid="5154200119919927434">"Koristi za mapu"</string>
+ <string name="bluetooth_sap_profile_summary_use_for" msgid="7085362712786907993">"Koristi za pristup SIM-u"</string>
+ <string name="bluetooth_a2dp_profile_summary_use_for" msgid="4630849022250168427">"Koristi za zvuk medija"</string>
+ <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Koristi za zvuk telefona"</string>
+ <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Koristi za prijenos fajlova"</string>
+ <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Koristi kao ulaz"</string>
+ <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Upari"</string>
+ <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"UPARI"</string>
+ <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Otkaži"</string>
+ <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"Uparivanje odobrava pristup kontaktima i istoriji poziva kada je uspostavljeno."</string>
+ <string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"Nije se moguće upariti s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"Nije se moguće upariti s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g> zbog pogrešnog PIN-a ili pristupnog koda."</string>
+ <string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"Ne može komunicirati sa uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"Uređaj <xliff:g id="DEVICE_NAME">%1$s</xliff:g> je odbio uparivanje."</string>
+ <string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi isključen."</string>
+ <string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi nije povezan."</string>
+ <string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fi jedna crtica."</string>
+ <string name="accessibility_wifi_two_bars" msgid="3569851234710034416">"Wi-Fi dvije crtice."</string>
+ <string name="accessibility_wifi_three_bars" msgid="8134185644861380311">"Wi-Fi tri crtice."</string>
+ <string name="accessibility_wifi_signal_full" msgid="7061045677694702">"Wi-Fi puni signal."</string>
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Uklonjene aplikacije"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Uklonjene aplikacije i korisnici"</string>
@@ -162,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Izlaz za pretvaranje teksta u govor"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Brzina govora"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Brzina kojom se izgovara tekst"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Visina"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Utječe na ton sintetiziranog govora"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Jezik"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Koristi sistemski jezik"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Jezik nije izabran"</string>
@@ -177,27 +118,27 @@
<string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> je u potpunosti podržan"</string>
<string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> zahtjeva mrežnu vezu"</string>
<string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> nije podržan"</string>
- <!-- no translation found for tts_status_checking (5339150797940483592) -->
- <skip />
+ <string name="tts_status_checking" msgid="5339150797940483592">"Provjerava se…"</string>
<string name="tts_engine_settings_title" msgid="3499112142425680334">"Postavke za <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
<string name="tts_engine_settings_button" msgid="1030512042040722285">"Pokreni postavke programa"</string>
<string name="tts_engine_preference_section_title" msgid="448294500990971413">"Željeni program"</string>
<string name="tts_general_section_title" msgid="4402572014604490502">"Opće"</string>
- <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
- <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
- <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
- <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
- <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
- <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
- <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
- <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
- <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
+ <string-array name="tts_rate_entries">
+ <item msgid="6695494874362656215">"Veoma sporo"</item>
+ <item msgid="4795095314303559268">"Sporo"</item>
+ <item msgid="8903157781070679765">"Normalno"</item>
+ <item msgid="164347302621392996">"Brzo"</item>
+ <item msgid="5794028588101562009">"Brže"</item>
+ <item msgid="7163942783888652942">"Veoma brzo"</item>
+ <item msgid="7831712693748700507">"Ubrzano"</item>
+ <item msgid="5194774745031751806">"Veoma ubrzano"</item>
+ <item msgid="9085102246155045744">"Najbrže"</item>
+ </string-array>
<string name="choose_profile" msgid="8229363046053568878">"Odaberite profil"</string>
<string name="category_personal" msgid="1299663247844969448">"Lično"</string>
<string name="category_work" msgid="8699184680584175622">"Posao"</string>
<string name="development_settings_title" msgid="215179176067683667">"Opcije za programere"</string>
- <!-- no translation found for development_settings_enable (542530994778109538) -->
- <skip />
+ <string name="development_settings_enable" msgid="542530994778109538">"Omogući opcije za programere"</string>
<string name="development_settings_summary" msgid="1815795401632854041">"Postavi opcije za razvoj aplikacija"</string>
<string name="development_settings_not_available" msgid="4308569041701535607">"Opcije za programere nisu dostupne za ovog korisnika"</string>
<string name="vpn_settings_not_available" msgid="956841430176985598">"VPN postavke nisu dostupne za ovog korisnika"</string>
@@ -306,18 +247,12 @@
<string name="app_process_limit_title" msgid="4280600650253107163">"Ograničenje procesa u pozadini"</string>
<string name="show_all_anrs" msgid="28462979638729082">"Prikaži sve ANR-ove"</string>
<string name="show_all_anrs_summary" msgid="641908614413544127">"Prik. dijalog Aplikacija ne reagira za apl. u poz."</string>
- <!-- no translation found for force_allow_on_external (3215759785081916381) -->
- <skip />
- <!-- no translation found for force_allow_on_external_summary (3191952505860343233) -->
- <skip />
- <!-- no translation found for force_resizable_activities (8615764378147824985) -->
- <skip />
- <!-- no translation found for force_resizable_activities_summary (4508217476997182216) -->
- <skip />
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="force_allow_on_external" msgid="3215759785081916381">"Nametni aplikacije na vanjskoj pohrani"</string>
+ <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Dozvoljava da bilo koja aplikacija bude upisana na vanjsku pohranu, bez obzira na vrijednosti manifesta."</string>
+ <string name="force_resizable_activities" msgid="8615764378147824985">"Nametni aktivnostima mijenjanje veličina"</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Neka sve aktivnosti budu takve da mogu mijenjati veličinu za prikaz sa više prozora, bez obzira na prikazane vrijednosti."</string>
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Omogući prozore nepravilnih oblika"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Omogućiti podršku za eksperimentalne prozore nepravilnih oblika."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Lozinka za rezervnu kopiju radne površine"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Potpune sigurnosne kopije za računare trenutno nisu zaštićene"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Dodirnite da promijenite ili uklonite lozinku za potpune rezervne kopije sa radne površine"</string>
@@ -339,32 +274,17 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktivno. Dodirnite za promjenu opcije."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Pokrenute usluge"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Prikažite trenutno pokrenute usluge i upravljajte njima"</string>
- <!-- no translation found for night_mode_title (2594133148531256513) -->
- <skip />
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <!-- no translation found for night_mode_no (9171772244775838901) -->
- <skip />
- <!-- no translation found for night_mode_yes (2218157265997633432) -->
- <skip />
- <string name="night_mode_auto" msgid="7508348175804304327">"Automatski"</string>
- <!-- no translation found for select_webview_provider_title (4628592979751918907) -->
- <skip />
- <!-- no translation found for select_webview_provider_dialog_title (4370551378720004872) -->
- <skip />
- <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
- <skip />
- <!-- no translation found for convert_to_file_encryption (3060156730651061223) -->
- <skip />
- <!-- no translation found for convert_to_file_encryption_enabled (2861258671151428346) -->
- <skip />
- <!-- no translation found for convert_to_file_encryption_done (7859766358000523953) -->
- <skip />
- <!-- no translation found for title_convert_fbe (1263622876196444453) -->
- <skip />
- <!-- no translation found for convert_to_fbe_warning (6139067817148865527) -->
- <skip />
- <!-- no translation found for button_convert_fbe (5152671181309826405) -->
- <skip />
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Omogućiti višeprocesni WebView"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Pokrenite WebView operatera u izolovanom procesu."</string>
+ <string name="select_webview_provider_title" msgid="4628592979751918907">"Postavljanje WebViewa"</string>
+ <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Podesi WebView"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Primjena izabranog prikaza weba ne važi jer je spisak izbora primjene zastario. Spisak se sada treba ažurirati."</string>
+ <string name="convert_to_file_encryption" msgid="3060156730651061223">"Pretvori u šifrirani fajl"</string>
+ <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Pretvaranje…"</string>
+ <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Fajl je već šifriran"</string>
+ <string name="title_convert_fbe" msgid="1263622876196444453">"Pretvaranje u šifrirane fajlove"</string>
+ <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Pretvori particiju sa podacima u particiju šifriranu sistemom fajlova.\n !! Upozorenje!! Ovo će izbrisati sve vaše podatke.\n Ova funkcija je u alfa fazi razvoja i možda neće ispravno raditi.\n Pritisnite \'Obriši i pretvori…\" da nastavite."</string>
+ <string name="button_convert_fbe" msgid="5152671181309826405">"Obriši i pretvori…"</string>
<string name="picture_color_mode" msgid="4560755008730283695">"Režim boja Slika"</string>
<string name="picture_color_mode_desc" msgid="1141891467675548590">"Koristi sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="7482661936053801862">"Onemogućeno"</string>
@@ -375,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Ispravka boje"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova funkcija je eksperimentalna te može utjecati na performanse."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Zamjenjuje <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Još otprilike <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo vreme je otprilike <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pune baterije"</string>
@@ -391,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Ne puni se"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ne puni se"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Puna"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Onemogućio administrator"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Pod kontrolom administratora"</string>
<string name="home" msgid="8263346537524314127">"Početna stranica"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"prije <xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"Još otprilike <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 333868b..d4d2f6c 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Síntesi de veu"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Velocitat de veu"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocitat de lectura del text"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"To"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Afecta el to de la veu sintetitzada"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Utilitza l\'idioma del sistema"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"No has seleccionat cap idioma"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Força permís d\'aplicacions a l\'emmagatzem. extern"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Permet que les aplicacions es puguin escriure en un dispositiu d’emmagatzematge extern, independentment dels valors definits"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Força l\'ajust de la mida de les activitats"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Permet ajustar la mida de totes les activitats per al mode multifinestra, independentment dels valors definits."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permet ajustar la mida de totes les activitats per al mode multifinestra, independentment dels valors definits."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Activa les finestres de format lliure"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Activa la compatibilitat amb les finestres de format lliure experimentals."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Activa la compatibilitat amb finestres de format lliure experimentals."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Contrasenya per a còpies d\'ordinador"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Les còpies de seguretat d\'ordinador completes no estan protegides"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Toca per canviar o suprimir la contrasenya per a les còpies de seguretat completes de l\'ordinador"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aplicació activa. Toca per desactivar-la."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Serveis en execució"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Visualitza i controla els serveis en execució"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Mode nocturn"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Desactivat"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Sempre activat"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automàtic"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Activa WebView amb multiprocés"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Executa els renderitzadors de WebView en un procés aïllat."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementació de WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Configura la implementació de WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"La implementació de WebView que has triat està desactivada i s\'ha d\'activar per utilitzar-la. Vols activar-la?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"La implementació de WebView que s\'ha triat no és vàlida perquè la llista d\'opcions d\'implementació ha quedat inactiva. Ara la llista ja hauria d\'estar actualitzada."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Converteix en l\'encriptació de fitxers"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converteix…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"El fitxer ja està encriptat"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correcció del color"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Aquesta funció és experimental i pot afectar el rendiment."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"S\'ha substituït per <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Temps restant aproximat: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g>: falten aproximadament <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"No s\'està carregant"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"No s\'està carregant"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Plena"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Opció desactivada per l\'administrador"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlat per l\'administrador"</string>
<string name="home" msgid="8263346537524314127">"Inici"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"Fa <xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"Temps restant: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index e219959..00d4f47 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Převod textu na řeč"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Rychlost řeči"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Rychlost mluveného textu"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Výška"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Určuje tón syntetizované řeči"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Jazyk"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Použít jazyk systému"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Nebyl vybrán jazyk"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Vynutit povolení aplikací na externím úložišti"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Každou aplikaci bude možné zapsat do externího úložiště, bez ohledu na hodnoty manifestu"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Vynutit možnost změny velikosti aktivit"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Velikost všech aktivit bude možné změnit na několik oken (bez ohledu na hodnoty manifestu)."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Umožnit změnu velikosti všech aktivit na několik oken (bez ohledu na hodnoty manifestu)"</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Aktivovat okna s volným tvarem"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Aktivuje podporu experimentálních oken s volným tvarem."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Aktivovat podporu experimentálních oken s volným tvarem"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Heslo pro zálohy v počítači"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Úplné zálohy v počítači nejsou v současné době chráněny"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tuto možnost vyberte, chcete-li změnit nebo odebrat heslo pro úplné zálohy do počítače"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktivní. Klepnutím možnost přepnete."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Spuštěné služby"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Umožňuje zobrazit a ovládat aktuálně spuštěné služby"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Noční režim"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Vypnuto"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Vždy zapnuto"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automatický"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Povolit WebView ve více procesech"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Spouštět moduly vykreslení WebView jako samostatné procesy."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementace WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Nastavte implementaci WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Vybraná implementace WebView je zakázána a nelze ji použít. Chcete ji povolit a použít?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Vybraná implementace WebView není platná, protože seznam možností implementace je zastaralý. Seznam je potřeba aktualizovat."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Převést na šifrování souborů"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Převést…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Obsah je již na úrovni souborů zašifrován"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korekce barev"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Funkce je experimentální a může mít vliv na výkon."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Přepsáno nastavením <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Zbývající čas: <xliff:g id="TIME">%1$s</xliff:g> (přibližně)"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – zbývá přibližně <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabití"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Nenabíjí se"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nenabíjí se"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Nabitá"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Zakázáno administrátorem"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Spravováno administrátorem"</string>
<string name="home" msgid="8263346537524314127">"Plocha"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"před <xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"Zbývající čas: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 6acdcc7..398875a 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Oplæsning"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Talehastighed"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Oplæsningshastighed for tekst"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Toneleje"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Påvirker tonen af den syntetiserede tale"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Sprog"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Brug systemsprog"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Der er ikke valgt sprog"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Gennemtving tilladelse til eksternt lager"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Gør det muligt at overføre enhver app til et eksternt lager uafhængigt af manifestværdier"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Tving aktiviteter til at kunne tilpasses"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Sørger for, at alle aktiviteter kan tilpasses flere vinduer uafhængigt af manifestværdier."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Tillad, at alle aktiviteter kan tilpasses flere vinduer uafhængigt af manifestværdier."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Aktivér vinduer i frit format"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Aktiverer understøttelse af eksperimentelle vinduer i frit format."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Aktivér understøttelse af eksperimentelle vinduer i frit format."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Kode til lokal sikkerhedskopi"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Lokale fuldstændige sikkerhedskopieringer er i øjeblikket ikke beskyttet"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tryk for at skifte eller fjerne adgangskoden til fuld lokal sikkerhedskopiering"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktiv. Tryk for at skifte."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Kørende tjenester"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Vis og kontrollér kørende tjenester"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Nattilstand"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Deaktiveret"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Altid slået til"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automatisk"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Aktivér WebView i flere processer"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Kør WebView-gengivelse i en isoleret proces."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementering"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Konfigurer WebView-implementering"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Den valgte WebView-implementering er deaktiveret og skal aktiveres, før den kan bruges. Vil du aktivere den?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Den valgte WebView-implementering er ugyldig, da listen over implementeringsvalg var forældet. Listen bør nu være opdateret."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertér til filkryptering"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertér…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Allerede filkrypteret"</string>
@@ -296,7 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korriger farver"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Denne funktion er eksperimentel og kan påvirke ydeevnen."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Tilsidesat af <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca. <xliff:g id="TIME">%2$s</xliff:g> tilbage"</string>
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca. <xliff:g id="TIME">%1$s</xliff:g> tilbage"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – ca. <xliff:g id="TIME">%2$s</xliff:g> tilbage"</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til fuldt opladet"</string>
@@ -311,7 +310,7 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Oplader ikke"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Oplader ikke"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Fuld"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Deaktiveret af administratoren"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kontrolleret af administratoren"</string>
<string name="home" msgid="8263346537524314127">"Start"</string>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> siden"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> tilbage"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 5f4f60b..2a56425 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Text-in-Sprache-Ausgabe"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Sprechgeschwindigkeit"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Geschwindigkeit, mit der der Text gesprochen wird"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tonlage"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Beeinflusst den Ton der künstlichen Sprache"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Sprache"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Systemsprache verwenden"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Keine Sprache ausgewählt"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Externe Speichernutzung von Apps erlauben"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Ermöglicht es jeder qualifizierten App, Daten auf externen Speicher zu schreiben, unabhängig von den Manifestwerten"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Anpassen der Größe von Aktivitäten erzwingen"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Ermöglicht es, die Größe aller Aktivitäten an den Mehrfenstermodus anzupassen, unabhängig von den Manifestwerten."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Größe aller Aktivitäten an den Mehrfenstermodus anpassen, unabhängig von den Manifestwerten."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Freiform-Fenster zulassen"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Unterstützt experimentelle Freiform-Fenster."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Experimentelle Freiform-Fenster unterstützen."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Desktop-Sicherungspasswort"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Vollständige Desktop-Sicherungen sind momentan nicht passwortgeschützt."</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Zum Ändern oder Entfernen des Passworts für vollständige Desktop-Sicherungen tippen"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktiv. Zum Wechseln tippen."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Aktive Dienste"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Momentan ausgeführte Dienste anzeigen und steuern"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Nachtmodus"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Deaktiviert"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Immer an"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automatisch"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"WebView-Simultanverarbeitung aktivieren"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView-Renderer isoliert ausführen."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-Implementierung"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView-Implementierung festlegen"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Die ausgewählte WebView-Implementierung ist deaktiviert. Um sie nutzen zu können, muss sie aktiviert sein. Möchtest du sie aktivieren?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Die ausgewählte WebView-Implementierung ist ungültig, weil die Liste der Implementierungsmöglichkeiten veraltet war. Die Liste sollte jetzt aktualisiert sein."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Zu Dateiverschlüsselung wechseln"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Wechseln…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Dateiverschlüsselung wird bereits verwendet."</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Farbkorrektur"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Hierbei handelt es sich um eine experimentelle Funktion. Dies kann sich auf die Leistung auswirken."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Außer Kraft gesetzt von \"<xliff:g id="TITLE">%1$s</xliff:g>\""</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Noch ca. <xliff:g id="TIME">%1$s</xliff:g> verbleibend"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – noch etwa <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – voll in <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Wird nicht geladen"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Wird nicht geladen"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Voll"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Vom Administrator deaktiviert"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Durch den Administrator verwaltet"</string>
<string name="home" msgid="8263346537524314127">"Startseite"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"Vor <xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"Noch <xliff:g id="ID_1">%1$s</xliff:g> verbleibend"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 826e823..dd6bb4f 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Έξοδος μετατροπής κειμένου σε ομιλία"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Ταχύτητα λόγου"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Ταχύτητα με την οποία εκφωνείται το κείμενο"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Τόνος"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Επηρεάζει τον τόνο της σύνθεσης ομιλίας"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Γλώσσα"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Χρήση γλώσσας συστήματος"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Δεν έχει επιλεγεί γλώσσα"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Να επιτρέπονται υποχρεωτικά εφαρμογές σε εξωτ.συσ."</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Κάνει κάθε εφαρμογή κατάλληλη για εγγραφή σε εξωτερικό χώρο αποθήκευσης, ανεξάρτητα από τις τιμές του μανιφέστου"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Αναγκαστική δυνατότητα αλλαγής μεγέθους δραστηριοτήτων"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Να έχουν όλες οι δραστηριότητες δυνατότητα αλλαγής μεγέθους για την προβολή πολλαπλών παραθύρων, ανεξάρτητα από τις τιμές του μανιφέστου."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Να έχουν όλες οι δραστηριότητες δυνατότητα αλλαγής μεγέθους για την προβολή πολλαπλών παραθύρων, ανεξάρτητα από τις τιμές του μανιφέστου."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Ενεργοποίηση παραθύρων ελεύθερης μορφής"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Ενεργοποιεί την υποστήριξη για πειραματικά παράθυρα ελεύθερης μορφής."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Ενεργοποίηση υποστήριξης για πειραματικά παράθυρα ελεύθερης μορφής."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Εφ/κός κωδικός desktop"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Τα πλήρη αντίγραφα ασφαλείας επιφάνειας εργασίας δεν προστατεύονται αυτήν τη στιγμή"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Πατήστε για αλλαγή ή κατάργηση του κωδικού πρόσβασης για τα πλήρη αντίγραφα ασφαλείας επιφάνειας εργασίας"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Ενεργό. Πατήστε για εναλλαγή."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Υπηρεσίες που εκτελούνται"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Προβολή και έλεγχος των εφαρμογών που εκτελούνται αυτή τη στιγμή"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Λειτουργία νύχτας"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Ανενεργό"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Πάντα ενεργό"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Αυτόματο"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Ενεργοποίηση WebView πολλαπλών διεργασιών"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Εκτέλεση λειτ.απόδοσης WebView σε μια απομονωμένη διεργασία."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Υλοποίηση WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Ορισμός υλοποίησης WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Η επιλεγμένη ενσωμάτωση WebView είναι απενεργοποιημένη και θα πρέπει να ενεργοποιηθεί για να χρησιμοποιηθεί. Θέλετε να την ενεργοποιήσετε;"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Η επιλεγμένη υλοποίηση WebView δεν είναι έγκυρη επειδή η λίστα των επιλογών υλοποίησης δεν είναι ενημερωμένη. Η λίστα θα πρέπει να ενημερωθεί."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Μετατροπή σε κρυπτογράφηση αρχείου"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Μετατροπή…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Με κρυπτογράφηση αρχείου"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Διόρθωση χρωμάτων"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Αυτή η λειτουργία είναι πειραματική και ενδεχομένως να επηρεάσει τις επιδόσεις."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Αντικαταστάθηκε από <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Απομένουν περίπου <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - απομένουν περίπου <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για πλήρη φόρτιση"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Δεν φορτίζει"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Δεν φορτίζει"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Πλήρης"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Απενεργοποιήθηκε από το διαχειριστή"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Ελέγχονται από το διαχειριστή"</string>
<string name="home" msgid="8263346537524314127">"Αρχική οθόνη"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"Πριν από <xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"Απομένουν <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 481cc47..1ed6dbd 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Text-to-speech output"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Speech rate"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Speed at which the text is spoken"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Pitch"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Affects the tone of the synthesised speech"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Language"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Use system language"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Language not selected"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Force allow apps on external"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Makes any app eligible to be written to external storage, regardless of manifest values"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Force activities to be re-sizable"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Makes all activities re-sizable for multi-window, regardless of manifest values."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Make all activities resizable for multi-window, regardless of manifest values."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Enable freeform windows"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Enables support for experimental freeform windows."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Enable support for experimental freeform windows."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Desktop backup password"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Desktop full backups aren\'t currently protected"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tap to change or remove the password for desktop full backups"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Active. Tap to toggle."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Running services"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"View and control currently running services"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Night mode"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Disabled"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Always on"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automatic"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Enable multi-process WebView"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Run WebView renderers in an isolated process."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView implementation"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Set WebView implementation"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"The chosen WebView implementation is disabled and must be enabled to be used, do you wish to enable it?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"The chosen WebView implementation is invalid because the list of implementation choices grew stale. The list should now be updated."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Convert to file encryption"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convert…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Already file encrypted"</string>
@@ -296,7 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Colour correction"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="power_remaining_duration_only" msgid="4400068916452346544">"Approx. <xliff:g id="TIME">%2$s</xliff:g> left"</string>
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Approx. <xliff:g id="TIME">%1$s</xliff:g> left"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – approx. <xliff:g id="TIME">%2$s</xliff:g> left"</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full"</string>
@@ -311,7 +310,7 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Not charging"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Not charging"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Full"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Disabled by administrator"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlled by admin"</string>
<string name="home" msgid="8263346537524314127">"Home"</string>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> ago"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> left"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 481cc47..1ed6dbd 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Text-to-speech output"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Speech rate"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Speed at which the text is spoken"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Pitch"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Affects the tone of the synthesised speech"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Language"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Use system language"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Language not selected"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Force allow apps on external"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Makes any app eligible to be written to external storage, regardless of manifest values"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Force activities to be re-sizable"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Makes all activities re-sizable for multi-window, regardless of manifest values."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Make all activities resizable for multi-window, regardless of manifest values."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Enable freeform windows"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Enables support for experimental freeform windows."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Enable support for experimental freeform windows."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Desktop backup password"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Desktop full backups aren\'t currently protected"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tap to change or remove the password for desktop full backups"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Active. Tap to toggle."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Running services"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"View and control currently running services"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Night mode"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Disabled"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Always on"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automatic"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Enable multi-process WebView"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Run WebView renderers in an isolated process."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView implementation"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Set WebView implementation"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"The chosen WebView implementation is disabled and must be enabled to be used, do you wish to enable it?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"The chosen WebView implementation is invalid because the list of implementation choices grew stale. The list should now be updated."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Convert to file encryption"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convert…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Already file encrypted"</string>
@@ -296,7 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Colour correction"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="power_remaining_duration_only" msgid="4400068916452346544">"Approx. <xliff:g id="TIME">%2$s</xliff:g> left"</string>
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Approx. <xliff:g id="TIME">%1$s</xliff:g> left"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – approx. <xliff:g id="TIME">%2$s</xliff:g> left"</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full"</string>
@@ -311,7 +310,7 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Not charging"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Not charging"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Full"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Disabled by administrator"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlled by admin"</string>
<string name="home" msgid="8263346537524314127">"Home"</string>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> ago"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> left"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 481cc47..1ed6dbd 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Text-to-speech output"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Speech rate"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Speed at which the text is spoken"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Pitch"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Affects the tone of the synthesised speech"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Language"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Use system language"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Language not selected"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Force allow apps on external"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Makes any app eligible to be written to external storage, regardless of manifest values"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Force activities to be re-sizable"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Makes all activities re-sizable for multi-window, regardless of manifest values."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Make all activities resizable for multi-window, regardless of manifest values."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Enable freeform windows"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Enables support for experimental freeform windows."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Enable support for experimental freeform windows."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Desktop backup password"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Desktop full backups aren\'t currently protected"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tap to change or remove the password for desktop full backups"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Active. Tap to toggle."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Running services"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"View and control currently running services"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Night mode"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Disabled"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Always on"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automatic"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Enable multi-process WebView"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Run WebView renderers in an isolated process."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView implementation"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Set WebView implementation"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"The chosen WebView implementation is disabled and must be enabled to be used, do you wish to enable it?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"The chosen WebView implementation is invalid because the list of implementation choices grew stale. The list should now be updated."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Convert to file encryption"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convert…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Already file encrypted"</string>
@@ -296,7 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Colour correction"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="power_remaining_duration_only" msgid="4400068916452346544">"Approx. <xliff:g id="TIME">%2$s</xliff:g> left"</string>
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Approx. <xliff:g id="TIME">%1$s</xliff:g> left"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – approx. <xliff:g id="TIME">%2$s</xliff:g> left"</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full"</string>
@@ -311,7 +310,7 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Not charging"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Not charging"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Full"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Disabled by administrator"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlled by admin"</string>
<string name="home" msgid="8263346537524314127">"Home"</string>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> ago"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> left"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 7380240..3f2befd 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Salida de texto a voz"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Velocidad de voz"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocidad en la que se habla el texto"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Sonido"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Afecta el tono de la voz sintetizada"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Usar el idioma del sistema"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Idioma no seleccionado"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Forzar permisos en almacenamiento externo"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Cualquier aplicación puede escribirse en una memoria externa, independientemente de los valores del manifiesto."</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Forzar actividades para que cambien de tamaño"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Permite que todas las actividades puedan cambiar de tamaño para el modo multiventana, sin importar los valores del manifiesto."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permitir que todas las actividades puedan cambiar de tamaño para el modo multiventana, sin importar los valores del manifiesto."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Habilitar ventanas de forma libre"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Habilita la admisión de ventanas de forma libre experimentales."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Habilitar la admisión de ventanas de forma libre experimentales."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Contraseñas"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Tus copias de seguridad de escritorio no están protegidas por contraseña."</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Presiona para cambiar o quitar la contraseña de las copias de seguridad completas de tu escritorio."</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Activa. Presiona para activar o desactivar."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"En ejecución"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Ver y controlar servicios actuales en ejecución"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Modo nocturno"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Inhabilitado"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Siempre activado"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automático"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Habilitar multiproceso WebView"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Ejecutar procesadores de WebView en un proceso aislado."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementación de WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Configurar la implementación de WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"La implementación de WebView que elegiste está inhabilitada. Debes habilitarla para poder usarla. ¿Quieres hacerlo?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"La implementación de WebView elegida no es válida debido a que las opciones de la lista de implementación están inactivas. Debes actualizar la lista."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Convertir a encriptación de archivo"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convertir…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Ya está encriptado"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Corrección de color"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta función es experimental y puede afectar el rendimiento."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Reemplazado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Falta <xliff:g id="TIME">%1$s</xliff:g> aproximadamente"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g>: alrededor de <xliff:g id="TIME">%2$s</xliff:g> para completar la carga"</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> para completar la carga"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"No se está cargando."</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"No se realiza la carga"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Cargado"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Inhabilitada por el administrador"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlada por el administrador"</string>
<string name="home" msgid="8263346537524314127">"Página principal"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"Hace <xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"Falta <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 1cf51fe..a01d2e9 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Síntesis de voz"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Velocidad de la voz"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocidad a la que se lee el texto"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tono"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Afecta al tono de la síntesis de voz"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Usar idioma del sistema"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Idioma no seleccionado"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Forzar permiso de aplicaciones de forma externa"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Hace que cualquier aplicación se pueda escribir en un dispositivo de almacenamiento externo, independientemente de los valores definidos"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Forzar el ajuste de tamaño de las actividades"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Permite que se pueda ajustar el tamaño de todas las actividades para el modo multiventana, independientemente de los valores establecidos."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permite que se pueda ajustar el tamaño de todas las actividades para el modo multiventana, independientemente de los valores establecidos."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Habilitar ventanas de forma libre"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Permite utilizar ventanas de forma libre experimentales."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Habilita la opción para utilizar ventanas de forma libre experimentales."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Contraseña para copias de ordenador"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Las copias de seguridad completas de ordenador no están protegidas"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Toca para cambiar o quitar la contraseña de las copias de seguridad completas del escritorio"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Activa. Toca para alternar."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Servicios en ejecución"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Ver y controlar los servicios en ejecución"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Modo nocturno"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Inhabilitado"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Siempre activado"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automático"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Habilitar WebView multiproceso"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Ejecuta procesadores de WebView en un proceso aislado."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementación de WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Establecer implementación de WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"La implementación de WebView seleccionada está inhabilitada y debes habilitarla para utilizarla. ¿Quieres hacerlo?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"La implementación de WebView seleccionada no es válida porque la lista de opciones de implementación estaba inactiva. Esta ya debería estar actualizada."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Convertir a cifrado de archivo"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convertir…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Ya está cifrado"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Corrección del color"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta función es experimental y puede afectar al rendimiento."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Tiempo restante (aproximado): <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - Quedan <xliff:g id="TIME">%2$s</xliff:g> aproximadamente"</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar la batería"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"No se está cargando"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"No se está cargando"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Completa"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Inhabilitada por el administrador"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlada por el administrador"</string>
<string name="home" msgid="8263346537524314127">"Inicio"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"Hace <xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"Tiempo restante: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-et-rEE/strings.xml b/packages/SettingsLib/res/values-et-rEE/strings.xml
index c5153ff..27546ce 100644
--- a/packages/SettingsLib/res/values-et-rEE/strings.xml
+++ b/packages/SettingsLib/res/values-et-rEE/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Kõnesünteesi väljund"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Kõnekiirus"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Teksti rääkimise kiirus"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Helikõrgus"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Mõjutab sünteesitud kõne tooni"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Keel"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Süsteemi keele kasutamine"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Keelt pole valitud"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Luba rakendused välises salvestusruumis"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Lubab rakendusi kirjutada välisesse salvestusruumi olenemata manifesti väärtustest"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Muuda tegevuste suurused muudetavaks"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Muudab kõigi tegevuste suurused mitme aknaga vaates olenemata manifesti väärtustest muudetavaks."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Muudetakse kõigi tegevuste suurused mitme aknaga vaates muudetavaks (manifesti väärtustest olenemata)."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Luba vabas vormis aknad"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Lubatakse katseliste vabas vormis akende tugi."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Lubatakse katseliste vabavormis akende tugi."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Arvutivarunduse parool"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Täielikud arvutivarundused pole praegu kaitstud"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Puudutage täielike arvutivarunduste parooli muutmiseks või eemaldamiseks"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktiivne. Puudutage vahetamiseks."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Käitatud teenused"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Praegu käitatud teenuste vaatamine ja juhtimine"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Öörežiim"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Keelatud"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Alati sees"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automaatne"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Luba mitme protsessiga WebView"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView\' renderdajad käitatakse eraldi protsessis."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView\' rakendamine"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView\' rakendamise seadistamine"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Valitud WebView\' rakendamisviis on keelatud ja see tuleb kasutamiseks lubada. Kas soovite selle lubada?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Valitud WebView\' rakendamine on sobimatu, kuna rakendamisvalikute loend aegus. Loendit tuleb nüüd värskendada."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Teisendamine failikrüpteeringuga andmeteks"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Teisenda …"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Juba failikrüpteeringuga"</string>
@@ -296,7 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Värviparandus"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"See funktsioon on katseline ja võib mõjutada toimivust."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Alistas <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="power_remaining_duration_only" msgid="4400068916452346544">"Umbes <xliff:g id="TIME">%2$s</xliff:g> on jäänud"</string>
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Umbes <xliff:g id="TIME">%1$s</xliff:g> on jäänud"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – jäänud on umbes <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, kuni aku on täis"</string>
@@ -311,7 +310,7 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Ei lae"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ei lae"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Täis"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Administraator on keelanud"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Juhib administraator"</string>
<string name="home" msgid="8263346537524314127">"Avaekraan"</string>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> tagasi"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> on jäänud"</string>
diff --git a/packages/SettingsLib/res/values-eu-rES/strings.xml b/packages/SettingsLib/res/values-eu-rES/strings.xml
index 1e06c6a..dd0e1cb 100644
--- a/packages/SettingsLib/res/values-eu-rES/strings.xml
+++ b/packages/SettingsLib/res/values-eu-rES/strings.xml
@@ -99,8 +99,10 @@
<string name="launch_defaults_none" msgid="4241129108140034876">"Ez dago hobespen lehenetsirik ezarrita"</string>
<string name="tts_settings" msgid="8186971894801348327">"Testua ahots bihurtzeko eginbidearen ezarpenak"</string>
<string name="tts_settings_title" msgid="1237820681016639683">"Testua ahots bihurtzeko eginbidearen irteera"</string>
- <string name="tts_default_rate_title" msgid="6030550998379310088">"Hizketa-abiadura"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Hizketaren abiadura"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Testua zer abiaduran esaten den"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tonua"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Hizketa sintetizatuaren tonuari eragiten dio"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Hizkuntza"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Erabili sistemaren hizkuntza"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Ez da hizkuntza hautatu"</string>
@@ -226,7 +228,7 @@
<string name="debug_layout" msgid="5981361776594526155">"Erakutsi diseinuaren mugak"</string>
<string name="debug_layout_summary" msgid="2001775315258637682">"Erakutsi kliparen mugak, marjinak, etab."</string>
<string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Behartu eskuin-ezker norabidea."</string>
- <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Behartu pantaila-diseinuaren norabidea eskuinetik ezkerrerakoa izatera eskualdeko ezarpen guztiekin."</string>
+ <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Behartu pantaila-diseinuaren norabidea eskuin-ezker izatera eskualdeko ezarpen guztiekin."</string>
<string name="show_cpu_usage" msgid="2389212910758076024">"Erakutsi PUZ erabilera"</string>
<string name="show_cpu_usage_summary" msgid="2113341923988958266">"PUZ erabilera erakusten duen pantaila-gainjartzea"</string>
<string name="force_hw_ui" msgid="6426383462520888732">"Behartu GPU errendatzea"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Behartu aplikazioak onartzea kanpoko biltegian"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Aplikazioek kanpoko memorian idatz dezakete, manifestuaren balioak kontuan izan gabe"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Behartu jardueren tamaina doitu ahal izatea"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Manifestuan jartzen duena jartzen duela ere, jarduera guztien tamaina doitzeko aukera ematen du, hainbat leihotan erabili ahal izan daitezen."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Eman aukera jarduera guztien tamaina doitzeko, hainbat leihotan erabili ahal izan daitezen, manifestuan jartzen duena jartzen duela ere."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Gaitu estilo libreko leihoak"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Estilo libreko leiho esperimentalak onartzen ditu."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Onartu estilo libreko leiho esperimentalak."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Tokiko babeskop. pasahitza"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Une honetan, ordenagailuko babeskopia osoak ez daude babestuta."</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Ordenagailuko eduki guztiaren babeskopia egiteko erabiltzen den pasahitza aldatzeko edo kentzeko, sakatu hau"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktibo. Aldatzeko, sakatu hau."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Abian diren zerbitzuak"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Ikusi eta kontrolatu unean abian diren zerbitzuak"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Gau modua"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Desgaituta"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Beti aktibatuta"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automatikoa"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Gaitu prozesu anitzeko WebView"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Exekutatu WebView errendatzaileak prozesu isolatu batean."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView implementation"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Set WebView implementation"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Desgaituta dago aukeratu den WebView inplementazioa. Erabili nahi izanez gero, gaitu egin behar duzu. Gaitu nahi al duzu?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Aukeratutako WebView inplementazioak ez du balio inplementazioen aukeren zerrenda zaharkituta gelditu delako. Zerrenda eguneratu behar da."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Eman fitxategietan oinarritutako enkriptatzea"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Enkriptatu…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Fitxategietan oinarritutako enkriptatzea dauka dagoeneko"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Kolore-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>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"<xliff:g id="TIME">%1$s</xliff:g> inguru guztiz kargatu arte"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> inguru. <xliff:g id="TIME">%2$s</xliff:g> geratzen d(ir)a"</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> guztiz kargatu arte"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Ez da kargatzen ari"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ez da kargatzen ari"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Beteta"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Administratzaileak desgaitu du"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Administratzaileak kontrolatzen du"</string>
<string name="home" msgid="8263346537524314127">"Hasierako pantaila"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"Duela <xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> guztiz kargatu arte"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index e023f247..0a2d111 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"خروجی تبدیل متن به گفتار"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"سرعت گفتار"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"سرعتی که متن خوانده میشود"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"زیر و بمی صدا"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"بر صدای متن گفته شده تأثیر میگذارد"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"زبان"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"استفاده از زبان سیستم"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"زبان انتخاب نشده است"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"اجازه اجباری به برنامههای دستگاه ذخیره خارجی"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"بدون توجه به مقادیر مانیفست، هر برنامهای را برای نوشتن در حافظه خارجی واجد شرایط میکند"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"اجبار فعالیتها به قابل تغییر اندازه بودن"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"بدون درنظر گرفتن مقادیر مانیفست، همه فعالیتها را برای چندپنجره قابل تغییر اندازه میکند."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"بدون توجه به مقادیر مانیفست، اندازه همه فعالیتها برای حالت چند پنجرهای میتواند تغییر کند."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"فعال کردن پنجرههای آزاد"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"پشتیبانی برای پنجرههای آزاد آزمایشی را امکانپذیر میکند"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"فعال کردن پشتیبانی برای پنجرههای آزاد آزمایشی."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"گذرواژه پشتیبانگیری محلی"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"پشتیبانگیری کامل رایانه درحال حاضر محافظت نمیشود"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"برای تغییر یا حذف گذرواژه برای نسخههای پشتیبان کامل رایانهای ضربه بزنید"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"فعال. برای تغییر حالت ضربه بزنید."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"سرویسهای در حال اجرا"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"مشاهده و کنترل سرویسهای در حال اجرای فعلی"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"حالت شب"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"غیرفعال است"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"همیشه روشن"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"خودکار"</string>
- <string name="select_webview_provider_title" msgid="4628592979751918907">"اجرای WebView"</string>
- <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"تنظیم اجرای WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"پیادهسازی WebView انتخابشده غیرفعال شده است و برای استفاده شدن باید فعال شود؛ میخواهید آن را فعال کنید؟"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"فعال کردن وبنما چند پردازشی"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"اجرای تولیدکننده تصویر وبنما در یک پردازش مجزا."</string>
+ <string name="select_webview_provider_title" msgid="4628592979751918907">"اجرای وبنما"</string>
+ <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"تنظیم اجرای وبنما"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"اجرای وبنما انتخابی نامعتبر است چون فهرست گزینههای اجرای انتخابی قدیمی شده است. این فهرست اکنون باید بهروزرسانی شود."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"تبدیل به رمزگذاری برحسب فایل"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"تبدیل…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"از قبل به رمزگذاری بر حسب فایل تبدیل شده است"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"تصحیح رنگ"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"این قابلیت آزمایشی است و ممکن است عملکرد را تحت تأثیر قرار دهد."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"توسط <xliff:g id="TITLE">%1$s</xliff:g> لغو شد"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"تقریباً <xliff:g id="TIME">%1$s</xliff:g> باقی مانده است"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - تقریباً <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"شارژ نمیشود"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"شارژ نمیشود"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"پر"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"سرپرست آن را غیرفعال کرده است"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"توسط سرپرست سیستم کنترل میشود"</string>
<string name="home" msgid="8263346537524314127">"صفحه اصلی"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> قبل"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> باقی مانده است"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index c4f572c..bb27bcf 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Tekstistä puheeksi -toisto"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Puheen nopeus"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Tekstin puhumisnopeus"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Äänenkorkeus"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Tämä vaikuttaa syntetisoidun puheen äänensävyyn."</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Kieli"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Käytä järjestelmän kieltä"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Kieltä ei ole valittu"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Salli aina ulkoinen tallennus"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Mahdollistaa sovellusten tallentamisen ulkoiseen tall.tilaan luettelosta riippumatta"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Pakota kaikki toiminnot hyväksymään koon muutos"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Pakottaa kaikki toiminnot hyväksymään koon muuttamisen rinnakkaisnäkymään luettelon arvoista riippumatta."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Pakota kaikki toiminnot hyväksymään koon muuttaminen usean ikkunan tilassa luettelon arvoista riippumatta."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Ota käyttöön vapaamuotoiset ikkunat"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Ottaa käyttöön kokeellisten vapaamuotoisten ikkunoiden tuen."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Ota kokeellisten vapaamuotoisten ikkunoiden tuki käyttöön."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Varmuuskop. salasana"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Tietokoneen kaikkien tietojen varmuuskopiointia ei ole tällä hetkellä suojattu"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Vaihda tai poista tietokoneen kaikkien tietojen varmuuskopioinnin salasana koskettamalla."</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Käytössä. Poista käytöstä koskettamalla."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Käynnissä olevat palvelut"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Tarkastele ja hallitse käynnissä olevia palveluita"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Yötila"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Ei käytössä"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Aina käytössä"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automaattinen"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"WebView\'n usean prosessin tila"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Suorita WebView\'n hahmontajat erillisinä prosesseina."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-käyttöönotto"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Määritä WebView-käyttöönotto"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Valittu WebView-käyttöönotto on poistettu käytöstä. Haluatko ottaa sen käyttöön?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Valittu WebView-toteutus ei kelpaa, sillä toteutusvaihtoehtojen lista vanhentui. Listan pitäisi nyt olla ajan tasalla."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Muunna tiedostojen salaukseksi"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Muunna…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Tiedostot on jo salattu."</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Värikorjaus"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Tämä ominaisuus on kokeellinen ja voi vaikuttaa suorituskykyyn."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Tämän ohittaa <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Noin <xliff:g id="TIME">%1$s</xliff:g> jäljellä"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – noin <xliff:g id="TIME">%2$s</xliff:g> jäljellä"</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kunnes täynnä"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Ei laturissa"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ei laturissa"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Täynnä"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Järjestelmänvalvojan käytöstä poistama"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Järjestelmänvalvoja hallinnoi tätä asetusta."</string>
<string name="home" msgid="8263346537524314127">"Aloitusnäyttö"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> sitten"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> jäljellä"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index f888ec8..7ca3f89 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Sortie de la synthèse vocale"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Cadence"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Vitesse à laquelle le texte est énoncé"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Ton"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Touche le ton utilisé pour la synthèse vocale"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Langue"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Utiliser la langue du système"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Langue non sélectionnée"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Forcer l\'autor. d\'applis sur stockage externe"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Permet enreg. d\'applis sur espace stockage externe"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Forcer les activités à être redimensionnables"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Permet de redimensionner toutes les activités pour le mode multifenêtre, indépendamment des valeurs du fichier manifeste."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permet de redimensionner toutes les activités pour le mode multifenêtre, indépendamment des valeurs du fichier manifeste."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Activer les fenêtres de forme libre"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Active la compatibilité avec les fenêtres de forme libre expérimentales."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Activer la compatibilité avec les fenêtres de forme libre expérimentales."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Mot de passe sauvegarde PC"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Les sauvegardes complètes sur PC ne sont pas protégées actuellement."</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Touchez pour modifier ou supprimer le mot de passe utilisé pour les sauvegardes complètes sur ordinateur."</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Application active. Touchez ici pour la désactiver."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Services en cours d\'exécution"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Afficher et contrôler les services en cours d\'exécution"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Mode Nuit"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Désactivé"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Toujours actif"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automatique"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Activer WebView multiprocessus"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Exécuter moteurs de rendu WebView dans un processus isolé."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Mise en œuvre WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Définir la mise en œuvre WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"La mise en œuvre WebView sélectionnée est désactivée. Vous devez l\'activer pour l\'utiliser. Souhaitez-vous l\'activer?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"La mise en œuvre WebView sélectionnée n\'est pas valide, car la liste de sélections de mises en œuvre est désormais obsolète. Cette liste devrait être mise à jour."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Convertir en chiffrement basé sur un fichier"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convertir..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Déjà chiffré par un fichier"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correction des couleurs"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Cette fonctionnalité est expérimentale et peut toucher les performances."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Il reste environ <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> %% – Temps restant : environ <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> %% (chargée à 100 %% dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"N\'est pas en charge"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"N\'est pas en charge"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Pleine"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Désactivé par l\'administrateur"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Contrôlé par l\'administrateur"</string>
<string name="home" msgid="8263346537524314127">"Accueil"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"Il y a <xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"Durée restante :<xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index dfc71f1..adfc7a3 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Synthèse vocale"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Cadence"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Vitesse à laquelle le texte est énoncé"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Ton"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Affecte le ton utilisé pour la synthèse vocale"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Langue"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Utiliser la langue du système"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Langue non sélectionnée"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Forcer disponibilité stockage externe pour applis"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Rend possible enregistrement de toute appli sur espace stockage externe, indépendamment valeurs fichier manifeste."</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Forcer possibilité de redimensionner les activités"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Permet de redimensionner toutes les activités pour le mode multifenêtre, indépendamment des valeurs du fichier manifeste."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permettre de redimensionner toutes les activités pour le mode multifenêtre, indépendamment des valeurs du fichier manifeste."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Activer les fenêtres de forme libre"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Active la compatibilité avec les fenêtres de forme libre expérimentales."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Activer la compatibilité avec les fenêtres de forme libre expérimentales."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Mot de passe sauvegarde PC"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Les sauvegardes complètes sur PC ne sont pas protégées actuellement."</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Appuyez pour modifier ou supprimer le mot de passe utilisé pour les sauvegardes complètes sur PC."</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Application active. Appuyez ici pour la désactiver."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Services en cours d\'exécution"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Afficher et contrôler les services en cours d\'exécution"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Mode Nuit"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Désactivé"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Toujours activé"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automatique"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Activer WebView multiprocessus"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Exécuter moteurs de rendu WebView dans un processus isolé."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Mise en œuvre WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Définir la mise en œuvre WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"La mise en œuvre WebView sélectionnée est désactivée. Vous devez l\'activer pour l\'utiliser. Souhaitez-vous l\'activer ?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"La mise en œuvre WebView sélectionnée n\'est pas valide, car la liste de sélections de mises en œuvre est désormais obsolète. Cette liste ne doit pas être mise à jour."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Convertir en chiffrement basé sur un fichier"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convertir…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Déjà chiffré via un fichier"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correction couleur"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Cette fonctionnalité est expérimentale et peut affecter les performances."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Il reste environ <xliff:g id="TIME">%1$s</xliff:g>."</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – Temps restant : <xliff:g id="TIME">%2$s</xliff:g> environ"</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> (chargée à 100 %% dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Pas en charge"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Débranchée"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"pleine"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Désactivé par l\'administrateur"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Contrôlé par l\'administrateur"</string>
<string name="home" msgid="8263346537524314127">"Accueil"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"Il y a <xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"Il reste <xliff:g id="ID_1">%1$s</xliff:g>."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-gl-rES/strings.xml b/packages/SettingsLib/res/values-gl-rES/strings.xml
index 20985bd..867a29d 100644
--- a/packages/SettingsLib/res/values-gl-rES/strings.xml
+++ b/packages/SettingsLib/res/values-gl-rES/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Síntese de voz"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Velocidade da fala"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocidade á que se di o texto"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Ton"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Afecta ao ton da voz sintetizada"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Utilizar idioma do sistema"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Idioma non seleccionado"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Forzar permiso de aplicacións de forma externa"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Fai que calquera aplicación se poida escribir nun almacenamento externo, independentemente dos valores expresados"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Forzar o axuste do tamaño das actividades"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Permite axustar o tamaño de todas as actividades para o modo de varias ventás, independentemente dos valores definidos."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permite axustar o tamaño de todas as actividades para o modo de varias ventás, independentemente dos valores definidos."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Activar ventás de forma libre"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Activa a compatibilidade con ventás de forma libre experimentais."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Activa a compatibilidade con ventás de forma libre experimentais."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Contrasinal para copias"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"As copias de seguridade de ordenador completas non están protexidas"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Toca para cambiar ou eliminar o contrasinal para as copias de seguranza completas do escritorio"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aplicación activa. Toca para alternar a configuración."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Servizos en execución"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Ver e controlar servizos actualmente en execución"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Modo nocturno"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Desactivado"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Sempre activada"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automático"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Activar WebView multiproceso"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Executa os procesadores de WebView nun proceso illado."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementación de WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Definir implementación de WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"A implementación de WebView escollida está desactivada e, para poder usala, debe estar activada. Queres activala?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"A implementación de WebView seleccionada non é válida porque a lista de opcións de implementación estaba inactiva. A lista xa debería estar actualizada."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Converter no encriptado baseado en ficheiros"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converter..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Xa se encriptou o ficheiro"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Corrección da cor"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta función é experimental e pode afectar ao rendemento."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Duración aproximada de <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - faltan aproximadamente <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar a carga"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Non se está cargando"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Non está cargando"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Completa"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Desactivado polo administrador"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Opción controlada polo administrador"</string>
<string name="home" msgid="8263346537524314127">"Inicio"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"Hai <xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"Tempo restante: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-gu-rIN/strings.xml b/packages/SettingsLib/res/values-gu-rIN/strings.xml
index 18917e0..54e7288 100644
--- a/packages/SettingsLib/res/values-gu-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-gu-rIN/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"ટેક્સ્ટ ટુ સ્પીચ આઉટપુટ"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"વાણી દર"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"ટેક્સ્ટ બોલાયેલ છે તે ઝડપ"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"પિચ"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"સિન્થેસાઇઝ કરેલ વાણીના ટોન પર અસર કરે છે"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"ભાષા"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"સિસ્ટમ ભાષાનો ઉપયોગ કરો"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"ભાષા પસંદ કરેલ નથી"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"બાહ્ય પર એપ્લિકેશનોને મંજૂરી આપવાની ફરજ પાડો"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"મેનિફેસ્ટ મૂલ્યોને ધ્યાનમાં લીધા સિવાય, કોઈપણ એપ્લિકેશનને બાહ્ય સ્ટોરેજ પર લખાવા માટે લાયક બનાવે છે"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"પ્રવૃત્તિઓને ફરીથી કદ યોગ્ય થવા માટે ફરજ પાડો"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"તમામ પ્રવૃત્તિઓને મલ્ટી-વિંડો માટે ફરીથી કદ બદલી શકે તેવી બનાવે છે, મેનીફેસ્ટ મુલ્યોને ધ્યાનમાં લીધા સિવાય."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"મૅનિફેસ્ટ મૂલ્યોને ધ્યાનમાં લીધા સિવાય, તમામ પ્રવૃત્તિઓને મલ્ટી-વિંડો માટે ફરીથી કદ બદલી શકે તેવી બનાવો."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"ફ્રિફોર્મ વિંડોઝ સક્ષમ કરો"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"પ્રાયોગિક ફ્રિફોર્મ વિંડોઝ માટે સમર્થનને સક્ષમ કરે છે."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"પ્રાયોગિક ફ્રિફોર્મ વિંડોઝ માટે સમર્થનને સક્ષમ કરો."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"ડેસ્કટૉપ બેકઅપ પાસવર્ડ"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"ડેસ્કટૉપ સંપૂર્ણ બેકઅપ હાલમાં સુરક્ષિત નથી"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"ડેસ્કટૉપ સંપૂર્ણ બેકઅપ્સ માટેનો પાસવર્ડ બદલવા અથવા દૂર કરવા માટે ટૅચ કરો"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"સક્રિય. ટોગલ કરવા માટે ટૅપ કરો."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"ચાલુ સેવાઓ"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"હાલમાં ચાલતી સેવાઓ જુઓ અને નિયંત્રિત કરો"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"રાત્રિ મોડ"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"અક્ષમ કરેલ"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"હંમેશાં ચાલુ"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"સ્વચલિત"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"મલ્ટિપ્રોસેસ WebView સક્ષમ કરો"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"પૃથક પ્રક્રિયામાં WebView રેંડરર્સ ચલાવો."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView અમલીકરણ"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView અમલીકરણ સેટ કરો"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"પસંદ કરેલ WebView અમલીકરણ અક્ષમ કરેલ છે અને ઉપયોગ કરવા માટે સક્ષમ કરવું આવશ્યક છે, શું તમે તેને સક્ષમ કરવા માગો છો?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"પસંદ કરેલ WebView અમલીકરણ અમાન્ય છે કારણ કે અમલીકરણ પસંદગીઓની સૂચિમાં જૂની છે. સૂચિ હવે અપડેટ કરવી જોઈએ."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ફાઇલ એન્ક્રિપ્શનમાં રૂપાંતરિત કરો"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"રૂપાંતરિત કરો..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ફાઇલ પહેલેથી જ એન્ક્રિપ્ટ કરેલ છે"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"રંગ સુધારણા"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"આ સુવિધા પ્રાયોગિક છે અને કામગીરી પર અસર કરી શકે છે."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> દ્વારા ઓવરરાઇડ થયું"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"અંદાજે. <xliff:g id="TIME">%1$s</xliff:g> બાકી"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - આશરે <xliff:g id="TIME">%2$s</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="2853265177761520490">"સંપૂર્ણ થવામાં <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"ચાર્જ થઈ રહ્યું નથી"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"ચાર્જ થઈ રહ્યું નથી"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"પૂર્ણ"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"વ્યવસ્થાપક દ્વારા અક્ષમ"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"વ્યવસ્થાપક દ્વારા નિયંત્રિત"</string>
<string name="home" msgid="8263346537524314127">"હોમ"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> પહેલાં"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> બાકી"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 32b2814..a7e838e 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"लेख को सुनें"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"बोली दर"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"बोलने की गति तय करें"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"पिच"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"कृत्रिम बोली के लहजे को प्रभावित करता है"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"भाषा"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"सिस्टम भाषा का उपयोग करें"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"भाषा नहीं चुनी गई है"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"ऐप्स को बाहरी मेमोरी पर बाध्य करें"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"इससे कोई भी ऐप मेनिफेस्ट मान अनदेखा करके, बाहरी मेमोरी पर लिखने योग्य बन जाता है"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"आकार बदले जाने के लिए गतिविधियों को बाध्य करें"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"एकाधिक-विंडो के लिए सभी गतिविधियों के आकार को बदले जाने योग्य बनाता है, चाहे मेनिफेस्ट मान कुछ भी हों."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"सभी गतिविधियों को एकाधिक विंडो के लिए आकार बदलने योग्य बनाएं, चाहे मेनिफेस्ट मान कुछ भी हों."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"फ़्रीफ़ॉर्म विंडो सक्षम करें"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"प्रयोगात्मक फ़्रीफ़ॉर्म विंडो का समर्थन सक्षम करती है."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"प्रयोगात्मक फ़्रीफ़ॉर्म विंडो का समर्थन सक्षम करें."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"डेस्कटॉप बैकअप पासवर्ड"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"डेस्कटॉप पूर्ण बैकअप वर्तमान में सुरक्षित नहीं हैं"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"डेस्कटॉप के पूर्ण बैकअप का पासवर्ड बदलने या निकालने के लिए टैप करें"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"सक्रिय. टॉगल करने पर टैप करें."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"चल रही सेवाएं"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"वर्तमान में चल रही सेवाओं को देखें और नियंत्रित करें"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"रात्रि मोड"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"अक्षम"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"हमेशा चालू"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"स्वचालित"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"मल्टीप्रोसेस WebView सक्षम करें"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"किसी अलग प्रक्रिया में WebView रेंडरर चलाएं."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView कार्यान्वयन"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView कार्यान्वयन सेट करें"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"चुना गया WebView कार्यान्वयन अक्षम है और उसे उपयोग करने के लिए सक्षम किया जाना आवश्यक है, क्या आप उसे सक्षम करना चाहते हैं?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"चुना गया WebView कार्यान्वयन अमान्य है क्योंकि कार्यान्वयन विकल्पों की सूची पुरानी हो चुकी है. सूची को अब अपडेट किया जाना चाहिए."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"फ़ाइल एन्क्रिप्शन में रूपांतरित करें"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"रूपांतरित करें..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"फ़ाइल पहले से एन्क्रिप्ट की हुई है"</string>
@@ -296,7 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"रंग सुधार"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"यह सुविधा प्रायोगिक है और निष्पादन को प्रभावित कर सकती है."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> के द्वारा ओवरराइड किया गया"</string>
- <string name="power_remaining_duration_only" msgid="4400068916452346544">"लगभग <xliff:g id="TIME">%2$s</xliff:g> शेष"</string>
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"लगभग <xliff:g id="TIME">%1$s</xliff:g> शेष"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - लगभग <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पूरी होने तक"</string>
@@ -311,7 +310,7 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"चार्ज नहीं हो रही है"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"चार्ज नहीं हो रही है"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"पूरी"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"व्यवस्थापक के द्वारा अक्षम किया गया"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"व्यवस्थापक द्वारा नियंत्रित"</string>
<string name="home" msgid="8263346537524314127">"होम"</string>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> पहले"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> शेष"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 37b5363..f315fe9 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Pretvaranje teksta u govor"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Brzina govora"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Brzina kojom se izgovara tekst"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Visina glasa"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Utječe na ton sintetiziranog govora"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Jezik"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"upotrijebi jezik sustava"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Jezik nije odabran"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Prisilno dopusti aplikacije u vanjskoj pohrani"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Aplikacije se mogu zapisivati u vanjsku pohranu neovisno o manifestu"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Nametni mogućnost promjene veličine za aktivnosti"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Veličina svih aktivnosti može se mijenjati za više prozora, neovisno o vrijednostima manifesta."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Omogući mijenjanje veličine svih aktivnosti za više prozora, neovisno o vrijednostima manifesta."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Omogući prozore slobodnog oblika"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Omogućuje podršku za eksperimentalne prozore slobodnog oblika."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Omogući podršku za eksperimentalne prozore slobodnog oblika."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Zaporka sigurnosne kopije"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Potpune sigurnosne kopije na stolnom računalu trenutačno nisu zaštićene"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Dodirnite da biste promijenili ili uklonili zaporku za potpune sigurnosne kopije na računalu"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktivno. Dodirnite da biste to promijenili."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Pokrenute usluge"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Pogledajte i nadzirite pokrenute procese"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Noćni način rada"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Onemogućeno"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Uvijek uključeno"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automatska"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Omogući višeprocesni WebView"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Pokreni ispunjivače WebViewa u izoliranim procesima."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementacija WebViewa"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Postavi implementaciju WebViewa"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Odabrana implementacija WebViewa onemogućena je i morate je omogućiti da biste je mogli upotrebljavati. Želite li je omogućiti?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Odabrana implementacija WebViewa nije važeća jer je popis odabira za implementaciju zastario. Popis se treba ažurirati."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Pretvori u enkripciju datoteka"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Pretvori…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Enkripcija datoteka već je izvršena"</string>
@@ -296,7 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korekcija boje"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova je značajka eksperimentalna i može utjecati na performanse."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Premošćeno postavkom <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="power_remaining_duration_only" msgid="4400068916452346544">"Još približno <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Još približno <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – još približno <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napunjenosti"</string>
@@ -311,7 +310,7 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Ne puni se"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ne puni se"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Puna"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Onemogućio administrator"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kontrolira administrator"</string>
<string name="home" msgid="8263346537524314127">"Početni zaslon"</string>
<string name="charge_length_format" msgid="8978516217024434156">"Prije <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Još <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 9113ab3..9b62eb1 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Szövegfelolvasás"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Beszéd sebessége"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"A szöveg kimondásának sebessége"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Hangmagasság"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Az előállított beszédhang hangszínét befolyásolja"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Nyelv"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"A rendszer nyelvének használata"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Nincs nyelv kiválasztva"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Külső tárhely alkalmazásainak engedélyezése"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Lehetővé teszi, hogy külső tárhelyre lehessen írni"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Tevékenységek átméretezésének kényszerítése"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Lehetővé teszi, hogy az összes tevékenység átméretezhető legyen a többablakos megjelenítés érdekében a jegyzékértékektől függetlenül."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Legyen az összes tevékenység átméretezhető a többablakos megjelenítés érdekében a jegyzékértékektől függetlenül."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Szabad formájú ablakok engedélyezése"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Engedélyezi a kísérleti jellegű, szabad formájú ablakok támogatását."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Kísérleti, szabad formájú ablakok támogatásának engedélyezése."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Asztali mentés jelszava"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Az asztali teljes biztonsági mentések jelenleg nem védettek."</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Koppintson ide az asztali teljes mentések jelszavának módosításához vagy eltávolításához"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Bekapcsolva. Koppintson ide a váltáshoz."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Futó szolgáltatások"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"A jelenleg futó szolgáltatások megtekintése és vezérlése"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Éjszakai mód"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Kikapcsolva"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Mindig bekapcsolva"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automatikus"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Többfolyamatos WebView indítása"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView-megjelenítők futtatása külön folyamatként."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-megvalósítás"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView-megvalósítás beállítása"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"A kiválasztott WebView-megvalósítás le van tiltva, a használathoz viszont engedélyezni kell. Szeretné engedélyezni?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"A kiválasztott WebView-megvalósítás érvénytelen, mert a megvalósítási lehetőségeket tartalmazó lista elévült. A listát elvileg már frissítették."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertálás fájlalapú titkosításra"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertálás…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Már fájlalapú titkosítást használ"</string>
@@ -296,7 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Színkorrekció"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ez egy kísérleti funkció, és hatással lehet a teljesítményre."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Felülírva erre: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="power_remaining_duration_only" msgid="4400068916452346544">"Kb. <xliff:g id="TIME">%2$s</xliff:g> van hátra"</string>
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Kb. <xliff:g id="TIME">%1$s</xliff:g> van hátra"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – kb. <xliff:g id="TIME">%2$s</xliff:g> van hátra"</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a teljes töltöttség eléréséig"</string>
@@ -311,7 +310,7 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Nem tölt"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nem töltődik"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Feltöltve"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Letiltva a rendszergazda által"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Rendszergazda által irányítva"</string>
<string name="home" msgid="8263346537524314127">"Főoldal"</string>
<string name="charge_length_format" msgid="8978516217024434156">"Ennyi ideje: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> van hátra"</string>
diff --git a/packages/SettingsLib/res/values-hy-rAM/strings.xml b/packages/SettingsLib/res/values-hy-rAM/strings.xml
index 2baa160..36a3813 100644
--- a/packages/SettingsLib/res/values-hy-rAM/strings.xml
+++ b/packages/SettingsLib/res/values-hy-rAM/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Գրվածքից խոսք ելք"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Խոսքի գնահատական"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Տեքստի արտասանման արագությունը"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Բարձրություն"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Ազդում է սինթեզած խոսքի ձայներանգի վրա"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Լեզու"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Օգտագործել համակարգի լեզուն"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Լեզուն ընտրված չէ"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Միշտ թույլատրել ծրագրեր արտաքին պահեստում"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Թույլ է տալիս պահել հավելվածը արտաքին սարքում՝ մանիֆեստի արժեքներից անկախ"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Ստիպել, որ ակտիվությունների չափերը լինեն փոփոխելի"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Բոլոր ակտիվությունների չափերը բազմապատուհան ռեժիմի համար դարձնել փոփոխելի՝ մանիֆեստի արժեքներից անկախ:"</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Բոլոր ակտիվությունների չափերը բազմապատուհան ռեժիմի համար դարձնել փոփոխելի՝ մանիֆեստի արժեքներից անկախ:"</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Ակտիվացնել կամայական ձևի պատուհանները"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Ակտիվացնում է կամայական ձևի փորձնական պատուհանների աջակցումը:"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Միացնել ազատ ձևի փորձնական պատուհանների աջակցումը:"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Աշխատասեղանի պահուստավորման գաղտնաբառ"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Աշխատասեղանի ամբողջական պահուստավորումները այժմ պաշտպանված չեն"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Հպեք՝ աշխատասեղանի ամբողջական պահուստավորման գաղտնաբառը փոխելու կամ հեռացնելու համար"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Ակտիվ է: Հպեք՝ փոխելու համար:"</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Աշխատեցվող ծառայություններ"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Դիտել և վերահսկել ընթացիկ աշխատեցվող ծառայությունները"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Գիշերային ռեժիմ"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Անջատված"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Միշտ միացված"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Ավտոմատ"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Միացնել բազմագործընթաց WebView"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Գործարկել WebView-ի մշակիչները առանձնացված գործընթացում:"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-ի իրականացում"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Ընտրեք WebView-ի իրականացումը"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"WebView-ի իրականացման ընտրված եղանակն անջատված է և օգտագործելու համար պետք է նախ միացվի: Միացնե՞լ:"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"WebView-ի իրագործման ընտրված եղանակն անվավեր է, քանի որ իրագործման ընտրանքների ցանկը արդի չէ: Այն այժմ կթարմացվի:"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Վերածել ֆայլային գաղտնագրման"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Փոխարկել…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Ֆայլային գաղտնագրումն արդեն կատարվել է"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Գունային կարգաբերում"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Սա փորձնական գործառույթ է և կարող է ազդել աշխատանքի վրա:"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Գերազանցված է <xliff:g id="TITLE">%1$s</xliff:g>-ից"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Մնացել է մոտ <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - մնաց մոտավորապես <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Չի լիցքավորվում"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Չի լիցքավորվում"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Լիցքավորված"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Կասեցված է ադմինիստրատորի կողմից"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Վերահսկվում է ադմինիստրատորի կողմից"</string>
<string name="home" msgid="8263346537524314127">"Գլխավոր էջ"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> առաջ"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"Մնացել է <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 1a47576..62372ee 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Keluaran text-to-speech"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Laju bicara"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Kecepatan teks diucapkan"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tinggi nada"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Memengaruhi nada ucapan yang disintesis"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Bahasa"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Gunakan bahasa sistem"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Bahasa tidak dipilih"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Paksa izinkan aplikasi di eksternal"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Membuat semua aplikasi dapat ditulis ke penyimpanan eksterna"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Paksa aktivitas agar ukurannya dapat diubah"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Membuat semua aktivitas dapat diubah ukurannya untuk banyak jendela, terlepas dari nilai manifes."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Buat semua aktivitas dapat diubah ukurannya untuk banyak jendela, terlepas dari nilai manifes."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Aktifkan jendela berformat bebas"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Mengaktifkan dukungan untuk jendela eksperimental berformat bebas."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Aktifkan dukungan untuk jendela eksperimental berformat bebas."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Sandi cadangan desktop"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Saat ini cadangan desktop penuh tidak dilindungi"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Ketuk guna mengubah atau menghapus sandi untuk cadangan lengkap desktop"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktif. Ketuk untuk beralih."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Layanan yang sedang berjalan"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Melihat dan mengontrol layanan yang sedang berjalan"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Mode malam"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Dinonaktifkan"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Selalu aktif"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Otomatis"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Aktifkan WebView multiproses"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Jalankan perender WebView dalam proses yang terisolasi."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Penerapan WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Setel penerapan WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Implementasi WebView yang dipilih telah dinonaktifkan, dan harus diaktifkan agar dapat digunakan. Ingin mengaktifkannya?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Implementasi WebView yang dipilih tidak valid karena daftar pilihan implementasi sudah usang. Daftar tersebut sekarang harus diperbarui."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Konversi ke enkripsi file"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konversi..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Sudah dienkripsi berbasis file"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Koreksi warna"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Fitur ini bersifat eksperimental dan dapat memengaruhi kinerja."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Digantikan oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Kira-kira tersisa <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - kira-kira tersisa. <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sampai penuh"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Tidak mengisi daya"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Tidak mengisi daya"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Penuh"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Dinonaktifkan oleh administrator"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Dikontrol oleh admin"</string>
<string name="home" msgid="8263346537524314127">"Layar Utama"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> lalu"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"Tersisa <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-is-rIS/strings.xml b/packages/SettingsLib/res/values-is-rIS/strings.xml
index 558f7bc..cd8734d 100644
--- a/packages/SettingsLib/res/values-is-rIS/strings.xml
+++ b/packages/SettingsLib/res/values-is-rIS/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Úttak upplesturs"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Talhraði"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Hraði talaðs texta"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tónhæð"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Hefur áhrif á raddblæ talgervils"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Tungumál"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Nota tungumál kerfis"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Tungumál ekki valið"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Þvinga fram leyfi forrita í ytri geymslu"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Gerir hvaða forriti sem er kleift að skrifa í ytri geymslu, burtséð frá gildum í upplýsingaskrá"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Þvinga breytanlega stærð virkni"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Gerir stærð allrar virkni breytanlega svo að hún henti fyrir marga glugga, óháð gildum í upplýsingaskrá."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Gera stærð allrar virkni breytanlega svo að hún henti fyrir marga glugga, óháð gildum í upplýsingaskrá."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Virkja glugga með frjálsu sniði"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Kveikir á stuðningi við glugga með frjálsu sniði á tilraunastigi."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Virkja stuðning við glugga með frjálsu sniði á tilraunastigi."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Aðgangsorð tölvuafritunar"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Heildarafritun á tölvu er ekki varin sem stendur."</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Ýttu til að breyta eða fjarlægja aðgangsorðið fyrir heildarafritun á tölvu"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Virkt. Ýttu til að breyta."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Þjónustur í gangi"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Skoða og stjórna þjónustum í gangi"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Næturstilling"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Óvirkt"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Alltaf kveikt"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Sjálfvirkt"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Virkja WebView í fjölvinnslu"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Keyra WebView teiknun í lokuðu ferli."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Innleiðing WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Stilla innleiðingu WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Slökkt er á valinni innleiðingu WebView. Kveikja þarf á henni til að hægt sé að nota hana. Viltu gera það?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Sú innleiðing WebView sem hér var valin er ógild vegna þess að innleiðingalistinn rann út. Uppfæra þarf listann."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Umbreyta í dulkóðun skráa"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Umbreyta…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Þegar dulkóðað á grundvelli skráa"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Litaleiðrétting"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Þessi eiginleiki er á tilraunastigi og getur haft áhrif á frammistöðu."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Hnekkt af <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Um það bil <xliff:g id="TIME">%1$s</xliff:g> eftir"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – u.þ.b. <xliff:g id="TIME">%2$s</xliff:g> eftir"</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> í fulla hleðslu"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Ekki í hleðslu"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ekki í hleðslu"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Fullhlaðin"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Stjórnandi gerði óvirkt"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Stjórnað af kerfisstjóra"</string>
<string name="home" msgid="8263346537524314127">"Heim"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"Fyrir <xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> eftir"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 24564c1..44bffcb 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Output sintesi vocale"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Velocità voce"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocità di pronuncia del testo"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tono"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Si applica al tono della sintesi vocale"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Lingua"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Usa lingua di sistema"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Lingua non selezionata"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Forza autorizzazione app su memoria esterna"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Rende l\'app idonea all\'installaz. su mem. esterna, senza considerare i valori manifest"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Imponi formato modificabile alle attività"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Rende il formato di tutte le attività modificabile per la modalità multi-finestra, indipendentemente dai valori manifest."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Rendi il formato di tutte le attività modificabile per la modalità multi-finestra, indipendentemente dai valori manifest."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Attiva finestre a forma libera"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Attiva il supporto per le finestre a forma libera sperimentali."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Attiva il supporto delle finestre a forma libera sperimentali."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Password di backup desktop"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"I backup desktop completi non sono attualmente protetti."</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tocca per modificare o rimuovere la password per i backup desktop completi"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Attiva. Tocca per attivare/disattivare."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Servizi in esecuzione"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Visualizza e controlla i servizi attualmente in esecuzione"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Modalità Notte"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Disattivato"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Sempre attivo"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automatico"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Attiva WebView multiprocesso"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Esegui renderer WebView in un processo isolato."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementazione di WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Imposta l\'implementazione di WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"L\'implementazione di WebView selezionata non è attiva e deve essere attivata per poterla utilizzare. Vuoi attivarla?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"L\'implementazione WebView selezionata non è valida perché l\'elenco di opzioni di implementazione è obsoleto. Aggiorna l\'elenco."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Converti in crittografia basata su file"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converti..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Crittografia su base file già eseguita"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correzione del colore"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Questa funzione è sperimentale e potrebbe influire sulle prestazioni."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Valore sostituito da <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Circa <xliff:g id="TIME">%1$s</xliff:g> rimanenti"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – Tempo rimanente: <xliff:g id="TIME">%2$s</xliff:g> circa"</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla carica completa"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Non in carica"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Non in carica"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Carica"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Disattivata dall\'amministratore"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Gestita dall\'amministratore"</string>
<string name="home" msgid="8263346537524314127">"Home page"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> fa"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> rimanenti"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 5dea0a2..de7f7e3 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"פלט טקסט לדיבור"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"קצב דיבור"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"המהירות שבה הטקסט נאמר"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"גובה צליל"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"משפיע על הטון של הדיבור המסונתז"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"שפה"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"שימוש בשפת המערכת"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"לא נבחרה שפה"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"אילוץ הרשאה של אפליקציות באחסון חיצוני"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"מאפשר כתיבה של כל אפליקציה באחסון חיצוני, ללא התחשבות בערכי המניפסט"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"אלץ יכולת קביעת גודל של הפעילויות"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"מאפשר יכולת קביעת גודל של כל הפעילויות לריבוי חלונות, ללא קשר לערך המניפסט."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"אפשר יכולת קביעת גודל של כל הפעילויות לריבוי חלונות, ללא קשר לערך המניפסט."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"הפעל את האפשרות לשנות את הגודל והמיקום של החלונות"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"מפעיל תמיכה בתכונה הניסיונית של שינוי הגודל והמיקום של החלונות."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"הפעל תמיכה בתכונה הניסיונית של שינוי הגודל והמיקום של החלונות."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"סיסמת גיבוי מקומי"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"גיבויים מלאים בשולחן העבודה אינם מוגנים כעת"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"הקש כדי לשנות או להסיר את הסיסמה לגיבויים מלאים בשולחן העבודה"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"אפליקציה פעילה. הקש כדי להחליף מצב."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"שירותים פועלים"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"הצג ושלוט בשירותים הפועלים כעת"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"מצב לילה"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"מושבת"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"פועל תמיד"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"באופן אוטומטי"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"הפעל תצוגת אתר לריבוי עיבודים"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"הרץ מעבדי תצוגת אתר בהליך מבודד"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"יישום WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"הגדרת יישום WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"יישום ה-WebView שנבחר מושבת, ויש להפעיל אותו כדי להשתמש בו. האם ברצונך להפעיל אותו?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"יישום WebView שנבחר אינו חוקי שכן רשימת מבחר היישומים אינה פעילה יותר. יש צורך לעדכן את הרשימה."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"המר להצפנת קבצים"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"המר..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"הצפנת קבצים כבר מוגדרת"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"תיקון צבע"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"תכונה זו היא ניסיונית ועשויה להשפיע על הביצועים."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"נעקף על ידי <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"נשארו <xliff:g id="TIME">%1$s</xliff:g> בערך"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> עד למילוי"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"לא בטעינה"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"לא טוען"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"מלא"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"הושבת על ידי מנהל המערכת"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"נמצא בשליטת מנהל מערכת"</string>
<string name="home" msgid="8263346537524314127">"דף הבית"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"לפני <xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"נשארו <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index eb7f8af..f341d71 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"テキスト読み上げの出力"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"音声の速度"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"テキストの読み上げ速度"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"音の高さ"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"合成音声のトーンに影響します"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"言語"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"システムの言語を使用"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"言語が選択されていません"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"外部ストレージへのアプリの書き込みを許可"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"マニフェストの値に関係なく、すべてのアプリを外部ストレージに書き込めるようになります"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"アクティビティをサイズ変更可能にする"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"マニフェストの値に関係なく、マルチウィンドウですべてのアクティビティのサイズを変更できるようになります。"</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"マニフェストの値に関係なく、マルチウィンドウですべてのアクティビティのサイズを変更できるようにします。"</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"フリーフォーム ウィンドウの有効化"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"テスト段階のフリーフォーム ウィンドウのサポートを有効にします。"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"外部のフリーフォーム ウィンドウのサポートを有効にします。"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"PCバックアップパスワード"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"デスクトップのフルバックアップは現在保護されていません"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"デスクトップのフルバックアップ用のパスワードを変更または削除する場合にタップします"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"有効です。タップすると切り替わります。"</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"実行中のサービス"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"現在実行中のサービスを表示して制御する"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"夜間モード"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"無効"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"常にON"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"自動"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"複数プロセス WebView を有効化"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"別個のプロセスで WebView レンダラを実行します。"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView の実装"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView の実装の設定"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"選択した WebView の実装は無効になっていますが、使用するには有効にする必要があります。有効にしますか?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"選択した WebView の実装は無効です。これは実装の選択に使用するリストが古くなっているためです。リストを更新する必要があります。"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ファイル暗号化に変換する"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"変換…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ファイルは既に暗号化済みです"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"色補正"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"この機能は試験運用機能であり、パフォーマンスに影響することがあります。"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g>によって上書き済み"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"あと約 <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 残り約<xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - フル充電まで<xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -314,10 +312,8 @@
<!-- String.format failed for translation -->
<!-- no translation found for battery_info_status_full (2824614753861462808) -->
<skip />
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"管理者によって無効にされています"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"管理者により管理されています"</string>
<string name="home" msgid="8263346537524314127">"ホーム"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g>前"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"あと <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ka-rGE/strings.xml b/packages/SettingsLib/res/values-ka-rGE/strings.xml
index 540dc81..08e6327 100644
--- a/packages/SettingsLib/res/values-ka-rGE/strings.xml
+++ b/packages/SettingsLib/res/values-ka-rGE/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"მეტყველების სინთეზი"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"მეტყველების ტემპი"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"ტექსტის თხრობის სიჩქარე"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"სიმაღლე"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"გავლენას ახდენს სინთეზირებული ხმის სიძლიერეზე"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"ენა"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"სისტემის ენის გამოყენება"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"ენა არჩეული არ არის"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"აპების დაშვება გარე მეხსიერებაში"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"აპები ჩაიწერ. გარე მეხს.-ზე აღწ. ფაილის მნიშვნ. მიუხედ."</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"ზომაცვლადი აქტივობების იძულება"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"მანიფესტის მნიშვნელობების მიუხედავად, ყველა აქტივობას მრავალი ფანჯრის რეჟიმისთვის ზომაცვლადად აქცევს."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"მანიფესტის მნიშვნელობების მიუხედავად, მრავალი ფანჯრის რეჟიმისთვის ყველა აქტივობის ზომაცვლადად გადაქცევა."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"თავისუფალი ფორმის მქონე ფანჯრების ჩართვა"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"ჩართავს თავისუფალი ფორმის მქონე ფანჯრების მხარდაჭერის ექსპერიმენტულ ფუნქციას"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"თავისუფალი ფორმის მქონე ფანჯრების მხარდაჭერის ექსპერიმენტული ფუნქციის ჩართვა."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"დესკტოპის სარეზერვო ასლის პაროლი"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"დესკტოპის სრული სარეზერვო ასლები ამჟამად დაცული არ არის"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"შეეხეთ დესკტოპის სრული სარეზერვო ასლების პაროლის შესაცვლელად ან წასაშლელად"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"აქტიური. შეეხეთ გადასართავად."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"მიმდინარე სერვისები"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"ამჟამად მოქმედი სერვისების ნახვა და მართვა"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"ღამის რეჟიმი"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"გამორთულია"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"ყოველთვის ჩართული"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"ავტომატური"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"მრავალპროც. WebView-ს ჩართვა"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView ვიზუალიზატორების იზოლირებულ პროცესში გაშვება."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView რეალიზაცია"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView რეალიზაციის დაყენება"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"არჩეული WebView რეალიზაცია გათიშულია და გამოყენებამდე უნდა ჩაირთოს. გსურთ მისი ჩართვა?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"არჩეული WebView რეალიზაცია არასწორია. რეალიზაციების სია მოძველდა და ახლა განახლდება."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ფაილების დაშიფვრაზე გარდაქმნა"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"გარდაქმნა…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"უკვე დაშიფრულია ფაილების დონეზე"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"ფერის კორექცია"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ეს ფუნქცია საცდელია და შეიძლება გავლენა იქონიოს შესრულებაზე."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"უკუგებულია <xliff:g id="TITLE">%1$s</xliff:g>-ის მიერ"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"დარჩენილია დაახლოებით <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"დაახლ. <xliff:g id="LEVEL">%1$s</xliff:g> დარჩენილია <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> სრულ დატენვამდე"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"არ იტენება"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"არ იტენება"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"ბატარეა დატენილია"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"გათიშულია ადმინისტრატორის მიერ"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"იმართება ადმინისტრატორის მიერ"</string>
<string name="home" msgid="8263346537524314127">"მთავარი"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"გავიდა <xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"დარჩენილია <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-kk-rKZ/strings.xml b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
index 7f59d97..921812a 100644
--- a/packages/SettingsLib/res/values-kk-rKZ/strings.xml
+++ b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Мәтінді тілге айналдыру"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Сөйлеу жылдамдығы"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Мәтіннің оқылу жылдамдығы"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Дауыс жиілігі"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Синтезделген сөйлеу үніне әсер етеді"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Тіл"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Жүйелік тілді пайдалану"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Тіл таңдалған жоқ"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Сыртқыда қолданбаларға мәжбүрлеп рұқсат ету"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Манифест мәндеріне қарамастан кез келген қолданбаны сыртқы жадқа жазуға жарамды етеді"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Әрекеттерді өлшемін өзгертуге болатын етуге мәжбүрлеу"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Манифест мәндеріне қарамастан барлық әрекеттерді бірнеше терезе үшін өлшемін өзгертуге болатын етеді."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Манифест мәндеріне қарамастан бірнеше терезе режимінде барлық әрекеттердің өлшемін өзгертуге рұқсат беру."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Еркін пішіндегі терезелерді қосу"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Эксперименттік еркін пішіндегі терезелерді қолдауды қосады."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Еркін пішінді терезелерді құру эксперименттік функиясын қосу."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Компьютер үстелінің сақтық көшірмесі"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Жұмыс үстелінің сақтық көшірмелері қазір қорғалмаған"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Үстелдік компьютердің толық сақтық көшірмелерінің кілтсөзін өзгерту немесе жою үшін түртіңіз"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Белсенді. Ауыстырып қосу үшін түртіңіз."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Қосылып тұрған қызметтер"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Ағымдағы қосылып тұрған қызметтерді көру және басқару"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Түнгі режим"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Өшірілген"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Әрқашан қосулы"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Aвтоматты"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Бірнеше процесті веб-көріністі қосу"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Веб-көрініс бейнелеушілерін оқшауланған процесте іске қосу."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ендіру"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView ендіруін орнату"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Таңдалған веб-көріністі енгізу өшірілген және пайдалану үшін оны қосу керек. Оны қосу керек пе?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Таңдалған WebView ендіру жарамсыз, өйткені ендіру таңдауларының тізімі ескірген. Тізімді қазір жаңарту керек."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Файлды шифрлауға түрлендіру"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Түрлендіру..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Файл шифрланып қойылған"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Түсті түзету"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Бұл мүмкіндік эксперименттік болып табылады және өнімділікке әсер етуі мүмкін."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> үстінен басқан"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Шамамен <xliff:g id="TIME">%1$s</xliff:g> қалды"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - шамамен <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - толғанша <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Зарядталу орындалып жатқан жоқ"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Зарядталып тұрған жоқ"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Толық"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Әкімші өшірген"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Әкімші басқарады"</string>
<string name="home" msgid="8263346537524314127">"Негізгі бет"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> бұрын"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> қалды"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-km-rKH/strings.xml b/packages/SettingsLib/res/values-km-rKH/strings.xml
index a949538..f64158c 100644
--- a/packages/SettingsLib/res/values-km-rKH/strings.xml
+++ b/packages/SettingsLib/res/values-km-rKH/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"លទ្ធផលអត្ថបទទៅការនិយាយ"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"អត្រានិយាយ"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"ល្បឿនពេលអានអត្ថបទ"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"ឡើង-ចុះ"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"ប៉ះពាល់ដល់សំឡេងនៃការនិយាយដែលបានបម្លែង"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"ភាសា"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"ប្រើភាសាប្រព័ន្ធ"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"មិនបានជ្រើសភាសា"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"បង្ខំឲ្យអនុញ្ញាតកម្មវិធីលើឧបករណ៍ផ្ទុកខាងក្រៅ"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"ធ្វើឲ្យកម្មវិធីទាំងឡាយមានសិទ្ធិសរសេរទៅកាន់ឧបករណ៍ផ្ទុកខាងក្រៅ ដោយមិនគិតពីតម្លៃជាក់លាក់"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"បង្ខំឲ្យសកម្មភាពអាចប្តូរទំហំបាន"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"កំណត់ឲ្យសកម្មភាពទាំងអស់អាចប្តូរទំហំបានសម្រាប់ពហុផ្ទាំងវិនដូ ដោយមិនគិតពីតម្លៃមេនីហ្វេសឡើយ។"</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"កំណត់ឲ្យសកម្មភាពទាំងអស់អាចប្តូរទំហំបានសម្រាប់ពហុផ្ទាំងវិនដូ ដោយមិនគិតពីតម្លៃមេនីហ្វេស។"</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"បើកដំណើរការផ្ទាំងវិនដូទម្រង់សេរី"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"បើកដំណើរការគាំទ្រផ្ទាំងវិនដូទម្រង់សេរីសាកល្បង"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"បើកដំណើរការគាំទ្រផ្ទាំងវិនដូទម្រង់សេរីសាកល្បង"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"ពាក្យសម្ងាត់បម្រុងទុកលើផ្ទៃតុ"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"ការបម្រុងទុកពេញលេញលើផ្ទៃតុបច្ចុប្បន្នមិនត្រូវបានការពារទេ។"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"ប៉ះដើម្បីប្ដូរ ឬយកពាក្យសម្ងាត់ចេញសម្រាប់ការបម្រុងទុកពេញលេញលើកុំព្យូទ័រ"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"សកម្ម។ ប៉ះដើម្បីបិទ/បើក។"</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"សេវាកម្មកំពុងដំណើរការ"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"មើល និងគ្រប់គ្រងសេវាកម្មកំពុងដំណើរការបច្ចុប្បន្ន"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"របៀបពេលយប់"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"បានបិទ"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"បើកជានិច្ច"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"ស្វ័យប្រវត្តិ"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"បើកដំណើរការ WebView ដែលមានអង្គដំណើរការច្រើន"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"ដំណើរការកម្មវិធីបំលែង WebView ក្នុងដំណើរការដាច់ដោយឡែក"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"ការប្រតិបត្តិ WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"កំណត់ការប្រតិបត្តិ WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"ការប្រតិបត្តិការ WebView ដែលបានជ្រើសត្រូវបានបិទដំណើរការ ប៉ុន្តែអ្នកត្រូវបើកដំណើរការវាដើម្បីប្រើ តើអ្នកចង់បើកដំណើរការវាដែរឬទេ?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"ការអនុវត្ត WebView ដែលបានជ្រើសមិនត្រូវត្រឹមត្រូវទេ ដោយសារតែបញ្ជីជម្រើសនៃការអនុវត្តន៍ចាស់ហើយ។ គួរតែអាប់ដេតបញ្ជីនោះ។"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"បម្លែងទៅជាការអ៊ីនគ្រីបឯកសារ"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"បម្លែង…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"បានអ៊ីនគ្រីបឯកសាររួចហើយ"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"ការកែពណ៌"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"លក្ខណៈនេះគឺជាការពិសោធន៍ ហើយអាចប៉ះពាល់ការអនុវត្ត។"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"បដិសេធដោយ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"នៅសល់ប្រហែល <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - នៅសល់ប្រហែល <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> រហូតដល់ពេញ"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"មិនកំពុងបញ្ចូលថ្ម"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"មិនបញ្ចូលថ្ម"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"ពេញ"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"បានបិទដំណើរការដោយអ្នកគ្រប់គ្រង"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"គ្រប់គ្រងដោយអ្នកគ្រប់គ្រង"</string>
<string name="home" msgid="8263346537524314127">"ដើម"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> មុន"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"នៅសល់ <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-kn-rIN/strings.xml b/packages/SettingsLib/res/values-kn-rIN/strings.xml
index bfe0c1e..7e68655 100644
--- a/packages/SettingsLib/res/values-kn-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-kn-rIN/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"ಧ್ವನಿಗೆ-ಪಠ್ಯದ ಔಟ್ಪುಟ್"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"ಧ್ವನಿಯ ದರ"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"ಪಠ್ಯವನ್ನು ಹೇಳಿದ ವೇಗ"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"ಪಿಚ್"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"ಸಂಯೋಜಿತ ಧ್ವನಿಯ ಟೋನ್ ಮೇಲೆ ಪರಿಣಾಮ ಬೀರುತ್ತದೆ"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"ಭಾಷೆ"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"ಸಿಸ್ಟಂ ಭಾಷೆಯನ್ನು ಬಳಸು"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"ಭಾಷೆಯನ್ನು ಆಯ್ಕೆಮಾಡಲಾಗಿಲ್ಲ"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"ಬಾಹ್ಯವಾಗಿ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಒತ್ತಾಯವಾಗಿ ಅನುಮತಿಸಿ"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"ಮ್ಯಾನಿಫೆಸ್ಟ್ ಮೌಲ್ಯಗಳನ್ನು ಪರಿಗಣಿಸದೇ, ಯಾವುದೇ ಅಪ್ಲಿಕೇಶನ್ಗೆ ಬಾಹ್ಯ ಸಂಗ್ರಹಣೆಗೆ ಬರೆಯಲು ಅರ್ಹಗೊಳಿಸುತ್ತದೆ"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"ಚಟುವಟಿಕೆಗಳನ್ನು ಮರುಗಾತ್ರಗೊಳಿಸುವಂತೆ ಒತ್ತಾಯ ಮಾಡಿ"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"ಮ್ಯಾನಿಫೆಸ್ಟ್ ಮೌಲ್ಯಗಳನ್ನು ಪರಿಗಣಿಸದೇ, ಬಹು-ವಿಂಡೊಗೆ ಎಲ್ಲಾ ಚಟುವಟಿಕೆಗಳನ್ನು ಮರುಗಾತ್ರಗೊಳಿಸುವಂತೆ ಮಾಡುತ್ತದೆ."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"ಮ್ಯಾನಿಫೆಸ್ಟ್ ಮೌಲ್ಯಗಳನ್ನು ಪರಿಗಣಿಸದೇ, ಬಹು-ವಿಂಡೊಗೆ ಎಲ್ಲಾ ಚಟುವಟಿಕೆಗಳನ್ನು ಮರುಗಾತ್ರಗೊಳಿಸುವಂತೆ ಮಾಡಿ."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"ಮುಕ್ತಸ್ವರೂಪದ ವಿಂಡೊಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"ಪ್ರಾಯೋಗಿಕ ಮುಕ್ತಸ್ವರೂಪದ ವಿಂಡೊಗಳಿಗೆ ಬೆಂಬಲವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"ಪ್ರಾಯೋಗಿಕ ಫ್ರೀಫಾರ್ಮ್ ವಿಂಡೊಗಳಿಗೆ ಬೆಂಬಲವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"ಡೆಸ್ಕ್ಟಾಪ್ ಬ್ಯಾಕಪ್ ಪಾಸ್ವರ್ಡ್"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"ಡೆಸ್ಕ್ಟಾಪ್ನ ಪೂರ್ಣ ಬ್ಯಾಕಪ್ಗಳನ್ನು ಪ್ರಸ್ತುತ ರಕ್ಷಿಸಲಾಗಿಲ್ಲ"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"ಡೆಸ್ಕ್ಟಾಪ್ನ ಪೂರ್ಣ ಬ್ಯಾಕಪ್ಗಳಿಗೆ ಪಾಸ್ವರ್ಡ್ ಬದಲಾಯಿಸಲು ಅಥವಾ ತೆಗೆದುಹಾಕಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"ಸಕ್ರಿಯ. ಟಾಗಲ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"ರನ್ ಆಗುತ್ತಿರುವ ಸೇವೆಗಳು"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"ಈಗ ರನ್ ಆಗುತ್ತಿರುವ ಸೇವೆಗಳನ್ನು ವೀಕ್ಷಿಸಿ ಮತ್ತು ನಿಯಂತ್ರಿಸಿ"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"ರಾತ್ರಿ ಮೋಡ್"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"ಯಾವಾಗಲೂ ಆನ್"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"ಸ್ವಯಂಚಾಲಿತ"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"ಬಹುಪ್ರಕ್ರಿಯೆ WebView ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"ಪ್ರತ್ಯೇಕಗೊಳಿಸಿದ ಪ್ರಕ್ರಿಯೆಯಲ್ಲಿ WebView ರೆಂಡರರ್ ರನ್ ಮಾಡಿ."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ಅನುಷ್ಠಾನಗೊಳಿಸುವಿಕೆ"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView ಅನುಷ್ಠಾನಗೊಳಿಸುವಿಕೆಯನ್ನು ಹೊಂದಿಸಿ"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"ಆಯ್ಕೆಮಾಡಲಾದ WebView ಅನುಷ್ಠಾನಗೊಳಿಸುವಿಕೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ ಮತ್ತು ಬಳಸಲು ಸಕ್ರಿಯಗೊಳಿಸಬೇಕಾಗಿದೆ, ಇದನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು ನೀವು ಬಯಸುತ್ತೀರಾ?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"ಅನುಷ್ಠಾನ ಆಯ್ಕೆಗಳ ಪಟ್ಟಿ ಸ್ಥಬ್ದವಾಗಿರುವ ಕಾರಣ ಆಯ್ಕೆಮಾಡಿದ WebView ಅನುಷ್ಠಾನಗೊಳಿಸುವಿಕೆಯು ಅಮಾನ್ಯವಾಗಿದೆ. ಈಗ ಪಟ್ಟಿಯನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡಬೇಕಾಗಿದೆ."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ಫೈಲ್ ಎನ್ಕ್ರಿಪ್ಶನ್ಗೆ ಪರಿವರ್ತಿಸು"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"ಪರಿವರ್ತಿಸು…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ಫೈಲ್ ಈಗಾಗಲೇ ಎನ್ಕ್ರಿಪ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string>
@@ -296,7 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"ಬಣ್ಣದ ತಿದ್ದುಪಡಿ"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ಇದು ಪ್ರಾಯೋಗಿಕ ವೈಶಿಷ್ಟ್ಯವಾಗಿದೆ. ಕಾರ್ಯಕ್ಷಮತೆ ಮೇಲೆ ಪರಿಣಾಮ ಬೀರಬಹುದು."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ಮೂಲಕ ಅತಿಕ್ರಮಿಸುತ್ತದೆ"</string>
- <string name="power_remaining_duration_only" msgid="4400068916452346544">"ಸುಮಾರು <xliff:g id="TIME">%2$s</xliff:g> ಉಳಿದಿದೆ"</string>
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"ಸುಮಾರು <xliff:g id="TIME">%1$s</xliff:g> ಉಳಿದಿದೆ"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"ಸುಮಾರು <xliff:g id="LEVEL">%1$s</xliff:g> <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ಪೂರ್ಣವಾಗುವವರೆಗೆ"</string>
@@ -311,7 +310,7 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"ಚಾರ್ಜ್ ಆಗುತ್ತಿಲ್ಲ"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"ಚಾರ್ಜ್ ಆಗುತ್ತಿಲ್ಲ"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"ಭರ್ತಿ"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"ನಿರ್ವಾಹಕರಿಂದ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"ನಿರ್ವಾಹಕರ ಮೂಲಕ ನಿಯಂತ್ರಿಸಲಾಗಿದೆ"</string>
<string name="home" msgid="8263346537524314127">"ಮುಖಪುಟ"</string>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> ಹಿಂದೆ"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> ಉಳಿದಿದೆ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 5d1176a..a7434d0 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"TTS 출력"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"말하는 속도"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"텍스트를 읽어주는 속도"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"피치"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"합성 음성의 어조에 영향을 미침"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"언어"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"시스템 언어 사용"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"언어가 선택되지 않음"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"외부에서 앱 강제 허용"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"매니페스트 값에 관계없이 앱을 외부 저장소에 작성"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"활동의 크기가 조정 가능하도록 설정"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"모든 활동을 매니페스트 값에 관계없이 멀티 윈도우용으로 크기 조정 가능하도록 설정"</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"모든 활동을 매니페스트 값에 관계없이 멀티 윈도우용으로 크기 조정 가능하도록 설정"</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"자유 형식 창 사용"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"자유 형식 창(베타) 지원 사용"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"자유 형식 창 지원 사용"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"데스크톱 백업 비밀번호"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"데스크톱 전체 백업에 비밀번호가 설정되어 있지 않음"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"데스크톱 전체 백업에 대한 비밀번호를 변경하거나 삭제하려면 탭하세요."</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"활성화되었습니다. 전환하려면 탭하세요."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"실행 중인 서비스"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"현재 실행 중인 서비스 보기 및 제어"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"야간 모드"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"사용 안함"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"항상 사용"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"자동"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"멀티 프로세스 WebView 사용"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"단독 프로세스 내에서 WebView 렌더러를 실행합니다."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView 구현"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView 구현 설정"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"선택한 WebView 구현이 사용 중지되어 있습니다. 사용하려면 사용 설정해야 합니다. 사용 설정하시겠습니까?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"구현 선택 목록이 비활성화되어 선택한 WebView 구현이 잘못되었습니다. 목록을 지금 업데이트해야 합니다."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"파일 암호화로 변환"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"변환..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"파일이 이미 암호화됨"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"색보정"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"실험실 기능이며 성능에 영향을 줄 수 있습니다."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> 우선 적용됨"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"약 <xliff:g id="TIME">%1$s</xliff:g> 남음"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 대략 <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 후 충전 완료"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"충전 안함"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"충전 안함"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"충전 완료"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"관리자가 사용 중지함"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"관리자가 제어"</string>
<string name="home" msgid="8263346537524314127">"홈"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> 전"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> 남음"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ky-rKG/strings.xml b/packages/SettingsLib/res/values-ky-rKG/strings.xml
index f0867f5..178d47e 100644
--- a/packages/SettingsLib/res/values-ky-rKG/strings.xml
+++ b/packages/SettingsLib/res/values-ky-rKG/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Текстти-оозекилөө"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Кеп ылдамдыгы"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Текст айтылчу ылдамдык"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Негизги тон"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Синтезделген кептин интонациясына таасирин тийгизет"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Тил"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Тутум тилин колдонуу"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Тил тандалган жок"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Тышкы сактагычка сактоого уруксат берүү"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Манифест маанилерине карабастан бардык колдонмолорду тышкы сактагычка сактоого уруксат берет"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Аракеттердин өлчөмүн өзгөртүүнү мажбурлоо"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Манифест маанилерине карабастан бардык аракеттерди мульти-терезеге өлчөмү өзгөртүлгүдөй кылат."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Манифест маанилерине карабастан бардык аракеттерди мульти-терезеге өлчөмү өзгөртүлгүдөй кылуу."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Эркин формадагы терезелерди түзүүнү иштетүү"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Эркин формадагы терезелерди түзүү боюнча сынамык функцияны иштетүү"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Эркин формадагы терезелерди түзүү боюнча сынамык функцияны иштетүү."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Компүтердеги бэкаптын сырсөзү"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Компүтердеги толук бэкап учурда корголгон эмес"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Иш тактасынын камдалган сырсөзүн өзгөртүү же алып салуу үчүн таптап коюңуз"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Иштеп турат. Которуштуруу үчүн таптап коюңуз."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Иштеп жаткан кызматтар"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Учурда иштеп жаткан кызматтарды көрүү жана көзөмөлдөө"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Түнкү режим"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Өчүрүлгөн"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Ар дайым күйгүзүлгөн"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Автоматтык"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Көп процесстүү WebView иштт"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView рендерерлерин корголгон процессте иштетүү."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView аткарылышы"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView аткарылышын коюу"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"WebView кызматын пайдалануу үчүн аны иштетүү керек. Иштетесизби?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Тандалган WebView кызматы колдоого алынбайт. Кызматтардын тизмеси эскирип калгандыктан ал азыр жаңыртылат."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Файл шифрлөөсүнө айландыруу"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Айландыруу…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Файл мурунтан эле шифрленген"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Түсүн тууралоо"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Бул сынамык мүмкүнчүлүк болгондуктан, иштин майнаптуулугуна таасир этиши мүмкүн."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> менен алмаштырылган"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Болжол менен <xliff:g id="TIME">%1$s</xliff:g> калды"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - болжол менен <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> толгончо"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Кубат алган жок"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Кубатталган жок"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Толук"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Администратор өчүрүп койгон"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Администратор тарабынан көзөмөлдөнөт"</string>
<string name="home" msgid="8263346537524314127">"Башкы бет"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> мурун"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> калды"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lo-rLA/strings.xml b/packages/SettingsLib/res/values-lo-rLA/strings.xml
index 1419466..e9017d9 100644
--- a/packages/SettingsLib/res/values-lo-rLA/strings.xml
+++ b/packages/SettingsLib/res/values-lo-rLA/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"ການປ່ຽນຂໍ້ຄວາມເປັນສຽງ"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"ອັດຕາການເວົ້າ"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"ຄວາມໄວໃນການເວົ້າຂໍ້ຄວາມ"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"ໂທນສຽງ"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"ມີຜົນກັບໂທນສຽງເວົ້າທີ່ສັງເຄາະ"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"ພາສາ"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"ໃຊ້ພາສາຂອງລະບົບ"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"ບໍ່ໄດ້ເລືອກພາສາ"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"ບັງຄັບອະນຸຍາດແອັບຢູ່ພາຍນອກ"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"ເຮັດໃຫ້ທຸກແອັບມີສິດໄດ້ຮັບການຂຽນໃສ່ບ່ອນຈັດເກັບພາຍນອກ, ໂດຍບໍ່ຄຳນຶງເຖິງຄ່າທີ່ຈະແຈ້ງ"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"ບັງຄັງໃຫ້ກິດຈະກຳປ່ຽນຂະໜາດໄດ້"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"ເຮັດໃຫ້ທຸກກິດຈະກຳປ່ຽນຂະໜາດໄດ້ສຳລັບຫຼາຍໜ້າຕ່າງ, ໂດຍບໍ່ຄຳນຶງເຖິງຄ່າທີ່ຈະແຈ້ງ."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"ເຮັດໃຫ້ທຸກກິດຈະກຳສາມາດປັບຂະໜາດໄດ້ສຳລັບຫຼາຍໜ້າຈໍ, ໂດຍບໍ່ຄຳນຶງເຖິງຄ່າ manifest."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"ເປີດໃຊ້ໜ້າຕ່າງຮູບແບບອິດສະຫຼະ"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"ເປີດໃຊ້ການຮອງຮັບໜ້າຕ່າງຮູບແບບອິດສະຫຼະທີ່ທົດລອງໃຊ້."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"ເປີດໃຊ້ການຮອງຮັບໜ້າຈໍຮູບແບບອິດສະຫຼະແບບທົດລອງ."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"ລະຫັດຜ່ານການສຳຮອງຂໍ້ມູນເດັກສະທັອບ"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"ການສຳຮອງຂໍ້ມູນເຕັມຮູບແບບໃນເດັກສະທັອບຍັງບໍ່ໄດ້ຮັບການປ້ອງກັນໃນເວລານີ້"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"ແຕະເພື່ອປ່ຽນ ຫຼືລຶບລະຫັດຂອງການສຳຮອງຂໍ້ມູນເຕັມຮູບແບບໃນເດັກສະທັອບ"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"ນຳໃຊ້ຢູ່. ແຕະເພື່ອສັບປ່ຽນ."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"ບໍລິການທີ່ເຮັດວຽກຢູ່"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"ເບິ່ງ ແລະຈັດການບໍລິການທີ່ກຳລັງເຮັດວຽກຢູ່ໃນປັດຈຸບັນ"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"ໂໝດກາງຄືນ"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"ປິດໃຊ້ງານແລ້ວ"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"ເປີດຕະຫຼອດ"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"ອັດຕະໂນມັດ"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"ອະນຸຍາດໃຫ້ມີໂປຣເຊສ WebView ຫຼາຍອັນໄດ້"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"ເປີດໃຊ້ຕົວປະມວນ WebView ໃນໂປຣເຊສທີ່ແຍກຈາກກັນໄດ້."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"ການຈັດຕັ້ງປະຕິບັດ WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"ຕັ້ງການຈັດຕັ້ງປະຕິບັດ WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"ການຈັດຕັ້ງປະຕິບັດ WebView ທີ່ເລືອກຖືກປິດນຳໃຊ້, ແລະຕ້ອງຖືກເປີດນຳໃຊ້, ທ່ານຕ້ອງການເປີດນຳໃຊ້ມັນບໍ?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"ການນຳໃຊ້ WebView ທີ່ເລືອກນັ້ນບໍ່ຖືກຕ້ອງເນື່ອງຈາກລາຍຊື່ຂອງການເລືອກນຳໃຊ້ນັ້ນເກົ່າເກີນໄປ. ລາຍຊື່ຕອນນີ້ແມ່ນອັບເດດແລ້ວ."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ປ່ຽນເປັນການເຂົ້າລະຫັດໄຟລ໌"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"ປ່ຽນ..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ໄຟລ໌ເຂົ້າລະຫັດຮຽບຮ້ອຍແລ້ວ"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"ການປັບແຕ່ງສີ"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ຄຸນສົມບັດນີ້ກຳລັງຢູ່ໃນການທົດລອງແລະອາດມີຜົນຕໍ່ປະສິດທິພາບ."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"ຖືກແທນໂດຍ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"ຍັງເຫຼືອປະມານ <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ເຫຼືອປະມານ <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈຶ່ງຈະເຕັມ"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"ບໍ່ໄດ້ສາກໄຟ"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"ບໍ່ໄດ້ສາກໄຟ"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"ເຕັມ"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"ຖືກປິດໃຊ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບ"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"ຄວບຄຸມໂດຍຜູ້ເບິ່ງແຍງ"</string>
<string name="home" msgid="8263346537524314127">"ໜ້າຫຼັກ"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> ກ່ອນນີ້"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"ຍັງເຫຼືອ <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 3f5493d..5c3f5be 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"„Teksto į kalbą“ išvestis"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Kalbėjimo greitis"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Greitis, kuriuo sakomas tekstas"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Garso aukštis"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Daro poveikį susintetintai kalbai"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Kalba"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Naudoti sistemos kalbą"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Kalba nepasirinkta"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Priverstinai leisti programas išorinėje atmintin."</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Vis. pr. gal. įr. į vid. saug. nepais. apr. vert."</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Priv. nust., kad veiksm. b. g. atl. kelių d. lang."</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Nustatoma, kad visus veiksmus būtų galima atlikti kelių dydžių languose, nepaisant aprašo verčių."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Nustatyti, kad visus veiksmus būtų galima atlikti kelių dydžių languose, nepaisant aprašo verčių."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Įgalinti laisvos formos langus"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Įgalinamas eksperimentinių laisvos formos langų palaikymas."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Įgalinti eksperimentinių laisvos formos langų palaikymą."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Viet. atsrg. kop. slapt."</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Šiuo metu visos vietinės atsarginės kopijos neapsaugotos"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Jei norite pakeisti ar pašalinti visų stalinio kompiuterio atsarginių kopijų slaptažodį, palieskite"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktyvi. Palieskite, kad perjungtumėte."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Vykdomos paslaugos"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Žiūrėti ir valdyti dabar vykdomas paslaugas"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Naktinis režimas"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Išjungta"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Visada įjungta"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automatinė"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Įgal. kelių procesų „WebView“"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Paleisti „WebView“ pateikimo priemones vienam procesui."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"„WebView“ diegimas"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"„WebView“ diegimo nustatymas"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Pasirinktas „WebView“ diegimas išjungtas ir jį būtina įgalinti, kad būtų galima naudoti. Ar norite jį įgalinti?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Pasirinktas „WebView“ diegimas netinkamas, nes diegimo pasirinkimų sąrašas tapo neaktyvus. Sąrašas dabar turėtų būti atnaujintas."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertuoti į failų šifruotę"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertuoti…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Jau konvertuota į failų šifruotę"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Spalvų taisymas"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ši funkcija yra eksperimentinė ir ji gali turėti įtakos našumui."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Nepaisyta naudojant nuostatą „<xliff:g id="TITLE">%1$s</xliff:g>“"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Liko maždaug <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – liko maždaug <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> iki visiško įkrovimo"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Nekraunama"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nekraunama"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Visiškai įkrautas"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Išjungė administratorius"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Valdo administratorius"</string>
<string name="home" msgid="8263346537524314127">"Pagrindinis ekranas"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"Prieš <xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"Liko <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index dd70703..27eeaf5 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Teksta-runas izvade"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Runas ātrums"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Teksta ierunāšanas ātrums"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tonis"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Ietekmē sintezētās runas toni"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Valoda"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Izmantot sistēmas valodu"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Nav atlasīta valoda."</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Lietotņu piespiedu atļaušana ārējā krātuvē"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Ļauj jebkuru lietotni ierakstīt ārējā krātuvē neatkarīgi no manifesta vērtības."</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Pielāgot darbības"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Pielāgo visas darbības vairāku logu režīmam neatkarīgi no vērtībām manifestā."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Pielāgot visas darbības vairāku logu režīmam neatkarīgi no vērtībām manifestā."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Iespējot brīvās formas logus"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Iespējo eksperimentālo brīvās formas logu atbalstu."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Iespējot eksperimentālo brīvās formas logu atbalstu."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Datora dublējuma parole"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Darbvirsmas pilnie dublējumi pašlaik nav aizsargāti."</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Pieskarieties, lai mainītu vai noņemtu paroli pilniem datora dublējumiem."</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktīva. Pieskarieties, lai pārslēgtu."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Aktīvie pakalpojumi"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Pašreiz darbojošos pakalpojumu skatīšana un vadība"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Nakts režīms"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Atspējots"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Vienmēr ieslēgts"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automātiski"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Iespējot vairākprocesu WebView"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Atsevišķā procesā tiek palaisti WebView renderētāji."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ieviešana"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Iestatīt WebView ieviešanu"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Izvēlētā WebView ieviešana ir atspējota, un tā ir jāiespējo, lai to varētu izmantot. Vai vēlaties to iespējot?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Izvēlētā WebView ieviešana nav derīga, jo ieviešanas iespēju saraksts ir novecojis. Saraksts ir jāatjaunina."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Pārvērst par failu šifrējumu"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Pārvērst…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Jau šifrēts failu līmenī"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Krāsu korekcija"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Šī funkcija ir eksperimentāla un var ietekmēt veiktspēju."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Jaunā preference: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Atlikušais laiks: aptuveni <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> — aptuvenais atlikušais laiks: <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai uzlādei"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Nenotiek uzlāde"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nenotiek uzlāde"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Pilns"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Atspējojis administrators"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kontrolē administrators"</string>
<string name="home" msgid="8263346537524314127">"Sākums"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"Pirms šāda laika: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"Atlikušais laiks: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mk-rMK/strings.xml b/packages/SettingsLib/res/values-mk-rMK/strings.xml
index 5bdfd01..ec09f21 100644
--- a/packages/SettingsLib/res/values-mk-rMK/strings.xml
+++ b/packages/SettingsLib/res/values-mk-rMK/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Излез текст-во-говор"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Брзина на говор"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Брзина со која се кажува текстот"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Интензитет"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Влијае на тонот на синтетизираниот говор"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Јазик"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Користете системски јазик"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Јазикот не е избран"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Принуд. дозволете апликации на надворешна меморија"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Запишува апл. во надв.меморија, незав. од манифест"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Принуди ги активностите да ја менуваат големината"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Ги прави сите активности да бидат со променлива големина за мултипрозорец, без разлика на вредностите на манифестот."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Направете сите активности да бидат со променлива големина за повеќе прозорци, без разлика на вредностите на манифестот."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Овозможи прозорци со слободна форма"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Овозможува поддршка за експериментални прозорци со слободна форма."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Овозможи поддршка за експериментални прозорци со слободна форма."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Резервна лозинка за работна површина"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Целосни резервни копии на работната површина кои во моментов не се заштитени"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Допрете за да се промени или отстрани лозинката за целосни резервни копии на работната површина"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Активно. Допрете за да смените."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Активни услуги"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Погледнете и контролирајте услуги што се моментално активни"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Ноќен режим"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Оневозможено"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Секогаш вклучено"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Автоматски"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Овозможи мултипроцесен WebView"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Активирајте ги WebView-прикажувачите во изолиран процес."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Воведување WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Поставете воведување WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Избраната примена на WebView е оневозможена, а за да се користи, мора да се овозможи. Дали сакате да ја овозможите?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Избраната WebView имплементација е неважечка поради неажуриран список со избори за имплементација. Списокот ќе се ажурира сега."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Конвертирајте до шифрирање датотеки"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Конвертирај..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Датотеката е веќе шифрирана"</string>
@@ -296,7 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Корекција на боја"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Функцијата е експериментална и може да влијае на изведбата."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Прескокнато според <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="power_remaining_duration_only" msgid="4400068916452346544">"Преостанаа прибл. <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Преостанаа прибл. <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – преостанува приближно <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до целосно полна"</string>
@@ -311,7 +310,7 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Не се полни"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не се полни"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Целосна"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Оневозможено од администраторот"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Контролирано од администраторот"</string>
<string name="home" msgid="8263346537524314127">"Почетна страница"</string>
<string name="charge_length_format" msgid="8978516217024434156">"Пред <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Преостанаа <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ml-rIN/strings.xml b/packages/SettingsLib/res/values-ml-rIN/strings.xml
index 38b4771..24ad333 100644
--- a/packages/SettingsLib/res/values-ml-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ml-rIN/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"ടെക്സ്റ്റ്-ടു-സ്പീച്ച് ഔട്ട്പുട്ട്"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"വായന നിരക്ക്"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"വാചകം പറയുന്ന വേഗത"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"പിച്ച്"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"സിന്തസൈസ് ചെയ്ത സംസാരത്തിന്റെ സ്വരഭേദത്തെ ബാധിക്കുന്നു"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"ഭാഷ"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"സിസ്റ്റം ഭാഷ ഉപയോഗിക്കുക"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"ഭാഷ തിരഞ്ഞെടുത്തിട്ടില്ല"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"ബാഹ്യമായതിൽ നിർബന്ധിച്ച് അനുവദിക്കുക"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"മാനിഫെസ്റ്റ് മൂല്യങ്ങൾ പരിഗണിക്കാതെ, ബാഹ്യ സ്റ്റോറേജിലേക്ക് എഴുതപ്പെടുന്നതിന് ഏതൊരു ആപ്പിനെയും യോഗ്യമാക്കുന്നു"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"വലിപ്പം മാറ്റാൻ പ്രവർത്തനങ്ങളെ നിർബന്ധിക്കുക"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"മാനിഫെസ്റ്റ് മൂല്യങ്ങൾ പരിഗണിക്കാതെ, എല്ലാ പ്രവർത്തനങ്ങളെയും മൾട്ടി-വിൻഡോയ്ക്കായി വലിപ്പം മാറ്റുന്നു."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"മാനിഫെസ്റ്റ് മൂല്യങ്ങൾ പരിഗണിക്കാതെ, എല്ലാ ആക്ടിവിറ്റികളെയും മൾട്ടി-വിൻഡോയ്ക്കായി വലിപ്പം മാറ്റുക."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"ഫ്രീഫോം വിൻഡോകൾ പ്രവർത്തനക്ഷമമാക്കുക"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"പരീക്ഷണാത്മക ഫ്രീഫോം വിൻഡോകൾക്കുള്ള പിന്തുണ പ്രവർത്തനക്ഷമമാക്കുന്നു."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"പരീക്ഷണാത്മക ഫ്രീഫോം വിൻഡോകൾക്കുള്ള പിന്തുണ പ്രവർത്തനക്ഷമമാക്കുക."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"ഡെസ്ക്ടോപ്പ് ബാക്കപ്പ് പാസ്വേഡ്"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"ഡെസ്ക്ടോപ്പ് പൂർണ്ണ ബാക്കപ്പുകൾ നിലവിൽ പരിരക്ഷിച്ചിട്ടില്ല"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"ഡെസ്ക്ടോപ്പ് പൂർണ്ണ ബാക്കപ്പുകൾക്കായി പാസ്വേഡുകൾ മാറ്റാനോ നീക്കംചെയ്യാനോ ടാപ്പുചെയ്യുക"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"സജീവം. മാറ്റുന്നതിന് ടാപ്പുചെയ്യുക."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"പ്രവർത്തിക്കുന്ന സേവനങ്ങൾ"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"നിലവിൽ പ്രവർത്തിക്കുന്ന സേവങ്ങൾ കാണുക, നിയന്ത്രിക്കുക"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"നൈറ്റ് മോഡ്"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"പ്രവർത്തനരഹിതമാക്കി"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"എല്ലായ്പ്പോഴും ഓണാണ്"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"ഓട്ടോമാറ്റിക്"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"മൾട്ടിപ്രോസസ്സ് WebView പ്രവർത്തനക്ഷമമാക്കൂ"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"ഒറ്റപ്പെട്ടൊരു പ്രോസസ്സിൽ WebView റെൻഡററുകൾ റൺ ചെയ്യുക."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView നടപ്പാക്കൽ"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView നടപ്പാക്കൽ സജ്ജമാക്കുക"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"തിരഞ്ഞെടുത്ത WebView നടപ്പാക്കൽ പ്രവർത്തനരഹിതമാക്കി, ഉപയോഗിക്കുന്നതിന് ഇത് പ്രവർത്തനക്ഷമമാക്കണം, പ്രവർത്തനക്ഷമമാക്കാൻ ആഗ്രഹിക്കുന്നുണ്ടോ?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"തിരഞ്ഞെടുത്ത WebView നടപ്പാക്കൽ അസാധുവാണ്, കാരണം നടപ്പാക്കൽ തിരഞ്ഞെടുപ്പുകളുടെ ലിസ്റ്റ് പഴകിപ്പോയി. ഈ ലിസ്റ്റിപ്പോൾ അപ്ഡേറ്റ് ചെയ്യേണ്ടതുണ്ട്."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ഫയൽ എൻക്രിപ്ഷനിലേക്ക് പരിവർത്തിപ്പിക്കുക"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"പരിവർത്തിപ്പിക്കുക…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ഇതിനകം തന്നെ ഫയൽ എൻക്രിപ്റ്റ് ചെയ്തു"</string>
@@ -296,7 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"വർണ്ണം ക്രമീകരിക്കൽ"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ഈ ഫീച്ചർ പരീക്ഷണാത്മകമായതിനാൽ പ്രകടനത്തെ ബാധിച്ചേക്കാം."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ഉപയോഗിച്ച് അസാധുവാക്കി"</string>
- <string name="power_remaining_duration_only" msgid="4400068916452346544">"ഏകദേശം <xliff:g id="TIME">%2$s</xliff:g> ശേഷിക്കുന്നു"</string>
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"ഏകദേശം <xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ഏകദേശം <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - പൂർണ്ണമായും ചാർജ്ജാകുന്നതിന്, <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -311,7 +310,7 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"ചാർജ്ജുചെയ്യുന്നില്ല"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"ചാർജ്ജുചെയ്യുന്നില്ല"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"നിറഞ്ഞു"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"അഡ്മിനിസ്ട്രേറ്റർ പ്രവർത്തനരഹിതമാക്കി"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"അഡ്മിൻ നിയന്ത്രിക്കുന്നത്"</string>
<string name="home" msgid="8263346537524314127">"ഹോം"</string>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> മുമ്പ്"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
diff --git a/packages/SettingsLib/res/values-mn-rMN/strings.xml b/packages/SettingsLib/res/values-mn-rMN/strings.xml
index 3b5d5f1..5466ff1 100644
--- a/packages/SettingsLib/res/values-mn-rMN/strings.xml
+++ b/packages/SettingsLib/res/values-mn-rMN/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Текст-яриа гаргах"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Ярианы түвшин"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Текстийг унших хурд"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Авиа тон"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Авоматаар үүссэн ярианы дуудлаганд нөлөөлдөг"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Хэл"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Системийн хэлийг ашиглах"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Хэл сонгогдоогүй байна"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Апп-ыг гадаад санах ойд хадгалахыг зөвшөөрөх"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Манифест утгыг нь үл хамааран дурын апп-ыг гадаад санах ойд бичих боломжтой болгодог"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Үйл ажиллагааны хэмжээг өөрчилж болохуйц болгох"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Тодорхойлогч файлын утгыг үл хамааран, бүх үйл ажиллагааг олон цонхонд хэмжээг нь өөрчилж болохуйц болгох."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Тодорхойлогч файлын утгыг үл хамааран, бүх үйл ажиллагааны хэмжээг олон цонхонд өөрчилж болохуйц болгоно уу."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Чөлөөт хэлбэрийн цонхыг идэвхжүүлэх"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Туршилтын чөлөөт хэлбэрийн цонхны дэмжлэгийг идэвхжүүлдэг."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Туршилтын чөлөөт хэлбэрийн цонхны дэмжлэгийг идэвхжүүлнэ үү."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Десктоп нөөшлөлтийн нууц үг"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Десктоп бүрэн нөөцлөлт одоогоор хамгаалалтгүй байна"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Компьютерийн бүтэн нөөцлөлтийн нууц үгийг өөрчлөх, устгах бол дарна уу"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Идэвхтэй байна. Унтраах/асаахын тулд дарна уу."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Ажиллаж байгаа үйлчилгээнүүд"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Одоо ажиллаж байгаа үйлчилгээнүүдийг харах болон хянах"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Шөнийн горим"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Идэвхгүй"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Байнга асаалттай"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Автоматаар"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"WebView-н олон боловсруулалтыг идэвхжүүлэх"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView хөрвүүлэгчийг тусдаа боловсруулалтаар ажиллуулна уу."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView хэрэгжилт"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView хэрэгжилтийг тохируулах"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Сонгосон WebView хэрэгжүүлэлтийг идэвхгүй болгосон бөгөөд хэрэглэхийн тулд заавал идэвхжүүлэх шаардлагатай. Үүнийг идэвхжүүлэх үү?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Хэрэгжүүлэлтийн сонголтын жагсаалт хуучирсан тул сонгосон WebView хэрэгжүүлэлт хүчингүй байна. Жагсаалтыг одоо шинэчлэх болно."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Файлын шифрлэлт болгон хөрвүүлэх"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Хөрвүүлэх..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Аль хэдийнэ файл шифрлэгдсэн"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Өнгө тохируулах"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Энэ функц туршилтынх бөгөөд ажиллагаанд нөлөөлж болзошгүй."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Давхарласан <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ойролцоогоор <xliff:g id="TIME">%1$s</xliff:g> үлдсэн"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ойролцоогоор <xliff:g id="TIME">%2$s</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="2853265177761520490">"дүүртэл <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Цэнэглэхгүй байна"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Цэнэглэхгүй байна"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Дүүрэн"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Админ идэвхгүй болгосон"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Админ удирдсан"</string>
<string name="home" msgid="8263346537524314127">"Нүүр"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> өмнө"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> үлдсэн"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mr-rIN/strings.xml b/packages/SettingsLib/res/values-mr-rIN/strings.xml
index 493f579..ab55a3d 100644
--- a/packages/SettingsLib/res/values-mr-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-mr-rIN/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"टेक्स्ट-टू-स्पीच आउटपुट"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"बोलण्याचा रेट"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"ज्या गतीने मजकूर बोलला जातो ती"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"पिच"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"संश्लेषित उच्चारांच्या आवाजास प्रभावित करते"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"भाषा"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"सिस्टम भाषा वापरा"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"भाषा निवडलेली नाही"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"बाह्यवर अॅप्सना अनुमती देण्याची सक्ती करा"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"मॅनिफेस्ट मूल्यांकडे दुर्लक्ष करून, कोणत्याही अॅपला बाह्य संचयनावर लेखन केले जाण्यासाठी पात्र बनविते"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"क्रियाकलापाचा आकार बदलण्यायोग्य होण्याची सक्ती करा"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"मॅनिफेस्ट मूल्यांकडे दुर्लक्ष करून, एकाधिक-विंडोसाठी सर्व क्रियाकलापांचा आकार बदलण्यायोग्य करा"</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"मॅनिफेस्ट मूल्यांकडे दुर्लक्ष करून, एकाधिक-विंडोसाठी सर्व क्रियाकलापांचा आकार बदलण्यायोग्य करा."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"freeform विंडो सक्षम करा"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"प्रायोगिक मुक्तस्वरूपाच्या विंडोसाठी समर्थन सक्षम करते."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"प्रायोगिक मुक्तस्वरूपाच्या विंडोसाठी समर्थन सक्षम करा."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"डेस्कटॉप बॅकअप संकेतशब्द"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"डेस्कटॉप पूर्ण बॅक अप सध्या संरक्षित नाहीत"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"डेस्कटॉपच्या पूर्ण बॅकअपसाठी असलेला संकेतशब्द बदलण्यासाठी किंवा काढण्यासाठी टॅप करा"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"सक्रिय. टॉगल करण्यासाठी टॅप करा."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"चालू सेवा"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"सध्या चालत असलेल्या सेवा पहा आणि नियंत्रित करा"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"रात्र मोड"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"अक्षम केले"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"नेहमी चालू"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"स्वयंचलित"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"एकाधिक प्रक्रिया WebView सक्षम करा"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"एक वेगळ्या प्रक्रियेत WebView प्रस्तुतकर्ते चालवा."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"वेबदृश्य अंमलबजावणी"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"वेबदृश्य अंमलबजावणी सेट करा"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"निवडलेली WebView अंमलबजावणी अक्षम आहे आणि वापरण्यास सक्षम असणे आवश्यक आहे, आपण ती सक्षम करू इच्छिता?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"अंमलबजावणीची निवडींची सूची जुनी झाली असल्याने निवडलेली WebView अंमलबजावणी अवैध आहे."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"फाईल कूटबद्धीकरणावर रूपांतरित करा"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"रूपांतरित करा..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"फाईल आधीपासून कूटबद्ध केली"</string>
@@ -296,7 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"रंग सुधारणा"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"हे वैशिष्ट्य प्रायोगिक आहे आणि कदाचित कार्यप्रदर्शन प्रभावित करू शकते."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारे अधिलिखित"</string>
- <string name="power_remaining_duration_only" msgid="4400068916452346544">"अंदाजे. <xliff:g id="TIME">%2$s</xliff:g> शिल्लक"</string>
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"अंदाजे. <xliff:g id="TIME">%1$s</xliff:g> शिल्लक"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - अंदाजे. <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पूर्ण होण्यात"</string>
@@ -311,7 +310,7 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"चार्ज होत नाही"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"चार्ज होत नाही"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"पूर्ण"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"प्रशासकाद्वारे अक्षम केलेले"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"प्रशासकाने नियंत्रित केलेले"</string>
<string name="home" msgid="8263346537524314127">"मुख्यपृष्ठ"</string>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> पूर्वी"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> शिल्लक"</string>
diff --git a/packages/SettingsLib/res/values-ms-rMY/strings.xml b/packages/SettingsLib/res/values-ms-rMY/strings.xml
index 0509159..01b52c1 100644
--- a/packages/SettingsLib/res/values-ms-rMY/strings.xml
+++ b/packages/SettingsLib/res/values-ms-rMY/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Output teks ke pertuturan"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Kadar pertuturan"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Kelajuan pertuturan teks"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Pic"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Mempengaruhi nada pertuturan disintesiskan"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Bahasa"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Gunakan bahasa sistem"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Bahasa tidak dipilih"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Benarkan apl secara paksa pada storan luaran"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Menjadikan sebarang apl layak ditulis ke storan luaran, walau apa juga nilai manifesnya"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Paksa aktiviti supaya boleh diubah saiz"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Menjadikan semua aktiviti boleh diubah saiz untuk berbilang tetingkap, tanpa mengambil kira nilai manifes."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Bolehkan semua saiz aktiviti diubah untuk berbilang tetingkap, tanpa mengambil kira nilai manifes."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Dayakan tetingkap bentuk bebas"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Mendayakan sokongan untuk tetingkap bentuk bebas percubaan."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Dayakan sokongan untuk tetingkap bentuk bebas percubaan."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Kata laluan sandaran komputer meja"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Sandaran penuh komputer meja tidak dilindungi pada masa ini"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Ketik untuk menukar atau mengalih keluar kata laluan untuk sandaran penuh desktop"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktif. Ketik untuk menogol."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Perkhidmatan dijalankan"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Lihat dan kawal perkhidmatan yang sedang dijalankan"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Mod malam"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Dilumpuhkan"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Sentiasa hidup"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automatik"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Dayakan WebView berbilang proses"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Jalankan pemapar WebView dalam proses terpencil."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Pelaksanaan WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Tetapkan pelaksanaan WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Pelaksanaan WebView pilihan telah dilumpuhkan dan mesti didayakan untuk digunakan, adakah anda mahu mendayakannya?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Pelaksanaan WebView yang dipilih tidak sah kerana senarai pilihan pelaksanaan telah lapuk. Senarai itu seharusnya dikemas kini sekarang."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Tukar kepada penyulitan fail"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Tukar..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Sudah disulitkan fail"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Pembetulan warna"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ciri ini adalah percubaan dan boleh menjejaskan prestasi."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Diatasi oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Kira-kira <xliff:g id="TIME">%1$s</xliff:g> lagi"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - kira-kira. <xliff:g id="TIME">%2$s</xliff:g> yang tinggal"</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga penuh"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Tidak mengecas"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Tidak mengecas"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Penuh"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Dilumpuhkan oleh pentadbir"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Dikawal oleh pentadbir"</string>
<string name="home" msgid="8263346537524314127">"Skrin Utama"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> yang lalu"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> lagi"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-my-rMM/strings.xml b/packages/SettingsLib/res/values-my-rMM/strings.xml
index 9f56479..d3659b7 100644
--- a/packages/SettingsLib/res/values-my-rMM/strings.xml
+++ b/packages/SettingsLib/res/values-my-rMM/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"စာသားမှ အသံထွက်စေခြင်း"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"စကားပြောနှုန်း"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"စာတမ်းအားပြောဆိုသော အမြန်နှုန်း"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"အသံအနိမ့်အမြင့်"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"စက်ဖြင့်ထုတ်လုပ်ထားသည့် စကားသံကို အကျိုးသက်ရောက်မှုရှိပါမည်။"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"ဘာသာစကား"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"စနစ်၏ ဘာသာစကားကို အသုံးပြုရန်"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"ဘာသာစကား မရွေးချယ်ထားပါ။"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"အပြင်မှာ အတင်း ခွင့်ပြုရန်"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"ပြနေတဲ့ တန်ဖိုး ဘယ်လိုပဲရှိနေနေ၊ ဘယ် appကို မဆို အပြင် သိုလှောင်ခန်းသို့ ရေးသားခွင့် ပေးတယ်"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"လုပ်ဆောင်ချက်များ ဆိုက်ညှိရနိုင်ရန် လုပ်ခိုင်းပါ"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"မန်နီးဖက်စ် တန်ဖိုးမရွေး၊ လုပ်ဆောင်ချက် အားလုံး ဆိုက်ညှိရနိုင်အောင် လုပ်ပေးပါ။"</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"မန်နီးဖက်စ်တန်ဖိုးများ မည်မျှပင်ရှိစေကာမူ၊ ဝင်းဒိုးများအတွက် လှုပ်ရှားမှုများအားလုံးကို အရွယ်အစားချိန်ခြင်း ပြုလုပ်ပါ။"</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"အခမဲ့ပုံစံ ဝင်းဒိုးကို ဖွင့်ပါ"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"စမ်းသပ်မှု အခမဲ့ပုံစံ ဝင်းဒိုးများအတွက် ပံ့ပိုးမှုကို ဖွင့်ပါ။"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"ပုံစံမျိုးစုံဝင်းဒိုးများစမ်းသပ်မှုအတွက် အထောက်အပံ့ကိုဖွင့်ပါ"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Desktop အရန်စကားဝှက်"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"အလုပ်ခုံတွင် အရန်သိမ်းဆည်းခြင်းများကို လောလောဆယ် မကာကွယ်နိုင်ပါ။"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"စားပွဲတင်ကွန်ပျူတာကို အပြည့်အဝအရံကူးထားရန်အတွက် စကားဝှက်ကို ပြောင်းရန် သို့မဟုတ် ဖယ်ရှားရန် တို့ပါ။"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"ပွင့်နေသည်။ ပြောင်းရန်တို့ပါ။"</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"အလုပ်လုပ်နေသောဝန်ဆောင်မှုများ"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"ယခုအလုပ်လုပ်နေသောဝန်ဆောင်မှုကို ကြည့်ခြင်းနှင့် ထိန်းသိမ်းခြင်းအား ပြုလုပ်မည်လား?"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"ညသုံး မုဒ်"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"ပိတ်ထား"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"အမြဲတမ်း ဖွင့်ထားရန်"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"အလိုအလျောက်"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"လုပ်ငန်းဖြစ်စဉ်များစွာကြည့်နိုင်သည့် ဝဘ်မြင်ကွင်းကိုဖွင့်ပါ"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"လုပ်ငန်းဖြစ်စဉ်တစ်ခုတည်းအတွက် ဝဘ်မြင်ကွင်း အဖြစ်ပြုလုပ်ခြင်းကို ဖွင့်ပါ။"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView အကောင်အထည်ဖော်မှု"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView အကောင်အထည်ဖော်မှု သတ်မှတ်ပါ"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"ရွေးချယ်ထားသည့် WebView လုပ်ဆောင်ခြင်းကို ပိတ်ထားသည်ပြီး အသုံးပြုရန်အတွက် ဖွင့်ရမည်၊ ဖွင့်လိုပါသလား။"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"ရွေးချယ်ထားသည့် ဝဘ်မြင်ကွင်းထည့်သွင်းမှု မမှန်ကန်ပါ၊ အဘယ့်ကြောင့်ဆိုသော် ရွေးချယ်ရန် ထည့်သွင်းမှုစာရင်းသည် အသစ်မဖြစ်တော့သောကြောင့်ဖြစ်သည်။ စာရင်းကို ယခုအပ်ဒိတ် ဖြစ်နေလောက်ပါပြီ။"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ဖိုင်လုံခြုံအောင်ပြုလုပ်ခြင်းသို့ ပြောင်းပါ"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"ပြောင်းရန်…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ဖိုင်ကို လုံခြုံအောင်ပြုလုပ်ပြီးပါပြီ"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"အရောင်ပြင်ဆင်မှု"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ဒီအင်္ဂါရပ်မှာ စမ်းသပ်မှု ဖြစ်၍ လုပ်ကိုင်မှုကို အကျိုးသက်ရောက်နိုင်သည်။"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> မှ ကျော်၍ လုပ်ထားသည်။"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"ခန့်မှန်းခြေ <xliff:g id="TIME">%1$s</xliff:g> ကျန်ပါသည်"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ခန့်မှန်းခြေ။ <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> အပြည့်အထိ"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"အားသွင်းမနေပါ"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"အားသွင်းမနေပါ"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"အပြည့်"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"စီမံခန့်ခွဲသူမှ ပိတ်ထားသည်"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"စီမံခန့်ခွဲသူမှ ထိန်းချုပ်ပါသည်"</string>
<string name="home" msgid="8263346537524314127">"ပင်မ"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"ပြီးခဲ့သည့် <xliff:g id="ID_1">%1$s</xliff:g> က"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> ကျန်ပါသည်"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 013fe26..6865d50 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Tekst-til-tale"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Talehastighet"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Hvor raskt teksten leses"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Stemmeleie"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Påvirker tonehøyden for syntetisert tale"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Språk"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Bruk systemspråk"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Språk er ikke valgt"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Tving frem tillatelse for ekstern lagring av apper"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Gjør at apper kan skrives til ekstern lagring, uavhengig av manifestverdier"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Tving aktiviteter til å kunne endre størrelse"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Dette gjør at alle aktivitene kan endre størrelse for flervindusmodus, uavhengig av manifestverdier."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Gjør at alle aktivitetene kan endre størrelse for flervindusmodus, uavhengig av manifestverdier."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Slå på vinduer i fritt format"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Slår på støtte for vinduer i eksperimentelt fritt format."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Slå på støtte for vinduer i eksperimentelt fritt format."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Passord for sikkerhetskopiering på datamaskin"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Fullstendig sikkerhetskopiering på datamaskin beskyttes ikke for øyeblikket."</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Trykk for å endre eller fjerne passordet for fullstendige sikkerhetskopier på datamaskinen"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktiv. Trykk for å slå av/på."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Aktive tjenester"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Se og kontrollér tjenester som kjører for øyeblikket"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Nattmodus"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Slått av"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Alltid på"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automatisk"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Slå på WebView for flere prosesser"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Kjør WebView-gjengivelser i en isolert prosess."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementering"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Angi WebView-implementering"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Den valgte implementeringen av nettvisningen er slått av – den må slås på for å brukes. Vil du slå den på?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Den valgte WebView-implementeringen er ugyldig fordi listen over implementeringsvalg er foreldet. Listen er nå oppdatert."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertér til kryptert fil"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertér …"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Allerede kryptert og lagret som fil"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Fargekorrigering"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Denne funksjonen er eksperimentell og kan påvirke ytelsen."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overstyres av <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca. <xliff:g id="TIME">%1$s</xliff:g> gjenstår"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – ca. <xliff:g id="TIME">%2$s</xliff:g> igjen"</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – fulladet om <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Lader ikke"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Lader ikke"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Fullt"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Avslått av administratoren"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kontrollert av administratoren"</string>
<string name="home" msgid="8263346537524314127">"Startside"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> siden"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> gjenstår"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ne-rNP/strings.xml b/packages/SettingsLib/res/values-ne-rNP/strings.xml
index 715f055..7742b9d 100644
--- a/packages/SettingsLib/res/values-ne-rNP/strings.xml
+++ b/packages/SettingsLib/res/values-ne-rNP/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"पाठ-बाट-वाणी उत्पादन"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"वाणी दर"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"पाठ वाचन हुने गति"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"पिच"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"संश्लेषित बोलीको टोनमा प्रभाव पार्छ"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"भाषा"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"प्रणाली भाषा प्रयोग गर्नुहोस्"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"भाषा चयन गरिएको छैन"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"बाह्यमा बल प्रयोगको अनुमति प्राप्त अनुप्रयोगहरू"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"म्यानिफेेस्टको उपेक्षा गरी, कुनै पनि अनुप्रयोगलाई बाह्य भण्डारणमा लेख्न योग्य बनाउँछ"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"गतिविधिहरू रिसाइज गर्नको लागि बाध्य गर्नुहोस्"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"म्यानिफेेस्ट मानहरूको ख्याल नगरी, बहु-विन्डोको लागि सबै रिसाइज गर्न सकिने गतिविधिहरू बनाउँछ।"</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"म्यानिफेेस्ट मानहरूको ख्याल नगरी, बहु-विन्डोको लागि सबै रिसाइज गर्न सकिने गतिविधिहरू बनाउनुहोस्।"</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"फ्रिफर्म विन्डोहरू सक्रिय गर्नुहोस्"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"प्रयोगात्मक फ्रिफर्म विन्डोहरूका लागि समर्थनलाई सक्रिय गर्छ।"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"प्रयोगात्मक फ्रिफर्म विन्डोहरूका लागि समर्थन सक्रिय गर्नुहोस्।"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"डेस्कटप ब्याकअप पासवर्ड"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"डेस्कटप पूर्ण जगेडाहरू हाललाई सुरक्षित छैनन्"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"डेस्कटप पूर्ण ब्याकअपको लागि पासवर्ड बदल्न वा हटाउन ट्याप गर्नुहोस्"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"सक्रिय। टगल गर्न ट्याप गर्नुहोस्।"</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"चलिरहेका सेवाहरू"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"हाल चालु भइरहेका सेवाहरू हेर्नुहोस् र नियन्त्रण गर्नुहोस्"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"रात्री मोड"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"असक्षम गरियो"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"सधैं खुल्ला"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"स्वचालित"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"मल्टिप्रोसेस वेबभ्यु सक्षम गर्नुहोस्"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"एउटा पृथक प्रक्रियामा वेबभ्यु रेन्डररहरू चलाउनुहोस्।"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView कार्यान्वयन"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView कार्यान्वयन सेट गर्नुहोस्"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"छनौट गरिएको WebView को कार्यान्वयन असक्षम गरिएको छ र प्रयोग गर्नका लागि सक्रिय गर्नुपर्छ, तपाईँ यसलाई सक्रिय गर्न चाहनुहुन्छ?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"कार्यान्वयनको सूची पुरानो भइसकेको हुनाले छनोट गरिएको WebView को कार्यान्वयन अमान्य छ। सूची अब अद्यावधिक हुनुपर्छ।"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"फाइल इन्क्रिप्सनमा रूपान्तरण गर्नुहोस्"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"रुपान्तरण गर्नुहोस्…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"पहिल्यै फाइल इन्क्रिप्ट गरिएको छ"</string>
@@ -296,7 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"रङ्ग सुधार"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"यो सुविधा प्रयोगात्मक छ र प्रदर्शनमा असर गर्न सक्छ।"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारा अधिरोहित"</string>
- <string name="power_remaining_duration_only" msgid="4400068916452346544">"लगभग <xliff:g id="TIME">%2$s</xliff:g> बाँकी छ"</string>
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"लगभग <xliff:g id="TIME">%1$s</xliff:g> बाँकी छ"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - लगभग। <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पूर्ण नभए सम्म"</string>
@@ -311,7 +310,7 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"चार्ज भइरहेको छैन"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"चार्ज हुँदै छैन"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"पूर्ण"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"प्रशासकद्वारा असक्षम गरिएको"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"प्रशासकद्वारा नियन्त्रित"</string>
<string name="home" msgid="8263346537524314127">"गृह"</string>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> पहिले"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> बाँकी"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index bd24201..efee429 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Spraakuitvoer"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Spreeksnelheid"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Snelheid waarmee de tekst wordt gesproken"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Hoogte"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Is van invloed op de toon van de synthetisch gegenereerde spraak"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Taal"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Systeemtaal gebruiken"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Taal niet geselecteerd"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Toestaan van apps op externe opslag afdwingen"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Hierdoor komt een app in aanmerking om te worden geschreven naar externe opslag, ongeacht de manifestwaarden"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Formaat activiteiten geforceerd aanpasbaar maken"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Hiermee wordt het formaat van alle activiteiten aanpasbaar gemaakt, ongeacht de manifestwaarden."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Het formaat van alle activiteiten aanpasbaar maken, ongeacht de manifestwaarden."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Vensters met vrije vorm inschakelen"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Schakelt ondersteuning in voor vensters met experimentele vrije vorm."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Ondersteuning voor vensters met experimentele vrije vorm inschakelen."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Wachtwoord desktopback-up"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Volledige back-ups naar desktops zijn momenteel niet beveiligd"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tik om het wachtwoord voor volledige back-ups naar desktops te wijzigen of te verwijderen"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Actief. Tik om te schakelen."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Actieve services"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Services die momenteel actief zijn, weergeven en beheren"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Nachtmodus"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Uitgeschakeld"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Altijd aan"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automatisch"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Multiproces-WebView aan"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView-weergaveprogramma\'s uitvoeren in geïsoleerd proces."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementatie"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView-implementatie instellen"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"De gekozen WebView-implementatie is uitgeschakeld en moet worden ingeschakeld voor gebruik. Wil je deze inschakelen?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"De geselecteerde WebView-implementatie is ongeldig omdat de lijst met implementatiekeuzes was verouderd. De lijst is nu geüpdatet."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Converteren naar versleuteling op basis van bestanden"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converteren…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Al versleuteld op basis van bestanden"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Kleurcorrectie"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Deze functie is experimenteel en kan invloed hebben op de prestaties."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overschreven door <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca. <xliff:g id="TIME">%1$s</xliff:g> resterend"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ca. <xliff:g id="TIME">%2$s</xliff:g> resterend"</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot vol"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Wordt niet opgeladen"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Wordt niet opgeladen"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Volledig"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Uitgeschakeld door beheerder"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Ingesteld door beheerder"</string>
<string name="home" msgid="8263346537524314127">"Startpagina"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> geleden"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> resterend"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pa-rIN/strings.xml b/packages/SettingsLib/res/values-pa-rIN/strings.xml
index f9c0c11..15e6635 100644
--- a/packages/SettingsLib/res/values-pa-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-pa-rIN/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"ਟੈਕਸਟ-ਟੂ-ਸਪੀਚ ਆਉਟਪੁਟ"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"ਸਪੀਚ ਰੇਟ"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"ਸਪੀਡ ਜਿਸਤੇ ਟੈਕਸਟ ਬੋਲਿਆ ਜਾਂਦਾ ਹੈ"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"ਪਿਚ"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"ਬਣਾਵਟੀ ਬੋਲੀ ਦੇ ਲਹਿਜੇ \'ਤੇ ਅਸਰ ਪਾਉਂਦੀ ਹੈ"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"ਭਾਸ਼ਾ"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"ਸਿਸਟਮ ਭਾਸ਼ਾ ਵਰਤੋ"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"ਭਾਸ਼ਾ ਨਹੀਂ ਚੁਣੀ"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"ਐਪਸ ਨੂੰ ਬਾਹਰਲੇ ਤੇ ਜ਼ਬਰਦਸਤੀ ਆਗਿਆ ਦਿਓ"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"ਇੱਕ ਐਪ ਨੂੰ ਬਾਹਰਲੀ ਸਟੋਰੇਜ ਤੇ ਲਿਖਣ ਦੇ ਯੋਗ ਬਣਾਉਂਦਾ ਹੈ, ਮੈਨੀਫੈਸਟ ਵੈਲਯੂਜ ਤੇ ਵਿਚਾਰ ਕੀਤੇ ਬਿਨਾਂ"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"ਮੁੜ-ਆਕਾਰ ਬਦਲਣ ਲਈ ਸਰਗਰਮੀਆਂ \'ਤੇ ਜ਼ੋਰ ਦਿਓ"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"ਮਲਟੀ-ਵਿੰਡੋ ਲਈ ਸਾਰੀਆਂ ਸਰਗਰਮੀਆਂ ਨੂੰ ਮੁੜ-ਆਕਾਰ ਵਿੱਚ ਲਿਆਉਂਦੀ ਹੈ, ਚਾਹੇ ਮੈਨੀਫੈਸਟ ਵੈਲਯੂਜ਼ ਕੁਝ ਵੀ ਹੋਣ।"</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"ਮੈਨੀਫੈਸਟ ਮੁੱਲਾਂ ਦੀ ਪਰਵਾਹ ਕੀਤੇ ਬਿਨਾਂ, ਮਲਟੀ-ਵਿੰਡੋ ਲਈ ਸਾਰੀਆਂ ਸਰਗਰਮੀਆਂ ਨੂੰ ਆਕਾਰ ਬਦਲਣਯੋਗ ਬਣਾਓ।"</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"freeform windows ਨੂੰ ਯੋਗ ਬਣਾਓ"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"ਪ੍ਰਯੋਗਾਤਮਕ freeform windows ਲਈ ਸਮਰਥਨ ਨੂੰ ਯੋਗ ਬਣਾਉਂਦੀ ਹੈ।"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"ਪ੍ਰਯੋਗਮਈ ਫ੍ਰੀਫਾਰਮ ਵਿੰਡੋਜ਼ ਲਈ ਸਮਰਥਨ ਨੂੰ ਯੋਗ ਬਣਾਓ।"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"ਡੈਸਕਟੌਪ ਬੈਕਅਪ ਪਾਸਵਰਡ"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"ਡੈਸਕਟੌਪ ਪੂਰੇ ਬੈਕਅਪਸ ਇਸ ਵੇਲੇ ਸੁਰੱਖਿਅਤ ਨਹੀਂ ਹਨ"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"ਡੈਸਕਟਾਪ ਦੇ ਮੁਕੰਮਲ ਬੈਕਅੱਪਾਂ ਲਈ ਪਾਸਵਰਡ ਨੂੰ ਬਦਲਣ ਜਾਂ ਹਟਾਉਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"ਕਿਰਿਆਸ਼ੀਲ। ਟੌਗਲ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"ਚੱਲ ਰਹੀਆਂ ਸੇਵਾਵਾਂ"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"ਇਸ ਵੇਲੇ ਚੱਲ ਰਹੀਆਂ ਸੇਵਾਵਾਂ ਦੇਖੋ ਅਤੇ ਇਹਨਾਂ ਤੇ ਨਿਯੰਤਰਣ ਪਾਓ"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"ਰਾਤ ਮੋਡ"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"ਅਸਮਰੱਥ ਬਣਾਇਆ"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"ਹਮੇਸ਼ਾ ਚਾਲੂ"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"ਆਟੋਮੈਟਿਕ"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"ਬਹੁ-ਮੰਤਵ WebView ਨੂੰ ਯੋਗ ਬਣਾਓ"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"ਕਿਸੇ ਵੱਖ ਕੀਤੀ ਗਈ ਪ੍ਰਕਿਰਿਆ ਵਿੱਚ WebView ਰੈਂਡਰਰਾਂ ਨੂੰ ਚਲਾਓ।"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ਅਮਲ"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView ਅਮਲ ਸੈੱਟ ਕਰੋ"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"ਚੁਣਿਆ ਗਿਆ WebView ਅਮਲ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ, ਅਤੇ ਵਰਤੋਂ ਕਰਨ ਲਈ ਇਸ ਨੂੰ ਯੋਗ ਬਣਾਇਆ ਜਾਣਾ ਜ਼ਰੂਰੀ ਹੈ, ਕੀ ਤੁਸੀਂ ਇਸ ਨੂੰ ਯੋਗ ਬਣਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"ਚੁਣਿਆ ਗਿਆ WebView ਅਮਲ ਅਵੈਧ ਹੈ ਕਿਉਂਕਿ ਅਮਲ ਚੋਣਾਂ ਦੀ ਸੂਚੀ ਪੁਰਾਣੀ ਹੋ ਗਈ ਹੈ। ਸੂਚੀ ਨੂੰ ਹੁਣ ਅੱਪਡੇਟ ਕੀਤਾ ਜਾਣਾ ਚਾਹੀਦਾ ਹੈ।"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ਫ਼ਾਈਲ ਇਨਕ੍ਰਿਪਸ਼ਨ ਵਿੱਚ ਤਬਦੀਲ ਕਰੋ"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"ਤਬਦੀਲ ਕਰੋ ..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ਫ਼ਾਈਲ ਪਹਿਲਾਂ ਤੋਂ ਇਨਕ੍ਰਿਪਟਡ ਹੈ"</string>
@@ -296,7 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"ਰੰਗ ਸੰਸ਼ੋਧਨ"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਪ੍ਰਯੋਗਾਤਮਿਕ ਹੈ ਅਤੇ ਪ੍ਰਦਰਸ਼ਨ ਤੇ ਅਸਰ ਪਾ ਸਕਦੀ ਹੈ।"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ਦੁਆਰਾ ਓਵਰਰਾਈਡ ਕੀਤਾ"</string>
- <string name="power_remaining_duration_only" msgid="4400068916452346544">"ਲਗਭਗ <xliff:g id="TIME">%2$s</xliff:g> ਬਾਕੀ"</string>
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"ਲਗਭਗ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਲਗਭਗ <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ਪੂਰੀ ਹੋਣ ਤੱਕ"</string>
@@ -311,7 +310,7 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"ਚਾਰਜ ਨਹੀਂ ਹੋ ਰਿਹਾ"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"ਚਾਰਜ ਨਹੀਂ ਹੋ ਰਿਹਾ"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"ਪੂਰੀ"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਕੰਟਰੋਲ ਕੀਤੀ ਗਈ"</string>
<string name="home" msgid="8263346537524314127">"ਮੁੱਖ ਸਕ੍ਰੀਨ"</string>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> ਪਹਿਲਾਂ"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> ਬਾਕੀ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 4ff0d03..9d8d97a 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Zamiana tekstu na mowę"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Szybkość mowy"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Szybkość czytania tekstu"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tony"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Wpływa na dźwięk syntezatora mowy"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Język"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Użyj języka systemu"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Nie wybrano języka"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Wymuś zezwalanie na aplikacje w pamięci zewn."</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Pozwala na zapis aplikacji w pamięci zewn. niezależnie od wartości w pliku manifestu"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Wymuś zmianę rozmiaru okien aktywności"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Umożliwia zmianę rozmiaru wszystkich okien aktywności w trybie wielu okien niezależnie od ustawień w pliku manifestu."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Zezwól na zmianę rozmiaru wszystkich okien aktywności w trybie wielu okien niezależnie od ustawień w pliku manifestu."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Włącz dowolny rozmiar okien"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Włącza obsługę eksperymentalnej funkcji dowolnego rozmiaru okien."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Włącz obsługę eksperymentalnej funkcji dowolnego rozmiaru okien."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Hasło kopii zapasowej"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Pełne kopie zapasowe na komputerze nie są obecnie chronione"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Dotknij, by zmienić lub usunąć hasło pełnych kopii zapasowych na komputerze."</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktywna. Dotknij, by zmienić."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Uruchomione usługi"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Wyświetl obecnie uruchomione usługi i zarządzaj nimi"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Tryb nocny"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Wyłączone"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Zawsze włączone"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automatycznie"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Włącz wieloprocesowy WebView"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Uruchom WebView jako izolowany proces."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementacja WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Ustaw implementację WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Wybrana implementacja WebView jest wyłączona. Aby jej używać, musisz ją włączyć. Chcesz to zrobić?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Wybrana implementacja WebView jest nieprawidłowa – lista implementacji do wyboru straciła ważność. Musisz zaktualizować listę."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Przekształć na szyfrowanie plików"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Przekształć…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Pliki są już zaszyfrowane"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korekcja kolorów"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"To jest funkcja eksperymentalna i może wpływać na działanie urządzenia."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Nadpisana przez <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Pozostało około <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – zostało ok. <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Nie podłączony"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nie podłączony"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Naładowana"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Wyłączone przez administratora"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kontrolowane przez administratora"</string>
<string name="home" msgid="8263346537524314127">"Ekran główny"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> temu"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"Pozostało <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index b4251a5..844ae41 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Conversão de texto em voz"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Taxa de fala"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocidade em que o texto é falado"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Frequência do som"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Afeta o tom da voz sintetizada"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Usar idioma do sistema"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Idioma não selecionado"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Forçar permissão de apps em armazenamento externo"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Qualifica apps p/ gravação em armazenamento externo, independentemente de valores de manifestos"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Forçar atividades a serem redimensionáveis"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Torna todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Tornar todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Ativar janelas de forma livre"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Ativa a compatibilidade com janelas de forma livre experimentais."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Ativar a compatibilidade com janelas de forma livre experimentais."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Senha do backup local"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Os backups completos do computador não estão protegidos no momento"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Toque para alterar ou remover a senha de backups completos do desktop"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Ativo. Tocar para alternar."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Serviços em execução"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Visualizar e controlar os serviços em execução no momento"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Modo noturno"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Desativada"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Sempre ativada"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automático"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Ativar WebView de vários processos"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Executar renderizadores de WebView em um processo isolado."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementação do WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Configurar implementação do WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"A implementação do WebView escolhida está desativada e deve ser ativada para ser usada. Deseja ativá-la?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"A implementação de WebView escolhida é inválida, porque a lista de opções de implementação estava desatualizada. A lista deve estar atualizada agora."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Converter para criptografia de arquivos"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converter..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Já criptografado com base em arquivos"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correção de cor"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Este recurso é experimental e pode afetar o desempenho."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Aproximadamente <xliff:g id="TIME">%1$s</xliff:g> restante(s)"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - cerca de <xliff:g id="TIME">%2$s</xliff:g> restantes"</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Não está carregando"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Não está carregando"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Cheio"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Desativada pelo administrador"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlada pelo admin"</string>
<string name="home" msgid="8263346537524314127">"Início"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> atrás"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> restante(s)"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 3dd9561..115f951 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Saída de texto para voz"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Taxa de voz"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocidade a que o texto é falado"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tonalidade"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Afeta o tom da voz sintetizada"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Utilizar idioma do sistema"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Idioma não selecionado"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Forçar perm. de aplicações no armazenamento ext."</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Qualquer aplic. pode ser gravada no arm. ext., independ. dos valores do manif."</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Forçar as atividades a serem redimensionáveis"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Torna todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Tornar todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Ativar janelas de forma livre"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Ativa a compatibilidade com janelas de forma livre experimentais."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Ativar a compatibilidade com janelas de forma livre experimentais."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Palavra-passe cópia do comp."</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"As cópias de segurança completas no ambiente de trabalho não estão atualmente protegidas"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tocar para alterar ou remover a palavra-passe para cópias de segurança completas no ambiente de trabalho"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Ativo. Toque para ativar/desativar."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Serviços em execução"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Ver e controlar os serviços actualmente em execução"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Modo noturno"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Desativado"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Sempre ativado"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automático"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Ativar WebView multiprocessos"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Executar renderizadores WebView num processo isolado."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementação WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Definir implementação WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"A implementação WebView escolhida foi desativada e tem de ser ativada para poder ser utilizada. Pretende ativá-la?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"A implementação WebView escolhida é inválida porque a lista de opções de implementação encontra-se desatualizada. A lista deve ser atualizada agora."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Converter para a encriptação de ficheiros"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converter..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Os ficheiros já estão encriptados"</string>
@@ -296,7 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correção da cor"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta funcionalidade é experimental e pode afetar o desempenho."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="power_remaining_duration_only" msgid="4400068916452346544">"Resta(m) aproximadamente <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Resta(m) aproximadamente <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – resta(m) aprox. <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até ficar completa"</string>
@@ -311,7 +310,7 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Não está a carregar"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Não está a carregar"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Completo"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Desativado pelo administrador"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlado pelo administrador"</string>
<string name="home" msgid="8263346537524314127">"Página inicial"</string>
<string name="charge_length_format" msgid="8978516217024434156">"Há <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Resta(m) <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index b4251a5..844ae41 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Conversão de texto em voz"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Taxa de fala"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocidade em que o texto é falado"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Frequência do som"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Afeta o tom da voz sintetizada"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Usar idioma do sistema"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Idioma não selecionado"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Forçar permissão de apps em armazenamento externo"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Qualifica apps p/ gravação em armazenamento externo, independentemente de valores de manifestos"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Forçar atividades a serem redimensionáveis"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Torna todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Tornar todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Ativar janelas de forma livre"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Ativa a compatibilidade com janelas de forma livre experimentais."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Ativar a compatibilidade com janelas de forma livre experimentais."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Senha do backup local"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Os backups completos do computador não estão protegidos no momento"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Toque para alterar ou remover a senha de backups completos do desktop"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Ativo. Tocar para alternar."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Serviços em execução"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Visualizar e controlar os serviços em execução no momento"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Modo noturno"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Desativada"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Sempre ativada"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automático"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Ativar WebView de vários processos"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Executar renderizadores de WebView em um processo isolado."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementação do WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Configurar implementação do WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"A implementação do WebView escolhida está desativada e deve ser ativada para ser usada. Deseja ativá-la?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"A implementação de WebView escolhida é inválida, porque a lista de opções de implementação estava desatualizada. A lista deve estar atualizada agora."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Converter para criptografia de arquivos"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converter..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Já criptografado com base em arquivos"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correção de cor"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Este recurso é experimental e pode afetar o desempenho."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Aproximadamente <xliff:g id="TIME">%1$s</xliff:g> restante(s)"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - cerca de <xliff:g id="TIME">%2$s</xliff:g> restantes"</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Não está carregando"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Não está carregando"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Cheio"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Desativada pelo administrador"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlada pelo admin"</string>
<string name="home" msgid="8263346537524314127">"Início"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> atrás"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> restante(s)"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ro/arrays.xml b/packages/SettingsLib/res/values-ro/arrays.xml
index 30d6cf3..1f0e05b 100644
--- a/packages/SettingsLib/res/values-ro/arrays.xml
+++ b/packages/SettingsLib/res/values-ro/arrays.xml
@@ -125,7 +125,7 @@
<item msgid="3191973083884253830">"Niciuna"</item>
<item msgid="9089630089455370183">"Logcat"</item>
<item msgid="5397807424362304288">"Systrace (imagini)"</item>
- <item msgid="1340692776955662664">"Apelaţi stiva pentru glGetError"</item>
+ <item msgid="1340692776955662664">"Apelați stiva pentru glGetError"</item>
</string-array>
<string-array name="show_non_rect_clip_entries">
<item msgid="993742912147090253">"Dezactivat"</item>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index e883d0a..0faf848 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -85,7 +85,7 @@
<string name="accessibility_wifi_signal_full" msgid="7061045677694702">"Semnal Wi-Fi: complet."</string>
<string name="process_kernel_label" msgid="3916858646836739323">"Sistem de operare Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Aplicații eliminate"</string>
- <string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Aplicaţii și utilizatori eliminaţi"</string>
+ <string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Aplicații și utilizatori eliminați"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Tethering prin USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Hotspot portabil"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Tethering prin Bluetooth"</string>
@@ -101,8 +101,10 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Transformare text în vorbire"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Ritmul vorbirii"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Viteza cu care este vorbit textul"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Înălțime"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Afectează tonalitatea vorbirii sintetizate"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Limbă"</string>
- <string name="tts_lang_use_system" msgid="2679252467416513208">"Utilizaţi limba sistemului"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Utilizați limba sistemului"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Nu ați selectat limba"</string>
<string name="tts_default_lang_summary" msgid="5219362163902707785">"Setează vocea caracteristică limbii pentru textul vorbit"</string>
<string name="tts_play_example_title" msgid="7094780383253097230">"Ascultați un exemplu"</string>
@@ -110,7 +112,7 @@
<string name="tts_install_data_title" msgid="4264378440508149986">"Instalați date vocale"</string>
<string name="tts_install_data_summary" msgid="5742135732511822589">"Instalați datele vocale necesare pentru sintetizarea vorbirii"</string>
<string name="tts_engine_security_warning" msgid="8786238102020223650">"Acest motor de sintetizare a vorbirii poate culege în întregime textul vorbit, inclusiv datele personale cum ar fi parolele și numerele cărților de credit. Metoda provine de la motorul <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Permiteți utilizarea acestui motor de sintetizare a vorbirii?"</string>
- <string name="tts_engine_network_required" msgid="1190837151485314743">"Pentru rezultatul transformării textului în vorbire pentru această limbă este necesară o conexiune de rețea care să funcţioneze."</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Pentru rezultatul transformării textului în vorbire pentru această limbă este necesară o conexiune de rețea care să funcționeze."</string>
<string name="tts_default_sample_string" msgid="4040835213373086322">"Acesta este un exemplu de sintetizare a vorbirii"</string>
<string name="tts_status_title" msgid="7268566550242584413">"Starea limbii prestabilite"</string>
<string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> este acceptată integral"</string>
@@ -175,7 +177,7 @@
<string name="select_usb_configuration_title" msgid="2649938511506971843">"Selectați configurația USB"</string>
<string name="select_usb_configuration_dialog_title" msgid="6385564442851599963">"Selectați configurația USB"</string>
<string name="allow_mock_location" msgid="2787962564578664888">"Permiteți locațiile fictive"</string>
- <string name="allow_mock_location_summary" msgid="317615105156345626">"Permiteți locaţiile fictive"</string>
+ <string name="allow_mock_location_summary" msgid="317615105156345626">"Permiteți locațiile fictive"</string>
<string name="debug_view_attributes" msgid="6485448367803310384">"Activați inspectarea atributelor de vizualizare"</string>
<string name="legacy_dhcp_client_summary" msgid="163383566317652040">"Folosiți clientul DHCP din Lollipop în locul noului client Android DHCP."</string>
<string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Păstrați întotdeauna conexiunea de date mobile activată, chiar și atunci când funcția Wi‑Fi este activată (pentru comutarea rapidă între rețele)."</string>
@@ -183,7 +185,7 @@
<string name="adb_warning_message" msgid="7316799925425402244">"Depanarea USB are exclusiv scopuri de dezvoltare. Utilizați-o pentru a copia date de pe computer pe dispozitiv, pentru a instala aplicații pe dispozitiv fără notificare și pentru a citi datele din jurnale."</string>
<string name="adb_keys_warning_message" msgid="5659849457135841625">"Revocați accesul la remedierea erorilor prin USB de pe toate computerele pe care le-ați autorizat anterior?"</string>
<string name="dev_settings_warning_title" msgid="7244607768088540165">"Permiteți setările pentru dezvoltare?"</string>
- <string name="dev_settings_warning_message" msgid="2298337781139097964">"Aceste setări sunt destinate exclusiv utilizării pentru dezvoltare. Din cauza lor, este posibil ca dispozitivul dvs. și aplicațiile de pe acesta să nu mai funcţioneze sau să funcţioneze necorespunzător."</string>
+ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Aceste setări sunt destinate exclusiv utilizării pentru dezvoltare. Din cauza lor, este posibil ca dispozitivul dvs. și aplicațiile de pe acesta să nu mai funcționeze sau să funcționeze necorespunzător."</string>
<string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificați aplicațiile prin USB"</string>
<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_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>
@@ -194,11 +196,11 @@
<string name="debug_debugging_category" msgid="6781250159513471316">"Depanare"</string>
<string name="debug_app" msgid="8349591734751384446">"Selectați aplicația de depanare"</string>
<string name="debug_app_not_set" msgid="718752499586403499">"Nu ați setat o aplicație de depanare"</string>
- <string name="debug_app_set" msgid="2063077997870280017">"Aplicaţie de depanare: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="select_application" msgid="5156029161289091703">"Selectaţi o aplicație"</string>
+ <string name="debug_app_set" msgid="2063077997870280017">"Aplicație de depanare: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="select_application" msgid="5156029161289091703">"Selectați o aplicație"</string>
<string name="no_application" msgid="2813387563129153880">"Niciuna"</string>
- <string name="wait_for_debugger" msgid="1202370874528893091">"Aşteptaţi depanatorul"</string>
- <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Înaintea executării, aplicația aşteaptă atașarea depanatorului"</string>
+ <string name="wait_for_debugger" msgid="1202370874528893091">"Așteptați depanatorul"</string>
+ <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Înaintea executării, aplicația așteaptă atașarea depanatorului"</string>
<string name="debug_input_category" msgid="1811069939601180246">"Intrare"</string>
<string name="debug_drawing_category" msgid="6755716469267367852">"Desen"</string>
<string name="debug_hw_drawing_category" msgid="6220174216912308658">"Redare accelerată hardware"</string>
@@ -218,7 +220,7 @@
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Straturile hardware clipesc verde la actualizare"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Depanați suprapunerea"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Dezactivați suprapun. HW"</string>
- <string name="disable_overlays_summary" msgid="3578941133710758592">"Utilizaţi mereu GPU pentru compunerea ecranului"</string>
+ <string name="disable_overlays_summary" msgid="3578941133710758592">"Utilizați mereu GPU pentru compunerea ecranului"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Simulați spațiu culoare"</string>
<string name="enable_opengl_traces_title" msgid="6790444011053219871">"Monitorizări OpenGL"</string>
<string name="usb_audio_disable_routing" msgid="8114498436003102671">"Dezactivați rutarea audio USB"</string>
@@ -239,7 +241,7 @@
<string name="transition_animation_scale_title" msgid="387527540523595875">"Scară tranziție animații"</string>
<string name="animator_duration_scale_title" msgid="3406722410819934083">"Scară durată Animator"</string>
<string name="overlay_display_devices_title" msgid="5364176287998398539">"Simulați afișaje secundare"</string>
- <string name="debug_applications_category" msgid="4206913653849771549">"Aplicaţii"</string>
+ <string name="debug_applications_category" msgid="4206913653849771549">"Aplicații"</string>
<string name="immediately_destroy_activities" msgid="1579659389568133959">"Nu păstrați activitățile"</string>
<string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"Elimină activitățile imediat ce utilizatorul le închide"</string>
<string name="app_process_limit_title" msgid="4280600650253107163">"Limită procese fundal"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Forțați accesul aplicațiilor la stocarea externă"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Face orice aplicație eligibilă să fie scrisă în stocarea externă, indiferent de valorile manifestului"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Forțați redimensionarea activităților"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Permite redimensionarea tuturor activităților pentru modul cu ferestre multiple, indiferent de valorile manifestului."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permiteți redimensionarea tuturor activităților pentru modul cu ferestre multiple, indiferent de valorile manifestului."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Activați ferestrele cu formă liberă"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Activează compatibilitatea pentru ferestrele experimentale cu formă liberă."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Activați compatibilitatea pentru ferestrele experimentale cu formă liberă."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Parolă copie rez. desktop"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"În prezent, copiile de rezervă complete pe desktop nu sunt protejate"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Atingeți ca să modificați sau să eliminați parola pentru backupurile complete pe desktop"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Activă. Atingeți pentru a comuta."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Servicii în curs de funcționare"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Vedeți și controlați serviciile care funcționează în prezent"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Modul Noapte"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Dezactivată"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Activată permanent"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automat"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Activați WebView cu mai multe procese"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Rulați programele de redare WebView într-un proces izolat."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementare WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Setați implementarea WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Implementarea WebView aleasă este dezactivată. Pentru a fi folosită, trebuie să fie activată. Doriți să o activați?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Implementarea WebView aleasă nu este validă, deoarece lista cu alegerile pentru implementare s-a învechit. Lista ar trebui să fie actualizată acum."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Faceți conversia la criptarea bazată pe sistemul de fișiere"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convertiți…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Criptarea bazată pe sistemul de fișiere este finalizată"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Corecția culorii"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Această funcție este experimentală și poate afecta performanțele."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Valoare înlocuită de <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Timp rămas: aproximativ <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – timp rămas: aproximativ <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> până la încărcare completă"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Nu se încarcă"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nu încarcă"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Complet"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Dezactivată de administrator"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlată de administrator"</string>
<string name="home" msgid="8263346537524314127">"Ecranul principal"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"Acum <xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"Timp rămas: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 0f4eaa1..09f792e 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Синтез речи"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Скорость речи"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Скорость чтения текста"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Тон"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Влияет на высоту синтезированной речи"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Язык"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Язык системы"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Язык не выбран"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Разрешить сохранение на внешние накопители"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Разрешает сохранение приложений на внешние накопители независимо от значения манифеста"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Изменение размера в многооконном режиме"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Позволяет менять размер в многооконном режиме (независимо от значений манифеста)"</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Разрешить изменение размера в многооконном режиме (независимо от значений манифеста)"</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Разрешить создание окон произвольной формы"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Включить экспериментальную функцию создания окон произвольной формы"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Включить экспериментальную функцию создания окон произвольной формы"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Пароль для резервного копирования"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Полные резервные копии в настоящее время не защищены"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Нажмите, чтобы изменить или удалить пароль для резервного копирования"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Включено. Нажмите, чтобы отключить."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Работающие приложения"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Просмотр и управление работающими приложениями"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Ночной режим"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Отключено"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Всегда включено"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Автоматическое переключение"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Включить многопроц. WebView"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Выполнять обработчики WebView в изолированном процессе"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Сервис WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Настройки сервиса WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Чтобы использовать сервис WebView, включите его. Сделать это?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Выбранный сервис WebView не поддерживается. Список сервисов устарел и сейчас будет обновлен."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Переход к шифрованию файлов"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Перейти…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Шифрование файлов уже включено"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Коррекция цвета"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Это экспериментальная функция, она может снизить производительность устройства."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Новая настройка: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Осталось примерно <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – осталось около <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Не заряжается"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не заряжается"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Батарея заряжена"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Отключено администратором"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Контролируется администратором"</string>
<string name="home" msgid="8263346537524314127">"Главная"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> назад"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"Осталось <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-si-rLK/strings.xml b/packages/SettingsLib/res/values-si-rLK/strings.xml
index 6483b18..20cff85 100644
--- a/packages/SettingsLib/res/values-si-rLK/strings.xml
+++ b/packages/SettingsLib/res/values-si-rLK/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"පෙළ-සිට-කථන ප්රතිදානය"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"කථන ශීඝ්රතාව"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"පෙළ කථා කරනා වේගය"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"තාරතාව"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"සංශ්ලේෂණය කළ කථනයෙහි ස්වරයට බලපායි"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"භාෂාව"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"පද්ධති භාෂාව භාවිතා කරන්න"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"භාෂාව තෝරා ගෙන නැත"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"බාහිර මත යෙදුම් ඉඩ දීම බල කරන්න"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"මැනිෆෙස්ට් අගයන් නොසලකා, ඕනෑම යෙදුමක් අභ්යන්තර ගබඩාවට ලිවීමට සුදුසුකම් ලබා දෙයි"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"ක්රියාකාරකම් ප්රතිප්රමාණ කළ හැකි බවට බල කරන්න"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"මැනිෆෙස්ට් අගයන් නොසලකා, සියලු ක්රියාකාරකම් බහු-කවුළු සඳහා ප්රතිප්රමාණ කළ හැකි බවට පත් කරයි."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"මැනිෆෙස්ට් අගයන් නොසලකා, සියලු ක්රියාකාරකම් බහු-කවුළුව සඳහා ප්රතිප්රමාණ කළ හැකි බවට පත් කරන්න."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"අනියම් හැඩැති කවුළු සබල කරන්න"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"පරීක්ෂණාත්මක අනියම් හැඩැති කවුළු සඳහා සහාය සබල කරයි."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"පරීක්ෂණාත්මක අනියම් හැඩැති කවුළු සඳහා සහාය සබල කරන්න."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"ඩෙස්ක්ටොප් උපස්ථ මුරපදය"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"ඩෙස්ක්ටොප් සම්පූර්ණ උපස්ථ දැනට ආරක්ෂා කර නොමැත"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"ඩෙස්ක්ටොප් සම්පූර්ණ උපස්ථ සඳහා මුරපදය වෙනස් කිරීමට හෝ ඉවත් කිරීමට තට්ටු කරන්න"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"සක්රියයි. ටොගල කිරීමට තට්ටු කරන්න."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"ධාවනය වන සේවා"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"දැනට ධාවනය වන සේවා බලන්න සහ පාලනය කරන්න"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"රාත්රී ප්රකාරය"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"අබලයි"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"සැමවිට ක්රියාත්මක"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"ස්වයංක්රීය"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"බහු සැකසීම් WebView සබල කරන්න"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"හුදකලා වූ ක්රියාවලියක WebView විදහා දැක්වීම් ධාවනය කරන්න."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ක්රියාත්මක කිරීම"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView ක්රියාත්මක කිරීම සකසන්න"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"තෝරන ලද WebView ක්රියාත්මක කිරීම අබල අතර, භාවිත කිරීමට සබල කළ යුතුය, ඔබ එය සබල කිරීමට අදහස් කරන්නේද?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"තෝරන ලද WebView ක්රියාත්මක කිරීම ක්රියාත්මක කිරීම් තේරීම් ලැයිස්තු යල් පැන ඇති නිසා වලංගු නැත. ලැයිස්තුව දැන් යාවත්කාලීන කළ යුතුය."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ගොනු සංකේතනයට පරිවර්තනය කරන්න"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"පරිවර්තනය කරන්න..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"දැනටමත් ගොනුව සංකේතනය කර ඇත"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"වර්ණ නිවැරදි කිරීම"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"මෙම විශේෂාංගය පරීක්ෂණාත්මක සහ ඇතැම් විට ක්රියාකාරිත්වයට බලපෑ හැක."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> මගින් ඉක්මවන ලදී"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"දළ වශයෙන් <xliff:g id="TIME">%1$s</xliff:g>ක් ඉතිරිය"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ආසන්න <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> සම්පුර්ණ වන තෙක්"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"ආරෝපණය නොවේ"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"ආරෝපණය නොවෙමින්"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"පූර්ණ"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"පරිපාලක විසින් අබල කරන ලදී"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"පරිපාලක විසින් පාලනය කරන ලදී"</string>
<string name="home" msgid="8263346537524314127">"මුල් පිටුව"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g>කට පෙර"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g>ක් ඉතිරිය"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index d8e2389..5640b13 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Výstup prevodu textu na reč"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Rýchlosť reči"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Rýchlosť hovoreného textu"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Výška"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Určuje zvuk syntetizovaného hlasu"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Jazyk"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Používať jazyk systému"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Nebol vybratý jazyk"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Vynútiť povolenie aplikácií na externom úložisku"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Umožňuje zapísať akúkoľvek aplikáciu do externého úložiska bez ohľadu na hodnoty v manifeste"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Vynútiť možnosť zmeny veľkosti aktivít"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Veľkosti všetkých aktivít bude možné zmeniť na niekoľko okien (bez ohľadu na hodnoty manifestu)."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Veľkosti všetkých aktivít bude možné zmeniť na niekoľko okien (bez ohľadu na hodnoty manifestu)."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Povoliť okná s voľným tvarom"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Povolenie podpory pre experimentálne okná s voľným tvarom."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Povolenie podpory pre experimentálne okná s voľným tvarom."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Heslo pre zálohy v počítači"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Úplné zálohy na počítači nie sú momentálne chránené"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Klepnutím zmeníte alebo odstránite heslo pre úplné zálohy do počítača"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktívne. Prepnite klepnutím."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Spustené služby"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Zobrazenie a ovládanie aktuálne spustených služieb"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Nočný režim"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Vypnuté"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Vždy zapnuté"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automatický"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Povoliť viacprocesové moduly WebView"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Spúšťať vykresľovacie moduly WebView v izolovanom procese."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementácia komponenta WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Nastavenie implementácie komponenta WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Zvolená implementácia technológie WebView je zakázaná. Ak ju chcete použiť, musíte ju najprv povoliť. Chcete ju povoliť?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Zvolená implementácia komponenta WebView nie je platná, pretože zoznam volieb implementácie nie je aktuálny. Zoznam by už mal byť aktualizovaný."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertovať na šifrovanie súborov"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertovať…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Súbory sú už šifrované"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Úprava farieb"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Funkcia je experimentálna a môže mať vplyv na výkonnosť."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Prekonané predvoľbou <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Zostáva cca. <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – zostáva približne <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Nenabíja sa"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nenabíja sa"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Nabitá"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Zakázané správcom"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Ovládané správcom"</string>
<string name="home" msgid="8263346537524314127">"Domov"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"pred <xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"Zostáva <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index fa0e784..ffe794e 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Besedilo v govor"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Hitrost govora"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Hitrost govorjenega besedila"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Višina tona"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Vpliva na ton sintetiziranega govora"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Jezik"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Uporabi sistemski jezik"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Jezik ni izbran"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Vsili omogočanje aplikacij v zunanji shrambi"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Poskrbi, da je ne glede na vrednosti v manifestu mogoče vsako aplikacijo zapisati v zunanjo shrambo"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Vsili povečanje velikosti za aktivnosti"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Poskrbi, da je ne glede na vrednosti v manifestu mogoče vsem aktivnostim povečati velikost za način z več okni."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Poskrbi, da je ne glede na vrednosti v manifestu mogoče vsem aktivnostim povečati velikost za način z več okni."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Omogočanje oken svobodne oblike"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Omogočanje podpore za poskusna okna svobodne oblike"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Omogočanje podpore za poskusna okna svobodne oblike"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Geslo za varn. kop. rač."</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Popolne varnostne kopije namizja trenutno niso zaščitene"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Dotaknite se, če želite spremeniti ali odstraniti geslo za popolno varnostno kopiranje namizja"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktivno. Dotaknite se za preklop."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Zagnane storitve"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Preglejte in nadzorujte storitve, ki so trenutno zagnane"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Nočni način"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Onemogočeno"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Vedno vklopljeno"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Samodejno"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Omogoči večprocesni WebView"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Izvajanje upodabljalnikov za WebView v ločenem procesu."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Izvedba spletnega pogleda"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Nastavitev izvedbe spletnega pogleda"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Izbrana izvedba spletnega pogleda je onemogočena in jo morate omogočiti, če jo želite uporabljati. Ali jo želite omogočiti?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Izbrana izvedba komponente WebView je neveljavna zaradi zastaranja seznama izbir za izvedbo. Seznam bi zdaj moral biti posodobljen."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Preklop na šifriranje podatkov"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Preklop …"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Šifriranje podatkov je že uveljavljeno"</string>
@@ -296,7 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Popravljanje barv"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"To je preskusna funkcija in lahko vpliva na učinkovitost delovanja."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Preglasila nastavitev: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="power_remaining_duration_only" msgid="4400068916452346544">"Še približno <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Še približno <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – še približno <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti"</string>
@@ -311,7 +310,7 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Se ne polni"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Se ne polni"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Poln"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Onemogočil skrbnik"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Nadzira skrbnik"</string>
<string name="home" msgid="8263346537524314127">"Začetni zaslon"</string>
<string name="charge_length_format" msgid="8978516217024434156">"Pred toliko časa: <xliff:g id="ID_1">%1$s</xliff:g>"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"Še <xliff:g id="ID_1">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-sq-rAL/strings.xml b/packages/SettingsLib/res/values-sq-rAL/strings.xml
index f9b62fb..c84430c 100644
--- a/packages/SettingsLib/res/values-sq-rAL/strings.xml
+++ b/packages/SettingsLib/res/values-sq-rAL/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Dalja \"tekst-në-ligjërim\""</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Shpejtësia e të folurit"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Shpejtësia me të cilën thuhet teksti"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tonaliteti"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Ndikon te toni i ligjërimit të sintetizuar"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Gjuha"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Përdor gjuhën e sistemit"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Nuk është përzgjedhur gjuha"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Detyro lejimin në hapësirën e jashtme"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Bën që çdo aplikacion të jetë i përshtatshëm për t\'u shkruar në hapësirën ruajtëse të jashtme, pavarësisht nga vlerat e manifestit"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Detyro madhësinë e ndryshueshme për aktivitetet"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Bën që të gjitha aktivitetet të kenë madhësi të ndryshueshme për përdorimin me shumë dritare, pavarësisht vlerave të manifestit."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Bëj që të gjitha aktivitetet të kenë madhësi të ndryshueshme për përdorimin me shumë dritare, pavarësisht vlerave të manifestit."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Aktivizo dritaret me formë të lirë"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Aktivizon mbështetjen për dritaret eksperimentale me formë të lirë."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Aktivizo mbështetjen për dritaret eksperimentale me formë të lirë."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Fjalëkalimi rezervë i kompjuterit"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Rezervimet e plota në kompjuter nuk janë të mbrojtura aktualisht"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Trokit për të ndryshuar ose hequr fjalëkalimin për rezervime të plota të desktopit"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktiv. Trokit për ta ndryshuar."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Shërbimet në ekzekutim"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Shiko dhe kontrollo shërbimet që po ekzekutohen aktualisht"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Modaliteti i natës"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Çaktivizuar"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Gjithmonë aktive"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automatike"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Aktivizo WebView të multiprocesit"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Ekzekuto renderizuesit e WebView në një proces të izoluar."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Zbatimi i WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Cakto zbatimin e WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Është çaktivizuar zbatimi i zgjedhur i WebView dhe duhet të aktivizohet për t\'u përdorur, dëshiron ta aktivizosh?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Zbatimi i WebView të zgjedhur është i pavlefshëm sepse lista e zgjedhjeve të zbatimit është bërë e pavlefshme. Lista duhet të përditësohet tani."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Konverto në enkriptimin e skedarit"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konverto..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Enkriptimi i skedarit është kryer tashmë"</string>
@@ -296,7 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korrigjimi i ngjyrës"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ky funksion është eksperimental dhe mund të ndikojë në veprimtari."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Mbivendosur nga <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="power_remaining_duration_only" msgid="4400068916452346544">"Afërsisht <xliff:g id="TIME">%2$s</xliff:g> të mbetura"</string>
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Afërsisht <xliff:g id="TIME">%1$s</xliff:g> të mbetura"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - afërsisht <xliff:g id="TIME">%2$s</xliff:g> të mbetura"</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> derisa të jetë e plotë"</string>
@@ -311,7 +310,7 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Nuk po ngarkohet"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nuk po ngarkohet"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"E mbushur"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Çaktivizuar nga administratori"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kontrolluar nga administratori"</string>
<string name="home" msgid="8263346537524314127">"Kreu"</string>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> më parë"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> të mbetura"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 002e963..af3daba 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Излаз за претварање текста у говор"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Брзина говора"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Брзина изговарања текста"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Ниво"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Утиче на тон синтетизованог говора"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Језик"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Користи језик система"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Језик није изабран"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Принудно дозволи апликације у спољној"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Омогућава уписивање свих апликација у спољну меморију, без обзира на вредности манифеста"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Принудно омогући промену величине активности"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Омогућава промену величине свих активности за режим са више прозора, без обзира на вредности манифеста."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Омогући промену величине свих активности за режим са више прозора, без обзира на вредности манифеста."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Омогући прозоре произвољног формата"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Омогућава подршку за експерименталне прозоре произвољног формата."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Омогућите подршку за експерименталне прозоре произвољног формата."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Лозинка резервне копије за рачунар"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Резервне копије читавог система тренутно нису заштићене"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Додирните да бисте променили или уклонили лозинку за прављење резервних копија читавог система на рачунару"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Активна. Додирните да бисте је деактивирали."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Покренуте услуге"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Приказ и контрола тренутно покренутих услуга"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Ноћни режим"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Онемогућено"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Увек укључено"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Аутоматски"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Омогући вишепроцесни WebView"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Покрећите WebView приказиваче у оквиру изолованог процеса."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Примена WebView-а"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Подесите примену WebView-а"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Изабрана примена WebView-а је онемогућена, а мора да буде омогућена ради коришћења. Желите ли да је омогућите?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Изабрана примена WebView-а је неважећа зато што је листа могућности за примену застарела. Сада би требало да ажурирате листу."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Конвертуј у шифровање датотека"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Конвертуј..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Већ се користи шифровање датотека"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Корекција боја"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ова функција је експериментална и може да утиче на перформансе."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Замењује га <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Још отприлике <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – преостало око <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> док се не напуни"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Не пуни се"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не пуни се"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Пуно"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Онемогућио је администратор"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Контролише администратор"</string>
<string name="home" msgid="8263346537524314127">"Почетни"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"Пре <xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"Још <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 9b6f302..1cd9b6f 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Text-till-tal"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Talhastighet"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Talhastighet för texten"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Ton"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Påverkar tonen i det syntetiska talet"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Språk"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Använd systemspråk"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Inget språk valt"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Tillåt appar i externt lagringsutrymme"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Appen kan skrivas till extern lagring, oavsett manifestvärden"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Framtvinga storleksanpassning för aktiviteter"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Detta gör det möjligt att ändra storleken på alla aktiviteter i flerfönsterläge, oavsett manifestvärden."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Gör det möjligt att ändra storleken på alla aktiviteter i flerfönsterläge, oavsett manifestvärden."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Aktivera frihandsfönster"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Aktiverar stöd för experimentella frihandsfönster."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Aktivera stöd för experimentella frihandsfönster."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Lösenord för säkerhetskopia av datorn"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"De fullständiga säkerhetskopiorna av datorn är för närvarande inte skyddade"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tryck om du vill ändra eller ta bort lösenordet för fullständig säkerhetskopiering av datorn"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktiv. Tryck om du vill inaktivera."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Aktiva tjänster"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Visa och styr aktiva tjänster"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Nattläge"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Inaktiverad"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Alltid på"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Automatiskt"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Aktivera WebView-multibearb."</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Kör WebView-renderare i en isolerad bearbetning."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementering"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Ange WebView-implementering"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Den valda WebView-implementeringen har inaktiverats och måste aktiveras om du ska kunna använda den. Vill du aktivera den?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Den valda WebView-implementeringen är ogiltig eftersom listan med implementeringsalternativ blev inaktuell. Listan ska nu ha uppdaterats."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertera till filkryptering"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertera …"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Filkryptering används redan"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Färgkorrigering"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Den här funktionen är experimentell och kan påverka prestandan."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Har åsidosatts av <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca <xliff:g id="TIME">%1$s</xliff:g> kvar"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – ca <xliff:g id="TIME">%2$s</xliff:g> kvar"</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> till fulladdat"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Laddar inte"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Laddar inte"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Fullt"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Har inaktiverats av administratören"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Strys av administratören"</string>
<string name="home" msgid="8263346537524314127">"Startsida"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"för <xliff:g id="ID_1">%1$s</xliff:g> sedan"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> kvar"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index f9171ce..24d626c 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Kubadilisha maandishi hadi usemi"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Kiwango cha usemaji"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Kasi ya kutamkwa kwa maneno"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Giza"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Huathiri sauti ya matamshi yaliyounganishwa"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Lugha"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Tumia lugha ya mfumo"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Lugha haijachaguliwa"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Lazima uruhusu programu kwenye hifadhi ya nje"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Huweka programu kwenye hifadhi ya nje, bila kujali maelezo"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Lazimisha shughuli ziweze kubadilishwa ukubwa"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Fanya shughuli zote ziweze kubadilishwa ukubwa kwa ajili ya dirisha nyingi, bila kujali thamani za faili ya maelezo."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Fanya shughuli zote ziweze kubadilishwa ukubwa kwenye madirisha mengi, bila kuzingatia thamani za faili ya maelezo."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Washa madirisha yenye muundo huru"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Huwasha uwezo wa kutumia madirisha ya majaribio yenye muundo huru."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Ruhusu uwezo wa kutumia madirisha ya majaribio yenye muundo huru."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Nenosiri la hifadhi rudufu ya eneo kazi"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Hifadhi rudufu kamili za eneo kazi hazijalindwa kwa sasa"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Gonga ili ubadilishe au uondoe nenosiri la hifadhi rudufu kamili za eneo kazi"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Inatumika. Gonga ili ugeuze."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Huduma zinazoendeshwa"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Onyesha na dhibiti huduma zinazoendeshwa kwa sasa"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Hali ya usiku"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Imezimwa"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Imewashwa kila wakati"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Otomatiki"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Washa WebView ya michakato mingi"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Tekeleza vitoaji huduma vya WebView katika mchakato mahususi."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Utekelezaji wa WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Weka utekelezaji wa WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Kipengee ulichochagua cha utekelezaji wa WebView kimezimwa. Ni lazima ukiwashe ili kitumike. Ungependa kukiwasha?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Utekelezaji wa WebView uliochaguliwa si sahihi kwa sababu orodha ya chaguo za utekelezaji imepitwa na muda. Ni sharti usasishe orodha sasa."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Badilisha kuwa usimbaji fiche wa faili"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Badilisha..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Tayari faili imesimbwa kwa njia fiche"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Usahihishaji wa rangi"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Kipengele hiki ni cha majaribio na huenda kikaathiri utendaji."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Imetanguliwa na <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Zimesalia takribani <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - imesalia takriban <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - imesalia <xliff:g id="TIME">%2$s</xliff:g> hadi ijae"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Haichaji"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Haichaji"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Imejaa"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Msimamizi amezima mapendeleo ya mipangilio"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Imedhibitiwa na msimamizi"</string>
<string name="home" msgid="8263346537524314127">"Mwanzo"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"Zimepita <xliff:g id="ID_1">%1$s</xliff:g>"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"Zimesalia <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ta-rIN/strings.xml b/packages/SettingsLib/res/values-ta-rIN/strings.xml
index 56970a7..fac31df 100644
--- a/packages/SettingsLib/res/values-ta-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ta-rIN/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"உரையிலிருந்து பேச்சாக மாற்றுதல்"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"பேச்சு வீதம்"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"பேசப்படும் உரையின் வேகம்"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"ஒலித்திறன்"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"உருவாக்கப்படும் பேச்சின் டோன் பாதிக்கப்படும்"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"மொழி"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"முறைமையின் மொழியைப் பயன்படுத்து"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"மொழி தேர்ந்தெடுக்கப்படவில்லை"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"பயன்பாடுகளை வெளிப்புறச் சேமிப்பிடத்தில் அனுமதி"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"மேனிஃபெஸ்ட் மதிப்புகளை பொருட்படுத்தாமல், எந்தப் பயன்பாட்டையும் வெளிப்புற சேமிப்பிடத்தில் எழுத அனுமதிக்கும்"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"செயல்பாடுகளை அளவுமாறக்கூடியதாக அமை"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"மேனிஃபெஸ்ட் மதிப்புகளைப் பொருட்படுத்தாமல், பல சாளரத்திற்கு எல்லா செயல்பாடுகளையும் அளவுமாறக்கூடியதாக அமைக்கும்."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"மேனிஃபெஸ்ட் மதிப்புகளைப் பொருட்படுத்தாமல், பல சாளரத்திற்கு எல்லா செயல்பாடுகளையும் அளவுமாறக்கூடியதாக அமை."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"குறிப்பிட்ட வடிவமில்லாத சாளரங்களை இயக்கு"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"பரிசோதனைக்குரிய குறிப்பிட்ட வடிவமில்லாத சாளரங்களுக்கான ஆதரவை இயக்கும்."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"சாளரங்களை அளவுமாற்ற மற்றும் எங்கும் நகர்த்த அனுமதிக்கும் பரிசோதனைக்குரிய அம்சத்திற்கான ஆதரவை இயக்கு."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"டெஸ்க்டாப் காப்புப்பிரதி கடவுச்சொல்"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"டெஸ்க்டாப்பின் முழு காப்புப்பிரதிகள் தற்போது பாதுகாக்கப்படவில்லை"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"டெஸ்க்டாப்பின் முழுக் காப்புப் பிரதிகளுக்கான கடவுச்சொல்லை மாற்ற அல்லது அகற்ற, தட்டவும்"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"செயலில் உள்ளது. மாற்ற, தட்டவும்."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"இயங்கும் சேவைகள்"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"தற்போது இயக்கத்தில் இருக்கும் சேவைகளைப் பார்த்து கட்டுப்படுத்து"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"இரவு பயன்முறை"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"முடக்கப்பட்டது"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"எப்போதும் இயக்கத்தில் வை"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"தானியங்கு"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"பல செயல்முறை WebViewஐ இயக்கு"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"தனிப்படுத்தப்பட்ட செயல்முறையில் WebView ரெண்டரர்களை இயக்கு."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView செயல்படுத்தல்"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView செயல்படுத்தலை அமை"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"தேர்வுசெய்த WebView செயல்படுத்தல் முடக்கப்பட்டுள்ளது, பயன்படுத்த வேண்டுமெனில் அதைக் கண்டிப்பாக இயக்க வேண்டும். இயக்க விரும்புகிறீர்களா?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"தேர்வுசெய்த WebView செயல்படுத்தல் தவறானது. ஏனெனில் செயல்படுத்தல் விருப்பங்கள் பட்டியல் காலாவதியாகியுள்ளது. பட்டியலை இப்போது புதுப்பிக்க வேண்டும்."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"கோப்பு முறைமையாக்கத்திற்கு மாற்று"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"மாற்று…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ஏற்கனவே கோப்பு முறைமையாக்கப்பட்டது"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"வண்ணத்திருத்தம்"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"இது சோதனை முறையிலான அம்சம், இது செயல்திறனைப் பாதிக்கலாம்."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> மூலம் மேலெழுதப்பட்டது"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"தோராயமாக <xliff:g id="TIME">%1$s</xliff:g> உள்ளது"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"தோராயம்: <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</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="2853265177761520490">"முழு சார்ஜிற்கு: <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"சார்ஜ் செய்யப்படவில்லை"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"சார்ஜ் ஏறவில்லை"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"முழுமை"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"நிர்வாகி முடக்கியுள்ளார்"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"நிர்வாகி கட்டுப்படுத்துகிறார்"</string>
<string name="home" msgid="8263346537524314127">"முகப்பு"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> முன்"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> உள்ளது"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-te-rIN/strings.xml b/packages/SettingsLib/res/values-te-rIN/strings.xml
index 5a8c824..4b4aabf 100644
--- a/packages/SettingsLib/res/values-te-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-te-rIN/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"వచనం నుండి ప్రసంగం అవుట్పుట్"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"ప్రసంగం రేట్"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"వచనాన్ని చదివి వినిపించాల్సిన వేగం"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"పిచ్"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"సమన్వయం చేసిన ప్రసంగం యొక్క టోన్ను ప్రభావితం చేస్తుంది"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"భాష"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"సిస్టమ్ భాషను ఉపయోగించు"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"భాష ఎంచుకోబడలేదు"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"అనువర్తనాలను బాహ్య నిల్వలో నిర్బంధంగా అనుమతించు"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"ఏ అనువర్తనాన్ని అయినా మానిఫెస్ట్ విలువలతో సంబంధం లేకుండా బాహ్య నిల్వలో వ్రాయగలిగేలా అనుమతిస్తుంది"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"కార్యాచరణలను పరిమాణం మార్చగలిగేలా నిర్బంధించు"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"మానిఫెస్ట్ విలువలతో సంబంధం లేకుండా అన్ని కార్యాచరణలను బహుళ విండోల్లో సరిపోయేటట్లు పరిమాణం మార్చగలిగేలా చేస్తుంది."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"మానిఫెస్ట్ విలువలతో సంబంధం లేకుండా అన్ని కార్యాచరణలను పలు రకాల విండోల్లో సరిపోయేట్లు పరిమాణం మార్చగలిగేలా చేస్తుంది."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"స్వతంత్ర రూప విండోలను ప్రారంభించండి"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"ప్రయోగాత్మక స్వతంత్ర రూప విండోలకు మద్దతును ప్రారంభిస్తుంది."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"ప్రయోగాత్మక స్వతంత్ర రూప విండోల కోసం మద్దతును ప్రారంభిస్తుంది."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"డెస్క్టాప్ బ్యాకప్ పాస్వర్డ్"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"డెస్క్టాప్ పూర్తి బ్యాకప్లు ప్రస్తుతం రక్షించబడలేదు"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"డెస్క్టాప్ పూర్తి బ్యాకప్ల కోసం పాస్వర్డ్ను మార్చడానికి లేదా తీసివేయడానికి నొక్కండి"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"సక్రియంగా ఉంది. టోగుల్ చేయడానికి నొక్కండి."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"అమలులో ఉన్న సేవలు"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"ప్రస్తుతం అమలులో ఉన్న సేవలను వీక్షించండి మరియు నియంత్రించండి"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"రాత్రి మోడ్"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"నిలిపివేయబడింది"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"ఎల్లప్పుడూ ఆన్లో ఉంచు"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"స్వయంచాలకం"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"మల్టీప్రాసెస్ వెబ్ వీక్షణ ఆరం."</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"ప్రత్యేకప్రాసెస్లో వెబ్ వీక్షణ రెండెరెర్లను అమలుచేస్తుంది."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"వెబ్ వీక్షణ అమలు"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"వెబ్ వీక్షణ అమలుని సెట్ చేయండి"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"ఎంచుకున్న వెబ్ వీక్షణ అమలు నిలిపివేయబడింది, కానీ ఉపయోగించడానికి తప్పనిసరిగా ప్రారంభించాల్సి ఉంటుంది, మీరు దీన్ని ప్రారంభించాలనుకుంటున్నారా?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"అమలు ఎంపికల జాబితా కాలం చెల్లినది అయినందున ఎంచుకున్న వెబ్ వీక్షణ అమలు చెల్లదు. జాబితా ఇప్పుడు నవీకరించబడుతుంది."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ఫైల్ గుప్తీకరణకు మార్చు"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"మార్చండి…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ఫైల్ ఇప్పటికే గుప్తీకరించబడింది"</string>
@@ -296,7 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"రంగు సవరణ"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ఈ లక్షణం ప్రయోగాత్మకమైనది మరియు పనితీరుపై ప్రభావం చూపవచ్చు."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ద్వారా భర్తీ చేయబడింది"</string>
- <string name="power_remaining_duration_only" msgid="4400068916452346544">"సుమారు <xliff:g id="TIME">%2$s</xliff:g> మిగిలి ఉంది"</string>
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"సుమారు <xliff:g id="TIME">%1$s</xliff:g> మిగిలి ఉంది"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - సుమారు <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - పూర్తిగా నిండటానికి <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -311,7 +310,7 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"ఛార్జ్ కావడం లేదు"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"ఛార్జ్ కావడం లేదు"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"నిండింది"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"నిర్వాహకుడు నిలిపివేసారు"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"నిర్వాహకుని ద్వారా నియంత్రించబడింది"</string>
<string name="home" msgid="8263346537524314127">"హోమ్"</string>
<string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> క్రితం"</string>
<string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> మిగిలి ఉంది"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 5ef3168..6906671 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"เอาต์พุตการอ่านออกเสียง"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"ความเร็วของคำพูด"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"ความเร็วในการพูดข้อความ"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"ความสูง-ต่ำของเสียง"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"มีผลต่อโทนเสียงของข้อความสังเคราะห์"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"ภาษา"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"ใช้ภาษาของระบบ"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"ไม่ได้เลือกภาษา"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"บังคับให้แอปสามารถใช้ที่เก็บภายนอก"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"ให้สามารถเขียนแอปต่างๆ ไปยังที่เก็บภายนอกได้ โดยไม่คำนึงถึงค่าในไฟล์ Manifest"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"บังคับให้กิจกรรมปรับขนาดได้"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"ทำให้กิจกรรมทั้งหมดปรับขนาดได้สำหรับหน้าต่างหลายบาน โดยไม่คำนึงถึงค่าในไฟล์ Manifest"</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"ทำให้กิจกรรมทั้งหมดปรับขนาดได้สำหรับหน้าต่างหลายบาน โดยไม่คำนึงถึงค่าในไฟล์ Manifest"</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"เปิดใช้หน้าต่างรูปแบบอิสระ"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"เปิดการสนับสนุนหน้าต่างรูปแบบอิสระแบบทดลอง"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"เปิดการสนับสนุนหน้าต่างรูปแบบอิสระแบบทดลอง"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"รหัสผ่านการสำรองข้อมูลในเดสก์ท็อป"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"การสำรองข้อมูลเต็มรูปแบบในเดสก์ท็อป ไม่ได้รับการป้องกันในขณะนี้"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"แตะเพื่อเปลี่ยนแปลงหรือลบรหัสผ่านสำหรับการสำรองข้อมูลเต็มรูปแบบในเดสก์ท็อป"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"ใช้งานอยู่ แตะเพื่อสลับ"</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"บริการที่ทำงานอยู่"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"ดูและควบคุมบริการที่ทำงานอยู่"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"โหมดกลางคืน"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"ปิดใช้แล้ว"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"เปิดใช้เสมอ"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"อัตโนมัติ"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"เปิดใช้ WebView แบบหลายขั้นตอน"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"เรียกใช้โหมดแสดงภาพ WebView ในการดำเนินการที่แยกออกมา"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"การใช้งาน WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"ตั้งค่าการใช้งาน WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"การใช้งาน WebView ที่เลือกไว้ถูกปิดใช้อยู่ คุณต้องการเปิดใช้เพื่อที่จะใช้งานไหม"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"การใช้งาน WebView ที่เลือกไม่สามารถใช้ได้เนื่องจากรายการตัวเลือกการนำไปใช้ล้าสมัยแล้ว ควรอัปเดตรายการนี้ได้แล้ว"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"แปลงเป็นการเข้ารหัสไฟล์"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"แปลง…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"เข้ารหัสไฟล์แล้ว"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"การแก้สี"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"คุณลักษณะนี้เป็นแบบทดลองและอาจส่งผลต่อประสิทธิภาพการทำงาน"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"แทนที่โดย <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"เหลืออีกประมาณ <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - เหลือประมาณ <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะเต็ม"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"ไม่ได้ชาร์จ"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"ไม่ได้ชาร์จ"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"เต็ม"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"ปิดใช้โดยผู้ดูแลระบบ"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"ผู้ดูแลระบบเป็นผู้ควบคุม"</string>
<string name="home" msgid="8263346537524314127">"หน้าแรก"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g>ที่ผ่านมา"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"เหลือ <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 8a7d6aa..a472075 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Output ng text-to-speech"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Rate ng pagsasalita"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Bilis ng pagsambit sa teksto"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Pitch"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Nakakaapekto sa tono ng naka-synthesize na pananalita"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Wika"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Gamitin ang wika ng system"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Walang napiling wika"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Pwersahang payagan ang mga app sa external"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Mara-write na sa external storage ang anumang app, anuman ang manifest value"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Sapilitang gawing resizable ang mga aktibidad"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Gawing resizable para sa multi-window ang lahat ng aktibidad, anuman ang mga manifest value."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Gawing nare-resize ang lahat ng aktibidad para sa multi-window, anuman ang mga value ng manifest."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"I-enable ang mga freeform window"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Ine-enable ang suporta para sa mga pang-eksperimentong freeform window."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"I-enable ang suporta para sa mga pang-eksperimentong freeform window."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Password ng pag-backup ng desktop"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Kasalukuyang hindi pinoprotektahan ang mga buong pag-backup ng desktop"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"I-tap upang baguhin o alisin ang password para sa mga kumpletong pag-back up sa desktop"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktibo. I-tap upang i-toggle."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Mga tumatakbong serbisyo"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Tingnan at kontrolin ang mga kasalukuyang tumatakbong serbisyo"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Night mode"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Naka-disable"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Palaging naka-on"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Awtomatiko"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"I-enable, multiprocess WebView"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Tagapag-render ng WebView, patakbuhin sa hiwalay na proseso."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Pagpapatupad sa WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Itakda ang pagpapatupad sa WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Naka-disable ang napiling pagpapatupad sa WebView, at dapat itong i-enable upang magamit, gusto mo ba itong i-enable?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Di-wasto ang piniling pag-implement ng WebView dahil luma na ang mga pagpipian ng pag-implement. Dapat na na-update na ngayon ang listahan."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"I-convert at gawing pag-encrypt ng file"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"I-convert..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Na-encrypt na ang file"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Pagtatama ng kulay"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ang feature na ito ay pinag-eeksperimentuhan at maaaring makaapekto sa pagganap."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Na-override ng <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g> na lang ang natitira"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - humigit kumulang <xliff:g id="TIME">%2$s</xliff:g> ang natitira"</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> bago mapuno"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Hindi nagcha-charge"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Hindi nagkakarga"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Puno"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Na-disable ng administrator"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Pinapamahalaan ng admin"</string>
<string name="home" msgid="8263346537524314127">"Home"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> na ang nakalipas"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> na lang"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 11b975e..85b6080 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Metin-konuşma çıktısı"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Konuşma hızı"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Metnin konuşulduğu hız"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Perde"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Sentezlenmiş konuşma sesini etkiler"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Dil"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Sistemin dilini kullan"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Dil seçilmedi"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Harici birimdeki uygulamalara izin vermeye zorla"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Bildirilen değerlerden bağımsız olarak uygulamaları harici depolamaya yazmak için uygun hale getirir"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Etkinlikleri yeniden boyutlandırılabilmeye zorla"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Manifest değerlerinden bağımsız olarak, tüm etkinlikleri birden fazla pencerede yeniden boyutlandırılabilir hale getirir."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Manifest değerlerinden bağımsız olarak, tüm etkinlikleri birden fazla pencerede yeniden boyutlandırılabilir yap."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Serbest biçimli pencereleri etkinleştir"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Deneysel serbest biçimli pencereleri etkinleştirir."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Deneysel serbest biçimli pencere desteğini etkinleştir."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Masaüstü yedekleme şifresi"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Masaüstü tam yedeklemeleri şu an korunmuyor"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Masaüstü tam yedeklemelerinin şifresini değiştirmek veya kaldırmak için hafifçe dokunun"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Etkin. Geçiş yapmak için hafifçe dokunun."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Çalışan hizmetler"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Şu anda çalışan hizmetleri görüntüle ve denetle"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Gece modu"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Devre dışı"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Her zaman açık"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Otomatik"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Çoklu işlem WebView\'ı etkinleştir"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView oluşturucuları yalıtılmış bir işlemde çalıştırın."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView kullanımı"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView kullanımını ayarla"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Seçilen WebView uygulama şekli devre dışı. Bu uygulama şeklinin kullanılabilmesi için etkinleştirilmesi gerekir. Etkinleştirmek istiyor musunuz?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Seçilen WebView uygulaması, uygulama seçenekleri listesi eskidiği için geçersiz. Listenin şimdi güncellenmesi gerekiyor."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Dosya şifrelemeye dönüştür"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Dönüştür…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Dosya şifreleme zaten uygulandı"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Renk düzeltme"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Bu özellik deneyseldir ve performansı etkileyebilir."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> tarafından geçersiz kılındı"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Yaklaşık <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - yaklaşık <xliff:g id="TIME">%2$s</xliff:g> kaldı"</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - tam şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> var"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Şarj olmuyor"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Şarj etmiyor"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Dolu"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Yönetici tarafından devre dışı bırakıldı"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Yönetici tarafından denetleniyor"</string>
<string name="home" msgid="8263346537524314127">"Ana Ekran"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> önce"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> kaldı"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index ad18d7f..32cd586 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Вивід синтезу мовлення з тексту"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Темп мовлення"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Швидкість відтворення тексту"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Вис. зв."</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Впливає на тон синтезованого мовлення"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Мова"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Використовувати мову системи"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Мову не вибрано"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Примусово записувати додатки в зовнішню пам’ять"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Додатки можна записувати на зовнішню пам’ять незалежно від значень маніфесту"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Примусово масштабувати активність"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Активність масштабуватиметься на кілька вікон, незалежно від значень у файлі маніфесту."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Масштабувати активність на кілька вікон, незалежно від значень у файлі маніфесту."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Увімкнути вікна довільного формату"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Увімкнуться експериментальні вікна довільного формату."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Увімкнути експериментальні вікна довільного формату."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Пароль резерв.копії на ПК"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Повні резервні копії на комп’ютері наразі не захищені"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Торкніться, щоб змінити або видалити пароль для повного резервного копіювання на комп’ютер"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Активний додаток. Торкніться, щоб дезактивувати."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Запущені служби"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Перегляд і керування запущеними службами"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Нічний режим"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Вимкнено"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Завжди ввімкнено"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Автоматично"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Увімк. багатопроцесний WebView"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Запустити засоби обробки відео WebView окремим процесом."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Застосування WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Налаштувати застосування WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Вибране застосування WebView вимкнено. Увімкнути його?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Недійсне застосування WebView, оскільки список вибору застосувань застарів. Тепер список оновлено."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Конвертувати в зашифрований файл"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Конвертація…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Уже конвертовано в зашифрований файл"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Корекція кольору"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Це експериментальна функція. Вона може вплинути на продуктивність."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Замінено на <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Залишилося приблизно <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – залишилось близько <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного зарядження"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Не заряджається"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не заряджається"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Акумулятор заряджено"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Вимкнено адміністратором"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Керується адміністратором"</string>
<string name="home" msgid="8263346537524314127">"Головний екран"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> тому"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"Залишилося <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ur-rPK/strings.xml b/packages/SettingsLib/res/values-ur-rPK/strings.xml
index 670f2e6..0eaead8 100644
--- a/packages/SettingsLib/res/values-ur-rPK/strings.xml
+++ b/packages/SettingsLib/res/values-ur-rPK/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"ٹیکسٹ ٹو اسپیچ آؤٹ پٹ"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"اسپیچ کی شرح"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"متن بولے جانے کی رفتار"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"پچ"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"تصنعی اسپیچ کی ٹون کو متاثر کرتا ہے"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"زبان"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"سسٹم کی زبان استعمال کریں"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"زبان منتخب نہیں کی گئی"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"بیرونی پر ایپس کو زبردستی اجازت دیں"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"manifest اقدار سے قطع نظر، کسی بھی ایپ کو بیرونی اسٹوریج پر لکھے جانے کا اہل بناتا ہے"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"سرگرمیوں کو ری سائز ایبل بنائیں"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"manifest اقدار سے قطع نظر، ملٹی ونڈو کیلئے تمام سرگرمیوں کو ری سائز ایبل بناتا ہے۔"</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"manifest اقدار سے قطع نظر، ملٹی ونڈو کیلئے تمام سرگرمیوں کو ری سائز ایبل بنائیں۔"</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"freeform ونڈوز فعال کریں"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"تجرباتی freeform ونڈوز کے لئے سپورٹ فعال کرتا ہے۔"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"تجرباتی freeform ونڈوز کیلئے سپورٹ فعال کریں۔"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"ڈیسک ٹاپ کا بیک اپ پاس ورڈ"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"ڈیسک ٹاپ کے مکمل بیک اپس فی الحال محفوظ کیے ہوئے نہیں ہیں"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"ڈیسک ٹاپ کے مکمل بیک اپس کیلئے پاس ورڈ کو تبدیل کرنے یا ہٹانے کیلئے تھپتھپائیں"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"فعال۔ ٹوگل کرنے کیلئے تھپتھپائیں۔"</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"چل رہی سروسز"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"فی الحال چل رہی سروسز دیکھیں اور انہیں کنٹرول کریں"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"رات موڈ"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"غیر فعال"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"ہمیشہ آن"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"خودکار"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"ملٹی پراسیس WebView بحال کریں"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView رینڈررز کو ایک علیحدہ پراسیس میں چلائیں۔"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView کا نفاذ"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView کا نفاذ سیٹ کریں"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"منتخب کردہ WebView کا نفاذ غیر فعال ہے اور استعمال کرنے کیلئے اسے فعال ہونا چاہئیے، کیا آپ اسے فعال کرنا چاہتے ہیں؟"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"WebView کا منتخب کردہ نفاذ غلط ہے کیونکہ نفاذ کے انتخابات کی فہرست باسی ہو گئی ہے۔ اب فہرست کو اپ ڈیٹ ہونا چاہئیے۔"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"فائل مرموز کاری میں بدلیں"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"بدلیں…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"فائل پہلے ہی مرموز شدہ ہے"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"رنگ کی اصلاح"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"یہ خصوصیت تجرباتی ہے اور اس کی وجہ سے کاکردگی متاثر ہو سکتی ہے۔"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> کے ذریعہ منسوخ کردیا گیا"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"تقریبا <xliff:g id="TIME">%1$s</xliff:g> باقی ہیں"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - تقریبا <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> پورا ہونے تک"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"چارج نہیں ہو رہا ہے"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"چارج نہیں ہو رہا ہے"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"مکمل"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"منتظم نے غیر فعال کر دیا"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"کنٹرول کردہ بذریعہ منتظم"</string>
<string name="home" msgid="8263346537524314127">"ہوم"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> قبل"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> باقی ہیں"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-uz-rUZ/strings.xml b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
index e7dccae..30a8576 100644
--- a/packages/SettingsLib/res/values-uz-rUZ/strings.xml
+++ b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
@@ -78,7 +78,7 @@
<string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"Quyidagi qurilma javob bermayapti: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> biriktirish so‘rovini rad qildi."</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi o‘chiq."</string>
- <string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi o‘chirilgan."</string>
+ <string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi o‘chiq."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fi: bitta ustun"</string>
<string name="accessibility_wifi_two_bars" msgid="3569851234710034416">"Wi-Fi: ikkita ustun"</string>
<string name="accessibility_wifi_three_bars" msgid="8134185644861380311">"Wi-Fi: uchta ustun"</string>
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Nutq sintezi"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Nutq tezligi"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Matnni o‘qish tezligi"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Chimdish"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Sintezlangan nutq balandligiga ta’sir qiladi"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Til"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Tizim tili"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Til tanlanmagan"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Tashqi xotira qurilmasidagi ilova dasturlariga majburiy ruxsat berish"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Manifest qiymatidan qat’i nazar istalgan ilovani tashqi xotiraga saqlash imkonini beradi"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Harakatlarni moslashuvchan o‘lchamga keltirish"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Manifest qiymatidan qat’i nazar barcha harakatlarni ko‘p oynali rejimga moslashtiradi."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Manifest qiymatidan qat’i nazar barcha harakatlarni ko‘p oynali rejimga moslashtirish."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Erkin shakldagi oynalarni yoqish"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Tajribaviy erkin shakldagi oynalar ta’minotini yoqadi"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Erkin shakldagi oynalar yaratish uchun mo‘ljallangan tajribaviy funksiyani yoqish."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Zaxira nusxa uchun parol"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Kompyuterdagi zaxira nusxalar hozirgi vaqtda himoyalanmagan"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Ish stoli to‘liq zaxira nusxalari parolini o‘zgartirish yoki o‘chirish uchun bu yerni bosing"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Faol. O‘zgartirish uchun bu yerga bosing."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Ishlab turgan ilovalar"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Ishlab turgan ilovalarni ko‘rish va boshqarish"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Tungi rejim"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"O‘chiq"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Har doim yoniq tursin"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Avtomatik"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"WebView multiprocess’ni yoqish"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView renderlovchilarini alohida jarayonda ishga tushirish."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ta’minotchisi"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView ta’minotchisini sozlash"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Tanlangan WebView ta’minotchisi o‘chirilgan va foydalanish uchun yoqilishi zarur. Yoqilsinmi?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Tanlangan WebView xizmati qo‘llab-quvvatlanmaydi. Xizmatlar ro‘yxati eskirgan va hozir ular yangilanadi."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Faylli shifrga o‘girish"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"O‘girish…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Fayl allaqachon shifrlangan"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Rangni tuzatish"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Bu funksiya tajribaviy bo‘lib, u qurilma unumdorligiga ta’sir qilishi mumkin."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> bilan almashtirildi"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> qoldi"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – taxminan <xliff:g id="TIME">%2$s</xliff:g> qoldi"</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, to‘lguncha"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Quvvat olmayapti"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Quvvatlanmayapti"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"To‘la"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Administrator tomonidan o‘chirib qo‘yilgan"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Administrator tomonidan boshqariladi"</string>
<string name="home" msgid="8263346537524314127">"Bosh ekran"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> oldin"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> qoldi"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index c803415..38ddcc0 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Đầu ra v.bản thành giọng nói"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Tốc độ nói"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Tốc độ đọc văn bản"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Độ cao"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Ảnh hưởng đến âm điệu giọng nói được tổng hợp"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Ngôn ngữ"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Sử dụng ngôn ngữ hệ thống"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Không thể chọn ngôn ngữ"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Buộc cho phép các ứng dụng trên bộ nhớ ngoài"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Giúp ứng dụng bất kỳ đủ điều kiện được ghi vào bộ nhớ ngoài bất kể giá trị tệp kê khai là gì"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Buộc các hoạt động có thể thay đổi kích thước"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Giúp tất cả hoạt động có thể thay đổi kích thước cho nhiều cửa sổ bất kể giá trị tệp kê khai là gì."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Giúp tất cả hoạt động có thể thay đổi kích thước cho nhiều cửa sổ bất kể giá trị tệp kê khai là gì."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Bật cửa sổ dạng tự do"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Bật tính năng hỗ trợ cửa sổ dạng tự do thử nghiệm."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Bật tính năng hỗ trợ cửa sổ dạng tự do thử nghiệm."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Mật khẩu sao lưu của máy tính"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Sao lưu toàn bộ máy tính hiện không được bảo vệ"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Nhấn để thay đổi hoặc xóa mật khẩu dành cho sao lưu toàn bộ tới máy tính"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Hiện hoạt. Nhấn để chuyển đổi."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Các dịch vụ đang hoạt động"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Xem và kiểm soát các dịch vụ hiện đang hoạt động"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Chế độ ban đêm"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Đã tắt"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Luôn bật"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Tự động"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Bật WebView đa quy trình"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Chạy kết xuất đồ họa WebView trong quy trình tách biệt."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Triển khai WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Đặt triển khai WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Triển khai WebView đã chọn bị vô hiệu hóa và bạn phải bật để sử dụng tính năng này. Bạn có muốn bật tính năng này không?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Triển khai WebView đã chọn không hợp lệ vì danh sách lựa chọn triển khai đã cũ. Phải cập nhật danh sách ngay bây giờ."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Chuyển đổi sang mã hóa tệp"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Chuyển đổi..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Đã mã hóa tệp"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Sửa màu"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Tính năng này là tính năng thử nghiệm và có thể ảnh hưởng đến hoạt động."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Bị ghi đè bởi <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Còn khoảng <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - còn khoảng <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> cho đến khi đầy"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Hiện không sạc"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Hiện không sạc"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Đầy"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Bị tắt bởi quản trị viên"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Do quản trị viên kiểm soát"</string>
<string name="home" msgid="8263346537524314127">"Màn hình chính"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> trước"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"Còn <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 54a6e7c..4001d2c 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"文字转语音 (TTS) 输出"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"语速"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"文字转换成语音后的播放速度"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"音高"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"会影响合成语音的音调"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"语言"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"使用系统语言"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"未选择语言"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"强制允许将应用写入外部存储设备"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"允许将任何应用写入外部存储设备(无论清单值是什么)"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"强制将活动设为可调整大小"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"将所有活动设为可配合多窗口环境调整大小(无论清单值是什么)。"</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"将所有 Activity 设为可配合多窗口环境调整大小(忽略清单值)。"</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"启用可自由调整的窗口"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"启用可自由调整的窗口这一实验性功能。"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"启用可自由调整的窗口这一实验性功能。"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"桌面备份密码"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"桌面完整备份当前未设置密码保护"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"点按即可更改或移除用于保护桌面完整备份的密码"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"已启用。点按即可切换。"</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"正在运行的服务"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"查看和控制当前正在运行的服务"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"夜间模式"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"已停用"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"始终开启"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"自动"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"启用多进程 WebView"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"在独立进程中运行 WebView 渲染程序。"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView 实现"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"设置 WebView 实现"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"所选的 WebView 实现已停用,您必须先启用 WebView 实现才能加以使用。要启用该 WebView 实现吗?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"所选的 WebView 实现无效,因为实现选项列表已过时。请立即更新列表。"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"转换为文件加密"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"转换…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"文件已加密"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"色彩校正"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"此功能为实验性功能,可能会影响性能。"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"已被“<xliff:g id="TITLE">%1$s</xliff:g>”覆盖"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"还剩大约 <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还可用大约<xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需<xliff:g id="TIME">%2$s</xliff:g>充满"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"未在充电"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"未在充电"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"电量充足"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"已被管理员禁用"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"由管理员控制"</string>
<string name="home" msgid="8263346537524314127">"主屏幕"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g>前"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"还剩 <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index e95a324..02be160 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"文字轉語音輸出"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"語音速率"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"文字轉語音的播放速度"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"音調"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"影響合成語音的音調"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"語言"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"使用系統語言"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"未選取語言"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"強制允許應用程式寫入到外部儲存空間"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"允許將所有應用程式寫入到外部儲存完間 (所有資訊清單值)"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"強制可變更活動尺寸"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"在任何資訊清單值下,允許為多個視窗變更所有活動的尺寸。"</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"在任何資訊清單值下,允許系統配合多重視窗環境調整所有活動的尺寸。"</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"啟用自由形態視窗"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"啟用實驗版自由形態視窗的支援功能。"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"啟用實驗版自由形態視窗的支援功能。"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"桌面電腦備份密碼"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"桌上電腦的完整備份目前未受保護"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"輕按即可變更或移除桌上電腦完整備份的密碼"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"已啟用。輕按即可切換。"</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"執行中的服務"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"查看並控制目前正在執行中的服務"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"夜間模式"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"已停用"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"永遠開啟"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"自動"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"啟用多重處理程序 WebView"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"在獨立的處理程序中執行 WebView 轉譯器。"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView 設置"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"設定 WebView 設置"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"您選擇的 WebView 設定已停用,您必須先啟用此設定才能加以使用。要啟用此設定嗎?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"WebView 的設定選項清單已過時,因此您所選的 WebView 設定無效。請立即更新這份清單。"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"轉換為檔案加密"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"轉換…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"已加密檔案"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"色彩校正"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"這是一項實驗性功能,可能會影響效能。"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"已由「<xliff:g id="TITLE">%1$s</xliff:g>」覆寫"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"尚餘大約 <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 尚餘大約 <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 後完成充電"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"非充電中"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"未開始充電"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"電量已滿"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"管理員已停用此設定"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"已由管理員停用"</string>
<string name="home" msgid="8263346537524314127">"主畫面"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g>前"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"尚餘 <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index bf7ea4e..7407e28 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"文字轉語音輸出"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"語音速率"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"文字轉語音的播放速度"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"音調"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"會影響合成語音的音調"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"語言"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"使用系統設定"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"未選取語言"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"強制允許將應用程式寫入外部儲存空間"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"允許將任何應用程式寫入外部儲存空間 (無論資訊清單值為何)"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"將活動強制設為可調整大小"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"將所有活動設為可配合多重視窗環境調整大小 (無論資訊清單值為何)。"</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"將所有活動設為可配合多重視窗環境調整大小 (無論資訊清單值為何)。"</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"啟用自由形式視窗"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"啟用實驗版自由形式視窗的支援功能。"</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"啟用實驗版自由形式視窗的支援功能。"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"電腦備份密碼"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"電腦完整備份目前未受保護"</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"輕按即可變更或移除電腦完整備份的密碼"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"已啟用。輕按即可切換。"</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"正在運作的服務"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"查看並管理目前正在執行的服務"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"夜間模式"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"已停用"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"一律開啟"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"自動"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"啟用多重處理程序 WebView"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"在獨立的處理程序中執行 WebView 轉譯器。"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView 實作"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"設定 WebView 實作"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"您所選的 WebView 實作已停用,您必須先啟用 WebView 實作才能加以使用。要啟用該 WebView 實作嗎?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"您所選的 WebView 實作無效,這是因為相關的實作選項清單已過時。請立即更新這份清單。"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"轉換成檔案加密"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"轉換..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"已將檔案加密"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"色彩校正"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"這是一項實驗性功能,可能會對效能造成影響。"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"已改為<xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"還剩大約 <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 大約還剩 <xliff:g id="TIME">%2$s</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"非充電中"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"非充電中"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"電力充足"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"已由管理員停用"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"已由管理員停用"</string>
<string name="home" msgid="8263346537524314127">"主畫面"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g>前"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"還剩 <xliff:g id="ID_1">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index c450f77..e563bff 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -101,6 +101,8 @@
<string name="tts_settings_title" msgid="1237820681016639683">"Umbhalo-uya-kokukhishwa ngokukhuluma"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Ukukala izwi"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Isivinini leso umbhalo okhulunywe ngaso"</string>
+ <string name="tts_default_pitch_title" msgid="6135942113172488671">"Ukuphakama"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Ithinta amathoni enkulumo akhiqiziwe"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Ulimi"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Sebenzisa ulimi lwesistimu"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Ulimi alukhethwanga"</string>
@@ -248,9 +250,9 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Phoqelela ukuvumela izinhlelo zokusebenza ngaphandle"</string>
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Yenza noma uluphi uhlelo lokusebenza lifaneleke ukuthi libhalwe kusitoreji sangaphandle, ngaphandle kwamavelu we-manifest"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Imisebenzi yamandla izonikezwa usayizi omusha"</string>
- <string name="force_resizable_activities_summary" msgid="4508217476997182216">"Yenza yonke imisebenzi ibe nosayizi abasha kuwindi lokuningi, ngokunganaki amanani we-manifest."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Yenza yonke imisebenzi ibe nosayizi abasha kumawindi amaningi, ngokunganaki amavelu e-manifest."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Nika amandla amawindi e-freeform"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Inika amandla usekelo lwamawindi okuhlola e-freeform."</string>
+ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Nika amandla usekelo lwe-windows yokuhlola kwe-freeform."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Iphasiwedi yokusekela ngokulondoloza ye-Desktop"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Ukusekela ngokulondoloza okugcwele kwe-Desktop akuvikelekile okwamanje."</string>
<string name="local_backup_password_summary_change" msgid="5376206246809190364">"Thepha ukushintsha noma ukususa iphasiwedi yokwenziwa kwezipele ngokugcwele kwideskithophu"</string>
@@ -272,14 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Kuyasebenza. Thepha ukuze ushintshe."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Amasevisi asebenzayo"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"Buka futhi ulawule amasevisi asebenzayo okwamanje"</string>
- <string name="night_mode_title" msgid="2594133148531256513">"Imodi yasebusuku"</string>
- <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
- <string name="night_mode_no" msgid="9171772244775838901">"Kukhutshaziwe"</string>
- <string name="night_mode_yes" msgid="2218157265997633432">"Njalo ivuliwe"</string>
- <string name="night_mode_auto" msgid="7508348175804304327">"Okuzenzakalelayo"</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"Nika amandla i-WebView kokucubungula okuningi"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Sebenzisa abasebenzeli be-WebView kwinqubo ekhethiwe."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Ukufakwa ke-WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Sesba ukufakwa kwe-WebView"</string>
- <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Ukusetshenziswa kwe-WebView okukhethiwe kukhutshaziwe, futhi kuzomele kunikwe amandla ukuze kusetshenziswe, ingabe ufisa ukukunika amandla?"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Ukusetshenziswa okukhethiwe kwe-WebView akuvumelekile ngoba uhlu lokukhetha ukusetshenziswa lukhule lwaba ludala. Uhlu kumele manje libuyekezwe."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Phendulisela ekubethelweni kwefayela"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Iyaphendulela..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Sekuvele kubethelwe ngefayela"</string>
@@ -296,8 +295,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Ukulungiswa kombala"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Lesi sici esesilingo futhi singathinta ukusebenza."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Igitshezwe ngaphezulu yi-<xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (4400068916452346544) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="4400068916452346544">"Cishe ngu-<xliff:g id="TIME">%1$s</xliff:g> osele"</string>
<string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - isilinganiso esingu-<xliff:g id="TIME">%2$s</xliff:g> esisele"</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="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> kuze igcwale"</string>
@@ -312,10 +310,8 @@
<string name="battery_info_status_discharging" msgid="310932812698268588">"Ayishaji"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ayishaji"</string>
<string name="battery_info_status_full" msgid="2824614753861462808">"Kugcwele"</string>
- <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Ikhutshazwe umlawuli"</string>
+ <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kulawulwa umqondisi"</string>
<string name="home" msgid="8263346537524314127">"Ekhaya"</string>
- <!-- no translation found for charge_length_format (8978516217024434156) -->
- <skip />
- <!-- no translation found for remaining_length_format (7886337596669190587) -->
- <skip />
+ <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> edlule"</string>
+ <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> osele"</string>
</resources>
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index 1bce7f9..525d6f4 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -344,28 +344,6 @@
<item>midi</item>
</string-array>
- <!-- Possible values for user theme in Display Settings.
- Do not translate. -->
- <string-array name="night_mode_entries" translatable="false">
- <!-- Do not translate. -->
- <item>@string/night_mode_no</item>
- <!-- Do not translate. -->
- <item>@string/night_mode_yes</item>
- <!-- Do not translate. -->
- <item>@string/night_mode_auto</item>
- </string-array>
-
- <!-- These values should match up with the MODE_NIGHT constants in UiModeManager.
- Do not translate. -->
- <string-array name="night_mode_values" translatable="false">
- <!-- Do not translate. -->
- <item>1</item>
- <!-- Do not translate. -->
- <item>2</item>
- <!-- Do not translate. -->
- <item>0</item>
- </string-array>
-
<!-- Display color space adjustment modes for developers -->
<string-array name="simulate_color_space_entries" translatable="false">
<item>@string/daltonizer_mode_disabled</item>
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index 9f78e87..c3b3cfc 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -33,8 +33,8 @@
<dimen name="user_spinner_item_height">56dp</dimen>
<!-- Lock icon for preferences locked by admin -->
- <dimen name="restricted_lock_icon_size">16dp</dimen>
- <dimen name="restricted_lock_icon_padding">4dp</dimen>
+ <dimen name="restricted_icon_size">16dp</dimen>
+ <dimen name="restricted_icon_padding">4dp</dimen>
<dimen name="wifi_preference_badge_padding">8dip</dimen>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 7012eb2..ae2c6e7 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -236,10 +236,14 @@
<string name="tts_settings">Text-to-speech settings</string>
<!-- TTS option item name in the main settings screen -->
<string name="tts_settings_title">Text-to-speech output</string>
- <!-- On main TTS Settings screen, in default settings section, setting default speech rate for synthesized voice -->
+ <!-- On main TTS Settings screen, in default settings section, setting default speech rate for synthesized voice -->
<string name="tts_default_rate_title">Speech rate</string>
<!-- On main TTS Settings screen, summary for default speech rate for synthesized voice -->
<string name="tts_default_rate_summary">Speed at which the text is spoken</string>
+ <!-- On main TTS Settings screen, in default settings section, setting default pitch for synthesized voice -->
+ <string name="tts_default_pitch_title">Pitch</string>
+ <!-- On main TTS Settings screen, summary for default pitch for synthesized voice -->
+ <string name="tts_default_pitch_summary">Affects the tone of the synthesized speech</string>
<!-- On main TTS Settings screen, in default settings section, setting default language for synthesized voice -->
<string name="tts_default_lang_title">Language</string>
<!-- Entry in the TTS engine language/locale picker, when selected will try to default to the system language [CHAR LIMIT=50] -->
@@ -673,23 +677,17 @@
<!-- Services settings screen, setting option summary for the user to go to the screen to view running services -->
<string name="runningservices_settings_summary">View and control currently running services</string>
- <!-- Sound & display settings screen, setting option name to change the user interface theme [CHAR LIMIT=30] -->
- <string name="night_mode_title">Night mode</string>
- <!-- Sound & display settings screen, setting option summary to change the user interface theme [CHAR LIMIT=100] -->
- <string name="night_mode_summary">%s</string>
- <!-- Sound & display settings screen, theme setting value to prefer a light-colored user interface [CHAR LIMIT=30] -->
- <string name="night_mode_no">Disabled</string>
- <!-- Sound & display settings screen, theme setting value to prefer a dark-colored user interface [CHAR LIMIT=30] -->
- <string name="night_mode_yes">Always on</string>
- <!-- Sound & display settings screen, theme setting value to automatically switch between a light- or dark-colored user interface [CHAR LIMIT=30] -->
- <string name="night_mode_auto">Automatic</string>
+ <!-- Developer settings: enable WebView multiprocess name [CHAR LIMIT=30] -->
+ <string name="enable_webview_multiprocess">Enable multiprocess WebView</string>
+ <!-- Developer settings: enable WebView multiprocess summary [CHAR LIMIT=60] -->
+ <string name="enable_webview_multiprocess_desc">Run WebView renderers in an isolated process.</string>
- <!-- Developer settings: select WebView provider title -->
+ <!-- Developer settings: select WebView provider title [CHAR LIMIT=30] -->
<string name="select_webview_provider_title">WebView implementation</string>
- <!-- Developer settings: select WebView provider dialog title -->
+ <!-- Developer settings: select WebView provider dialog title [CHAR LIMIT=30] -->
<string name="select_webview_provider_dialog_title">Set WebView implementation</string>
- <!-- Developer settings: confirmation dialog text for the WebView provider selection dialog -->
- <string name="select_webview_provider_confirmation_text">The chosen WebView implementation is disabled, and must be enabled to be used, do you wish to enable it?</string>
+ <!-- Developer settings: text for the WebView provider selection toast shown if an invalid provider was chosen (i.e. the setting list was stale). [CHAR LIMIT=NONE] -->
+ <string name="select_webview_provider_toast_text">The chosen WebView implementation is invalid because the list of implementation choices grew stale. The list should now be updated.</string>
<!-- Developer settings screen, convert userdata to file encryption option name -->
<string name="convert_to_file_encryption">Convert to file encryption</string>
@@ -773,7 +771,12 @@
<string name="battery_info_status_full">Full</string>
<!-- Summary for settings preference disabled by administrator [CHAR LIMIT=50] -->
- <string name="disabled_by_admin_summary_text">Disabled by administrator</string>
+ <string name="disabled_by_admin_summary_text">Controlled by admin</string>
+
+ <!-- Summary for switch preference to denote it is switched on [CHAR LIMIT=50] -->
+ <string name="enabled_by_admin">Enabled by administrator</string>
+ <!-- Summary for switch preference to denote it is switched on [CHAR LIMIT=50] -->
+ <string name="disabled_by_admin">Disabled by administrator</string>
<!-- Option in navigation drawer that leads to Settings main screen [CHAR LIMIT=30] -->
<string name="home">Home</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java b/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java
index b16b8ec..6b29e21 100644
--- a/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java
+++ b/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java
@@ -39,121 +39,59 @@
public String remainingLabel;
private BatteryStats mStats;
private boolean mCharging;
+ private long timePeriod;
public interface Callback {
void onBatteryInfoLoaded(BatteryInfo info);
}
- public void bindHistory(UsageView view) {
- long startWalltime = 0;
- long endDateWalltime = 0;
- long endWalltime = 0;
- long historyStart = 0;
- long historyEnd = 0;
- byte lastLevel = -1;
- long curWalltime = startWalltime;
- long lastWallTime = 0;
- long lastRealtime = 0;
- int lastInteresting = 0;
- int pos = 0;
- boolean first = true;
- if (mStats.startIteratingHistoryLocked()) {
- final HistoryItem rec = new HistoryItem();
- while (mStats.getNextHistoryLocked(rec)) {
- pos++;
- if (first) {
- first = false;
- historyStart = rec.time;
+ public void bindHistory(final UsageView view, BatteryDataParser... parsers) {
+ BatteryDataParser parser = new BatteryDataParser() {
+ SparseIntArray points = new SparseIntArray();
+
+ @Override
+ public void onParsingStarted(long startTime, long endTime) {
+ timePeriod = endTime - startTime - remainingTimeUs / 1000;
+ view.clearPaths();
+ view.configureGraph((int) (endTime - startTime), 100, remainingTimeUs != 0,
+ mCharging);
+ }
+
+ @Override
+ public void onDataPoint(long time, HistoryItem record) {
+ points.put((int) time, record.batteryLevel);
+ }
+
+ @Override
+ public void onDataGap() {
+ if (points.size() > 1) {
+ view.addPath(points);
}
- if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
- || rec.cmd == HistoryItem.CMD_RESET) {
- // If there is a ridiculously large jump in time, then we won't be
- // able to create a good chart with that data, so just ignore the
- // times we got before and pretend like our data extends back from
- // the time we have now.
- // Also, if we are getting a time change and we are less than 5 minutes
- // since the start of the history real time, then also use this new
- // time to compute the base time, since whatever time we had before is
- // pretty much just noise.
- if (rec.currentTime > (lastWallTime+(180*24*60*60*1000L))
- || rec.time < (historyStart+(5*60*1000L))) {
- startWalltime = 0;
- }
- lastWallTime = rec.currentTime;
- lastRealtime = rec.time;
- if (startWalltime == 0) {
- startWalltime = lastWallTime - (lastRealtime-historyStart);
- }
- }
- if (rec.isDeltaData()) {
- if (rec.batteryLevel != lastLevel || pos == 1) {
- lastLevel = rec.batteryLevel;
- }
- lastInteresting = pos;
- historyEnd = rec.time;
+ points.clear();
+ }
+
+ @Override
+ public void onParsingDone() {
+ if (points.size() > 1) {
+ view.addPath(points);
}
}
+ };
+ BatteryDataParser[] parserList = new BatteryDataParser[parsers.length + 1];
+ for (int i = 0; i < parsers.length; i++) {
+ parserList[i] = parsers[i];
}
- mStats.finishIteratingHistoryLocked();
- endDateWalltime = lastWallTime + historyEnd - lastRealtime;
- endWalltime = endDateWalltime + (remainingTimeUs / 1000);
-
- int i = 0;
- final int N = lastInteresting;
- SparseIntArray points = new SparseIntArray();
- view.clearPaths();
- view.configureGraph((int) (endWalltime - startWalltime), 100, remainingTimeUs != 0,
- mCharging);
- if (endDateWalltime > startWalltime && mStats.startIteratingHistoryLocked()) {
- final HistoryItem rec = new HistoryItem();
- while (mStats.getNextHistoryLocked(rec) && i < N) {
- if (rec.isDeltaData()) {
- curWalltime += rec.time - lastRealtime;
- lastRealtime = rec.time;
- long x = (curWalltime - startWalltime);
- if (x < 0) {
- x = 0;
- }
- points.put((int) x, rec.batteryLevel);
- } else {
- long lastWalltime = curWalltime;
- if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
- || rec.cmd == HistoryItem.CMD_RESET) {
- if (rec.currentTime >= startWalltime) {
- curWalltime = rec.currentTime;
- } else {
- curWalltime = startWalltime + (rec.time - historyStart);
- }
- lastRealtime = rec.time;
- }
-
- if (rec.cmd != HistoryItem.CMD_OVERFLOW
- && (rec.cmd != HistoryItem.CMD_CURRENT_TIME
- || Math.abs(lastWalltime-curWalltime) > (60*60*1000))) {
- if (points.size() > 1) {
- view.addPath(points);
- }
- points.clear();
- }
- }
- i++;
- }
- }
- if (points.size() > 1) {
- view.addPath(points);
- }
- long timePast = endDateWalltime - startWalltime;
+ parserList[parsers.length] = parser;
+ parse(mStats, remainingTimeUs, parserList);
final Context context = view.getContext();
String timeString = context.getString(R.string.charge_length_format,
- Formatter.formatShortElapsedTime(context, timePast));
+ Formatter.formatShortElapsedTime(context, timePeriod));
String remaining = "";
if (remainingTimeUs != 0) {
remaining = context.getString(R.string.remaining_length_format,
Formatter.formatShortElapsedTime(context, remainingTimeUs / 1000));
}
- view.setBottomLabels(new CharSequence[] { timeString, remaining});
-
- mStats.finishIteratingHistoryLocked();
+ view.setBottomLabels(new CharSequence[]{timeString, remaining});
}
public static void getBatteryInfo(final Context context, final Callback callback) {
@@ -233,4 +171,119 @@
}
return info;
}
+
+ public interface BatteryDataParser {
+ void onParsingStarted(long startTime, long endTime);
+
+ void onDataPoint(long time, HistoryItem record);
+
+ void onDataGap();
+
+ void onParsingDone();
+ }
+
+ private static void parse(BatteryStats stats, long remainingTimeUs,
+ BatteryDataParser... parsers) {
+ long startWalltime = 0;
+ long endDateWalltime = 0;
+ long endWalltime = 0;
+ long historyStart = 0;
+ long historyEnd = 0;
+ byte lastLevel = -1;
+ long curWalltime = startWalltime;
+ long lastWallTime = 0;
+ long lastRealtime = 0;
+ int lastInteresting = 0;
+ int pos = 0;
+ boolean first = true;
+ if (stats.startIteratingHistoryLocked()) {
+ final HistoryItem rec = new HistoryItem();
+ while (stats.getNextHistoryLocked(rec)) {
+ pos++;
+ if (first) {
+ first = false;
+ historyStart = rec.time;
+ }
+ if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
+ || rec.cmd == HistoryItem.CMD_RESET) {
+ // If there is a ridiculously large jump in time, then we won't be
+ // able to create a good chart with that data, so just ignore the
+ // times we got before and pretend like our data extends back from
+ // the time we have now.
+ // Also, if we are getting a time change and we are less than 5 minutes
+ // since the start of the history real time, then also use this new
+ // time to compute the base time, since whatever time we had before is
+ // pretty much just noise.
+ if (rec.currentTime > (lastWallTime + (180 * 24 * 60 * 60 * 1000L))
+ || rec.time < (historyStart + (5 * 60 * 1000L))) {
+ startWalltime = 0;
+ }
+ lastWallTime = rec.currentTime;
+ lastRealtime = rec.time;
+ if (startWalltime == 0) {
+ startWalltime = lastWallTime - (lastRealtime - historyStart);
+ }
+ }
+ if (rec.isDeltaData()) {
+ if (rec.batteryLevel != lastLevel || pos == 1) {
+ lastLevel = rec.batteryLevel;
+ }
+ lastInteresting = pos;
+ historyEnd = rec.time;
+ }
+ }
+ }
+ stats.finishIteratingHistoryLocked();
+ endDateWalltime = lastWallTime + historyEnd - lastRealtime;
+ endWalltime = endDateWalltime + (remainingTimeUs / 1000);
+
+ int i = 0;
+ final int N = lastInteresting;
+
+ for (int j = 0; j < parsers.length; j++) {
+ parsers[j].onParsingStarted(startWalltime, endWalltime);
+ }
+ if (endDateWalltime > startWalltime && stats.startIteratingHistoryLocked()) {
+ final HistoryItem rec = new HistoryItem();
+ while (stats.getNextHistoryLocked(rec) && i < N) {
+ if (rec.isDeltaData()) {
+ curWalltime += rec.time - lastRealtime;
+ lastRealtime = rec.time;
+ long x = (curWalltime - startWalltime);
+ if (x < 0) {
+ x = 0;
+ }
+ for (int j = 0; j < parsers.length; j++) {
+ parsers[j].onDataPoint(x, rec);
+ }
+ } else {
+ long lastWalltime = curWalltime;
+ if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
+ || rec.cmd == HistoryItem.CMD_RESET) {
+ if (rec.currentTime >= startWalltime) {
+ curWalltime = rec.currentTime;
+ } else {
+ curWalltime = startWalltime + (rec.time - historyStart);
+ }
+ lastRealtime = rec.time;
+ }
+
+ if (rec.cmd != HistoryItem.CMD_OVERFLOW
+ && (rec.cmd != HistoryItem.CMD_CURRENT_TIME
+ || Math.abs(lastWalltime - curWalltime) > (60 * 60 * 1000))) {
+ for (int j = 0; j < parsers.length; j++) {
+ parsers[j].onDataGap();
+ }
+ }
+ }
+ i++;
+ }
+ }
+
+ stats.finishIteratingHistoryLocked();
+
+ for (int j = 0; j < parsers.length; j++) {
+ parsers[j].onParsingDone();
+ }
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedDropDownPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedDropDownPreference.java
index c2f885d..4c0450e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedDropDownPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedDropDownPreference.java
@@ -49,7 +49,7 @@
mRestrictedPadlock = RestrictedLockUtils.getRestrictedPadlock(context);
mRestrictedPadlockPadding = context.getResources().getDimensionPixelSize(
- R.dimen.restricted_lock_icon_padding);
+ R.dimen.restricted_icon_padding);
}
private final OnItemSelectedListener mItemSelectedListener = new OnItemSelectedListener() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockImageSpan.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockImageSpan.java
index e63130d..360a34c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockImageSpan.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockImageSpan.java
@@ -36,7 +36,7 @@
mContext = context;
mExtraPadding = mContext.getResources().getDimensionPixelSize(
- R.dimen.restricted_lock_icon_padding);
+ R.dimen.restricted_icon_padding);
mRestrictedPadlock = RestrictedLockUtils.getRestrictedPadlock(mContext);
}
@@ -53,7 +53,7 @@
// Add extra padding before the padlock.
float transX = x + mExtraPadding;
- float transY = bottom - drawable.getBounds().bottom - paint.getFontMetricsInt().descent;
+ float transY = (bottom - drawable.getBounds().bottom) / 2.0f;
canvas.translate(transX, transY);
drawable.draw(canvas);
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
index c44b638..d0c249f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
@@ -49,9 +49,9 @@
* @return drawables for displaying with settings that are locked by a device admin.
*/
public static Drawable getRestrictedPadlock(Context context) {
- Drawable restrictedPadlock = context.getDrawable(R.drawable.ic_settings_lock_outline);
+ Drawable restrictedPadlock = context.getDrawable(R.drawable.ic_info);
final int iconSize = context.getResources().getDimensionPixelSize(
- R.dimen.restricted_lock_icon_size);
+ R.dimen.restricted_icon_size);
restrictedPadlock.setBounds(0, 0, iconSize, iconSize);
return restrictedPadlock;
}
@@ -113,6 +113,12 @@
return admin;
}
+ public static boolean hasBaseUserRestriction(Context context,
+ String userRestriction, int userId) {
+ UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ return um.hasBaseUserRestriction(userRestriction, UserHandle.of(userId));
+ }
+
/**
* Checks if keyguard features are disabled by policy.
*
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java
index 810f6eb..e69497a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java
@@ -23,6 +23,7 @@
import android.support.v7.preference.PreferenceManager;
import android.support.v7.preference.PreferenceViewHolder;
import android.util.AttributeSet;
+import android.view.View;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
@@ -36,6 +37,7 @@
public RestrictedPreference(Context context, AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
+ setWidgetLayoutResource(R.layout.restricted_icon);
mHelper = new RestrictedPreferenceHelper(context, this, attrs);
}
@@ -56,6 +58,10 @@
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
mHelper.onBindViewHolder(holder);
+ final View restrictedIcon = holder.findViewById(R.id.restricted_icon);
+ if (restrictedIcon != null) {
+ restrictedIcon.setVisibility(isDisabledByAdmin() ? View.VISIBLE : View.GONE);
+ }
}
@Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
index 9bd4eb1..0c0af24 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
@@ -54,7 +54,7 @@
mRestrictedPadlock = RestrictedLockUtils.getRestrictedPadlock(mContext);
mRestrictedPadlockPadding = mContext.getResources().getDimensionPixelSize(
- R.dimen.restricted_lock_icon_padding);
+ R.dimen.restricted_icon_padding);
if (attrs != null) {
final TypedArray attributes = context.obtainStyledAttributes(attrs,
@@ -70,6 +70,12 @@
}
}
mAttrUserRestriction = data == null ? null : data.toString();
+ // If the system has set the user restriction, then we shouldn't add the padlock.
+ if (RestrictedLockUtils.hasBaseUserRestriction(mContext, mAttrUserRestriction,
+ UserHandle.myUserId())) {
+ mAttrUserRestriction = null;
+ return;
+ }
final TypedValue useAdminDisabledSummary =
attributes.peekValue(R.styleable.RestrictedPreference_useAdminDisabledSummary);
@@ -85,12 +91,8 @@
* Modify PreferenceViewHolder to add padlock if restriction is disabled.
*/
public void onBindViewHolder(PreferenceViewHolder holder) {
- final TextView titleView = (TextView) holder.findViewById(android.R.id.title);
- if (titleView != null) {
- RestrictedLockUtils.setTextViewPadlock(mContext, titleView, mDisabledByAdmin);
- if (mDisabledByAdmin) {
- holder.itemView.setEnabled(true);
- }
+ if (mDisabledByAdmin) {
+ holder.itemView.setEnabled(true);
}
if (mUseAdminDisabledSummary) {
final TextView summaryView = (TextView) holder.findViewById(android.R.id.summary);
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
index 6cae8aa..f381286 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
@@ -23,6 +23,8 @@
import android.support.v7.preference.PreferenceViewHolder;
import android.support.v14.preference.SwitchPreference;
import android.util.AttributeSet;
+import android.view.View;
+import android.widget.TextView;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
@@ -36,6 +38,7 @@
public RestrictedSwitchPreference(Context context, AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
+ setWidgetLayoutResource(R.layout.restricted_switch_widget);
mHelper = new RestrictedPreferenceHelper(context, this, attrs);
}
@@ -56,6 +59,20 @@
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
mHelper.onBindViewHolder(holder);
+ final View restrictedIcon = holder.findViewById(R.id.restricted_icon);
+ final View switchWidget = holder.findViewById(android.R.id.switch_widget);
+ if (restrictedIcon != null) {
+ restrictedIcon.setVisibility(isDisabledByAdmin() ? View.VISIBLE : View.GONE);
+ }
+ if (switchWidget != null) {
+ switchWidget.setVisibility(isDisabledByAdmin() ? View.GONE : View.VISIBLE);
+ }
+ final TextView summaryView = (TextView) holder.findViewById(android.R.id.summary);
+ if (summaryView != null && isDisabledByAdmin()) {
+ summaryView.setText(
+ isChecked() ? R.string.enabled_by_admin : R.string.disabled_by_admin);
+ summaryView.setVisibility(View.VISIBLE);
+ }
}
@Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java b/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java
index 1859207..741b0ea 100644
--- a/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java
+++ b/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java
@@ -25,6 +25,12 @@
import android.util.Log;
import android.util.Pair;
import android.util.Xml;
+import android.provider.Settings;
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.content.ContentValues;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.view.InflateException;
import com.android.settingslib.drawer.Tile;
import com.android.settingslib.drawer.TileUtils;
@@ -42,6 +48,12 @@
// If defined, only returns this suggestion if the feature is supported.
public static final String META_DATA_REQUIRE_FEATURE = "com.android.settings.require_feature";
+ // If defined, only display this optional step if an account of that type exists.
+ private static final String META_DATA_REQUIRE_ACCOUNT = "com.android.settings.require_account";
+
+ // If defined and not true, do not should optional step.
+ private static final String META_DATA_IS_SUPPORTED = "com.android.settings.is_supported";
+
/**
* Allows suggestions to appear after a certain number of days, and to re-appear if dismissed.
* For instance:
@@ -110,7 +122,10 @@
TileUtils.getTilesForIntent(mContext, new UserHandle(UserHandle.myUserId()), intent,
addCache, null, suggestions, true, false);
for (int i = countBefore; i < suggestions.size(); i++) {
- if (!isAvailable(suggestions.get(i)) || isDismissed(suggestions.get(i))) {
+ if (!isAvailable(suggestions.get(i)) ||
+ !isSupported(suggestions.get(i)) ||
+ !satisfiesRequiredAccount(suggestions.get(i)) ||
+ isDismissed(suggestions.get(i))) {
suggestions.remove(i--);
}
}
@@ -124,7 +139,10 @@
item = last;
}
}
- suggestions.add(item);
+ // If category is marked as done, do not add any item.
+ if (!isCategoryDone(category.category)) {
+ suggestions.add(item);
+ }
}
}
@@ -136,6 +154,41 @@
return true;
}
+ public boolean satisfiesRequiredAccount(Tile suggestion) {
+ String requiredAccountType = suggestion.metaData.getString(META_DATA_REQUIRE_ACCOUNT);
+ if (requiredAccountType == null) {
+ return true;
+ }
+ AccountManager accountManager = AccountManager.get(mContext);
+ Account[] accounts = accountManager.getAccountsByType(requiredAccountType);
+ return accounts.length > 0;
+ }
+
+ public boolean isSupported(Tile suggestion) {
+ int isSupportedResource = suggestion.metaData.getInt(META_DATA_IS_SUPPORTED);
+ try {
+ if (suggestion.intent == null) {
+ return false;
+ }
+ final Resources res = mContext.getPackageManager().getResourcesForActivity(
+ suggestion.intent.getComponent());
+ return isSupportedResource != 0 ? res.getBoolean(isSupportedResource) : true;
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "Cannot find resources for " + suggestion.intent.getComponent());
+ return false;
+ }
+ }
+
+ public boolean isCategoryDone(String category) {
+ String name = Settings.Secure.COMPLETED_CATEGORY_PREFIX + category;
+ return Settings.Secure.getInt(mContext.getContentResolver(), name, 0) != 0;
+ }
+
+ public void markCategoryDone(String category) {
+ String name = Settings.Secure.COMPLETED_CATEGORY_PREFIX + category;
+ Settings.Secure.putInt(mContext.getContentResolver(), name, 1);
+ }
+
private boolean isDismissed(Tile suggestion) {
Object dismissObj = suggestion.metaData.get(META_DATA_DISMISS_CONTROL);
if (dismissObj == null) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index 1c032fa..7a1c741 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
@@ -18,6 +18,7 @@
import android.annotation.LayoutRes;
import android.annotation.Nullable;
import android.app.Activity;
+import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -68,16 +69,18 @@
long startTime = System.currentTimeMillis();
- getWindow().addFlags(LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
- getWindow().addFlags(LayoutParams.FLAG_TRANSLUCENT_STATUS);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
+ TypedArray theme = getTheme().obtainStyledAttributes(android.R.styleable.Theme);
+ if (!theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {
+ getWindow().addFlags(LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+ getWindow().addFlags(LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ }
super.setContentView(R.layout.settings_with_drawer);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
if (mDrawerLayout == null) {
return;
}
Toolbar toolbar = (Toolbar) findViewById(R.id.action_bar);
- TypedArray theme = getTheme().obtainStyledAttributes(android.R.styleable.Theme);
if (theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {
toolbar.setVisibility(View.GONE);
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
@@ -235,20 +238,24 @@
Intent.FLAG_ACTIVITY_CLEAR_TASK));
return true;
}
- int numUserHandles = tile.userHandle.size();
- if (numUserHandles > 1) {
- ProfileSelectDialog.show(getFragmentManager(), tile);
- return false;
- } else if (numUserHandles == 1) {
- // Show menu on top level items.
- tile.intent.putExtra(EXTRA_SHOW_MENU, true);
- tile.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
- startActivityAsUser(tile.intent, tile.userHandle.get(0));
- } else {
- // Show menu on top level items.
- tile.intent.putExtra(EXTRA_SHOW_MENU, true);
- tile.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
- startActivity(tile.intent);
+ try {
+ int numUserHandles = tile.userHandle.size();
+ if (numUserHandles > 1) {
+ ProfileSelectDialog.show(getFragmentManager(), tile);
+ return false;
+ } else if (numUserHandles == 1) {
+ // Show menu on top level items.
+ tile.intent.putExtra(EXTRA_SHOW_MENU, true);
+ tile.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ startActivityAsUser(tile.intent, tile.userHandle.get(0));
+ } else {
+ // Show menu on top level items.
+ tile.intent.putExtra(EXTRA_SHOW_MENU, true);
+ tile.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ startActivity(tile.intent);
+ }
+ } catch (ActivityNotFoundException e) {
+ Log.w(TAG, "Couldn't find tile " + tile.intent, e);
}
return true;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
index 2dfdfda..418b138 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
@@ -41,7 +41,7 @@
public class TileUtils {
private static final boolean DEBUG = false;
- private static final boolean DEBUG_TIMING = true;
+ private static final boolean DEBUG_TIMING = false;
private static final String LOG_TAG = "TileUtils";
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 5b8ed28..380fcd4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -110,6 +110,7 @@
private final Context mContext;
private String ssid;
+ private String bssid;
private int security;
private int networkId = WifiConfiguration.INVALID_NETWORK_ID;
@@ -335,6 +336,10 @@
return ssid;
}
+ public String getBssid() {
+ return bssid;
+ }
+
public CharSequence getSsid() {
SpannableString str = new SpannableString(ssid);
str.setSpan(new TtsSpan.VerbatimBuilder(ssid).build(), 0, ssid.length(),
@@ -657,6 +662,7 @@
else
ssid = (config.SSID == null ? "" : removeDoubleQuotes(config.SSID));
+ bssid = config.BSSID;
security = getSecurity(config);
networkId = config.networkId;
mConfig = config;
@@ -664,6 +670,7 @@
private void initWithScanResult(ScanResult result) {
ssid = result.SSID;
+ bssid = result.BSSID;
security = getSecurity(result);
if (security == SECURITY_PSK)
pskType = getPskType(result);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 57d495f..a424d55 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -49,6 +49,7 @@
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
+import android.os.SELinux;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
@@ -457,8 +458,28 @@
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
- throw new FileNotFoundException("Direct file access no longer supported; "
- + "ringtone playback is available through android.media.Ringtone");
+ final String cacheName;
+ if (Settings.System.RINGTONE_CACHE_URI.equals(uri)) {
+ cacheName = Settings.System.RINGTONE_CACHE;
+ } else if (Settings.System.NOTIFICATION_SOUND_CACHE_URI.equals(uri)) {
+ cacheName = Settings.System.NOTIFICATION_SOUND_CACHE;
+ } else if (Settings.System.ALARM_ALERT_CACHE_URI.equals(uri)) {
+ cacheName = Settings.System.ALARM_ALERT_CACHE;
+ } else {
+ throw new FileNotFoundException("Direct file access no longer supported; "
+ + "ringtone playback is available through android.media.Ringtone");
+ }
+
+ final File cacheFile = new File(
+ getRingtoneCacheDir(UserHandle.getCallingUserId()), cacheName);
+ return ParcelFileDescriptor.open(cacheFile, ParcelFileDescriptor.parseMode(mode));
+ }
+
+ private File getRingtoneCacheDir(int userId) {
+ final File cacheDir = new File(Environment.getDataSystemDeDirectory(userId), "ringtones");
+ cacheDir.mkdir();
+ SELinux.restorecon(cacheDir);
+ return cacheDir;
}
@Override
@@ -901,6 +922,21 @@
return false;
}
+ // Invalidate any relevant cache files
+ String cacheName = null;
+ if (Settings.System.RINGTONE.equals(name)) {
+ cacheName = Settings.System.RINGTONE_CACHE;
+ } else if (Settings.System.NOTIFICATION_SOUND.equals(name)) {
+ cacheName = Settings.System.NOTIFICATION_SOUND_CACHE;
+ } else if (Settings.System.ALARM_ALERT.equals(name)) {
+ cacheName = Settings.System.ALARM_ALERT_CACHE;
+ }
+ if (cacheName != null) {
+ final File cacheFile = new File(
+ getRingtoneCacheDir(UserHandle.getCallingUserId()), cacheName);
+ cacheFile.delete();
+ }
+
// Mutate the value.
synchronized (mLock) {
switch (operation) {
@@ -1092,10 +1128,15 @@
private PackageInfo getCallingPackageInfoOrThrow(int userId) {
try {
- return mPackageManager.getPackageInfo(getCallingPackage(), 0, userId);
+ PackageInfo packageInfo = mPackageManager.getPackageInfo(
+ getCallingPackage(), 0, userId);
+ if (packageInfo != null) {
+ return packageInfo;
+ }
} catch (RemoteException e) {
- throw new IllegalStateException("Calling package doesn't exist");
+ /* ignore */
}
+ throw new IllegalStateException("Calling package doesn't exist");
}
private int getGroupParentLocked(int userId) {
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 7416fb5..5b865f9 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -40,6 +40,7 @@
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+ <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
<!-- System tool permissions granted to the shell. -->
<uses-permission android:name="android.permission.REAL_GET_TASKS" />
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
@@ -109,6 +110,7 @@
<uses-permission android:name="android.permission.GET_APP_OPS_STATS" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
+ <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
<application android:label="@string/app_label"
android:forceDeviceEncrypted="true"
diff --git a/packages/Shell/res/layout/dialog_bugreport_info.xml b/packages/Shell/res/layout/dialog_bugreport_info.xml
index 5d1e9f9..b6b8d6b 100644
--- a/packages/Shell/res/layout/dialog_bugreport_info.xml
+++ b/packages/Shell/res/layout/dialog_bugreport_info.xml
@@ -16,28 +16,44 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
+ android:paddingTop="15dp"
+ android:paddingStart="24dp"
+ android:paddingEnd="24dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
+ <TextView
+ android:inputType="textNoSuggestions"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/bugreport_info_name"/>
<EditText
android:id="@+id/name"
android:maxLength="30"
android:singleLine="true"
+ android:selectAllOnFocus="true"
android:inputType="textNoSuggestions"
android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+ <TextView
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:hint="@string/bugreport_info_name"/>
+ android:text="@string/bugreport_info_title"/>
<EditText
android:id="@+id/title"
android:maxLength="80"
android:singleLine="true"
+ android:inputType="textAutoCorrect|textCapSentences"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+ <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:hint="@string/bugreport_info_title"/>
+ android:editable="false"
+ android:text="@string/bugreport_info_description"/>
<EditText
android:id="@+id/description"
android:singleLine="false"
- android:inputType="textMultiLine"
+ android:inputType="textMultiLine|textAutoCorrect|textCapSentences"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:hint="@string/bugreport_info_description"/>
+ android:layout_height="wrap_content"/>
</LinearLayout>
diff --git a/packages/Shell/res/values-af/strings.xml b/packages/Shell/res/values-af/strings.xml
index 9d399c1..f86b551 100644
--- a/packages/Shell/res/values-af/strings.xml
+++ b/packages/Shell/res/values-af/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Kon nie skermkiekie neem nie."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Foutverslag <xliff:g id="ID">#%d</xliff:g> se besonderhede"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Lêernaam"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Titel"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Gedetailleerde beskrywing"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Fouttitel"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Foutopsomming"</string>
+ <string name="save" msgid="4781509040564835759">"Stoor"</string>
</resources>
diff --git a/packages/Shell/res/values-am/strings.xml b/packages/Shell/res/values-am/strings.xml
index 2545222..55c5390 100644
--- a/packages/Shell/res/values-am/strings.xml
+++ b/packages/Shell/res/values-am/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"ቅጽበታዊ ገጽ እይታ ሊነሳ አይችልም"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"የሳንካ ሪፖርት <xliff:g id="ID">#%d</xliff:g> ዝርዝሮች"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"የፋይል ስም"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"ርዕስ"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"ዝርዝር መግለጫ"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"የሳንካ ርዕስ"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"የሳንካ ማጠቃለያ"</string>
+ <string name="save" msgid="4781509040564835759">"አስቀምጥ"</string>
</resources>
diff --git a/packages/Shell/res/values-ar/strings.xml b/packages/Shell/res/values-ar/strings.xml
index 7593110..f0af8ce 100644
--- a/packages/Shell/res/values-ar/strings.xml
+++ b/packages/Shell/res/values-ar/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"تعذر التقاط لقطة الشاشة."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"تفاصيل تقرير الخطأ <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"اسم الملف"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"العنوان"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"وصف تفصيلي"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"عنوان الخطأ"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"ملخص الخطأ"</string>
+ <string name="save" msgid="4781509040564835759">"حفظ"</string>
</resources>
diff --git a/packages/Shell/res/values-az-rAZ/strings.xml b/packages/Shell/res/values-az-rAZ/strings.xml
index 9130255..6d375fe 100644
--- a/packages/Shell/res/values-az-rAZ/strings.xml
+++ b/packages/Shell/res/values-az-rAZ/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Displey görüntüsü əlçatan deyil."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Baq hesabatı <xliff:g id="ID">#%d</xliff:g> detalları"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Fayl adı"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Başlıq"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Ətraflı təsvir"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Baq başlığı"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Baq xülasə"</string>
+ <string name="save" msgid="4781509040564835759">"Yadda saxlayın"</string>
</resources>
diff --git a/packages/Shell/res/values-b+sr+Latn/strings.xml b/packages/Shell/res/values-b+sr+Latn/strings.xml
index 597e545..ad84941 100644
--- a/packages/Shell/res/values-b+sr+Latn/strings.xml
+++ b/packages/Shell/res/values-b+sr+Latn/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Snimanje ekrana nije uspelo."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalji izveštaja o grešci <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Naziv datoteke"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Naslov"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Detaljni opis"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Naslov greške"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Rezime greške"</string>
+ <string name="save" msgid="4781509040564835759">"Sačuvaj"</string>
</resources>
diff --git a/packages/Shell/res/values-bg/strings.xml b/packages/Shell/res/values-bg/strings.xml
index 6ca7914..e543839 100644
--- a/packages/Shell/res/values-bg/strings.xml
+++ b/packages/Shell/res/values-bg/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Екранната снимка не можа да бъде направена."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Подробности за сигнала за програмна грешка „<xliff:g id="ID">#%d</xliff:g>“"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Име на файла"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Заглавие"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Подробно описание"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Заглавие на сигнала за програмна грешка"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Обобщена информация за сигнала за програмна грешка"</string>
+ <string name="save" msgid="4781509040564835759">"Запазване"</string>
</resources>
diff --git a/packages/Shell/res/values-bn-rBD/strings.xml b/packages/Shell/res/values-bn-rBD/strings.xml
index 5390315..bba778d 100644
--- a/packages/Shell/res/values-bn-rBD/strings.xml
+++ b/packages/Shell/res/values-bn-rBD/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"স্ক্রীনশট নেওয়া যায়নি৷"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ত্রুটির প্রতিবেদন <xliff:g id="ID">#%d</xliff:g> এর বিশদ বিবরণ"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ফাইলের নাম"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"শীর্ষক"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"বিস্তারিত বিবরণ"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"ত্রুটির শীর্ষক"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"ত্রুটির সারাংশ"</string>
+ <string name="save" msgid="4781509040564835759">"সংরক্ষণ করুন"</string>
</resources>
diff --git a/packages/Shell/res/values-bs-rBA/strings.xml b/packages/Shell/res/values-bs-rBA/strings.xml
index 903c2ab..54be955 100644
--- a/packages/Shell/res/values-bs-rBA/strings.xml
+++ b/packages/Shell/res/values-bs-rBA/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Ekran nije moguće snimiti."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalji izvještaja o grešci <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Naziv fajla"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Naslov"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Detaljan opis"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Naslov greške"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Sažetak greške"</string>
+ <string name="save" msgid="4781509040564835759">"Sačuvaj"</string>
</resources>
diff --git a/packages/Shell/res/values-ca/strings.xml b/packages/Shell/res/values-ca/strings.xml
index 0836946..a92177e 100644
--- a/packages/Shell/res/values-ca/strings.xml
+++ b/packages/Shell/res/values-ca/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"No s\'ha pogut fer la captura de pantalla."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalls de l\'informe d\'errors <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nom del fitxer"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Títol"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Descripció detallada"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Títol de l\'error"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Resum d\'errors"</string>
+ <string name="save" msgid="4781509040564835759">"Desa"</string>
</resources>
diff --git a/packages/Shell/res/values-cs/strings.xml b/packages/Shell/res/values-cs/strings.xml
index 215ec87..6f7549a 100644
--- a/packages/Shell/res/values-cs/strings.xml
+++ b/packages/Shell/res/values-cs/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Snímek obrazovky se nepodařilo pořídit."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Podrobnosti zprávy o chybě <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Název souboru"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Název"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Podrobný popis"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Název chyby"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Přehled chyby"</string>
+ <string name="save" msgid="4781509040564835759">"Uložit"</string>
</resources>
diff --git a/packages/Shell/res/values-da/strings.xml b/packages/Shell/res/values-da/strings.xml
index e956d3a..72a9a99 100644
--- a/packages/Shell/res/values-da/strings.xml
+++ b/packages/Shell/res/values-da/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Der kunne ikke tages et skærmbillede."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Oplysninger om fejlrapporten <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Filnavn"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Titel"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Detaljeret beskrivelse"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Fejlrapportens titel"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Oversigt over fejl"</string>
+ <string name="save" msgid="4781509040564835759">"Gem"</string>
</resources>
diff --git a/packages/Shell/res/values-de/strings.xml b/packages/Shell/res/values-de/strings.xml
index 07f8898..f848c9d 100644
--- a/packages/Shell/res/values-de/strings.xml
+++ b/packages/Shell/res/values-de/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Screenshot konnte nicht aufgenommen werden."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Details zum Fehlerbericht <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Dateiname"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Titel"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Detaillierte Beschreibung"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Titel des Programmfehlers"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Zusammenfassung des Programmfehlers"</string>
+ <string name="save" msgid="4781509040564835759">"Speichern"</string>
</resources>
diff --git a/packages/Shell/res/values-el/strings.xml b/packages/Shell/res/values-el/strings.xml
index 6746976..0c04809 100644
--- a/packages/Shell/res/values-el/strings.xml
+++ b/packages/Shell/res/values-el/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Δεν ήταν δυνατή η λήψη του στιγμιότυπου οθόνης."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Λεπτομέρειες της αναφοράς σφάλματος <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Όνομα αρχείου"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Τίτλος"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Αναλυτική περιγραφή"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Τίτλος σφάλματος"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Περίληψη σφάλματος"</string>
+ <string name="save" msgid="4781509040564835759">"Αποθήκευση"</string>
</resources>
diff --git a/packages/Shell/res/values-en-rAU/strings.xml b/packages/Shell/res/values-en-rAU/strings.xml
index ac681e2..ad637f5 100644
--- a/packages/Shell/res/values-en-rAU/strings.xml
+++ b/packages/Shell/res/values-en-rAU/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Screenshot could not be taken."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Bug report <xliff:g id="ID">#%d</xliff:g> details"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Filename"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Title"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Detailed description"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Bug title"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Bug summary"</string>
+ <string name="save" msgid="4781509040564835759">"Save"</string>
</resources>
diff --git a/packages/Shell/res/values-en-rGB/strings.xml b/packages/Shell/res/values-en-rGB/strings.xml
index ac681e2..ad637f5 100644
--- a/packages/Shell/res/values-en-rGB/strings.xml
+++ b/packages/Shell/res/values-en-rGB/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Screenshot could not be taken."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Bug report <xliff:g id="ID">#%d</xliff:g> details"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Filename"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Title"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Detailed description"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Bug title"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Bug summary"</string>
+ <string name="save" msgid="4781509040564835759">"Save"</string>
</resources>
diff --git a/packages/Shell/res/values-en-rIN/strings.xml b/packages/Shell/res/values-en-rIN/strings.xml
index ac681e2..ad637f5 100644
--- a/packages/Shell/res/values-en-rIN/strings.xml
+++ b/packages/Shell/res/values-en-rIN/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Screenshot could not be taken."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Bug report <xliff:g id="ID">#%d</xliff:g> details"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Filename"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Title"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Detailed description"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Bug title"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Bug summary"</string>
+ <string name="save" msgid="4781509040564835759">"Save"</string>
</resources>
diff --git a/packages/Shell/res/values-es-rUS/strings.xml b/packages/Shell/res/values-es-rUS/strings.xml
index 96ca14c..a9a1e08 100644
--- a/packages/Shell/res/values-es-rUS/strings.xml
+++ b/packages/Shell/res/values-es-rUS/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"No se pudo tomar la captura de pantalla."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalles del informe de errores <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nombre del archivo"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Título"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Descripción completa"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Título del error"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Resumen del error"</string>
+ <string name="save" msgid="4781509040564835759">"Guardar"</string>
</resources>
diff --git a/packages/Shell/res/values-es/strings.xml b/packages/Shell/res/values-es/strings.xml
index 00874c6..b82d372 100644
--- a/packages/Shell/res/values-es/strings.xml
+++ b/packages/Shell/res/values-es/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"No se puede realizar la captura de pantalla."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalles del informe de errores <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nombre de archivo"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Título"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Descripción completa"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Nombre del informe de errores"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Resumen del informe de errores"</string>
+ <string name="save" msgid="4781509040564835759">"Guardar"</string>
</resources>
diff --git a/packages/Shell/res/values-et-rEE/strings.xml b/packages/Shell/res/values-et-rEE/strings.xml
index bc469bc..cdb774a0 100644
--- a/packages/Shell/res/values-et-rEE/strings.xml
+++ b/packages/Shell/res/values-et-rEE/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Ekraanipilti ei saanud teha."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Veaaruande <xliff:g id="ID">#%d</xliff:g> üksikasjad"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Faili nimi"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Pealkiri"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Üksikasjalik kirjeldus"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Vea pealkiri"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Vea kokkuvõte"</string>
+ <string name="save" msgid="4781509040564835759">"Salvesta"</string>
</resources>
diff --git a/packages/Shell/res/values-eu-rES/strings.xml b/packages/Shell/res/values-eu-rES/strings.xml
index 614f17e..42dfe27 100644
--- a/packages/Shell/res/values-eu-rES/strings.xml
+++ b/packages/Shell/res/values-eu-rES/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Ezin izan da atera pantaila-argazkia."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Akatsen <xliff:g id="ID">#%d</xliff:g> txostenaren xehetasunak"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Fitxategi-izena"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Izena"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Azalpen xehatua"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Akatsaren izena"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Akatsaren laburpena"</string>
+ <string name="save" msgid="4781509040564835759">"Gorde"</string>
</resources>
diff --git a/packages/Shell/res/values-fa/strings.xml b/packages/Shell/res/values-fa/strings.xml
index ab00562..e825f3a 100644
--- a/packages/Shell/res/values-fa/strings.xml
+++ b/packages/Shell/res/values-fa/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"نمیتوان عکس صفحهنمایش گرفت."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"جزئیات گزارش اشکال <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"نام فایل"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"عنوان"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"جزئیات دقیق"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"عنوان اشکال"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"خلاصه اشکال"</string>
+ <string name="save" msgid="4781509040564835759">"ذخیره کردن"</string>
</resources>
diff --git a/packages/Shell/res/values-fi/strings.xml b/packages/Shell/res/values-fi/strings.xml
index be7aabd..8c67c66 100644
--- a/packages/Shell/res/values-fi/strings.xml
+++ b/packages/Shell/res/values-fi/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Kuvakaappauksen tallentaminen epäonnistui."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Virheraportin <xliff:g id="ID">#%d</xliff:g> tiedot"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Tiedostonimi"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Otsikko"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Yksityiskohtainen kuvaus"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Virheen nimi"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Virheen yhteenveto"</string>
+ <string name="save" msgid="4781509040564835759">"Tallenna"</string>
</resources>
diff --git a/packages/Shell/res/values-fr-rCA/strings.xml b/packages/Shell/res/values-fr-rCA/strings.xml
index 7d9f97d..3daa120 100644
--- a/packages/Shell/res/values-fr-rCA/strings.xml
+++ b/packages/Shell/res/values-fr-rCA/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Une erreur s\'est produite lors de la saisie d\'écran."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Détails du rapport de bogue <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nom de fichier"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Titre"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Description détaillée"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Titre du bogue"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Sommaire des bogues"</string>
+ <string name="save" msgid="4781509040564835759">"Enregistrer"</string>
</resources>
diff --git a/packages/Shell/res/values-fr/strings.xml b/packages/Shell/res/values-fr/strings.xml
index 74025d9..c512aca 100644
--- a/packages/Shell/res/values-fr/strings.xml
+++ b/packages/Shell/res/values-fr/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Impossible d\'effectuer une capture d\'écran."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Informations sur le rapport de bug \"<xliff:g id="ID">#%d</xliff:g>\""</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nom de fichier"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Titre"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Description détaillée"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Titre du bug"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Résumé du bug"</string>
+ <string name="save" msgid="4781509040564835759">"Enregistrer"</string>
</resources>
diff --git a/packages/Shell/res/values-gl-rES/strings.xml b/packages/Shell/res/values-gl-rES/strings.xml
index d3be7c5..ea95c97 100644
--- a/packages/Shell/res/values-gl-rES/strings.xml
+++ b/packages/Shell/res/values-gl-rES/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Non se puido realizar a captura de pantalla."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalles do informe de erros <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nome do ficheiro"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Título"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Descrición detallada"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Título do informe de erros"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Resumo do informe de erros"</string>
+ <string name="save" msgid="4781509040564835759">"Gardar"</string>
</resources>
diff --git a/packages/Shell/res/values-gu-rIN/strings.xml b/packages/Shell/res/values-gu-rIN/strings.xml
index 45df7b3..1436c3d 100644
--- a/packages/Shell/res/values-gu-rIN/strings.xml
+++ b/packages/Shell/res/values-gu-rIN/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"સ્ક્રીનશોટ લઇ શકાયો નથી."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"બગ રિપોર્ટ <xliff:g id="ID">#%d</xliff:g> ની વિગતો"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ફાઇલનું નામ"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"શીર્ષક"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"વિગતવાર વર્ણન"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"બગનું શીર્ષક"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"બગનો સારાંશ"</string>
+ <string name="save" msgid="4781509040564835759">"સાચવો"</string>
</resources>
diff --git a/packages/Shell/res/values-hi/strings.xml b/packages/Shell/res/values-hi/strings.xml
index 8858bc3..9a735f2 100644
--- a/packages/Shell/res/values-hi/strings.xml
+++ b/packages/Shell/res/values-hi/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"स्क्रीनशॉट नहीं लिया जा सका."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"बग रिपोर्ट <xliff:g id="ID">#%d</xliff:g> के विवरण"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"फ़ाइल नाम"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"शीर्षक"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"विस्तृत वर्णन"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"बग शीर्षक"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"बग सारांश"</string>
+ <string name="save" msgid="4781509040564835759">"सहेजें"</string>
</resources>
diff --git a/packages/Shell/res/values-hr/strings.xml b/packages/Shell/res/values-hr/strings.xml
index cb03f9c..71d50b8 100644
--- a/packages/Shell/res/values-hr/strings.xml
+++ b/packages/Shell/res/values-hr/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Snimanje zaslona nije uspjelo."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Pojedinosti izvješća o programskoj pogrešci <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Naziv datoteke"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Naslov"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Detaljan opis"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Naslov izvješća o programskoj pogrešci"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Sažetak izvješća o programskoj pogrešci"</string>
+ <string name="save" msgid="4781509040564835759">"Spremi"</string>
</resources>
diff --git a/packages/Shell/res/values-hu/strings.xml b/packages/Shell/res/values-hu/strings.xml
index 390cd2f..cf10315 100644
--- a/packages/Shell/res/values-hu/strings.xml
+++ b/packages/Shell/res/values-hu/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Nem sikerült elkészíteni a képernyőképet."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Hibajelentés (<xliff:g id="ID">#%d</xliff:g>) részletei"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Fájlnév"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Név"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Részletes leírás"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Hibajelentés címe"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Hibajelentés összefoglalója"</string>
+ <string name="save" msgid="4781509040564835759">"Mentés"</string>
</resources>
diff --git a/packages/Shell/res/values-hy-rAM/strings.xml b/packages/Shell/res/values-hy-rAM/strings.xml
index 68478ab..1cf5c94 100644
--- a/packages/Shell/res/values-hy-rAM/strings.xml
+++ b/packages/Shell/res/values-hy-rAM/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Չհաջողվեց ստանալ էկրանի պատկերը:"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"<xliff:g id="ID">#%d</xliff:g> վրիպակի զեկույցի մանրամասները"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Ֆայլի անունը"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Անվանումը"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Մանրամասն նկարագրություն"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Վրիպակի զեկույցի վերնագիրը"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Վրիպակի զեկույցի ամփոփագիրը"</string>
+ <string name="save" msgid="4781509040564835759">"Պահել"</string>
</resources>
diff --git a/packages/Shell/res/values-in/strings.xml b/packages/Shell/res/values-in/strings.xml
index 4416fc7..1e8fe87 100644
--- a/packages/Shell/res/values-in/strings.xml
+++ b/packages/Shell/res/values-in/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Tangkapan layar tidak dapat diambil."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detail laporan bug <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nama file"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Judul"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Deskripsi detail"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Judul bug"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Ringkasan bug"</string>
+ <string name="save" msgid="4781509040564835759">"Simpan"</string>
</resources>
diff --git a/packages/Shell/res/values-is-rIS/strings.xml b/packages/Shell/res/values-is-rIS/strings.xml
index 0d43719..afcea59 100644
--- a/packages/Shell/res/values-is-rIS/strings.xml
+++ b/packages/Shell/res/values-is-rIS/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Ekki tókst að taka skjámynd."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Upplýsingar villutilkynningar <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Skráarheiti"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Titill"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Ítarleg lýsing"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Heiti villu"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Villusamantekt"</string>
+ <string name="save" msgid="4781509040564835759">"Vista"</string>
</resources>
diff --git a/packages/Shell/res/values-it/strings.xml b/packages/Shell/res/values-it/strings.xml
index fc9383a..d7ac9a5 100644
--- a/packages/Shell/res/values-it/strings.xml
+++ b/packages/Shell/res/values-it/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Impossibile acquisire lo screenshot."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Dettagli sulla segnalazione di bug <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nome file"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Titolo"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Descrizione dettagliata"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Titolo bug"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Riepilogo bug"</string>
+ <string name="save" msgid="4781509040564835759">"Salva"</string>
</resources>
diff --git a/packages/Shell/res/values-iw/strings.xml b/packages/Shell/res/values-iw/strings.xml
index 335a2e8..fd64ee1 100644
--- a/packages/Shell/res/values-iw/strings.xml
+++ b/packages/Shell/res/values-iw/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"לא ניתן היה לצלם מסך."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"פרטי הדוח על הבאג <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"שם קובץ"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"כותרת"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"תיאור מפורט"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"כותרת הבאג"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"סיכום הבאג"</string>
+ <string name="save" msgid="4781509040564835759">"שמור"</string>
</resources>
diff --git a/packages/Shell/res/values-ja/strings.xml b/packages/Shell/res/values-ja/strings.xml
index b98b05f..050c5df 100644
--- a/packages/Shell/res/values-ja/strings.xml
+++ b/packages/Shell/res/values-ja/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"スクリーンショットを撮影できませんでした。"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"バグレポート <xliff:g id="ID">#%d</xliff:g> の詳細"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ファイル名"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"タイトル"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"詳細説明"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"バグのタイトル"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"バグの概要"</string>
+ <string name="save" msgid="4781509040564835759">"保存"</string>
</resources>
diff --git a/packages/Shell/res/values-ka-rGE/strings.xml b/packages/Shell/res/values-ka-rGE/strings.xml
index 24d83a4..8c5c6fb 100644
--- a/packages/Shell/res/values-ka-rGE/strings.xml
+++ b/packages/Shell/res/values-ka-rGE/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"ეკრანის ანაბეჭდის გადაღება ვერ მოხერხდა."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ხარვეზების შესახებ ანგარიში <xliff:g id="ID">#%d</xliff:g>-ის დეტალები"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ფაილის სახელი"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"სათაური"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"დეტალური აღწერა"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"შეცდომის სათაური"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"შეცდომის რეზიუმე"</string>
+ <string name="save" msgid="4781509040564835759">"შენახვა"</string>
</resources>
diff --git a/packages/Shell/res/values-kk-rKZ/strings.xml b/packages/Shell/res/values-kk-rKZ/strings.xml
index 5878b17..edb2dd0 100644
--- a/packages/Shell/res/values-kk-rKZ/strings.xml
+++ b/packages/Shell/res/values-kk-rKZ/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Скриншот түсіру мүмкін болмады."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"<xliff:g id="ID">#%d</xliff:g> қате туралы есебі туралы мәліметтер"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Файл атауы"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Атауы"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Егжей-тегжейлі сипаттама"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Қатенің атауы"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Қате туралы жиынтық мәліметтер"</string>
+ <string name="save" msgid="4781509040564835759">"Сақтау"</string>
</resources>
diff --git a/packages/Shell/res/values-km-rKH/strings.xml b/packages/Shell/res/values-km-rKH/strings.xml
index 9c95e98..ba0de9f 100644
--- a/packages/Shell/res/values-km-rKH/strings.xml
+++ b/packages/Shell/res/values-km-rKH/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"មិនអាចថតរូបថតអេក្រង់បានទេ"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ព័ត៌មានលម្អិតពី <xliff:g id="ID">#%d</xliff:g> របាយការណ៍កំហុស"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ឈ្មោះឯកសារ"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"ចំណងជើង"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"ការពិពណ៌នាលម្អិត"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"ចំណងជើងកំហុស"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"សង្ខេបកំហុស"</string>
+ <string name="save" msgid="4781509040564835759">"រក្សាទុក"</string>
</resources>
diff --git a/packages/Shell/res/values-kn-rIN/strings.xml b/packages/Shell/res/values-kn-rIN/strings.xml
index ce6f3c0..b041f35 100644
--- a/packages/Shell/res/values-kn-rIN/strings.xml
+++ b/packages/Shell/res/values-kn-rIN/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ತೆಗೆದುಕೊಳ್ಳಲು ಸಾಧ್ಯವಾಗುವುದಿಲ್ಲ."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ದೋಷ ವರದಿಯ <xliff:g id="ID">#%d</xliff:g> ವಿವರಗಳು"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ಫೈಲ್ಹೆಸರು"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"ಶೀರ್ಷಿಕೆ"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"ವಿವರವಾದ ವಿವರಣೆ"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"ಬಗ್ ಶೀರ್ಷಿಕೆ"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"ಬಗ್ ಸಾರಾಂಶ"</string>
+ <string name="save" msgid="4781509040564835759">"ಉಳಿಸು"</string>
</resources>
diff --git a/packages/Shell/res/values-ko/strings.xml b/packages/Shell/res/values-ko/strings.xml
index 70df8e2..2a86360 100644
--- a/packages/Shell/res/values-ko/strings.xml
+++ b/packages/Shell/res/values-ko/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"스크린샷을 찍을 수 없습니다."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"버그 신고 <xliff:g id="ID">#%d</xliff:g> 세부정보"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"파일 이름"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"제목"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"자세한 설명"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"버그 제목"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"버그 요약"</string>
+ <string name="save" msgid="4781509040564835759">"저장"</string>
</resources>
diff --git a/packages/Shell/res/values-ky-rKG/strings.xml b/packages/Shell/res/values-ky-rKG/strings.xml
index 49d8d8d..1903109 100644
--- a/packages/Shell/res/values-ky-rKG/strings.xml
+++ b/packages/Shell/res/values-ky-rKG/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Скриншот тартылбай койду."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Мүчүлүштүк тууралуу билдирүүнүн <xliff:g id="ID">#%d</xliff:g> чоо-жайы"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Файлдын аталышы"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Аталышы"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Кененирээк маалымат"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Мүчүлүштүктүн аталышы"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Мүчүлүштүктүн корутундусу"</string>
+ <string name="save" msgid="4781509040564835759">"Сактоо"</string>
</resources>
diff --git a/packages/Shell/res/values-lo-rLA/strings.xml b/packages/Shell/res/values-lo-rLA/strings.xml
index 61b06c8..4348250 100644
--- a/packages/Shell/res/values-lo-rLA/strings.xml
+++ b/packages/Shell/res/values-lo-rLA/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"ບໍ່ສາມາດຖ່າຍພາບໜ້າຈໍໄດ້."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ລາຍລະອຽດຂອງລາຍງານຂໍ້ຜິດພາດ <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ຊື່ໄຟລ໌"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"ຊື່"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"ຄຳອະທິບາຍແບບລະອຽດ"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"ຊື່ຂໍ້ຜິດພາດ"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"ສະຫຼຸບຂໍ້ຜິດພາດ"</string>
+ <string name="save" msgid="4781509040564835759">"ບັນທຶກ"</string>
</resources>
diff --git a/packages/Shell/res/values-lt/strings.xml b/packages/Shell/res/values-lt/strings.xml
index 3418213..a714efc 100644
--- a/packages/Shell/res/values-lt/strings.xml
+++ b/packages/Shell/res/values-lt/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Nepavyko padaryti ekrano kopijos."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Išsami informacija apie pranešimą apie riktą (<xliff:g id="ID">#%d</xliff:g>)"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Failo pavadinimas"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Pavadinimas"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Išsamus aprašas"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Rikto pavadinimas"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Rikto suvestinė"</string>
+ <string name="save" msgid="4781509040564835759">"Išsaugoti"</string>
</resources>
diff --git a/packages/Shell/res/values-lv/strings.xml b/packages/Shell/res/values-lv/strings.xml
index 6108716..880d651 100644
--- a/packages/Shell/res/values-lv/strings.xml
+++ b/packages/Shell/res/values-lv/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Nevarēja veikt ekrānuzņēmumu."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Kļūdas pārskats <xliff:g id="ID">#%d</xliff:g>: detalizēta informācija"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Faila nosaukums"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Nosaukums"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Detalizēts apraksts"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Kļūdas nosaukums"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Kļūdas kopsavilkums"</string>
+ <string name="save" msgid="4781509040564835759">"Saglabāt"</string>
</resources>
diff --git a/packages/Shell/res/values-mk-rMK/strings.xml b/packages/Shell/res/values-mk-rMK/strings.xml
index 500196d..478c189 100644
--- a/packages/Shell/res/values-mk-rMK/strings.xml
+++ b/packages/Shell/res/values-mk-rMK/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Не може да се направи слика од екранот."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Детали за извештајот за грешки <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Име на датотека"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Наслов"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Детален опис"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Наслов на грешката"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Преглед на грешката"</string>
+ <string name="save" msgid="4781509040564835759">"Зачувај"</string>
</resources>
diff --git a/packages/Shell/res/values-ml-rIN/strings.xml b/packages/Shell/res/values-ml-rIN/strings.xml
index 696aab2..70e6333 100644
--- a/packages/Shell/res/values-ml-rIN/strings.xml
+++ b/packages/Shell/res/values-ml-rIN/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"സ്ക്രീൻഷോട്ട് എടുക്കാൻ കഴിഞ്ഞില്ല."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ബഗ് റിപ്പോർട്ട് <xliff:g id="ID">#%d</xliff:g> വിശദാംശങ്ങൾ"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ഫയല്നാമം"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"പേര്"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"വിശദമായ വിവരണം"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"ബഗിന്റെ പേര്"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"ബഗ് സംഗ്രഹം"</string>
+ <string name="save" msgid="4781509040564835759">"സംരക്ഷിക്കുക"</string>
</resources>
diff --git a/packages/Shell/res/values-mn-rMN/strings.xml b/packages/Shell/res/values-mn-rMN/strings.xml
index 62d83cb..49196a2 100644
--- a/packages/Shell/res/values-mn-rMN/strings.xml
+++ b/packages/Shell/res/values-mn-rMN/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Дэлгэцийн зураг авах боломжгүй."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Програмд гарсан алдааны мэдээллийн <xliff:g id="ID">#%d</xliff:g>-ны дэлгэрэнгүй"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Файлын нэр"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Гарчиг"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Дэлгэрэнгүй тайлбар"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Алдааны нэр"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Алдааны хураангуй"</string>
+ <string name="save" msgid="4781509040564835759">"Хадгалах"</string>
</resources>
diff --git a/packages/Shell/res/values-mr-rIN/strings.xml b/packages/Shell/res/values-mr-rIN/strings.xml
index e6b2b04..19a8706 100644
--- a/packages/Shell/res/values-mr-rIN/strings.xml
+++ b/packages/Shell/res/values-mr-rIN/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"स्क्रीनशॉट घेणे शक्य झाले नाही."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"दोष अहवाल <xliff:g id="ID">#%d</xliff:g> तपशील"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"फाईलनाव"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"शीर्षक"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"तपशीलवार वर्णन"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"दोष शीर्षक"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"दोष सारांश"</string>
+ <string name="save" msgid="4781509040564835759">"जतन करा"</string>
</resources>
diff --git a/packages/Shell/res/values-ms-rMY/strings.xml b/packages/Shell/res/values-ms-rMY/strings.xml
index 1d04253..c9f5375 100644
--- a/packages/Shell/res/values-ms-rMY/strings.xml
+++ b/packages/Shell/res/values-ms-rMY/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Tangkapan skrin tidak dapat diambil."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Butiran laporan pepijat <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nama fail"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Tajuk"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Perihalan terperinci"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Tajuk pepijat"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Ringkasan pepijat"</string>
+ <string name="save" msgid="4781509040564835759">"Simpan"</string>
</resources>
diff --git a/packages/Shell/res/values-my-rMM/strings.xml b/packages/Shell/res/values-my-rMM/strings.xml
index f63c8c5..4250eda 100644
--- a/packages/Shell/res/values-my-rMM/strings.xml
+++ b/packages/Shell/res/values-my-rMM/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"မျက်နှာပြင် လျှပ်တစ်ပြက်ပုံ မရိုက်နိုင်ပါ"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ချွတ်ယွင်းမှုအစီရင်ခံချက် <xliff:g id="ID">#%d</xliff:g> အသေးစိတ်များ"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ဖိုင်အမည်"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"ခေါင်းစဉ်"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"အသေးစိတ် ဖော်ပြချက်"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"ချွတ်ယွင်းချက် ခေါင်းစဉ်"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"ချွတ်ယွင်းချက် အကျဉ်းချုပ်"</string>
+ <string name="save" msgid="4781509040564835759">"သိမ်းဆည်းပါ"</string>
</resources>
diff --git a/packages/Shell/res/values-nb/strings.xml b/packages/Shell/res/values-nb/strings.xml
index 328e8ae..aa86ae4 100644
--- a/packages/Shell/res/values-nb/strings.xml
+++ b/packages/Shell/res/values-nb/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Skjermdumpen kunne ikke tas."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detaljer om feilrapporten <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Filnavn"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Tittel"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Detaljert beskrivelse"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Navn på feil"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Oppsummering av feil"</string>
+ <string name="save" msgid="4781509040564835759">"Lagre"</string>
</resources>
diff --git a/packages/Shell/res/values-ne-rNP/strings.xml b/packages/Shell/res/values-ne-rNP/strings.xml
index 62bfead..43c2a5c 100644
--- a/packages/Shell/res/values-ne-rNP/strings.xml
+++ b/packages/Shell/res/values-ne-rNP/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"स्क्रिनशट लिन सकिएन।"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"बग रिपोर्ट <xliff:g id="ID">#%d</xliff:g>का विवरणहरू"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"फाइलको नाम"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"शीर्षक"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"विस्तृत विवरण"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"बगको शीर्षक"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"बगको सारांश"</string>
+ <string name="save" msgid="4781509040564835759">"सुरक्षित गर्नुहोस्"</string>
</resources>
diff --git a/packages/Shell/res/values-nl/strings.xml b/packages/Shell/res/values-nl/strings.xml
index 2f4b215..01fd577 100644
--- a/packages/Shell/res/values-nl/strings.xml
+++ b/packages/Shell/res/values-nl/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Screenshot kan niet worden gemaakt."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Details van bugrapport <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Bestandsnaam"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Titel"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Gedetailleerde beschrijving"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Titel van bug"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Overzicht van bug"</string>
+ <string name="save" msgid="4781509040564835759">"Opslaan"</string>
</resources>
diff --git a/packages/Shell/res/values-pa-rIN/strings.xml b/packages/Shell/res/values-pa-rIN/strings.xml
index dc2277f..3494199 100644
--- a/packages/Shell/res/values-pa-rIN/strings.xml
+++ b/packages/Shell/res/values-pa-rIN/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਨਹੀਂ ਲਿਆ ਜਾ ਸਕਿਆ।"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ਬੱਗ ਰਿਪੋਰਟ <xliff:g id="ID">#%d</xliff:g> ਵੇਰਵੇ"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ਫ਼ਾਈਲ ਨਾਮ"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"ਸਿਰਲੇਖ"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"ਵਿਸਥਾਰ ਸਹਿਤ ਵਰਣਨ"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"ਬੱਗ ਸਿਰਲੇਖ"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"ਬੱਗ ਸਾਰਾਂਸ਼"</string>
+ <string name="save" msgid="4781509040564835759">"ਰੱਖਿਅਤ ਕਰੋ"</string>
</resources>
diff --git a/packages/Shell/res/values-pl/strings.xml b/packages/Shell/res/values-pl/strings.xml
index c585568..91934c9 100644
--- a/packages/Shell/res/values-pl/strings.xml
+++ b/packages/Shell/res/values-pl/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Nie udało się zrobić zrzutu ekranu."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Szczegóły raportu o błędzie <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nazwa pliku"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Tytuł"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Szczegółowy opis"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Tytuł raportu o błędzie"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Podsumowanie raportu o błędzie"</string>
+ <string name="save" msgid="4781509040564835759">"Zapisz"</string>
</resources>
diff --git a/packages/Shell/res/values-pt-rBR/strings.xml b/packages/Shell/res/values-pt-rBR/strings.xml
index fc6e21c..41f4e24 100644
--- a/packages/Shell/res/values-pt-rBR/strings.xml
+++ b/packages/Shell/res/values-pt-rBR/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Não foi possível fazer a captura de tela."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalhes do relatório de bugs <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nome do arquivo"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Título"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Descrição detalhada"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Título do bug"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Resumo do bug"</string>
+ <string name="save" msgid="4781509040564835759">"Salvar"</string>
</resources>
diff --git a/packages/Shell/res/values-pt-rPT/strings.xml b/packages/Shell/res/values-pt-rPT/strings.xml
index 252edb1..416db80 100644
--- a/packages/Shell/res/values-pt-rPT/strings.xml
+++ b/packages/Shell/res/values-pt-rPT/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Não foi possível tirar a captura de ecrã."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalhes do relatório de erro <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nome do ficheiro"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Título"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Descrição detalhada"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Título do erro"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Resumo de erros"</string>
+ <string name="save" msgid="4781509040564835759">"Guardar"</string>
</resources>
diff --git a/packages/Shell/res/values-pt/strings.xml b/packages/Shell/res/values-pt/strings.xml
index fc6e21c..41f4e24 100644
--- a/packages/Shell/res/values-pt/strings.xml
+++ b/packages/Shell/res/values-pt/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Não foi possível fazer a captura de tela."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalhes do relatório de bugs <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nome do arquivo"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Título"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Descrição detalhada"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Título do bug"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Resumo do bug"</string>
+ <string name="save" msgid="4781509040564835759">"Salvar"</string>
</resources>
diff --git a/packages/Shell/res/values-ro/strings.xml b/packages/Shell/res/values-ro/strings.xml
index d720417..4112e60 100644
--- a/packages/Shell/res/values-ro/strings.xml
+++ b/packages/Shell/res/values-ro/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Captura de ecran nu a putut fi făcută."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detaliile raportului de eroare <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Numele fișierului"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Titlu"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Descriere detaliată"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Titlul erorii"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Rezumat privind eroarea"</string>
+ <string name="save" msgid="4781509040564835759">"Salvați"</string>
</resources>
diff --git a/packages/Shell/res/values-ru/strings.xml b/packages/Shell/res/values-ru/strings.xml
index ed5ecaf..ffd2e66 100644
--- a/packages/Shell/res/values-ru/strings.xml
+++ b/packages/Shell/res/values-ru/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Не удалось сделать скриншот"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Данные отчета об ошибке <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Название файла"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Название"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Подробное описание"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Название ошибки"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Описание ошибки"</string>
+ <string name="save" msgid="4781509040564835759">"Сохранить"</string>
</resources>
diff --git a/packages/Shell/res/values-si-rLK/strings.xml b/packages/Shell/res/values-si-rLK/strings.xml
index cd8fba3..807ebb1 100644
--- a/packages/Shell/res/values-si-rLK/strings.xml
+++ b/packages/Shell/res/values-si-rLK/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"තිර රුවක් ගත නොහැකි විය."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"දෝෂ වාර්තා <xliff:g id="ID">#%d</xliff:g> විස්තර"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ගොනුවේ නම"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"මාතෘකාව"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"සවිස්තර විස්තරය"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"දෝෂ මාතෘකාව"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"දෝෂ සාරාංශය"</string>
+ <string name="save" msgid="4781509040564835759">"සුරකින්න"</string>
</resources>
diff --git a/packages/Shell/res/values-sk/strings.xml b/packages/Shell/res/values-sk/strings.xml
index 23e67f5..a62a6eb 100644
--- a/packages/Shell/res/values-sk/strings.xml
+++ b/packages/Shell/res/values-sk/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Snímku obrazovky sa nepodarilo zaznamenať."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Podrobnosti hlásenia chyby <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Názov súboru"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Názov"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Podrobný popis"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Názov chyby"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Súhrn chyby"</string>
+ <string name="save" msgid="4781509040564835759">"Uložiť"</string>
</resources>
diff --git a/packages/Shell/res/values-sl/strings.xml b/packages/Shell/res/values-sl/strings.xml
index 519f3f2..6d1be5a 100644
--- a/packages/Shell/res/values-sl/strings.xml
+++ b/packages/Shell/res/values-sl/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Posnetka zaslon ni bilo mogoče ustvariti."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Podrobnosti poročila o napaki <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Ime datoteke"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Naslov"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Podroben opis"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Naslov poročila o napakah"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Povzetek poročila o napakah"</string>
+ <string name="save" msgid="4781509040564835759">"Shrani"</string>
</resources>
diff --git a/packages/Shell/res/values-sq-rAL/strings.xml b/packages/Shell/res/values-sq-rAL/strings.xml
index 5e3c706..ce990e9 100644
--- a/packages/Shell/res/values-sq-rAL/strings.xml
+++ b/packages/Shell/res/values-sq-rAL/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Pamja e ekranit nuk mund të realizohej."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detajet e raportit të defekteve në kod <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Emri i skedarit"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Titulli"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Përshkrimi i detajuar"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Titulli i defektit në kod"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Përmbledhja e defekteve në kod"</string>
+ <string name="save" msgid="4781509040564835759">"Ruaj"</string>
</resources>
diff --git a/packages/Shell/res/values-sr/strings.xml b/packages/Shell/res/values-sr/strings.xml
index 55119b6..0157a25 100644
--- a/packages/Shell/res/values-sr/strings.xml
+++ b/packages/Shell/res/values-sr/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Снимање екрана није успело."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Детаљи извештаја о грешци <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Назив датотеке"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Наслов"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Детаљни опис"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Наслов грешке"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Резиме грешке"</string>
+ <string name="save" msgid="4781509040564835759">"Сачувај"</string>
</resources>
diff --git a/packages/Shell/res/values-sv/strings.xml b/packages/Shell/res/values-sv/strings.xml
index 085f57e..88af0db 100644
--- a/packages/Shell/res/values-sv/strings.xml
+++ b/packages/Shell/res/values-sv/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Det gick inte att ta skrämdump."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Information för felrapporten <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Filnamn"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Namn"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Detaljerad beskrivning"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Felets titel"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Sammanfattning av felet"</string>
+ <string name="save" msgid="4781509040564835759">"Spara"</string>
</resources>
diff --git a/packages/Shell/res/values-sw/strings.xml b/packages/Shell/res/values-sw/strings.xml
index c5a8ef1..01df55e 100644
--- a/packages/Shell/res/values-sw/strings.xml
+++ b/packages/Shell/res/values-sw/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Haikupiga picha ya skrini."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Maelezo ya ripoti ya hitilafu ya <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Jina la faili"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Kichwa"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Maelezo ya kina"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Jina la hitilafu"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Muhtasari wa hitilafu"</string>
+ <string name="save" msgid="4781509040564835759">"Hifadhi"</string>
</resources>
diff --git a/packages/Shell/res/values-ta-rIN/strings.xml b/packages/Shell/res/values-ta-rIN/strings.xml
index 7ef89e2..8238d25 100644
--- a/packages/Shell/res/values-ta-rIN/strings.xml
+++ b/packages/Shell/res/values-ta-rIN/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"ஸ்கிரீன் ஷாட்டை எடுக்க முடியவில்லை."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"பிழை அறிக்கை <xliff:g id="ID">#%d</xliff:g> இன் விவரங்கள்"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"கோப்புப்பெயர்"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"தலைப்பு"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"விரிவான விளக்கம்"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"பிழைத் தலைப்பு"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"பிழை குறித்த சுருக்க விவரம்"</string>
+ <string name="save" msgid="4781509040564835759">"சேமி"</string>
</resources>
diff --git a/packages/Shell/res/values-te-rIN/strings.xml b/packages/Shell/res/values-te-rIN/strings.xml
index 6ba816b..3ed1f95 100644
--- a/packages/Shell/res/values-te-rIN/strings.xml
+++ b/packages/Shell/res/values-te-rIN/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"స్క్రీన్షాట్ను తీయడం సాధ్యపడలేదు."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"బగ్ నివేదిక <xliff:g id="ID">#%d</xliff:g> వివరాలు"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ఫైల్ పేరు"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"శీర్షిక"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"సమగ్ర వివరణ"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"బగ్ శీర్షిక"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"బగ్ సారాంశం"</string>
+ <string name="save" msgid="4781509040564835759">"సేవ్ చేయి"</string>
</resources>
diff --git a/packages/Shell/res/values-th/strings.xml b/packages/Shell/res/values-th/strings.xml
index d68ca26..f28bac6 100644
--- a/packages/Shell/res/values-th/strings.xml
+++ b/packages/Shell/res/values-th/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"ไม่สามารถจับภาพหน้าจอได้"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"รายละเอียดรายงานข้อบกพร่อง <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ชื่อไฟล์"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"ชื่อ"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"คำอธิบายโดยละเอียด"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"ชื่อข้อบกพร่อง"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"สรุปข้อบกพร่อง"</string>
+ <string name="save" msgid="4781509040564835759">"บันทึก"</string>
</resources>
diff --git a/packages/Shell/res/values-tl/strings.xml b/packages/Shell/res/values-tl/strings.xml
index 432eb90..d270401 100644
--- a/packages/Shell/res/values-tl/strings.xml
+++ b/packages/Shell/res/values-tl/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Hindi makunan ng screenshot."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Mga detalye ng ulat ng bug na <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Filename"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Pamagat"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Detalyadong paglalarawan"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Pamagat ng bug"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Buod ng bug"</string>
+ <string name="save" msgid="4781509040564835759">"I-save"</string>
</resources>
diff --git a/packages/Shell/res/values-tr/strings.xml b/packages/Shell/res/values-tr/strings.xml
index dae377f..6da3490 100644
--- a/packages/Shell/res/values-tr/strings.xml
+++ b/packages/Shell/res/values-tr/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Ekran görüntüsü alınamadı."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Hata raporu (<xliff:g id="ID">#%d</xliff:g>) ayrıntıları"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Dosya adı"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Başlık"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Ayrıntılı açıklama"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Hata başlığı"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Hata özeti"</string>
+ <string name="save" msgid="4781509040564835759">"Kaydet"</string>
</resources>
diff --git a/packages/Shell/res/values-uk/strings.xml b/packages/Shell/res/values-uk/strings.xml
index 02eeb2f..00a7793 100644
--- a/packages/Shell/res/values-uk/strings.xml
+++ b/packages/Shell/res/values-uk/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Не вдалося зробити знімок екрана."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Деталі повідомлення про помилку <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Назва файлу"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Назва"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Детальний опис"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Назва помилки"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Опис помилки"</string>
+ <string name="save" msgid="4781509040564835759">"Зберегти"</string>
</resources>
diff --git a/packages/Shell/res/values-ur-rPK/strings.xml b/packages/Shell/res/values-ur-rPK/strings.xml
index 23cada6..abf6940 100644
--- a/packages/Shell/res/values-ur-rPK/strings.xml
+++ b/packages/Shell/res/values-ur-rPK/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"سکرین شاٹ نہیں لیا جا سکا۔"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"بگ رپورٹ <xliff:g id="ID">#%d</xliff:g> کی تفصیلات"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"فائل کا نام"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"عنوان"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"تفصیلی وضاحت"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"بَگ کا عنوان"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"بَگ کا خلاصہ"</string>
+ <string name="save" msgid="4781509040564835759">"محفوظ کریں"</string>
</resources>
diff --git a/packages/Shell/res/values-uz-rUZ/strings.xml b/packages/Shell/res/values-uz-rUZ/strings.xml
index 39703a2..7782b42 100644
--- a/packages/Shell/res/values-uz-rUZ/strings.xml
+++ b/packages/Shell/res/values-uz-rUZ/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Skrinshot olib bo‘lmadi."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Xatoliklar hisoboti (<xliff:g id="ID">#%d</xliff:g>) tafsilotlari"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Fayl nomi"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Nomi"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Batafsil ta’rif"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Xatolik nomi"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Xatolik ta’rifi"</string>
+ <string name="save" msgid="4781509040564835759">"Saqlash"</string>
</resources>
diff --git a/packages/Shell/res/values-vi/strings.xml b/packages/Shell/res/values-vi/strings.xml
index 16ffaff..27a9c7f 100644
--- a/packages/Shell/res/values-vi/strings.xml
+++ b/packages/Shell/res/values-vi/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Không thể chụp ảnh màn hình."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Chi tiết báo cáo lỗi <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Tên tệp"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Tiêu đề"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Mô tả chi tiết"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Tiêu đề lỗi"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Tóm tắt lỗi"</string>
+ <string name="save" msgid="4781509040564835759">"Lưu"</string>
</resources>
diff --git a/packages/Shell/res/values-zh-rCN/strings.xml b/packages/Shell/res/values-zh-rCN/strings.xml
index 382478e..65cfbbc 100644
--- a/packages/Shell/res/values-zh-rCN/strings.xml
+++ b/packages/Shell/res/values-zh-rCN/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"无法截图。"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"错误报告 <xliff:g id="ID">#%d</xliff:g> 详情"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"文件名"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"标题"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"详细说明"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"错误标题"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"错误摘要"</string>
+ <string name="save" msgid="4781509040564835759">"保存"</string>
</resources>
diff --git a/packages/Shell/res/values-zh-rHK/strings.xml b/packages/Shell/res/values-zh-rHK/strings.xml
index 04b5e48..34a849e 100644
--- a/packages/Shell/res/values-zh-rHK/strings.xml
+++ b/packages/Shell/res/values-zh-rHK/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"無法擷取螢幕畫面。"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"錯誤報告 <xliff:g id="ID">#%d</xliff:g> 的詳情"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"檔案名稱"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"標題"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"詳細說明"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"錯誤標題"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"錯誤摘要"</string>
+ <string name="save" msgid="4781509040564835759">"儲存"</string>
</resources>
diff --git a/packages/Shell/res/values-zh-rTW/strings.xml b/packages/Shell/res/values-zh-rTW/strings.xml
index 7a1ab77..fff73bb 100644
--- a/packages/Shell/res/values-zh-rTW/strings.xml
+++ b/packages/Shell/res/values-zh-rTW/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"無法拍攝螢幕擷取畫面。"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"錯誤報告 <xliff:g id="ID">#%d</xliff:g> 的詳細資料"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"檔案名稱"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"標題"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"詳細說明"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"錯誤標題"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"錯誤摘要"</string>
+ <string name="save" msgid="4781509040564835759">"儲存"</string>
</resources>
diff --git a/packages/Shell/res/values-zu/strings.xml b/packages/Shell/res/values-zu/strings.xml
index 29b7dd83..868de3e 100644
--- a/packages/Shell/res/values-zu/strings.xml
+++ b/packages/Shell/res/values-zu/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Isithombe-skrini asikwazanga ukuthathwa."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Imininingwane yombiko wesiphazamisi ongu-<xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Igama lefayela"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Isihloko"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Incazelo enemininingwane"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Isihloko sesiphazamisi"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Isifinyezo sesiphazamisi"</string>
+ <string name="save" msgid="4781509040564835759">"Londoloza"</string>
</resources>
diff --git a/packages/Shell/res/values/strings.xml b/packages/Shell/res/values/strings.xml
index c26b549..38ea880 100644
--- a/packages/Shell/res/values/strings.xml
+++ b/packages/Shell/res/values/strings.xml
@@ -59,13 +59,16 @@
<!-- Title of the dialog asking for user-defined bug report details like name, title, and description. -->
<string name="bugreport_info_dialog_title">Bug report <xliff:g id="id">#%d</xliff:g> details</string>
- <!-- Text of the hint asking for the bug report name, which when set will define a suffix in the
+ <!-- Text of the label identifying the bug report name, which when set will define a suffix in the
bug report file names. [CHAR LIMIT=30] -->
<string name="bugreport_info_name">Filename</string>
- <!-- Text of hint asking for the bug report title, which when set will define the
+ <!-- Text of the label identifying the bug report title, which when set will define the
Subject of the email message. [CHAR LIMIT=60] -->
- <string name="bugreport_info_title">Title</string>
- <!-- Text of hint asking for the bug report description, which when set will describe
+ <string name="bugreport_info_title">Bug title</string>
+ <!-- Text of the label identifying the bug report description, which when set will describe
what the bug report is about. [CHAR LIMIT=NONE] -->
- <string name="bugreport_info_description">Detailed description</string>
+ <string name="bugreport_info_description">Bug summary</string>
+
+ <!-- Label of button that save bugreport details. -->
+ <string name="save">Save</string>
</resources>
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 9926ae5..0b52588 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -41,6 +41,8 @@
import libcore.io.Streams;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.google.android.collect.Lists;
import android.accounts.Account;
@@ -147,6 +149,9 @@
private static final int MSG_SCREENSHOT_REQUEST = 4;
private static final int MSG_SCREENSHOT_RESPONSE = 5;
+ // Passed to Message.obtain() when msg.arg2 is not used.
+ private static final int UNUSED_ARG2 = -2;
+
/**
* Delay before a screenshot is taken.
* <p>
@@ -300,8 +305,7 @@
}
final String action = intent.getAction();
final int pid = intent.getIntExtra(EXTRA_PID, 0);
- // TODO: temporarily using pid as id until test cases and dumpstate are changed.
- final int id = intent.getIntExtra(EXTRA_ID, pid);
+ final int id = intent.getIntExtra(EXTRA_ID, 0);
final int max = intent.getIntExtra(EXTRA_MAX, -1);
final String name = intent.getStringExtra(EXTRA_NAME);
@@ -432,10 +436,12 @@
final Intent infoIntent = new Intent(mContext, BugreportProgressService.class);
infoIntent.setAction(INTENT_BUGREPORT_INFO_LAUNCH);
infoIntent.putExtra(EXTRA_ID, info.id);
+ final PendingIntent infoPendingIntent =
+ PendingIntent.getService(mContext, info.id, infoIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT);
final Action infoAction = new Action.Builder(null,
mContext.getString(R.string.bugreport_info_action),
- PendingIntent.getService(mContext, info.id, infoIntent,
- PendingIntent.FLAG_UPDATE_CURRENT)).build();
+ infoPendingIntent).build();
final Intent screenshotIntent = new Intent(mContext, BugreportProgressService.class);
screenshotIntent.setAction(INTENT_BUGREPORT_SCREENSHOT);
screenshotIntent.putExtra(EXTRA_ID, info.id);
@@ -462,6 +468,7 @@
.setLocalOnly(true)
.setColor(mContext.getColor(
com.android.internal.R.color.system_notification_accent_color))
+ .setContentIntent(infoPendingIntent)
.addAction(infoAction)
.addAction(screenshotAction)
.addAction(cancelAction)
@@ -472,7 +479,10 @@
+ info + ")");
return;
}
- Log.v(TAG, "Sending 'Progress' notification for id " + info.id + ": " + percentText);
+ if (DEBUG) {
+ Log.d(TAG, "Sending 'Progress' notification for id " + info.id + "(pid " + info.pid
+ + "): " + percentText);
+ }
NotificationManager.from(mContext).notify(TAG, info.id, notification);
}
@@ -506,6 +516,7 @@
* Cancels a bugreport upon user's request.
*/
private void cancel(int id) {
+ MetricsLogger.action(this, MetricsEvent.ACTION_BUGREPORT_NOTIFICATION_ACTION_CANCEL);
Log.v(TAG, "cancel: ID=" + id);
final BugreportInfo info = getInfo(id);
if (info != null && !info.finished) {
@@ -538,7 +549,7 @@
final int pid = info.pid;
final int id = info.id;
if (info.finished) {
- if (DEBUG) Log.v(TAG, "Skipping finished process " + pid + "(id: " + id + ")");
+ if (DEBUG) Log.v(TAG, "Skipping finished process " + pid + " (id: " + id + ")");
continue;
}
activeProcesses++;
@@ -582,6 +593,7 @@
* change its values.
*/
private void launchBugreportInfoDialog(int id) {
+ MetricsLogger.action(this, MetricsEvent.ACTION_BUGREPORT_NOTIFICATION_ACTION_DETAILS);
// Copy values so it doesn't lock mProcesses while UI is being updated
final String name, title, description;
final BugreportInfo info = getInfo(id);
@@ -589,7 +601,8 @@
// Most likely am killed Shell before user tapped the notification. Since system might
// be too busy anwyays, it's better to ignore the notification and switch back to the
// non-interactive mode (where the bugerport will be shared upon completion).
- Log.d(TAG, "launchBugreportInfoDialog(" + id + "): cancel notification");
+ Log.w(TAG, "launchBugreportInfoDialog(): canceling notification because id " + id
+ + " was not found");
// TODO: add test case to make sure notification is canceled.
NotificationManager.from(mContext).cancel(TAG, id);
return;
@@ -610,11 +623,13 @@
* upon receiving a {@link #INTENT_BUGREPORT_STARTED}.
*/
private void takeScreenshot(int id, boolean delayed) {
+ MetricsLogger.action(this, MetricsEvent.ACTION_BUGREPORT_NOTIFICATION_ACTION_SCREENSHOT);
if (getInfo(id) == null) {
// Most likely am killed Shell before user tapped the notification. Since system might
// be too busy anwyays, it's better to ignore the notification and switch back to the
// non-interactive mode (where the bugerport will be shared upon completion).
- Log.d(TAG, "takeScreenshot(" + id + ", " + delayed + "): cancel notification");
+ Log.w(TAG, "takeScreenshot(): canceling notification because id " + id
+ + " was not found");
// TODO: add test case to make sure notification is canceled.
NotificationManager.from(mContext).cancel(TAG, id);
return;
@@ -657,11 +672,8 @@
final String screenshotPath =
new File(mScreenshotsDir, info.getPathNextScreenshot()).getAbsolutePath();
- final Message requestMsg = new Message();
- requestMsg.what = MSG_SCREENSHOT_REQUEST;
- requestMsg.arg1 = id;
- requestMsg.obj = screenshotPath;
- mScreenshotHandler.sendMessage(requestMsg);
+ Message.obtain(mScreenshotHandler, MSG_SCREENSHOT_REQUEST, id, UNUSED_ARG2, screenshotPath)
+ .sendToTarget();
}
/**
@@ -687,12 +699,8 @@
boolean taken = takeScreenshot(mContext, screenshotFile);
setTakingScreenshot(false);
- final Message resultMsg = new Message();
- resultMsg.what = MSG_SCREENSHOT_RESPONSE;
- resultMsg.arg1 = requestMsg.arg1;
- resultMsg.arg2 = taken ? 1 : 0;
- resultMsg.obj = screenshotFile;
- mMainHandler.sendMessage(resultMsg);
+ Message.obtain(mMainHandler, MSG_SCREENSHOT_RESPONSE, requestMsg.arg1, taken ? 1 : 0,
+ screenshotFile).sendToTarget();
}
private void handleScreenshotResponse(Message resultMsg) {
@@ -703,7 +711,7 @@
}
final File screenshotFile = new File((String) resultMsg.obj);
- final int msgId;
+ final String msg;
if (taken) {
info.addScreenshot(screenshotFile);
if (info.finished) {
@@ -711,14 +719,13 @@
info.renameScreenshots(mScreenshotsDir);
sendBugreportNotification(mContext, info);
}
- msgId = R.string.bugreport_screenshot_taken;
+ msg = mContext.getString(R.string.bugreport_screenshot_taken);
} else {
// TODO: try again using Framework APIs instead of relying on screencap.
- msgId = R.string.bugreport_screenshot_failed;
+ msg = mContext.getString(R.string.bugreport_screenshot_failed);
+ Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show();
}
- final String msg = mContext.getString(msgId);
Log.d(TAG, msg);
- Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show();
}
/**
@@ -764,6 +771,12 @@
info.renameScreenshots(mScreenshotsDir);
info.bugreportFile = bugreportFile;
+ final int max = intent.getIntExtra(EXTRA_MAX, -1);
+ if (max != -1) {
+ MetricsLogger.histogram(this, "dumpstate_duration", max);
+ info.max = max;
+ }
+
final File screenshot = getFileExtra(intent, EXTRA_SCREENSHOT);
if (screenshot != null) {
info.addScreenshot(screenshot);
@@ -859,6 +872,7 @@
* intent, but issuing a warning dialog the first time.
*/
private void shareBugreport(int id, BugreportInfo sharedInfo) {
+ MetricsLogger.action(this, MetricsEvent.ACTION_BUGREPORT_NOTIFICATION_ACTION_SHARE);
BugreportInfo info = getInfo(id);
if (info == null) {
// Service was terminated but notification persisted
@@ -1113,7 +1127,7 @@
private static boolean setSystemProperty(String key, String value) {
try {
- if (DEBUG) Log.v(TAG, "Setting system property" + key + " to " + value);
+ if (DEBUG) Log.v(TAG, "Setting system property " + key + " to " + value);
SystemProperties.set(key, value);
} catch (IllegalArgumentException e) {
Log.e(TAG, "Could not set property " + key + " to " + value, e);
@@ -1139,9 +1153,16 @@
if (info == null) {
return;
}
+ if (title != null && !title.equals(info.title)) {
+ MetricsLogger.action(this, MetricsEvent.ACTION_BUGREPORT_DETAILS_TITLE_CHANGED);
+ }
info.title = title;
+ if (description != null && !description.equals(info.description)) {
+ MetricsLogger.action(this, MetricsEvent.ACTION_BUGREPORT_DETAILS_DESCRIPTION_CHANGED);
+ }
info.description = description;
if (name != null && !name.equals(info.name)) {
+ MetricsLogger.action(this, MetricsEvent.ACTION_BUGREPORT_DETAILS_NAME_CHANGED);
info.name = name;
updateProgress(info);
}
@@ -1229,7 +1250,9 @@
/**
* Sets its internal state and displays the dialog.
*/
- private void initialize(Context context, BugreportInfo info) {
+ private void initialize(final Context context, BugreportInfo info) {
+ final String dialogTitle =
+ context.getString(R.string.bugreport_info_dialog_title, info.id);
// First initializes singleton.
if (mDialog == null) {
@SuppressLint("InflateParams")
@@ -1247,15 +1270,18 @@
if (hasFocus) {
return;
}
+ // Select-all is useful just initially, since the date-based filename is
+ // full of hyphens.
+ mInfoName.setSelectAllOnFocus(false);
sanitizeName();
}
});
mDialog = new AlertDialog.Builder(context)
.setView(view)
- .setTitle(context.getString(R.string.bugreport_info_dialog_title, info.id))
+ .setTitle(dialogTitle)
.setCancelable(false)
- .setPositiveButton(context.getString(com.android.internal.R.string.ok),
+ .setPositiveButton(context.getString(R.string.save),
null)
.setNegativeButton(context.getString(com.android.internal.R.string.cancel),
new DialogInterface.OnClickListener()
@@ -1263,6 +1289,8 @@
@Override
public void onClick(DialogInterface dialog, int id)
{
+ MetricsLogger.action(context,
+ MetricsEvent.ACTION_BUGREPORT_DETAILS_CANCELED);
if (!mTempName.equals(mSavedName)) {
// Must restore dumpstate's name since it was changed
// before user clicked OK.
@@ -1276,6 +1304,12 @@
new WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG));
+ } else {
+ // Re-use view, but reset fields first.
+ mDialog.setTitle(dialogTitle);
+ mInfoName.setText(null);
+ mInfoTitle.setText(null);
+ mInfoDescription.setText(null);
}
// Then set fields.
@@ -1307,6 +1341,7 @@
@Override
public void onClick(View view) {
+ MetricsLogger.action(context, MetricsEvent.ACTION_BUGREPORT_DETAILS_SAVED);
sanitizeName();
final String name = mInfoName.getText().toString();
final String title = mInfoTitle.getText().toString();
@@ -1350,7 +1385,7 @@
// Must update system property for the cases where dumpstate finishes
// while the user is still entering other fields (like title or
// description)
- setBugreportNameProperty(mId, name);
+ setBugreportNameProperty(mPid, name);
}
/**
@@ -1495,7 +1530,7 @@
final List<File> renamedFiles = new ArrayList<>(screenshotFiles.size());
for (File oldFile : screenshotFiles) {
final String oldName = oldFile.getName();
- final String newName = oldName.replace(Integer.toString(pid), name);
+ final String newName = oldName.replaceFirst(Integer.toString(pid), name);
final File newFile;
if (!newName.equals(oldName)) {
final File renamedFile = new File(screenshotDir, newName);
@@ -1525,7 +1560,7 @@
return "id: " + id + ", pid: " + pid + ", name: " + name + ", finished: " + finished
+ "\n\ttitle: " + title + "\n\tdescription: " + description
+ "\n\tfile: " + bugreportFile + "\n\tscreenshots: " + screenshotFiles
- + "\n\tprogress: " + progress + "/" + max + "(" + percent + ")"
+ + "\n\tprogress: " + progress + "/" + max + " (" + percent + ")"
+ "\n\tlast_update: " + getFormattedLastUpdate()
+ "\naddingDetailsToZip: " + addingDetailsToZip
+ " addedDetailsToZip: " + addedDetailsToZip;
diff --git a/packages/Shell/src/com/android/shell/BugreportStorageProvider.java b/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
index 814aa8c..49759c5 100644
--- a/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
+++ b/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
@@ -56,7 +56,7 @@
final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
final RowBuilder row = result.newRow();
row.add(Root.COLUMN_ROOT_ID, DOC_ID_ROOT);
- row.add(Root.COLUMN_FLAGS, Root.FLAG_LOCAL_ONLY | Root.FLAG_ADVANCED);
+ row.add(Root.COLUMN_FLAGS, Root.FLAG_LOCAL_ONLY);
row.add(Root.COLUMN_ICON, android.R.mipmap.sym_def_app_icon);
row.add(Root.COLUMN_TITLE, getContext().getString(R.string.bugreport_storage_title));
row.add(Root.COLUMN_DOCUMENT_ID, DOC_ID_ROOT);
diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
index 8c62670..a629aac 100644
--- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
+++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
@@ -19,6 +19,7 @@
import static android.test.MoreAsserts.assertContainsRegex;
import static com.android.shell.ActionSendMultipleConsumerActivity.UI_NAME;
import static com.android.shell.BugreportProgressService.EXTRA_BUGREPORT;
+import static com.android.shell.BugreportProgressService.EXTRA_ID;
import static com.android.shell.BugreportProgressService.EXTRA_MAX;
import static com.android.shell.BugreportProgressService.EXTRA_NAME;
import static com.android.shell.BugreportProgressService.EXTRA_PID;
@@ -60,6 +61,7 @@
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.support.test.uiautomator.UiSelector;
import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import android.text.TextUtils;
@@ -98,24 +100,33 @@
private static final String BUGREPORTS_DIR = "bugreports";
private static final String BUGREPORT_FILE = "test_bugreport.txt";
private static final String ZIP_FILE = "test_bugreport.zip";
+ private static final String ZIP_FILE2 = "test_bugreport2.zip";
private static final String SCREENSHOT_FILE = "test_screenshot.png";
private static final String BUGREPORT_CONTENT = "Dump, might as well dump!\n";
private static final String SCREENSHOT_CONTENT = "A picture is worth a thousand words!\n";
private static final int PID = 42;
- private static final String PROGRESS_PROPERTY = "dumpstate.42.progress";
- private static final String MAX_PROPERTY = "dumpstate.42.max";
- private static final String NAME_PROPERTY = "dumpstate.42.name";
+ private static final int PID2 = 24;
+ private static final int ID = 108;
+ private static final int ID2 = 801;
+ private static final String PROGRESS_PROPERTY = "dumpstate." + PID + ".progress";
+ private static final String MAX_PROPERTY = "dumpstate." + PID + ".max";
+ private static final String NAME_PROPERTY = "dumpstate." + PID + ".name";
private static final String NAME = "BUG, Y U NO REPORT?";
+ private static final String NAME2 = "A bugreport's life";
private static final String NEW_NAME = "Bug_Forrest_Bug";
+ private static final String NEW_NAME2 = "BugsyReportsy";
private static final String TITLE = "Wimbugdom Champion 2015";
+ private static final String TITLE2 = "Master of the Universe";
+ private static final String DESCRIPTION = "One's description...";
+ private static final String DESCRIPTION2 = "...is another's treasure.";
private static final String NO_DESCRIPTION = null;
private static final String NO_NAME = null;
private static final String NO_SCREENSHOT = null;
private static final String NO_TITLE = null;
- private static final int NO_PID = 0;
+ private static final int NO_ID = 0;
private static final boolean RENAMED_SCREENSHOTS = true;
private static final boolean DIDNT_RENAME_SCREENSHOTS = false;
@@ -123,6 +134,7 @@
private String mPlainTextPath;
private String mZipPath;
+ private String mZipPath2;
private String mScreenshotPath;
private Context mContext;
@@ -141,10 +153,12 @@
mPlainTextPath = getPath(BUGREPORT_FILE);
mZipPath = getPath(ZIP_FILE);
+ mZipPath2 = getPath(ZIP_FILE2);
mScreenshotPath = getPath(SCREENSHOT_FILE);
createTextFile(mPlainTextPath, BUGREPORT_CONTENT);
createTextFile(mScreenshotPath, SCREENSHOT_CONTENT);
createZipFile(mZipPath, BUGREPORT_FILE, BUGREPORT_CONTENT);
+ createZipFile(mZipPath2, BUGREPORT_FILE, BUGREPORT_CONTENT);
// Creates a multi-line description.
StringBuilder sb = new StringBuilder();
@@ -177,13 +191,32 @@
assertProgressNotification(NAME, nf.format(0.25));
Bundle extras =
- sendBugreportFinishedAndGetSharedIntent(PID, mPlainTextPath, mScreenshotPath);
- assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, PID, ZIP_FILE,
+ sendBugreportFinishedAndGetSharedIntent(ID, mPlainTextPath, mScreenshotPath);
+ assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, ZIP_FILE,
NAME, NO_TITLE, NO_DESCRIPTION, 1, RENAMED_SCREENSHOTS);
assertServiceNotRunning();
}
+ public void testProgress_cancel() throws Exception {
+ resetProperties();
+ sendBugreportStarted(1000);
+ waitForScreenshotButtonEnabled(true);
+
+ final NumberFormat nf = NumberFormat.getPercentInstance();
+ nf.setMinimumFractionDigits(2);
+ nf.setMaximumFractionDigits(2);
+
+ assertProgressNotification(NAME, nf.format(0));
+
+ openProgressNotification(ID);
+ UiObject cancelButton = mUiBot.getVisibleObject(mContext.getString(
+ com.android.internal.R.string.cancel).toUpperCase());
+ mUiBot.click(cancelButton, "cancel_button");
+
+ waitForService(false);
+ }
+
public void testProgress_takeExtraScreenshot() throws Exception {
takeExtraScreenshotTest(false);
}
@@ -201,15 +234,15 @@
assertScreenshotButtonEnabled(false);
waitForScreenshotButtonEnabled(true);
- sendBugreportFinished(PID, mPlainTextPath, mScreenshotPath);
+ sendBugreportFinished(ID, mPlainTextPath, mScreenshotPath);
if (serviceDies) {
- waitShareNotification(PID);
+ waitShareNotification(ID);
killService();
}
- Bundle extras = acceptBugreportAndGetSharedIntent(PID);
- assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, PID, ZIP_FILE,
+ Bundle extras = acceptBugreportAndGetSharedIntent(ID);
+ assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, ZIP_FILE,
NAME, NO_TITLE, NO_DESCRIPTION, 2, RENAMED_SCREENSHOTS);
assertServiceNotRunning();
@@ -227,8 +260,8 @@
resetProperties();
sendBugreportStarted(1000);
- sendBugreportFinished(PID, mPlainTextPath, NO_SCREENSHOT);
- waitShareNotification(PID);
+ sendBugreportFinished(ID, mPlainTextPath, NO_SCREENSHOT);
+ waitShareNotification(ID);
// There's no indication in the UI about the screenshot finish, so just sleep like a baby...
Thread.sleep(SAFE_SCREENSHOT_DELAY * DateUtils.SECOND_IN_MILLIS);
@@ -237,8 +270,8 @@
killService();
}
- Bundle extras = acceptBugreportAndGetSharedIntent(PID);
- assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT, PID, ZIP_FILE,
+ Bundle extras = acceptBugreportAndGetSharedIntent(ID);
+ assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT, ID, PID, ZIP_FILE,
NAME, NO_TITLE, NO_DESCRIPTION, 1, RENAMED_SCREENSHOTS);
assertServiceNotRunning();
@@ -249,11 +282,10 @@
sendBugreportStarted(1000);
waitForScreenshotButtonEnabled(true);
- DetailsUi detailsUi = new DetailsUi(mUiBot, PID);
+ DetailsUi detailsUi = new DetailsUi(mUiBot, ID);
// Check initial name.
- String actualName = detailsUi.nameField.getText().toString();
- assertEquals("Wrong value on field 'name'", NAME, actualName);
+ detailsUi.assertName(NAME);
// Change name - it should have changed system property once focus is changed.
detailsUi.nameField.setText(NEW_NAME);
@@ -281,9 +313,9 @@
assertPropertyValue(NAME_PROPERTY, NEW_NAME);
assertProgressNotification(NEW_NAME, "0.00%");
- Bundle extras = sendBugreportFinishedAndGetSharedIntent(PID, mPlainTextPath,
+ Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID, mPlainTextPath,
mScreenshotPath);
- assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, PID, TITLE,
+ assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, TITLE,
NEW_NAME, TITLE, mDescription, 1, RENAMED_SCREENSHOTS);
assertServiceNotRunning();
@@ -302,11 +334,10 @@
sendBugreportStarted(1000);
waitForScreenshotButtonEnabled(true);
- DetailsUi detailsUi = new DetailsUi(mUiBot, PID);
+ DetailsUi detailsUi = new DetailsUi(mUiBot, ID);
// Check initial name.
- String actualName = detailsUi.nameField.getText().toString();
- assertEquals("Wrong value on field 'name'", NAME, actualName);
+ detailsUi.assertName(NAME);
// Change fields.
detailsUi.reOpen();
@@ -319,33 +350,87 @@
assertPropertyValue(NAME_PROPERTY, NEW_NAME);
assertProgressNotification(NEW_NAME, "0.00%");
- Bundle extras = sendBugreportFinishedAndGetSharedIntent(PID,
+ Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID,
plainText? mPlainTextPath : mZipPath, mScreenshotPath);
- assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, PID, TITLE,
+ assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, TITLE,
NEW_NAME, TITLE, mDescription, 1, RENAMED_SCREENSHOTS);
assertServiceNotRunning();
}
- public void testProgress_changeJustDetails() throws Exception {
+ public void testProgress_changeJustDetailsTouchingDetails() throws Exception {
+ changeJustDetailsTest(true);
+ }
+
+ public void testProgress_changeJustDetailsTouchingNotification() throws Exception {
+ changeJustDetailsTest(false);
+ }
+
+ private void changeJustDetailsTest(boolean touchDetails) throws Exception {
resetProperties();
sendBugreportStarted(1000);
waitForScreenshotButtonEnabled(true);
- DetailsUi detailsUi = new DetailsUi(mUiBot, PID);
+ DetailsUi detailsUi = new DetailsUi(mUiBot, ID, touchDetails);
detailsUi.nameField.setText("");
detailsUi.titleField.setText("");
detailsUi.descField.setText(mDescription);
detailsUi.clickOk();
- Bundle extras = sendBugreportFinishedAndGetSharedIntent(PID, mZipPath, mScreenshotPath);
- assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, PID, ZIP_FILE,
+ Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID, mZipPath, mScreenshotPath);
+ assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, ZIP_FILE,
NO_NAME, NO_TITLE, mDescription, 1, DIDNT_RENAME_SCREENSHOTS);
assertServiceNotRunning();
}
+ /*
+ * TODO: this test can be flanky because it relies in the order the notifications are displayed,
+ * since mUiBot gets the first notification.
+ * Ideally, openProgressNotification() should return the whole notification, so DetailsUi
+ * could use it and find children instead, but unfortunately the notification object hierarchy
+ * is too complex and getting it from the notification text object would be to fragile
+ * (for instance, it could require navigating many parents up in the hierarchy).
+ */
+ public void testProgress_changeJustDetailsIsClearedOnSecondBugreport() throws Exception {
+ resetProperties();
+ sendBugreportStarted(ID, PID, NAME, 1000);
+ waitForScreenshotButtonEnabled(true);
+
+ DetailsUi detailsUi = new DetailsUi(mUiBot, ID);
+ detailsUi.assertName(NAME);
+ detailsUi.assertTitle("");
+ detailsUi.assertDescription("");
+ detailsUi.nameField.setText(NEW_NAME);
+ detailsUi.titleField.setText(TITLE);
+ detailsUi.descField.setText(DESCRIPTION);
+ detailsUi.clickOk();
+
+ sendBugreportStarted(ID2, PID2, NAME2, 1000);
+
+ Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID, mZipPath, mScreenshotPath);
+ assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, TITLE,
+ NEW_NAME, TITLE, DESCRIPTION, 1, RENAMED_SCREENSHOTS);
+
+ detailsUi = new DetailsUi(mUiBot, ID2);
+ detailsUi.assertName(NAME2);
+ detailsUi.assertTitle("");
+ detailsUi.assertDescription("");
+ detailsUi.nameField.setText(NEW_NAME2);
+ detailsUi.titleField.setText(TITLE2);
+ detailsUi.descField.setText(DESCRIPTION2);
+ detailsUi.clickOk();
+
+ // Must use a different zip file otherwise it will fail because zip already contains
+ // title.txt and description.txt entries.
+ extras = sendBugreportFinishedAndGetSharedIntent(ID2, mZipPath2, NO_SCREENSHOT);
+ assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT, ID2, PID2, TITLE2,
+ NEW_NAME2, TITLE2, DESCRIPTION2, 1, RENAMED_SCREENSHOTS);
+
+ assertServiceNotRunning();
+ }
+
/**
* Tests the scenario where the initial screenshot and dumpstate are finished while the user
* is changing the info in the details screen.
@@ -369,14 +454,14 @@
waitForScreenshotButtonEnabled(true);
}
- DetailsUi detailsUi = new DetailsUi(mUiBot, PID);
+ DetailsUi detailsUi = new DetailsUi(mUiBot, ID);
// Finish the bugreport while user's still typing the name.
detailsUi.nameField.setText(NEW_NAME);
- sendBugreportFinished(PID, mPlainTextPath, mScreenshotPath);
+ sendBugreportFinished(ID, mPlainTextPath, mScreenshotPath);
// Wait until the share notification is received...
- waitShareNotification(PID);
+ waitShareNotification(ID);
// ...then close notification bar.
mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
@@ -390,8 +475,8 @@
detailsUi.clickOk();
// Finally, share bugreport.
- Bundle extras = acceptBugreportAndGetSharedIntent(PID);
- assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, PID, TITLE,
+ Bundle extras = acceptBugreportAndGetSharedIntent(ID);
+ assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, TITLE,
NAME, TITLE, mDescription, 1, RENAMED_SCREENSHOTS);
assertServiceNotRunning();
@@ -402,8 +487,8 @@
BugreportPrefs.setWarningState(mContext, BugreportPrefs.STATE_SHOW);
// Send notification and click on share.
- sendBugreportFinished(NO_PID, mPlainTextPath, null);
- acceptBugreport(NO_PID);
+ sendBugreportFinished(NO_ID, mPlainTextPath, null);
+ acceptBugreport(NO_ID);
// Handle the warning
mUiBot.getVisibleObject(mContext.getString(R.string.bugreport_confirm));
@@ -425,9 +510,9 @@
}
public void testShareBugreportAfterServiceDies() throws Exception {
- sendBugreportFinished(NO_PID, mPlainTextPath, NO_SCREENSHOT);
+ sendBugreportFinished(NO_ID, mPlainTextPath, NO_SCREENSHOT);
killService();
- Bundle extras = acceptBugreportAndGetSharedIntent(NO_PID);
+ Bundle extras = acceptBugreportAndGetSharedIntent(NO_ID);
assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
}
@@ -463,32 +548,38 @@
private void assertProgressNotification(String name, String percent) {
// TODO: it currently looks for 3 distinct objects, without taking advantage of their
// relationship.
- openProgressNotification(PID);
+ openProgressNotification(ID);
Log.v(TAG, "Looking for progress notification details: '" + name + "-" + percent + "'");
mUiBot.getObject(name);
mUiBot.getObject(percent);
}
- private void openProgressNotification(int pid) {
- String title = mContext.getString(R.string.bugreport_in_progress_title, pid);
+ private UiObject openProgressNotification(int id) {
+ String title = mContext.getString(R.string.bugreport_in_progress_title, id);
Log.v(TAG, "Looking for progress notification title: '" + title + "'");
- mUiBot.getNotification(title);
+ return mUiBot.getNotification(title);
}
void resetProperties() {
// TODO: call method to remove property instead
- SystemProperties.set(PROGRESS_PROPERTY, "0");
- SystemProperties.set(MAX_PROPERTY, "0");
+ SystemProperties.set(PROGRESS_PROPERTY, "Reset");
+ SystemProperties.set(MAX_PROPERTY, "Reset");
+ SystemProperties.set(NAME_PROPERTY, "Reset");
}
/**
* Sends a "bugreport started" intent with the default values.
*/
private void sendBugreportStarted(int max) throws Exception {
+ sendBugreportStarted(ID, PID, NAME, max);
+ }
+
+ private void sendBugreportStarted(int id, int pid, String name, int max) throws Exception {
Intent intent = new Intent(INTENT_BUGREPORT_STARTED);
intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- intent.putExtra(EXTRA_PID, PID);
- intent.putExtra(EXTRA_NAME, NAME);
+ intent.putExtra(EXTRA_ID, id);
+ intent.putExtra(EXTRA_PID, pid);
+ intent.putExtra(EXTRA_NAME, name);
intent.putExtra(EXTRA_MAX, max);
mContext.sendBroadcast(intent);
}
@@ -500,7 +591,7 @@
*/
private Bundle sendBugreportFinishedAndGetSharedIntent(String bugreportPath,
String screenshotPath) {
- return sendBugreportFinishedAndGetSharedIntent(NO_PID, bugreportPath, screenshotPath);
+ return sendBugreportFinishedAndGetSharedIntent(NO_ID, bugreportPath, screenshotPath);
}
/**
@@ -508,10 +599,10 @@
*
* @return extras sent in the shared intent.
*/
- private Bundle sendBugreportFinishedAndGetSharedIntent(int pid, String bugreportPath,
+ private Bundle sendBugreportFinishedAndGetSharedIntent(int id, String bugreportPath,
String screenshotPath) {
- sendBugreportFinished(pid, bugreportPath, screenshotPath);
- return acceptBugreportAndGetSharedIntent(pid);
+ sendBugreportFinished(id, bugreportPath, screenshotPath);
+ return acceptBugreportAndGetSharedIntent(id);
}
/**
@@ -519,8 +610,8 @@
*
* @return extras sent in the shared intent.
*/
- private Bundle acceptBugreportAndGetSharedIntent(int pid) {
- acceptBugreport(pid);
+ private Bundle acceptBugreportAndGetSharedIntent(int id) {
+ acceptBugreport(id);
mUiBot.chooseActivity(UI_NAME);
return mListener.getExtras();
}
@@ -528,25 +619,25 @@
/**
* Waits for the notification to share the finished bugreport.
*/
- private void waitShareNotification(int pid) {
- mUiBot.getNotification(mContext.getString(R.string.bugreport_finished_title, pid));
+ private void waitShareNotification(int id) {
+ mUiBot.getNotification(mContext.getString(R.string.bugreport_finished_title, id));
}
/**
* Accepts the notification to share the finished bugreport.
*/
- private void acceptBugreport(int pid) {
- mUiBot.clickOnNotification(mContext.getString(R.string.bugreport_finished_title, pid));
+ private void acceptBugreport(int id) {
+ mUiBot.clickOnNotification(mContext.getString(R.string.bugreport_finished_title, id));
}
/**
* Sends a "bugreport finished" intent.
*/
- private void sendBugreportFinished(int pid, String bugreportPath, String screenshotPath) {
+ private void sendBugreportFinished(int id, String bugreportPath, String screenshotPath) {
Intent intent = new Intent(INTENT_BUGREPORT_FINISHED);
intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- if (pid != NO_PID) {
- intent.putExtra(EXTRA_PID, pid);
+ if (id != NO_ID) {
+ intent.putExtra(EXTRA_ID, id);
}
if (bugreportPath != null) {
intent.putExtra(EXTRA_BUGREPORT, bugreportPath);
@@ -563,7 +654,7 @@
*/
private void assertActionSendMultiple(Bundle extras, String bugreportContent,
String screenshotContent) throws IOException {
- assertActionSendMultiple(extras, bugreportContent, screenshotContent, PID, ZIP_FILE,
+ assertActionSendMultiple(extras, bugreportContent, screenshotContent, ID, PID, ZIP_FILE,
NO_NAME, NO_TITLE, NO_DESCRIPTION, 0, DIDNT_RENAME_SCREENSHOTS);
}
@@ -573,6 +664,7 @@
* @param extras extras received in the intent
* @param bugreportContent expected content in the bugreport file
* @param screenshotContent expected content in the screenshot file (sent by dumpstate), if any
+ * @param id emulated dumpstate id
* @param pid emulated dumpstate pid
* @param name expected subject
* @param name bugreport name as provided by the user (or received by dumpstate)
@@ -582,7 +674,7 @@
* @param renamedScreenshots whether the screenshots are expected to be renamed
*/
private void assertActionSendMultiple(Bundle extras, String bugreportContent,
- String screenshotContent, int pid, String subject,
+ String screenshotContent, int id, int pid, String subject,
String name, String title, String description,
int numberScreenshots, boolean renamedScreenshots) throws IOException {
String body = extras.getString(Intent.EXTRA_TEXT);
@@ -745,7 +837,7 @@
fail("Service status didn't change to " + expectRunning);
}
- private static void createTextFile(String path, String content) throws IOException {
+ private void createTextFile(String path, String content) throws IOException {
Log.v(TAG, "createFile(" + path + ")");
try (Writer writer = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(path)))) {
@@ -781,7 +873,7 @@
* Gets the notification button used to take a screenshot.
*/
private UiObject getScreenshotButton() {
- openProgressNotification(PID);
+ openProgressNotification(ID);
return mUiBot.getVisibleObject(
mContext.getString(R.string.bugreport_screenshot_action).toUpperCase());
}
@@ -833,15 +925,28 @@
/**
* Gets the UI objects by opening the progress notification and clicking DETAILS.
*/
- DetailsUi(UiBot uiBot, int pid) throws UiObjectNotFoundException {
- openProgressNotification(pid);
- detailsButton = mUiBot.getVisibleObject(
- mContext.getString(R.string.bugreport_info_action).toUpperCase());
- mUiBot.click(detailsButton, "details_button");
+ DetailsUi(UiBot uiBot, int id) throws UiObjectNotFoundException {
+ this(uiBot, id, true);
+ }
+
+ /**
+ * Gets the UI objects by opening the progress notification and clicking on DETAILS or in
+ * the notification itself.
+ */
+ DetailsUi(UiBot uiBot, int id, boolean clickDetails) throws UiObjectNotFoundException {
+ UiObject notification = openProgressNotification(id);
+ detailsButton = mUiBot.getVisibleObject(mContext.getString(
+ R.string.bugreport_info_action).toUpperCase());
+
+ if (clickDetails) {
+ mUiBot.click(detailsButton, "details_button");
+ } else {
+ mUiBot.click(notification, "notification");
+ }
// TODO: unhardcode resource ids
UiObject dialogTitle = mUiBot.getVisibleObjectById("android:id/alertTitle");
assertEquals("Wrong title", mContext.getString(R.string.bugreport_info_dialog_title,
- pid), dialogTitle.getText().toString());
+ id), dialogTitle.getText().toString());
nameField = mUiBot.getVisibleObjectById("com.android.shell:id/name");
titleField = mUiBot.getVisibleObjectById("com.android.shell:id/title");
descField = mUiBot.getVisibleObjectById("com.android.shell:id/description");
@@ -849,6 +954,28 @@
cancelButton = mUiBot.getObjectById("android:id/button2");
}
+ private void assertField(String name, UiObject field, String expected) {
+ try {
+ String actual = field.getText().toString();
+ assertEquals("Wrong value on field '" + name + "'", expected, actual);
+ } catch (UiObjectNotFoundException e) {
+ // Should not happen...
+ throw new IllegalStateException("field not found: " + name, e);
+ }
+ }
+
+ void assertName(String expected) {
+ assertField("name", nameField, expected);
+ }
+
+ void assertTitle(String expected) {
+ assertField("title", titleField, expected);
+ }
+
+ void assertDescription(String expected) {
+ assertField("description", descField, expected);
+ }
+
/**
* Takes focus away from the name field so it can be validated.
*/
@@ -858,7 +985,7 @@
}
void reOpen() {
- openProgressNotification(PID);
+ openProgressNotification(ID);
mUiBot.click(detailsButton, "details_button");
}
diff --git a/packages/StatementService/src/com/android/statementservice/IntentFilterVerificationReceiver.java b/packages/StatementService/src/com/android/statementservice/IntentFilterVerificationReceiver.java
index 712347a..57809ac 100644
--- a/packages/StatementService/src/com/android/statementservice/IntentFilterVerificationReceiver.java
+++ b/packages/StatementService/src/com/android/statementservice/IntentFilterVerificationReceiver.java
@@ -106,6 +106,10 @@
try {
ArrayList<String> sourceAssets = new ArrayList<String>();
for (String host : hostList) {
+ // "*.example.tld" is validated via https://example.tld
+ if (host.startsWith("*.")) {
+ host = host.substring(2);
+ }
sourceAssets.add(createWebAssetString(scheme, host));
}
extras.putStringArrayList(DirectStatementService.EXTRA_SOURCE_ASSET_DESCRIPTORS,
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index 88313bb..ad3c26b 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -1,10 +1,24 @@
LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := SystemUI-proto-tags
+
+LOCAL_SRC_FILES := $(call all-proto-files-under,src) \
+ src/com/android/systemui/EventLogTags.logtags
+
+LOCAL_PROTOC_OPTIMIZE_TYPE := nano
+LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# ------------------
+
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
-LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-proto-files-under,src) $(call all-Iaidl-files-under, src) \
- src/com/android/systemui/EventLogTags.logtags
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-Iaidl-files-under, src)
LOCAL_STATIC_JAVA_LIBRARIES := \
Keyguard \
@@ -13,13 +27,12 @@
android-support-v7-appcompat \
android-support-v14-preference \
android-support-v17-leanback \
- framework-protos
+ framework-protos \
+ SystemUI-proto-tags
LOCAL_JAVA_LIBRARIES := telephony-common
LOCAL_PACKAGE_NAME := SystemUI
-LOCAL_PROTOC_OPTIMIZE_TYPE := nano
-LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
LOCAL_CERTIFICATE := platform
LOCAL_PRIVILEGED_MODULE := true
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 9e07c6d..637551c 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -82,6 +82,7 @@
<uses-permission android:name="android.permission.GET_TOP_ACTIVITY_INFO" />
<uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
<uses-permission android:name="android.permission.START_TASKS_FROM_RECENTS" />
+ <uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT" />
<!-- WindowManager -->
<uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
@@ -244,7 +245,7 @@
android:stateNotNeeded="true"
android:resumeWhilePausing="true"
android:screenOrientation="behind"
- android:theme="@style/RecentsTheme.Wallpaper">
+ android:theme="@style/RecentsTvTheme.Wallpaper">
<intent-filter>
<action android:name="com.android.systemui.recents.TOGGLE_RECENTS" />
</intent-filter>
@@ -337,7 +338,7 @@
android:launchMode="singleTop"
android:taskAffinity=""
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
- android:resizeable="true"
+ android:resizeableActivity="true"
android:supportsPictureInPicture="true"
androidprv:alwaysFocusable="true"
android:excludeFromRecents="true" />
@@ -348,7 +349,7 @@
android:launchMode="singleTop"
android:taskAffinity=""
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
- android:resizeable="true"
+ android:resizeableActivity="true"
android:supportsPictureInPicture="true"
android:excludeFromRecents="true" />
<activity
diff --git a/packages/SystemUI/res/color/notification_guts_buttons.xml b/packages/SystemUI/res/color/notification_guts_buttons.xml
new file mode 100644
index 0000000..f7a4ee9
--- /dev/null
+++ b/packages/SystemUI/res/color/notification_guts_buttons.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_checked="true"
+ android:color="@*android:color/material_deep_teal_500" />
+ <item android:color="@android:color/black"
+ android:alpha=".87" />
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable-nodpi/icon.xml b/packages/SystemUI/res/drawable-nodpi/icon.xml
index 9c36b5a..5e08fcb 100644
--- a/packages/SystemUI/res/drawable-nodpi/icon.xml
+++ b/packages/SystemUI/res/drawable-nodpi/icon.xml
@@ -1,5 +1,5 @@
<!--
-Copyright (C) 2015 The Android Open Source Project
+Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,30 +14,25 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48.0dp"
- android:height="48.0dp"
+ android:width="48dp"
+ android:height="48dp"
android:viewportWidth="48.0"
android:viewportHeight="48.0">
<path
- android:pathData="M24.0,2.0C11.8,2.0 2.0,11.8 2.0,24.0c0.0,6.1 2.5,11.6 6.4,15.6L39.6,8.4C35.6,4.5 30.1,2.0 24.0,2.0z"
- android:fillColor="#E91E63"/>
+ android:fillColor="#00796B"
+ android:pathData="M32.0,12.5l0.0,28.0l12.0,-5.0l0.0,-28.0z"/>
<path
- android:pathData="M39.6,8.4L8.4,39.6c4.0,4.0 9.5,6.4 15.6,6.4c12.2,0.0 22.0,-9.8 22.0,-22.0C46.0,17.9 43.5,12.4 39.6,8.4z"
- android:fillColor="#F06292"/>
+ android:fillColor="#00796B"
+ android:pathData="M4.0,40.5l12.0,-5.0l0.0,-11.0l-12.0,-12.0z"/>
<path
- android:pathData="M45.9,25.9L34.0,14.0L14.0,34.0l11.9,11.9C36.5,45.0 45.0,36.5 45.9,25.9z"
- android:fillAlpha="0.33"
- android:fillColor="#E91E63"/>
+ android:fillColor="#40000000"
+ android:pathData="M44.0,35.5l-12.0,-12.0l0.0,-4.0z"/>
<path
- android:pathData="M24.0,24.0c0.0,0.0 0.0,2.2 0.0,5.0s0.0,5.0 0.0,5.0l10.0,-10.0L34.0,14.0L24.0,24.0z"
- android:fillColor="#FFFFFF"/>
+ android:fillColor="#40000000"
+ android:pathData="M4.0,12.5l12.0,12.0l0.0,4.0z"/>
<path
- android:pathData="M24.0,24.0L14.0,14.0l0.0,10.0l10.0,10.0c0.0,0.0 0.0,-2.2 0.0,-5.0S24.0,24.0 24.0,24.0z"
- android:fillColor="#EEEEEE"/>
- <path
- android:pathData="M14.0,34.0l10.0,0.0 -10.0,-10.0z"
- android:fillColor="#DDDDDD"/>
- <path
- android:pathData="M34.0,34.0l0.0,-10.0 -10.0,10.0z"
- android:fillColor="#DDDDDD"/>
+ android:fillColor="#4DB6AC"
+ android:pathData="M32.0,23.5l-16.0,-16.0l-12.0,5.0l0.0,0.0l12.0,12.0l16.0,16.0l12.0,-5.0l0.0,0.0z"/>
</vector>
+
+
diff --git a/packages/SystemUI/res/drawable/ic_fullscreen_white_24dp.xml b/packages/SystemUI/res/drawable/ic_fullscreen_white_24dp.xml
new file mode 100644
index 0000000..7ddb40c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_fullscreen_white_24dp.xml
@@ -0,0 +1,27 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:pathData="M0 0h24v24H0z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_info.xml b/packages/SystemUI/res/drawable/ic_info.xml
deleted file mode 100644
index 65e7bf5..0000000
--- a/packages/SystemUI/res/drawable/ic_info.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT 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="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:pathData="M12.000000,2.000000C6.500000,2.000000 2.000000,6.500000 2.000000,12.000000s4.500000,10.000000 10.000000,10.000000c5.500000,0.000000 10.000000,-4.500000 10.000000,-10.000000S17.500000,2.000000 12.000000,2.000000zM13.000000,17.000000l-2.000000,0.000000l0.000000,-6.000000l2.000000,0.000000L13.000000,17.000000zM13.000000,9.000000l-2.000000,0.000000L11.000000,7.000000l2.000000,0.000000L13.000000,9.000000z"
- android:fillColor="#FFFFFF"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_colorize.xml b/packages/SystemUI/res/drawable/ic_night_mode.xml
similarity index 95%
rename from packages/SystemUI/res/drawable/ic_colorize.xml
rename to packages/SystemUI/res/drawable/ic_night_mode.xml
index 79fd6d9..caa7a47 100644
--- a/packages/SystemUI/res/drawable/ic_colorize.xml
+++ b/packages/SystemUI/res/drawable/ic_night_mode.xml
@@ -1,5 +1,5 @@
<!--
- Copyright (C) 2015 The Android Open Source Project
+ Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/packages/SystemUI/res/drawable/ic_colorize.xml b/packages/SystemUI/res/drawable/ic_night_mode_disabled.xml
similarity index 91%
copy from packages/SystemUI/res/drawable/ic_colorize.xml
copy to packages/SystemUI/res/drawable/ic_night_mode_disabled.xml
index 79fd6d9..010815a 100644
--- a/packages/SystemUI/res/drawable/ic_colorize.xml
+++ b/packages/SystemUI/res/drawable/ic_night_mode_disabled.xml
@@ -1,5 +1,5 @@
<!--
- Copyright (C) 2015 The Android Open Source Project
+ Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -19,6 +19,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="#FFFFFFFF"
+ android:fillColor="#4DFFFFFF"
android:pathData="M20.71,5.63l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0.0l-3.12,3.12 -1.93,-1.91 -1.41,1.41 1.42,1.42L3.0,16.25L3.0,21.0l4.75,0.0l8.92,-8.92 1.42,1.42 1.41,-1.41 -1.92,-1.92 3.12,-3.12c0.4,0.0 0.4,-1.0 0.01,-1.42zM6.92,19.0L5.0,17.08l8.06,-8.06 1.92,1.92L6.92,19.0z"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_pause_white_24dp.xml b/packages/SystemUI/res/drawable/ic_pause_white_24dp.xml
new file mode 100644
index 0000000..d9a4f7b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_pause_white_24dp.xml
@@ -0,0 +1,27 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
+ <path
+ android:pathData="M0 0h24v24H0z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_play_arrow_white_24dp.xml b/packages/SystemUI/res/drawable/ic_play_arrow_white_24dp.xml
new file mode 100644
index 0000000..b8fa99e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_play_arrow_white_24dp.xml
@@ -0,0 +1,27 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M8 5v14l11-7z" />
+ <path
+ android:pathData="M0 0h24v24H0z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/qs_btn_borderless_rect.xml b/packages/SystemUI/res/drawable/qs_btn_borderless_rect.xml
new file mode 100644
index 0000000..03bfd1a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_btn_borderless_rect.xml
@@ -0,0 +1,32 @@
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<inset
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:insetTop="4dp"
+ android:insetBottom="4dp">
+ <ripple
+ android:color="?android:attr/colorControlHighlight" >
+
+ <item android:id="@android:id/mask">
+ <shape>
+ <corners android:radius="@dimen/borderless_button_radius" />
+
+ <solid android:color="@android:color/white" />
+ </shape>
+ </item>
+
+ </ripple>
+</inset>
diff --git a/packages/SystemUI/res/drawable/qs_customizer_background.xml b/packages/SystemUI/res/drawable/qs_customizer_background.xml
index 6bb27cc..d90f820 100644
--- a/packages/SystemUI/res/drawable/qs_customizer_background.xml
+++ b/packages/SystemUI/res/drawable/qs_customizer_background.xml
@@ -15,5 +15,5 @@
-->
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/qs_detail_transition" />
- <item android:drawable="?android:attr/windowBackground" />
+ <item android:drawable="@color/system_primary_color" />
</transition>
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/packages/SystemUI/res/drawable/recents_tv_background_gradient.xml
similarity index 75%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to packages/SystemUI/res/drawable/recents_tv_background_gradient.xml
index 31c0162..e98d43f 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/packages/SystemUI/res/drawable/recents_tv_background_gradient.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,9 +13,10 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/system_secondary_color" />
- <corners
- android:topLeftRadius="0dp"
- android:topRightRadius="0dp" />
-</shape>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <gradient
+ android:startColor="#99000000"
+ android:endColor="#E6000000"
+ android:angle="90"/>
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_saver.xml b/packages/SystemUI/res/drawable/stat_sys_data_saver.xml
new file mode 100644
index 0000000..a45f9a2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_data_saver.xml
@@ -0,0 +1,32 @@
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:insetLeft="2.5dp"
+ android:insetRight="2.5dp">
+ <vector
+ android:width="17.0dp"
+ android:height="17.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="
+ M9.0,16.0l2.0,0.0L11.0,8.0L9.0,8.0l0.0,8.0z
+ m3.0,-14.0C6.48,2.0 2.0,6.48 2.0,12.0s4.48,10.0 10.0,10.0 10.0,-4.48 10.0,-10.0S17.52,2.0 12.0,2.0z
+ m0.0,18.0c-4.41,0.0 -8.0,-3.59 -8.0,-8.0s3.59,-8.0 8.0,-8.0 8.0,3.59 8.0,8.0 -3.59,8.0 -8.0,8.0z
+ m1.0,-4.0l2.0,0.0l0.0,-8.0l-2.0,0.0l0.0,8.0z"/>
+ </vector>
+</inset>
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/packages/SystemUI/res/drawable/tv_pip_button_focused.xml
similarity index 76%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to packages/SystemUI/res/drawable/tv_pip_button_focused.xml
index 31c0162..5cabb77 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/packages/SystemUI/res/drawable/tv_pip_button_focused.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,9 +13,12 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/system_secondary_color" />
- <corners
- android:topLeftRadius="0dp"
- android:topRightRadius="0dp" />
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval">
+ <size
+ android:width="36dp"
+ android:height="36dp" />
+ <solid
+ android:color="#4DFFFFFF" />
</shape>
diff --git a/packages/SystemUI/res/drawable/tv_pip_close_button.xml b/packages/SystemUI/res/drawable/tv_pip_close_button.xml
new file mode 100644
index 0000000..86fda0d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/tv_pip_close_button.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:constantSize="true">
+ <item android:state_focused="true">
+ <layer-list>
+ <item android:drawable="@drawable/tv_pip_button_focused" />
+ <item android:drawable="@drawable/ic_close_white" />
+ </layer-list>
+ </item>
+ <item android:drawable="@drawable/ic_close_white" />
+</selector>
diff --git a/packages/SystemUI/res/drawable/tv_pip_full_button.xml b/packages/SystemUI/res/drawable/tv_pip_full_button.xml
new file mode 100644
index 0000000..332c669
--- /dev/null
+++ b/packages/SystemUI/res/drawable/tv_pip_full_button.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:constantSize="true">
+ <item android:state_focused="true">
+ <layer-list>
+ <item android:drawable="@drawable/tv_pip_button_focused" />
+ <item android:drawable="@drawable/ic_fullscreen_white_24dp" />
+ </layer-list>
+ </item>
+ <item android:drawable="@drawable/ic_fullscreen_white_24dp" />
+</selector>
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/packages/SystemUI/res/drawable/tv_pip_outline.xml
similarity index 76%
rename from packages/SystemUI/res/drawable/qs_background_secondary.xml
rename to packages/SystemUI/res/drawable/tv_pip_outline.xml
index 31c0162..c84438c 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/packages/SystemUI/res/drawable/tv_pip_outline.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,9 +13,8 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/system_secondary_color" />
- <corners
- android:topLeftRadius="0dp"
- android:topRightRadius="0dp" />
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <stroke android:width="2dp" android:color="#EEEEEE" />
</shape>
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/packages/SystemUI/res/drawable/tv_pip_overlay_background.xml
similarity index 72%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to packages/SystemUI/res/drawable/tv_pip_overlay_background.xml
index 31c0162..e247dec 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/packages/SystemUI/res/drawable/tv_pip_overlay_background.xml
@@ -1,5 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!--
+ Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,9 +13,11 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/system_secondary_color" />
- <corners
- android:topLeftRadius="0dp"
- android:topRightRadius="0dp" />
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+
+ <gradient
+ android:startColor="#B2000000"
+ android:endColor="#00000000"
+ android:angle="90"/>
</shape>
diff --git a/packages/SystemUI/res/drawable/tv_pip_pause_button.xml b/packages/SystemUI/res/drawable/tv_pip_pause_button.xml
new file mode 100644
index 0000000..d277b07
--- /dev/null
+++ b/packages/SystemUI/res/drawable/tv_pip_pause_button.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:constantSize="true">
+ <item android:state_focused="true">
+ <layer-list>
+ <item android:drawable="@drawable/tv_pip_button_focused" />
+ <item android:drawable="@drawable/ic_pause_white_24dp" />
+ </layer-list>
+ </item>
+ <item android:drawable="@drawable/ic_pause_white_24dp" />
+</selector>
diff --git a/packages/SystemUI/res/drawable/tv_pip_play_button.xml b/packages/SystemUI/res/drawable/tv_pip_play_button.xml
new file mode 100644
index 0000000..fecdc09
--- /dev/null
+++ b/packages/SystemUI/res/drawable/tv_pip_play_button.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:constantSize="true">
+ <item android:state_focused="true">
+ <layer-list>
+ <item android:drawable="@drawable/tv_pip_button_focused" />
+ <item android:drawable="@drawable/ic_play_arrow_white_24dp" />
+ </layer-list>
+ </item>
+ <item android:drawable="@drawable/ic_play_arrow_white_24dp" />
+</selector>
diff --git a/packages/SystemUI/res/layout/preference_matrix.xml b/packages/SystemUI/res/layout/calibrate_sliders.xml
similarity index 93%
rename from packages/SystemUI/res/layout/preference_matrix.xml
rename to packages/SystemUI/res/layout/calibrate_sliders.xml
index 1f6066e..0dec8a1 100644
--- a/packages/SystemUI/res/layout/preference_matrix.xml
+++ b/packages/SystemUI/res/layout/calibrate_sliders.xml
@@ -94,11 +94,4 @@
android:layout_weight="1" />
</LinearLayout>
- <Button
- android:id="@+id/apply"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="end"
- android:text="@string/color_apply" />
-
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/docked_stack_divider.xml b/packages/SystemUI/res/layout/docked_stack_divider.xml
index 7ea5027..cfaf018 100644
--- a/packages/SystemUI/res/layout/docked_stack_divider.xml
+++ b/packages/SystemUI/res/layout/docked_stack_divider.xml
@@ -27,6 +27,7 @@
<com.android.systemui.stackdivider.DividerHandleView
style="@style/DockedDividerHandle"
android:id="@+id/docked_divider_handle"
+ android:contentDescription="@string/accessibility_divider"
android:background="@null"/>
</com.android.systemui.stackdivider.DividerView>
diff --git a/packages/SystemUI/res/layout/color_matrix_settings.xml b/packages/SystemUI/res/layout/night_mode_settings.xml
similarity index 100%
rename from packages/SystemUI/res/layout/color_matrix_settings.xml
rename to packages/SystemUI/res/layout/night_mode_settings.xml
diff --git a/packages/SystemUI/res/layout/notification_guts.xml b/packages/SystemUI/res/layout/notification_guts.xml
index e550d9c..1ab6bf9 100644
--- a/packages/SystemUI/res/layout/notification_guts.xml
+++ b/packages/SystemUI/res/layout/notification_guts.xml
@@ -26,7 +26,7 @@
android:orientation="vertical"
android:paddingStart="@*android:dimen/notification_content_margin_start"
android:paddingEnd="8dp"
- android:background="@color/notification_guts_bg_color" >
+ android:background="@color/notification_guts_bg_color">
<!-- header -->
<LinearLayout
@@ -39,7 +39,7 @@
android:layout_gravity="center_vertical|start">
<ImageView
- android:id="@android:id/icon"
+ android:id="@+id/app_icon"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_marginEnd="6dp"
@@ -58,8 +58,41 @@
android:layout_gravity="bottom|start"
android:visibility="gone" />
</LinearLayout>
+ <!-- Importance radio buttons -->
+ <RadioGroup
+ android:id="@+id/importance_buttons"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="4dp"
+ android:paddingBottom="16dip"
+ android:paddingEnd="8dp" >
+ <RadioButton
+ android:id="@+id/silent_importance"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:paddingStart="32dp"
+ android:text="@string/show_silently"
+ style="@style/TextAppearance.NotificationGuts.Radio"
+ android:buttonTint="@color/notification_guts_buttons" />
+ <RadioButton
+ android:id="@+id/block_importance"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:paddingStart="32dp"
+ android:text="@string/block"
+ style="@style/TextAppearance.NotificationGuts.Radio"
+ android:buttonTint="@color/notification_guts_buttons" />
+ <RadioButton
+ android:id="@+id/reset_importance"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:paddingStart="32dp"
+ style="@style/TextAppearance.NotificationGuts.Radio"
+ android:buttonTint="@color/notification_guts_buttons" />
+ </RadioGroup>
<!-- Importance slider -->
<LinearLayout
+ android:id="@+id/importance_slider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
@@ -67,7 +100,8 @@
android:clickable="false"
android:focusable="false"
android:paddingBottom="8dip"
- android:paddingEnd="8dp" >
+ android:paddingEnd="8dp"
+ android:visibility="gone">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
@@ -126,27 +160,6 @@
android:tint="@color/notification_guts_icon_tint" />
</FrameLayout>
-
- <RadioGroup
- android:id="@+id/apply_to"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" >
- <RadioButton android:id="@+id/apply_to_topic"
- android:layout_width="wrap_content"
- android:layout_height="48dp"
- style="@style/TextAppearance.NotificationGuts.Primary"
- android:visibility="gone"
- android:buttonTint="#858383"
- />
- <RadioButton android:id="@+id/apply_to_app"
- android:layout_width="wrap_content"
- android:layout_height="48dp"
- android:text="@string/apply_to_app"
- style="@style/TextAppearance.NotificationGuts.Primary"
- android:visibility="gone"
- android:buttonTint="#858383"
- />
- </RadioGroup>
</LinearLayout>
<!-- buttons -->
<LinearLayout
diff --git a/packages/SystemUI/res/layout/notification_settings_icon_row.xml b/packages/SystemUI/res/layout/notification_settings_icon_row.xml
new file mode 100644
index 0000000..f47083a
--- /dev/null
+++ b/packages/SystemUI/res/layout/notification_settings_icon_row.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2016, The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<com.android.systemui.statusbar.NotificationSettingsIconRow
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="invisible"
+ >
+
+ <com.android.systemui.statusbar.AlphaOptimizedImageView
+ android:id="@+id/gear_icon"
+ android:layout_width="@dimen/notification_gear_width"
+ android:layout_height="@dimen/notification_gear_height"
+ android:paddingTop="@dimen/notification_gear_top_padding"
+ android:paddingStart="@dimen/notification_gear_padding"
+ android:paddingEnd="@dimen/notification_gear_padding"
+ android:paddingBottom="@dimen/notification_gear_padding"
+ android:src="@drawable/ic_settings"
+ android:tint="@color/notification_gear_color"
+ android:alpha="0"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ />
+
+</com.android.systemui.statusbar.NotificationSettingsIconRow>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_customize_panel.xml b/packages/SystemUI/res/layout/qs_customize_panel.xml
index 73a92d9..582ad48 100644
--- a/packages/SystemUI/res/layout/qs_customize_panel.xml
+++ b/packages/SystemUI/res/layout/qs_customize_panel.xml
@@ -22,53 +22,21 @@
android:background="@drawable/qs_customizer_background"
android:gravity="center_horizontal">
- <LinearLayout
+ <Toolbar
+ android:id="@*android:id/action_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingTop="28dp"
- android:paddingEnd="8dp">
-
- <ImageView
- android:id="@+id/close"
- android:layout_width="56dp"
- android:layout_height="56dp"
- android:padding="16dp"
- android:src="@drawable/ic_close_white" />
-
- <Space
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:layout_weight="1" />
-
- <Button
- android:id="@+id/save"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingStart="12dp"
- android:paddingEnd="12dp"
- android:background="?android:attr/selectableItemBackground"
- android:textAppearance="@android:style/TextAppearance.Material.Widget.Button.Inverse"
- android:textColor="?android:attr/colorAccent"
- android:text="@string/save" />
-
- <Button
- android:id="@+id/reset"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingStart="12dp"
- android:paddingEnd="12dp"
- android:background="?android:attr/selectableItemBackground"
- android:textAppearance="@android:style/TextAppearance.Material.Widget.Button.Inverse"
- android:textColor="?android:attr/colorAccent"
- android:text="@*android:string/reset" />
-
- </LinearLayout>
+ android:layout_marginTop="28dp"
+ android:navigationContentDescription="@*android:string/action_bar_up_description"
+ style="?android:attr/toolbarStyle" />
<android.support.v7.widget.RecyclerView
android:id="@android:id/list"
android:layout_width="@dimen/notification_panel_width"
android:layout_height="0dp"
- android:layout_weight="1" />
+ android:layout_weight="1"
+ android:scrollIndicators="top"
+ android:scrollbars="vertical" />
<View
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/qs_paged_page.xml b/packages/SystemUI/res/layout/qs_paged_page.xml
index eef08ba..a246e0d 100644
--- a/packages/SystemUI/res/layout/qs_paged_page.xml
+++ b/packages/SystemUI/res/layout/qs_paged_page.xml
@@ -19,4 +19,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tile_page"
android:layout_width="match_parent"
- android:layout_height="wrap_content" />
+ android:layout_height="wrap_content"
+ android:clipChildren="false"
+ android:clipToPadding="false" />
diff --git a/packages/SystemUI/res/layout/qs_paged_tile_layout.xml b/packages/SystemUI/res/layout/qs_paged_tile_layout.xml
index c23c745..9dd3ad2 100644
--- a/packages/SystemUI/res/layout/qs_paged_tile_layout.xml
+++ b/packages/SystemUI/res/layout/qs_paged_tile_layout.xml
@@ -18,12 +18,14 @@
<com.android.systemui.qs.PagedTileLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="wrap_content">
+ android:layout_height="wrap_content"
+ android:clipChildren="false"
+ android:clipToPadding="false">
<FrameLayout
android:id="@+id/page_decor"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_height="48dp"
android:layout_gravity="bottom">
<com.android.systemui.qs.PageIndicator
diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml
index 9f90af2..994d3c9 100644
--- a/packages/SystemUI/res/layout/qs_panel.xml
+++ b/packages/SystemUI/res/layout/qs_panel.xml
@@ -18,7 +18,9 @@
android:id="@+id/quick_settings_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="@drawable/qs_background_primary">
+ android:background="@drawable/qs_background_primary"
+ android:clipToPadding="false"
+ android:clipChildren="false">
<com.android.systemui.qs.QSPanel
android:id="@+id/quick_settings_panel"
diff --git a/packages/SystemUI/res/layout/qs_tile_label.xml b/packages/SystemUI/res/layout/qs_tile_label.xml
index 603ebbf..b0dca9a 100644
--- a/packages/SystemUI/res/layout/qs_tile_label.xml
+++ b/packages/SystemUI/res/layout/qs_tile_label.xml
@@ -20,22 +20,22 @@
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView android:id="@+id/tile_label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="@color/qs_tile_text"
- android:gravity="center_horizontal"
- android:minLines="2"
- android:padding="0dp"
- android:fontFamily="sans-serif-condensed"
- android:textStyle="normal"
- android:textSize="@dimen/qs_tile_text_size"
- android:clickable="false" />
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="@color/qs_tile_text"
+ android:gravity="center_horizontal"
+ android:minLines="2"
+ android:padding="0dp"
+ android:fontFamily="sans-serif-condensed"
+ android:textStyle="normal"
+ android:textSize="@dimen/qs_tile_text_size"
+ android:clickable="false" />
<ImageView android:id="@+id/restricted_padlock"
- android:layout_width="@dimen/qs_tile_text_size"
- android:layout_height="@dimen/qs_tile_text_size"
- android:src="@drawable/ic_settings_lock_outline"
- android:layout_marginLeft="@dimen/restricted_padlock_pading"
- android:baselineAlignBottom="true"
- android:scaleType="centerInside"
- android:visibility="gone" />
+ android:layout_width="@dimen/qs_tile_text_size"
+ android:layout_height="match_parent"
+ android:paddingBottom="@dimen/qs_tile_text_size"
+ android:src="@drawable/ic_info"
+ android:layout_marginLeft="@dimen/restricted_padlock_pading"
+ android:scaleType="centerInside"
+ android:visibility="gone" />
</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_user_detail_item.xml b/packages/SystemUI/res/layout/qs_user_detail_item.xml
index a22c360..661d74a 100644
--- a/packages/SystemUI/res/layout/qs_user_detail_item.xml
+++ b/packages/SystemUI/res/layout/qs_user_detail_item.xml
@@ -53,10 +53,10 @@
<ImageView
android:id="@+id/restricted_padlock"
android:layout_width="@dimen/qs_detail_item_secondary_text_size"
- android:layout_height="@dimen/qs_detail_item_secondary_text_size"
- android:src="@drawable/ic_settings_lock_outline"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical"
+ android:src="@drawable/ic_info"
android:layout_marginLeft="@dimen/restricted_padlock_pading"
- android:baselineAlignBottom="true"
android:scaleType="centerInside"
android:visibility="gone" />
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index 8df2c280..0a9baa0 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -108,7 +108,7 @@
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
- android:layout_marginTop="4dp"
+ android:layout_marginTop="8dp"
android:layout_marginStart="16dp"
android:gravity="start"
android:orientation="vertical">
diff --git a/packages/SystemUI/res/layout/recents_on_tv.xml b/packages/SystemUI/res/layout/recents_on_tv.xml
index b4543bd..3a7c1d1 100644
--- a/packages/SystemUI/res/layout/recents_on_tv.xml
+++ b/packages/SystemUI/res/layout/recents_on_tv.xml
@@ -18,9 +18,10 @@
android:id="@+id/recents_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:background="@drawable/recents_tv_background_gradient"
android:clipChildren="false"
- android:clipToPadding="false" >
-
+ android:clipToPadding="false"
+ android:layoutDirection="rtl">
<com.android.systemui.recents.tv.views.TaskStackHorizontalGridView
android:id="@+id/task_list"
android:layout_width="wrap_content"
@@ -28,10 +29,26 @@
android:clipChildren="false"
android:clipToPadding="false"
android:descendantFocusability="beforeDescendants"
+ android:layout_gravity="center"
android:gravity="center"
android:paddingStart="@dimen/recents_tv_grid_row_padding"
android:paddingEnd="@dimen/recents_tv_grid_row_padding"
- android:focusable="true"/>
+ android:focusable="true" />
+ <View
+ android:id="@+id/pip_shade"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="invisible"
+ android:background="#76000000"/>
+
+ <!-- Placeholder view to handle key events for PIP when it's focused.
+ Size and positions will be adjusted to comply with
+ config_pictureInPictureBoundsInRecents -->
+ <View
+ android:id="@+id/pip"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:visibility="invisible"
+ android:focusable="true" />
</com.android.systemui.recents.tv.views.RecentsTvView>
-
diff --git a/packages/SystemUI/res/layout/recents_task_view_header.xml b/packages/SystemUI/res/layout/recents_task_view_header.xml
index deb8e91..fa65758 100644
--- a/packages/SystemUI/res/layout/recents_task_view_header.xml
+++ b/packages/SystemUI/res/layout/recents_task_view_header.xml
@@ -26,29 +26,52 @@
android:layout_width="@dimen/recents_task_view_header_icon_width"
android:layout_height="@dimen/recents_task_view_header_icon_height"
android:layout_gravity="center_vertical|start"
- android:padding="9dp" />
- <TextView
- android:id="@+id/title"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:paddingStart="12dp"
+ android:paddingEnd="16dp" />
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|start"
- android:layout_marginStart="64dp"
- android:layout_marginEnd="112dp"
- android:textSize="16sp"
- android:textColor="#ffffffff"
- android:text="@string/recents_empty_message"
- android:fontFamily="sans-serif-medium"
- android:singleLine="true"
- android:maxLines="2"
- android:ellipsize="marquee"
- android:fadingEdge="horizontal" />
+ android:layout_marginStart="56dp"
+ android:layout_marginEnd="56dp"
+ android:orientation="vertical">
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="start"
+ android:textSize="16sp"
+ android:textColor="#ffffffff"
+ android:text="@string/recents_empty_message"
+ android:fontFamily="sans-serif-medium"
+ android:singleLine="true"
+ android:maxLines="1"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal" />
+ <TextView
+ android:id="@+id/sub_title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="start"
+ android:textSize="11sp"
+ android:textColor="#ffffffff"
+ android:text="@string/recents_launch_non_dockable_task_label"
+ android:fontFamily="sans-serif-medium"
+ android:singleLine="true"
+ android:maxLines="1"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"
+ android:visibility="gone" />
+ </LinearLayout>
<com.android.systemui.recents.views.FixedSizeImageView
android:id="@+id/move_task"
android:layout_width="@dimen/recents_task_view_header_button_width"
android:layout_height="@dimen/recents_task_view_header_button_height"
android:layout_marginEnd="@dimen/recents_task_view_header_button_width"
android:layout_gravity="center_vertical|end"
- android:padding="15dp"
+ android:padding="13dp"
android:src="@drawable/star"
android:background="?android:selectableItemBackground"
android:alpha="0"
@@ -58,7 +81,7 @@
android:layout_width="@dimen/recents_task_view_header_button_width"
android:layout_height="@dimen/recents_task_view_header_button_height"
android:layout_gravity="center_vertical|end"
- android:padding="15dp"
+ android:padding="13dp"
android:src="@drawable/recents_dismiss_light"
android:background="?android:selectableItemBackground"
android:alpha="0"
diff --git a/packages/SystemUI/res/layout/recents_task_view_header_overlay.xml b/packages/SystemUI/res/layout/recents_task_view_header_overlay.xml
index 10659a3..1becdab 100644
--- a/packages/SystemUI/res/layout/recents_task_view_header_overlay.xml
+++ b/packages/SystemUI/res/layout/recents_task_view_header_overlay.xml
@@ -23,13 +23,16 @@
android:layout_width="@dimen/recents_task_view_header_icon_width"
android:layout_height="@dimen/recents_task_view_header_icon_height"
android:layout_gravity="center_vertical|start"
- android:padding="9dp" />
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:paddingStart="12dp"
+ android:paddingEnd="16dp" />
<TextView
android:id="@+id/app_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|start"
- android:layout_marginStart="64dp"
+ android:layout_marginStart="56dp"
android:layout_marginEnd="112dp"
android:textSize="16sp"
android:textColor="#ffffffff"
@@ -44,7 +47,7 @@
android:layout_width="@dimen/recents_task_view_header_button_width"
android:layout_height="@dimen/recents_task_bar_height"
android:layout_gravity="center_vertical|end"
- android:padding="15dp"
+ android:padding="13dp"
android:background="?android:selectableItemBackground"
android:src="@drawable/recents_info_light" />
</FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_task_card_view.xml b/packages/SystemUI/res/layout/recents_tv_task_card_view.xml
similarity index 65%
rename from packages/SystemUI/res/layout/recents_task_card_view.xml
rename to packages/SystemUI/res/layout/recents_tv_task_card_view.xml
index fa1daad..c5b1a7a 100644
--- a/packages/SystemUI/res/layout/recents_task_card_view.xml
+++ b/packages/SystemUI/res/layout/recents_tv_task_card_view.xml
@@ -20,28 +20,28 @@
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_gravity="center"
- android:layout_centerInParent="true">
+ android:layout_centerInParent="true"
+ android:layoutDirection="ltr">
- <RelativeLayout
+ <LinearLayout
android:layout_width="@dimen/recents_tv_card_width"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
- android:layout_gravity="center">
- <ImageView
- android:id="@+id/card_view_thumbnail"
- android:layout_width="match_parent"
- android:layout_height="@dimen/recents_tv_card_height"
- android:scaleType="centerCrop"
- android:gravity="center"
- android:layout_alignParentTop="true"
- android:layout_centerHorizontal="true"/>
-
- <RelativeLayout
+ android:layout_gravity="center"
+ android:orientation="vertical" >
+ <LinearLayout
android:id="@+id/card_info_field"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/card_view_thumbnail"
- android:background="@color/recents_tv_card_background_color" >
+ android:layout_height="wrap_content">
+ <ImageView
+ android:id="@+id/card_extra_badge"
+ android:layout_width="@dimen/recents_tv_card_extra_badge_size"
+ android:layout_height="@dimen/recents_tv_card_extra_badge_size"
+ android:layout_marginBottom="@dimen/recents_tv_icon_padding_bottom"
+ android:layout_marginEnd="@dimen/recents_tv_icon_padding_end"
+ android:scaleType="fitCenter"
+ android:layout_centerVertical="true"
+ android:layout_alignParentRight="true" />
<TextView
android:id="@+id/card_title_text"
android:layout_width="match_parent"
@@ -49,29 +49,21 @@
android:layout_alignParentTop="false"
android:includeFontPadding="true"
android:minLines="1"
- android:maxLines="2"
+ android:maxLines="1"
android:textColor="@color/recents_tv_card_title_text_color"
- android:ellipsize="end" />
- <TextView
- android:id="@+id/card_content_text"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentStart="true"
- android:layout_below="@id/card_title_text"
- android:includeFontPadding="true"
- android:minLines="1"
- android:maxLines="2"
- android:textColor="@color/recents_tv_card_content_text_color"
- android:ellipsize="end" />
- <ImageView
- android:id="@+id/card_extra_badge"
- android:layout_width="@dimen/recents_tv_card_extra_badge_size"
- android:layout_height="@dimen/recents_tv_card_extra_badge_size"
- android:scaleType="fitCenter"
- android:background="@android:color/transparent"
- android:contentDescription="@null"
- android:layout_centerVertical="true"
- android:layout_alignParentRight="true"/>
- </RelativeLayout>
- </RelativeLayout>
+ android:fontFamily="@string/font_roboto_regular"
+ android:textSize="@dimen/recents_tv_title_text_size"
+ android:layout_marginBottom="@dimen/recents_tv_text_padding_bottom"
+ android:ellipsize="end"/>
+ </LinearLayout>
+ <ImageView
+ android:id="@+id/card_view_thumbnail"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/recents_tv_card_height"
+ android:scaleType="centerCrop"
+ android:gravity="center"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ android:layout_below="@id/card_title_text" />
+ </LinearLayout>
</com.android.systemui.recents.tv.views.TaskCardView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/remote_input.xml b/packages/SystemUI/res/layout/remote_input.xml
index cce07bd..75195c4 100644
--- a/packages/SystemUI/res/layout/remote_input.xml
+++ b/packages/SystemUI/res/layout/remote_input.xml
@@ -42,7 +42,8 @@
android:background="@null"
android:singleLine="true"
android:ellipsize="start"
- android:imeOptions="actionSend" />
+ android:inputType="textShortMessage|textAutoCorrect|textCapSentences"
+ android:imeOptions="actionSend|flagNoExtractUi" />
<FrameLayout
android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 289b1d9..656941f 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -39,8 +39,9 @@
android:clipToPadding="false"
android:clipChildren="false">
- <include
- layout="@layout/qs_panel"
+ <com.android.systemui.DensityContainer
+ android:id="@+id/qs_density_container"
+ android:layout="@layout/qs_panel"
android:layout_width="@dimen/notification_panel_width"
android:layout_height="wrap_content"
android:layout_gravity="@integer/notification_panel_layout_gravity" />
diff --git a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
index f699fce..7df6bc6 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
@@ -22,6 +22,7 @@
android:focusable="true"
android:clickable="true"
>
+
<com.android.systemui.statusbar.NotificationBackgroundView android:id="@+id/backgroundNormal"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -65,4 +66,9 @@
/>
</com.android.keyguard.AlphaOptimizedLinearLayout>
+ <com.android.systemui.statusbar.notification.FakeShadowView
+ android:id="@+id/fake_shadow"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
</com.android.systemui.statusbar.NotificationOverflowContainer>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml
index 62fdd42..e456984 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_row.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml
@@ -23,6 +23,14 @@
android:clickable="true"
>
+ <ViewStub
+ android:layout="@layout/notification_settings_icon_row"
+ android:id="@+id/settings_icon_row_stub"
+ android:inflatedId="@+id/notification_settings_icon_row"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ />
+
<com.android.systemui.statusbar.NotificationBackgroundView
android:id="@+id/backgroundNormal"
android:layout_width="match_parent"
@@ -68,4 +76,9 @@
android:layout_height="wrap_content"
/>
+ <com.android.systemui.statusbar.notification.FakeShadowView
+ android:id="@+id/fake_shadow"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
</com.android.systemui.statusbar.ExpandableNotificationRow>
diff --git a/packages/SystemUI/res/layout/tv_pip_menu.xml b/packages/SystemUI/res/layout/tv_pip_menu.xml
index 3562c64..1fec49e 100644
--- a/packages/SystemUI/res/layout/tv_pip_menu.xml
+++ b/packages/SystemUI/res/layout/tv_pip_menu.xml
@@ -18,36 +18,93 @@
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_gravity="end"
- android:paddingStart="10dp"
- android:paddingEnd="10dp"
- android:background="#88FFFFFF"
- android:gravity="center_vertical" >
+ android:orientation="horizontal"
+ android:paddingTop="350dp"
+ android:background="#CC000000"
+ android:gravity="top|center_horizontal"
+ android:clipChildren="false">
- <Button android:id="@+id/full"
- android:layout_width="match_parent"
+ <LinearLayout
+ android:layout_width="34dp"
android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:text="@string/pip_fullscreen"
- android:textSize="10sp"
- android:focusable="true" />
+ android:layout_marginEnd="3dp"
+ android:orientation="vertical"
+ android:gravity="center"
+ android:clipChildren="false">
- <Button android:id="@+id/exit"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:text="@string/pip_exit"
- android:textSize="10sp"
- android:focusable="true" />
+ <ImageView android:id="@+id/full_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:focusable="true"
+ android:src="@drawable/tv_pip_full_button" />
- <Button android:id="@+id/cancel"
- android:layout_width="match_parent"
+ <TextView android:id="@+id/full_desc"
+ android:layout_width="100dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="3dp"
+ android:gravity="center"
+ android:visibility="invisible"
+ android:text="@string/pip_fullscreen"
+ android:fontFamily="sans-serif"
+ android:textSize="12sp"
+ android:textColor="#EEEEEE"
+ android:clipChildren="false" />
+ </LinearLayout>
+
+ <LinearLayout android:id="@+id/play_pause"
+ android:layout_width="34dp"
android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:text="@string/pip_cancel"
- android:textSize="10sp"
- android:focusable="true" />
+ android:layout_marginStart="3dp"
+ android:layout_marginEnd="3dp"
+ android:orientation="vertical"
+ android:gravity="center"
+ android:clipChildren="false">
+
+ <ImageView android:id="@+id/play_pause_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:focusable="true"
+ android:src="@drawable/tv_pip_pause_button" />
+
+ <TextView android:id="@+id/play_pause_desc"
+ android:layout_width="100dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="3dp"
+ android:gravity="center"
+ android:visibility="invisible"
+ android:text="@string/pip_pause"
+ android:fontFamily="sans-serif"
+ android:textSize="12sp"
+ android:textColor="#EEEEEE"
+ android:clipChildren="false" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="34dp"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="3dp"
+ android:orientation="vertical"
+ android:gravity="center"
+ android:clipChildren="false">
+
+ <ImageView android:id="@+id/close_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:focusable="true"
+ android:src="@drawable/tv_pip_close_button" />
+
+ <TextView android:id="@+id/close_desc"
+ android:layout_width="100dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="3dp"
+ android:gravity="center"
+ android:visibility="invisible"
+ android:text="@string/pip_close"
+ android:fontFamily="sans-serif"
+ android:textSize="12sp"
+ android:textColor="#EEEEEE"
+ android:clipChildren="false" />
+ </LinearLayout>
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/tv_pip_onboarding.xml b/packages/SystemUI/res/layout/tv_pip_onboarding.xml
index ef39555..f031bb4 100644
--- a/packages/SystemUI/res/layout/tv_pip_onboarding.xml
+++ b/packages/SystemUI/res/layout/tv_pip_onboarding.xml
@@ -18,34 +18,43 @@
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/pip_onboarding"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#C00288D1"
- android:gravity="center"
- android:orientation="vertical" >
+ android:gravity="top|center_horizontal"
+ android:orientation="vertical">
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="30sp"
- android:textColor="@android:color/white"
- android:text="@string/pip_onboarding_title" />
+ <!-- A rectangle arounds the PIP.
+ Size and positions will be programatically set up
+ to comply with config_defaultPictureInPictureBounds. -->
<ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_sysbar_home" />
+ android:id="@+id/pip_outline"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:src="@drawable/tv_pip_outline" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:padding="30dp"
- android:textSize="13sp"
- android:textColor="@android:color/white"
+ android:layout_marginTop="24dp"
+ android:fontFamily="sans-serif"
+ android:textSize="16sp"
+ android:textColor="#EEEEEE"
+ android:lineSpacingMultiplier="1.28"
android:text="@string/pip_onboarding_description" />
<Button
android:id="@+id/close"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="15sp"
+ android:layout_height="36dp"
+ android:layout_marginTop="24dp"
+ android:gravity="center"
+ android:paddingStart="24dp"
+ android:paddingEnd="24dp"
+ android:fontFamily="sans-serif-condensed"
+ android:textSize="16sp"
+ android:textColor="#026089"
android:textAllCaps="true"
- android:text="@string/pip_onboarding_button" />
+ android:text="@string/pip_onboarding_button"
+ android:background="#EEEEEE"
+ android:elevation="4dp" />
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/tv_pip_overlay.xml b/packages/SystemUI/res/layout/tv_pip_overlay.xml
index 6d9c48d..40c6fa1 100644
--- a/packages/SystemUI/res/layout/tv_pip_overlay.xml
+++ b/packages/SystemUI/res/layout/tv_pip_overlay.xml
@@ -17,13 +17,39 @@
*/
-->
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/guide_overlay"
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="bottom"
- android:padding="3dp"
- android:textSize="13sp"
- android:textColor="#111111"
- android:background="#99EEEEEE"
- android:text="@string/pip_hold_home" />
+ android:layout_height="match_parent">
+
+ <TextView
+ android:id="@+id/guide_overlay"
+ android:layout_width="match_parent"
+ android:layout_height="32dp"
+ android:layout_alignParentBottom="true"
+ android:textSize="14sp"
+ android:textColor="#EEEEEE"
+ android:fontFamily="sans-serif"
+ android:background="@drawable/tv_pip_overlay_background"
+ android:gravity="center"
+ android:text="@string/pip_hold_home" />
+ <LinearLayout
+ android:id="@+id/guide_buttons"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_centerHorizontal="true"
+ android:orientation="horizontal">
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_fullscreen_white_24dp" />
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_pause_white_24dp" />
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_close_white" />
+ </LinearLayout>
+</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index e4effd4..baec8ef 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -13,25 +13,15 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/volume_dialog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/volume_dialog_margin_bottom"
android:background="@drawable/volume_dialog_background"
- android:translationZ="4dp" >
-
- <com.android.keyguard.AlphaOptimizedImageButton
- android:id="@+id/volume_expand_button"
- style="@style/VolumeButtons"
- android:layout_width="@dimen/volume_button_size"
- android:layout_height="@dimen/volume_button_size"
- android:layout_alignParentLeft="true"
- android:clickable="true"
- android:soundEffectsEnabled="false"
- android:src="@drawable/ic_volume_collapse_animation"
- tools:ignore="RtlHardcoded" />
+ android:translationZ="4dp"
+ android:paddingTop="8dp">
<LinearLayout
android:id="@+id/volume_dialog_content"
@@ -39,9 +29,15 @@
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="8dp"
- android:paddingTop="8dp" >
+ android:paddingStart="8dp">
<!-- volume rows added and removed here! :-) -->
+ <LinearLayout
+ android:id="@+id/volume_row_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/volume_button_size"
+ android:orientation="vertical"/>
<include layout="@layout/volume_zen_footer" />
@@ -49,4 +45,18 @@
<include layout="@layout/tuner_zen_mode_panel" />
</LinearLayout>
+ <com.android.keyguard.AlphaOptimizedImageButton
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/volume_expand_button"
+ style="@style/VolumeButtons"
+ android:layout_width="@dimen/volume_button_size"
+ android:layout_height="@dimen/volume_button_size"
+ android:clickable="true"
+ android:soundEffectsEnabled="false"
+ android:src="@drawable/ic_volume_collapse_animation"
+ tools:ignore="RtlHardcoded"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentTop="true"/>
+
</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/volume_dialog_row.xml b/packages/SystemUI/res/layout/volume_dialog_row.xml
index 91e931d..57bac41 100644
--- a/packages/SystemUI/res/layout/volume_dialog_row.xml
+++ b/packages/SystemUI/res/layout/volume_dialog_row.xml
@@ -13,13 +13,12 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
- android:id="@+id/volume_dialog_row"
- android:paddingEnd="8dp"
- android:paddingStart="8dp" >
+ android:id="@+id/volume_dialog_row" >
<TextView
android:id="@+id/volume_row_header"
@@ -31,7 +30,8 @@
android:paddingBottom="0dp"
android:paddingEnd="12dp"
android:paddingStart="12dp"
- android:paddingTop="4dp" />
+ android:paddingTop="4dp"
+ android:visibility="gone" />
<com.android.keyguard.AlphaOptimizedImageButton
android:id="@+id/volume_row_icon"
@@ -55,12 +55,4 @@
android:paddingEnd="8dp"
android:paddingStart="8dp" />
- <com.android.keyguard.AlphaOptimizedImageButton
- android:id="@+id/volume_settings_button"
- style="@style/VolumeButtons"
- android:layout_width="@dimen/volume_button_size"
- android:layout_height="@dimen/volume_button_size"
- android:layout_alignParentEnd="true"
- android:layout_below="@id/volume_row_header" />
-
</RelativeLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/volume_zen_footer.xml b/packages/SystemUI/res/layout/volume_zen_footer.xml
index 28447d7..f30023d 100644
--- a/packages/SystemUI/res/layout/volume_zen_footer.xml
+++ b/packages/SystemUI/res/layout/volume_zen_footer.xml
@@ -32,9 +32,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
- android:orientation="horizontal"
- android:paddingEnd="8dp"
- android:paddingStart="8dp" >
+ android:orientation="horizontal" >
<ImageView
android:id="@+id/volume_zen_icon"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 8d37e74..30d9ed7 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Skermkiekie geneem."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Raak om jou skermkiekie te sien."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Kon nie skermkiekie neem nie."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Kan nie skermkiekie neem nie oor beperkte bergingspasie of die program of organisasie verbied dit."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Kan weens beperkte bergingspasie nie skermkiekie stoor nie."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Die program of jou organisasie laat nie toe dat skermkiekies geneem word nie."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB-lêeroordrag-opsies"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Heg as \'n mediaspeler (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Heg as \'n kamera (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Meer tyd."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Minder tyd."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Flitslig af."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Flitslig is nie beskikbaar nie."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Flitslig aan."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Flitslig afgeskakel."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Flitslig aangeskakel."</string>
@@ -304,6 +306,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> is in veiligmodus gedeaktiveer."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Geskiedenis"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Vee uit"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Hierdie program steun nie veelvuldige vensters nie"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Program steun nie veelvuldige vensters nie"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Verdeel horisontaal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Verdeel vertikaal"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Verdeel gepasmaak"</string>
@@ -333,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Volkome\nstilte"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Net\nprioriteit"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Net\nwekkers"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Alles"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Alle\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Laai tans (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> tot vol)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Laai tans vinnig (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> tot vol)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Laai tans stadig (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> tot vol)"</string>
@@ -447,34 +449,43 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Wys horlosiesekondes op die statusbalk. Sal batterylewe dalk beïnvloed."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Herrangskik Kitsinstellings"</string>
<string name="show_brightness" msgid="6613930842805942519">"Wys helderheid in Kitsinstellings"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Aktiveer versneller om skerm te verdeel deur op te swiep"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Aktiveer die verdeling van die skerm deur op te swiep"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Aktiveer gebaar om skerm te verdeel deur van die Oorsig-knoppie af op te swiep"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimenteel"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Skakel Bluetooth aan?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Jy moet Bluetooth aanskakel om jou sleutelbord aan jou tablet te koppel."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Skakel aan"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Pas toe op <xliff:g id="TOPIC_NAME">%1$s</xliff:g>-kennisgewings"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Pas toe op alle kennisgewings van hierdie program af"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Wys kennisgewings sonder klank"</string>
+ <string name="block" msgid="2734508760962682611">"Blokkeer alle kennisgewings"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Moenie stilmaak nie"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Moenie stilmaak of blokkeer nie"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Wys volledige belangrikheidinstellings"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Geblokkeer"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Onbelangrik"</string>
<string name="low_importance" msgid="4109929986107147930">"Min belang"</string>
<string name="default_importance" msgid="8192107689995742653">"Normale belang"</string>
<string name="high_importance" msgid="1527066195614050263">"Groot belang"</string>
<string name="max_importance" msgid="5089005872719563894">"Dringende belang"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Moet nooit hierdie kennisgewings wys nie"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Wys onderaan die kennisgewinglys sonder \'n geluid"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Wys hierdie kennisgewings sonder geluide"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Wys boaan die kennisgewinglys en maak \'n geluid"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Verskyn vlugtig op die skerm en maak \'n geluid"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Wys sonder klank aan die onderkant van die kennisgewinglys"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Wys hierdie kennisgewings sonder klank"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Laat hierdie kennisgewing toe om geluide te maak"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Verskyn vlugtig op die skerm en laat klank toe"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Wys boaan die kennisgewingslys, verskyn vlugtig op die skerm en laat klank toe"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Meer instellings"</string>
<string name="notification_done" msgid="5279426047273930175">"Klaar"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Normale kleure"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Aandkleure"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Gepasmaakte kleure"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Outo"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Onbekende kleure"</string>
- <string name="color_transform" msgid="6985460408079086090">"Kleurverandering"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Wys kitsinstellings-teël"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Aktiveer gepasmaakte omskepping"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Kleur en voorkoms"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Nagmodus"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Kalibreer skerm"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Aan"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Af"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Skakel outomaties aan"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Skakel oor na Nagmodus soos gepas vir ligging en tyd van die dag"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Wanneer Nagmodus aan is"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Gebruik donkertema vir Android-bedryfstelsel"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Verstel tint"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Verstel helderheid"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Die donkertema word toegepas op kernareas van Android-bedryfstelsel wat gewoonlik in \'n ligtema gewys word, soos instellings."</string>
<string name="color_apply" msgid="9212602012641034283">"Pas toe"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Bevestig instellings"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Sommige kleurinstellings kan hierdie toestel onbruikbaar maak. Klik OK om hierdie kleurinstellings te bevestig; andersins sal hierdie instellings ná 10 sekondes teruggestel word."</string>
@@ -486,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Tuis"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Onlangs"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Terug"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Wys \'moenie steur nie\' in volume"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Laat volledige beheer van \'moenie steur nie\' toe in die volumedialoog."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Volume en Moenie steur nie"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Aktiveer \'moenie steur nie\' met volume af"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Wys saam met volumekontroles"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Moenie steur nie"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Volumeknoppieskortpad"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Verlaat \'moenie steur nie\' met volume op"</string>
<string name="battery" msgid="7498329822413202973">"Battery"</string>
<string name="clock" msgid="7416090374234785905">"Horlosie"</string>
<string name="headset" msgid="4534219457597457353">"Kopstuk"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Oorfone is gekoppel"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Kopstuk is gekoppel"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Aktiveer of deaktiveer ikone om op die statusbalk gewys te word."</string>
<string name="data_saver" msgid="5037565123367048522">"Databespaarder"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Databespaarder is aan"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Databespaarder is af"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Aan"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Af"</string>
<string name="nav_bar" msgid="1993221402773877607">"Navigasiebalk"</string>
<string name="start" msgid="6873794757232879664">"Begin"</string>
<string name="center" msgid="4327473927066010960">"Middel"</string>
@@ -523,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Voorskou"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Sleep om teëls by te voeg"</string>
<string name="qs_edit" msgid="2232596095725105230">"Wysig"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Tyd"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Wys ure, minute en sekondes"</item>
+ <item msgid="1427801730816895300">"Wys ure en minute (verstek)"</item>
+ <item msgid="3830170141562534721">"Moenie hierdie ikoon wys nie"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Wys altyd persentasie"</item>
+ <item msgid="2139628951880142927">"Wys persentasie wanneer gelaai word (verstek)"</item>
+ <item msgid="3327323682209964956">"Moenie hierdie ikoon wys nie"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Ander"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Skermverdeler"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Skuif af"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Skuif op"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Skuif links"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Skuif regs"</string>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 2b31ece..9692ae8 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"ቅጽበታዊ ገጽ እይታ ተቀርጿል"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"የእርስዎን ቅጽበታዊ ገጽ እይታ ለማየት ይንኩ"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"ቅጽበታዊ ገጽ እይታ መቅረጽ አልተቻለም::"</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"በተገደበ የማከማቻ ቦታ ምክንያት ወይም በመተግበሪያው ወይም በድርጅትዎ ስለማይፈቀድ የማያ ገጽ ቅጽበታዊ እይታዎችን ማንሳት አይቻልም።"</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ባለው የተገደበ የማከማቻ ቦታ ምክንያት ቅጽበታዊ ገጽ ዕይታን ማስቀመጥ አይችልም።"</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ቅጽበታዊ ገጽ እይታዎችን ማንሳት በመተግበሪያው ወይም በእርስዎ ድርጅት አይፈቀድም።"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"የUSB ፋይል ሰደዳ አማራጮች"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"እንደ ማህደረ አጫዋች (MTP) ሰካ"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"እንደ ካሜራ (PTP) ሰካ"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"ተጨማሪ ጊዜ።"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"ያነሰ ጊዜ።"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"የባትሪ ብርሃን ጠፍቷል።"</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"የባትሪ ብርሃን አይገኝም።"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"የባትሪ ብርሃን በርቷል።"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"የባትሪ ብርሃን ጠፍቷል።"</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"የባትሪ ብርሃን በርቷል።"</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ማያ ገጽ መሰካት"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ፈልግ"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>ን መጀመር አልተቻለም።"</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> በጥንቃቄ ሁነታ ውስጥ ታግዷል።"</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"ታሪክ"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"ጥረግ"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"ይህ መተግበሪያ ብዝሃ-መስኮትን አይደግፍም"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"መተግበሪያው ብዝሃ-መስኮትን አይደግፍም"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"አግድም ክፈል"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ቁልቁል ክፈል"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"በብጁ ክፈል"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"ሙሉ ለሙሉ\nጸጥታ"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"ቅድሚያ ተሰጪ\nብቻ"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"ማንቂያዎች\nብቻ"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"ሁሉም"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"ሁሉም\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"ኃይል በዝግታ በመሙላት ላይ (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> እስከሚሞላ ድረስ)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"የሰዓት ሰከንዶችን በሁኔታ አሞሌ ውስጥ አሳይ። በባትሪ ዕድሜ ላይ ተጽዕኖ ሊኖርው ይችል ይሆናል።"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"ፈጣን ቅንብሮችን ዳግም ያደራጁ"</string>
<string name="show_brightness" msgid="6613930842805942519">"በፈጣን ቅንብሮች ውስጥ ብሩህነትን አሳይ"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"የተከፈለ ማያ ገጽ ወደላይ አንሸራትቶ ማፍጠንን ያንቁ"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"የተከፈለ ማያ ገጽ ወደ ላይ የማንሸራተት ጣት ምልክትን ያንቁ"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"ከአጠቃላይ እይታ አዝራሩ ወደ ላይ በማንሸራተት ወደ የተከፈለ ማያ ገጽ የሚገቡበትን የጣት ምልክት ያንቁ"</string>
<string name="experimental" msgid="6198182315536726162">"የሙከራ"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"ብሉቱዝ ይብራ?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"የቁልፍ ሰሌዳዎን ከእርስዎ ጡባዊ ጋር ለማገናኘት በመጀመሪያ ብሉቱዝን ማብራት አለብዎት።"</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"አብራ"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"በ<xliff:g id="TOPIC_NAME">%1$s</xliff:g> ማሳወቂያዎች ላይ ተግብር"</string>
- <string name="apply_to_app" msgid="363016783939815960">"ከዚህ መተግበሪያ በሚመጡ ሁሉም ማሳወቂያዎች ላይ ተግብር"</string>
+ <string name="show_silently" msgid="6841966539811264192">"ማሳወቂያዎችን በጸጥታ አሳይ"</string>
+ <string name="block" msgid="2734508760962682611">"ሁሉንም ማሳወቂያዎች አግድ"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"ድምፅ አትዝጋ"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"ድምፅ አትዝጋ ወይም አታግድ"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"ሙሉ የአስፈላጊነት ቅንብሮችን አሳይ"</string>
<string name="blocked_importance" msgid="5198578988978234161">"የታገዱ"</string>
+ <string name="min_importance" msgid="1901894910809414782">"አነስተኛ አስፈላጊነት"</string>
<string name="low_importance" msgid="4109929986107147930">"ዝቅተኛ አስፈላጊነት"</string>
<string name="default_importance" msgid="8192107689995742653">"መደበኛ አስፈላጊነት"</string>
<string name="high_importance" msgid="1527066195614050263">"ከፍተኛ አስፈላጊነት"</string>
<string name="max_importance" msgid="5089005872719563894">"አስቸኳይ አስፈላጊነት"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"እነዚህን ማሳወቂያዎች በጭራሽ አታሳይ"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"በማሳወቂያ ዝርዝሩ ታችኛውን ክፍል ላይ በጸጥታ አሳይ"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"እነዚህን ማሳወቂያዎች በጸጥታ አሳይ"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"በማሳወቂያዎች ዝርዝር ላይኛው ክፍል ላይ አሳይና ድምፅ አሰማ"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"ወደ ገጸ ማያው ይመልከቱና ድምፅ ይቅረጹ"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"በማሳወቂያ ዝርዝሩ ታችኛውን ክፍል ላይ በጸጥታ አሳይ"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"እነዚህን ማሳወቂያዎች በጸጥታ አሳይ"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"እነዚህ ማሳወቂያዎች ድምፆችን እንዲፈጥሩ ፍቀድ"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"ወደ ማያ ገጹ አስገባና ድምፅ ፍቀድ"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"በማሳወቂያዎች ዝርዝር አናት ላይ አሳይ፣ ወደ ማያ ገጹ አሳይና ድምፅ ፍቀድ"</string>
<string name="notification_more_settings" msgid="816306283396553571">"ተጨማሪ ቅንብሮች"</string>
<string name="notification_done" msgid="5279426047273930175">"ተከናውኗል"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"መደበኛ ቀለሞች"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"የለሊት ቀለሞች"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"ብጁ ቀለሞች"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"ራስ-ሰር"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"የማይታወቁ ቀለሞች"</string>
- <string name="color_transform" msgid="6985460408079086090">"የቀለም ማሻሻያ"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"የፈጣን ቅንብሮች ሰቅን አሳይ"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"ብጁ ቅየራን አንቃ"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"ቀለም እና መልክ"</string>
+ <string name="night_mode" msgid="3540405868248625488">"የሌሊት ሁነታ"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"ማሳያን ይለኩ"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"በርቷል"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"ጠፍቷል"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"በራስ-ሰር አብራ"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"ለአካባቢው እና ለሰዓቱ ተገቢ በሆነ መልኩ ወደ የማታ ሁነታ ለውጥ"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"የማታ ሁነታ ሲበራ"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"ለAndroid ስርዓተ ክወና ጨለማ ገጽታን ተጠቀም"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"ቅልም አስተካክል"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"ብሩህነት አስተካክል"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"ጨለማ ገጽታው እንደ ቅንብሮች ያሉ በመደበኛነት በብርሃን ገጽታ በሚታዩ የAndroid ስርዓተ ክወና ዋና ክፍሎች ላይ ይተገበራል።"</string>
<string name="color_apply" msgid="9212602012641034283">"ተግብር"</string>
<string name="color_revert_title" msgid="4746666545480534663">"ቅንብሮችን ያረጋግጡ"</string>
<string name="color_revert_message" msgid="9116001069397996691">"አንዳንድ የቀለም ቅንብሮች ይህን መሣሪያ የማይጠቅም ሊያደርጉት ይችላሉ። እነዚህን የቀለም ቅንብሮች ለማረጋገጥ እሺ የሚለውን ጠቅ ያድርጉ፣ አለበለዚያ እነዚህ ቅንብሮች ከ10 ሰከንዶች በኋላ ዳግም ይጀምራሉ።"</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"የባትሪ አጠቃቀም"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"ኃይል በሚሞላበት ጊዜ ባትሪ ቆጣቢ አይገኝም"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"ባትሪ ቆጣቢ"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"አፈጻጸምን እና የጀርባ ውሂብን ይቀንሳል"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"መነሻ"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"የቅርብ ጊዜዎቹ"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"ተመለስ"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"በድምጽ ውስጥ አትረብሽን አሳይ"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"በድምጽ ንግግር ውስጥ አትረብሽን ሙሉ ቁጥጥር ይፍቀዱ።"</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"ድምጽ እና አትረብሽ"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"ድምጽ ሲቀነስ አትረብሽ አስገባ"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"ከድምፅ መቆጣጠሪያዎች ጋር አሳይ"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"አትረብሽ"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"የድምፅ አዝራሮች አቋራጭ"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"ድምጽ ሲጨመር አትረብሽን ትተህ ውጣ"</string>
<string name="battery" msgid="7498329822413202973">"ባትሪ"</string>
<string name="clock" msgid="7416090374234785905">"ሰዓት"</string>
<string name="headset" msgid="4534219457597457353">"ጆሮ ማዳመጫ"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"የጆር ማዳመጫዎች ተገናኝተዋል"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"የጆሮ ማዳመጫ ተገናኝቷል"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"አዶዎች በሁኔታ አሞሌ ላይ እንዲታዩ ወይም እንዳይታዩ ያንቁ ወይም ያሰናክሉ።"</string>
<string name="data_saver" msgid="5037565123367048522">"ውሂብ ቆጣቢ"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"ውሂብ ቆጣቢ በርቷል"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"ውሂብ ቆጣቢ ጠፍቷል"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"በርቷል"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"ጠፍቷል"</string>
<string name="nav_bar" msgid="1993221402773877607">"የአሰሳ አሞሌ"</string>
<string name="start" msgid="6873794757232879664">"ጀምር"</string>
<string name="center" msgid="4327473927066010960">"መሃል"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"ቅድመ-እይታ"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"ሰቆችን ለማከል ይጎትቱ"</string>
<string name="qs_edit" msgid="2232596095725105230">"አርትዕ"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"ሰዓት"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"ሰዓቶችን፣ ደቂቃዎችን፣ ሴኮንዶችን አሳይ"</item>
+ <item msgid="1427801730816895300">"ሰዓቶችን እና ደቂቃዎችን አሳይ (ነባሪ)"</item>
+ <item msgid="3830170141562534721">"ይህን አዶ አታሳይ"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"ሁልጊዜ መቶኛ አሳይ"</item>
+ <item msgid="2139628951880142927">"የባትሪ ኃይል በሚሞላበት ጊዜ መቶኛ አሳይ (ነባሪ)"</item>
+ <item msgid="3327323682209964956">"ይህን አዶ አታሳይ"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"ሌላ"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"የተከፈለ የማያ ገጽ ከፋይ"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"ወደ ታች ሂድ"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"ወደ ላይ ሂድ"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"ወደ ግራ ሂድ"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"ወደ ቀኝ ሂድ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 1a1fc2b..181f68b 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -77,7 +77,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"تم التقاط لقطة الشاشة."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"المس لعرض لقطة الشاشة."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"تعذر التقاط لقطة الشاشة."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"يتعذر التقاط لقطة شاشة نظرًا لأن مساحة التخزين المتاحة محدودة، أو نظرًا لعدم سماح التطبيق أو المؤسسة بذلك."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"يتعذر حفظ لقطة الشاشة نظرًا لأن مساحة التخزين المتاحة محدودة."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"غير مسموح بالتقاط لقطات شاشة نظرًا لإذن يتعلق بالتطبيق أو بالمؤسسة."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"خيارات نقل الملفات عبر USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"تحميل كمشغل وسائط (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"تحميل ككاميرا (PTP)"</string>
@@ -210,6 +211,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"وقت أكثر."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"وقت أقل."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"إيقاف الفلاش."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"تطبيق المصباح اليدوي غير متاح."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"تشغيل الفلاش."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"تم إيقاف الفلاش."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"تم تشغيل الفلاش."</string>
@@ -305,10 +307,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"تثبيت الشاشة"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"بحث"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"تعذر بدء <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"تم تعطيل <xliff:g id="APP">%s</xliff:g> في الوضع الآمن."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"السجلّ"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"محو"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"لا يتيح هذا التطبيق النوافذ المتعددة."</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"لا يتيح التطبيق النوافذ المتعددة."</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"تقسيم أفقي"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"تقسيم رأسي"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"تقسيم مخصص"</string>
@@ -338,8 +341,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"كتم الصوت\nتمامًا"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"الأولوية \nفقط"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"التنبيهات\nفقط"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"الكل"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"الكل\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"جارٍ الشحن ببطء (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> حتى الاكتمال)"</string>
@@ -452,39 +453,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"عرض ثواني الساعة في شريط الحالة. قد يؤثر ذلك في عمر البطارية."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"إعادة ترتيب الإعدادات السريعة"</string>
<string name="show_brightness" msgid="6613930842805942519">"عرض السطوع في الإعدادات السريعة"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"تمكين مسارع تقسيم الشاشة بالتمرير السريع لأعلى"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"تمكين إيماءة تقسيم الشاشة بالتمرير السريع لأعلى"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"تمكين الإيماء لإدخال تقسيم الشاشة من خلال التمرير السريع لأعلى من زر النظرة العامة"</string>
<string name="experimental" msgid="6198182315536726162">"إعدادات تجريبية"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"تشغيل البلوتوث؟"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"لتوصيل لوحة المفاتيح بالجهاز اللوحي، يلزمك تشغيل بلوتوث أولاً."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"تشغيل"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"التطبيق على إشعارات <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"التطبيق في جميع الإشعارات من هذا التطبيق"</string>
+ <string name="show_silently" msgid="6841966539811264192">"عرض الإشعارات بدون تنبيه صوتي"</string>
+ <string name="block" msgid="2734508760962682611">"حظر كل الإشعارات"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"عدم كتم التنبيه الصوتي"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"عدم كتم التنبيه الصوتي أو حظر الإشعار"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"عرض الإعدادات الكاملة لمدى الأهمية"</string>
<string name="blocked_importance" msgid="5198578988978234161">"تم الحظر"</string>
+ <string name="min_importance" msgid="1901894910809414782">"الأقل أهمية"</string>
<string name="low_importance" msgid="4109929986107147930">"أهمية منخفضة"</string>
<string name="default_importance" msgid="8192107689995742653">"أهمية عادية"</string>
<string name="high_importance" msgid="1527066195614050263">"أهمية عالية"</string>
<string name="max_importance" msgid="5089005872719563894">"أهمية ملحَّة"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"عدم عرض هذه الإشعارات"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"العرض أسفل قائمة الإشعارات بدون تنبيه صوتي"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"عرض هذه الإشعارات بدون تنبيه صوتي"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"العرض أعلى قائمة الإشعارات مع تنبيه صوتي"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"الظهور سريعًا على الشاشة مع تنبيه صوتي"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"عرض الإشعار بأسفل قائمة الإشعارات بدون تنبيه صوتي"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"عرض هذه الإشعارات بدون تنبيه صوتي"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"السماح لهذه الإشعارات بإصدار تنبيهات صوتية"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"يتم عرض الإشعار بسرعة على الشاشة مع السماح بإصدار تنبيه صوتي"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"عرض هذا الإشعار بأعلى قائمة الإشعارات وعرضه بسرعة على الشاشة مع السماح بإصدار تنبيه صوتي"</string>
<string name="notification_more_settings" msgid="816306283396553571">"المزيد من الإعدادات"</string>
<string name="notification_done" msgid="5279426047273930175">"تم"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"ألوان عادية"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"ألوان ليلية"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"ألوان مخصصة"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"تلقائي"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"ألوان غير معروفة"</string>
- <string name="color_transform" msgid="6985460408079086090">"إشعار الألوان"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"إظهار قسم الإعدادات السريعة"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"تمكين التحويل المخصص"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"اللون والمظهر"</string>
+ <string name="night_mode" msgid="3540405868248625488">"الوضع الليلي"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"معايرة الشاشة"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"تشغيل"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"إيقاف"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"التشغيل تلقائيًا"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"التبديل إلى الوضع الليلي بما يتناسب مع الموقع والوقت من اليوم"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"عند تشغيل الوضع الليلي"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"استخدام مظهر معتم لنظام التشغيل Android"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"ضبط التلوين الخفيف"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"ضبط السطوع"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"يتم تطبيق المظهر المعتم على المناطق الأساسية في نظام التشغيل Android والتي يتم عرضها عادة في مظهر مضيء، مثل الإعدادات."</string>
<string name="color_apply" msgid="9212602012641034283">"تطبيق"</string>
<string name="color_revert_title" msgid="4746666545480534663">"تأكيد الإعدادات"</string>
<string name="color_revert_message" msgid="9116001069397996691">"يمكن أن تتسبب بعض إعدادات الألوان في تعطيل إمكانية استخدام الجهاز. يمكنك النقر على \"موافق\" لتأكيد إعدادات الألوان هذه، وإلا فستتم إعادة تعيين هذه الإعدادات بعد 10 ثوانٍ."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"استخدام البطارية"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"وضع توفير شحن البطارية غير متاح أثناء الشحن."</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"توفير شحن البطارية"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"لخفض مستوى الأداء وبيانات الخلفية"</string>
@@ -492,21 +501,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"الشاشة الرئيسية"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"الأحدث"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"رجوع"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"إظهار خيار \"الرجاء عدم الإزعاج\" في مستوى الصوت"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"السماح بالتحكم الكامل في خيار \"الرجاء عدم الإزعاج\" ضمن مربع حوار مستوى الصوت."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"إعدادات مستوى الصوت و\"الرجاء عدم الإزعاج\""</string>
- <string name="volume_down_silent" msgid="66962568467719591">"تشغيل \"الرجاء عدم الإزعاج\" عند خفض مستوى الصوت"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"عرض مع عناصر التحكم في مستوى الصوت"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"الرجاء عدم الإزعاج"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"اختصار أزرار مستوى الصوت"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"تعطيل \"الرجاء عدم الإزعاج\" عند رفع مستوى الصوت"</string>
<string name="battery" msgid="7498329822413202973">"البطارية"</string>
<string name="clock" msgid="7416090374234785905">"ساعة"</string>
<string name="headset" msgid="4534219457597457353">"سماعة الرأس"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"تم توصيل سماعات رأس"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"تم توصيل سماعات رأس"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"يمكنك تمكين أو تعطيل الرموز بحيث لا تظهر في شريط الحالة."</string>
<string name="data_saver" msgid="5037565123367048522">"توفير البيانات"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"تم تشغيل توفير البيانات"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"تم تعطيل توفير البيانات"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"تشغيل"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"إيقاف"</string>
<string name="nav_bar" msgid="1993221402773877607">"شريط التنقل"</string>
<string name="start" msgid="6873794757232879664">"البدء"</string>
<string name="center" msgid="4327473927066010960">"وسط"</string>
@@ -529,4 +537,21 @@
<string name="preview" msgid="9077832302472282938">"معاينة"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"اسحب لإضافة مربعات"</string>
<string name="qs_edit" msgid="2232596095725105230">"تعديل"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"الوقت"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"عرض الساعات والدقائق والثواني"</item>
+ <item msgid="1427801730816895300">"عرض الساعات والدقائق (افتراضي)"</item>
+ <item msgid="3830170141562534721">"عدم عرض هذا الرمز"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"عرض النسبة المئوية دائمًا"</item>
+ <item msgid="2139628951880142927">"عرض النسبة المئوية عند الشحن (افتراضي)"</item>
+ <item msgid="3327323682209964956">"عدم عرض هذا الرمز"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"غير ذلك"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"أداة تقسيم الشاشة"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"نقل لأسفل"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"نقل لأعلى"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"نقل لليسار"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"نقل لليمين"</string>
</resources>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index 690317f..9e88f35 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Skrinşot çəkildi."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Skrinşotunuza baxmaq üçün toxunun"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Skrinşot götürülə bilinmədi."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Yaddaş ehtiyatının az olması səbəbindən skrinşot çəkmək olmur və ya bunu etmək ya tətbiq, ya da şirkət tərəfindən qadağan olunub."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Yaddaş ehtiyatının az olması səbəbindən skrinşotu yadda saxlamaq olmur."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Tətbiq və ya təşkilatınız tərəfindən skrinşot çəkməyə icazə verilmir."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB fayl transferi seçimləri"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Media pleyer (MTP) kimi montaj edin"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Kamera kimi birləşdir (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Daha çox vaxt."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Daha az vaxt."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Fənər deaktiv."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Fənər əlçatan deyil."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Fənər aktiv."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Fənər deaktivdir."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Fənər aktivdir."</string>
@@ -304,6 +306,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> güvənli rejimdə deaktiv edildi."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Tarixçə"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Təmizləyin"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Bu tətbiq çoxsaylı pəncərəni dəstəkləmir"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Bu tətbiq çoxsaylı pəncərəni dəstəkləyir"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Üfüqi Böl"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Şaquli Böl"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Fərdi Böl"</string>
@@ -333,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Tam\nsakitlik"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Yalnız\nprioritet"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Yalnız\nalarmlar"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Bütün"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Bütün\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Qidalanır (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> dolana kimi)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Sürətli qidalanır (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> dolana kimi)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Ləng qidalanır (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> dolana kimi)"</string>
@@ -447,34 +449,43 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Saatın saniyəsini status panelində göstərin. Batareyaya təsir edə bilər."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Sürətli Ayarları yenidən tənzimləyin"</string>
<string name="show_brightness" msgid="6613930842805942519">"Sürətli ayarlarda parlaqlılığı göstərin"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Bölünmüş ekran sürüşdürməsi akseleratorunu aktiv edin"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Bölünmüş ekran sürüşdürməsi aktiv edin"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Jestlərin icmal düyməsindən yuxarı sürüşdürərək bölünmüş ekrana daxil olmasını aktiv edin"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimental"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth aktivləşsin?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Tabletinizlə klaviaturaya bağlanmaq üçün ilk olaraq Bluetooth\'u aktivləşdirməlisiniz."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Aktivləşdirin"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> bildirişlərinə müraciət edin"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Bu tətbiqdən olan bütün bildirişlərə müraciət edin"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Bildirişləri səssiz göstərin"</string>
+ <string name="block" msgid="2734508760962682611">"Bütün bildirişləri blok edin"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Səssiz etməyin"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Səssiz və ya blok etməyin"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Tam əhəmiyyətlilik ayarlarını göstərin"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloklanmış"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Minimum əhəmiyyətli"</string>
<string name="low_importance" msgid="4109929986107147930">"Az əhəmiyyətli"</string>
<string name="default_importance" msgid="8192107689995742653">"Normal əhəmiyyətli"</string>
<string name="high_importance" msgid="1527066195614050263">"Çox əhəmiyyətli"</string>
<string name="max_importance" msgid="5089005872719563894">"Təcili əhəmiyyətli"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Bu bildirişləri heç vaxt göstərməyin"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Bildirişlər siyahısının aşağısında səssiz göstərin"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Bu bildişləri səssiz göstərin"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Bildirişlər siyahısında yuxarıda göstərin və səsli edin"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Ekranda nəzər salın və səsli edin"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Bildirişlər siyahısının aşağısında səssiz göstərin"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Bu bildişləri səssiz göstərin"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Bu bildirişi səsli edin"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Ekranda nəzər salın və səsə icazə verin"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Bildirişlər siyahısında yuxarıda göstərin, ekrana nəzər salın və səsə icazə verin"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Daha çox ayar"</string>
<string name="notification_done" msgid="5279426047273930175">"Hazırdır"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Normal rənglər"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Gecə rəngləri"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Xüsusi rənglər"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Avto"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Naməlum rəng"</string>
- <string name="color_transform" msgid="6985460408079086090">"Rəng modifikasiyası"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Cəld ayarlar örtüyünü göstərin"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Xüsusi dəyişikliyi aktiv edin"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Rəng və görünüş"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Gecə rejimi"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Ekranı kalibrləyin"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Aktiv"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Deaktiv"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Avtomatik aktivləşdirin"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Məkana və günün vaxtına uyğun olaraq Gecə Rejiminə keçin"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Gecə Rejimi aktiv olduqda"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Android OS üçün tünd tema istifadə edin"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Çaları nizamlayın"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Parlaqlığı nizamlayın"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Tünd tema Android OS sisteminin adətən işıqlı tema göstərilən Ayarlar kimi əsas sahələri üçün tətbiq edilir."</string>
<string name="color_apply" msgid="9212602012641034283">"Tətbiq edin"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Ayarları təsdiq edin"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Bəzi renk ayarları bu cihazı yararsız edə bilər. Bu rənk ayarlarını təsdiq etmək üçün OK basın, əks halda bu ayarlar 10 saniyə sonra sıfırlanacaq."</string>
@@ -486,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Əsas səhifə"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Sonuncular"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Geri"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Səsdə \"narahat etməyin\" rejimini göstərin"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Səs dioloqunda \"narahat etməyin\" rejiminin tam nərarətinə icazə verin."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Səs və \"narahat etməyin\" rejimi"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Aşağı səsdə \"narahat etməyin\" rejimini daxil edin"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Həcm nəzarəti ilə göstərin"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Narahat etməyin"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Səs düymələri qısayolu"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Yuxarı səsdə \"narahat etməyin\" rejimini daxil edin"</string>
<string name="battery" msgid="7498329822413202973">"Batareya"</string>
<string name="clock" msgid="7416090374234785905">"Saat"</string>
<string name="headset" msgid="4534219457597457353">"Qulaqlıq"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Qulaqlıq qoşulub"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Qulaqlıq qoşulub"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"İkonaların status panelində görünməsini aktiv və ya deaktiv edin."</string>
<string name="data_saver" msgid="5037565123367048522">"Data Qənaəti"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Data Qənaəti aktivdir"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Data Qənaəti deaktivdir"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Aktiv"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Deaktiv"</string>
<string name="nav_bar" msgid="1993221402773877607">"Naviqasiya paneli"</string>
<string name="start" msgid="6873794757232879664">"Başladın"</string>
<string name="center" msgid="4327473927066010960">"Mərkəz"</string>
@@ -523,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Önizləmə"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Xanalar əlavə etmək üçün sürüşdürün"</string>
<string name="qs_edit" msgid="2232596095725105230">"Redaktə edin"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Vaxt"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Saat, dəqiqə və saniyəni göstərin"</item>
+ <item msgid="1427801730816895300">"Saat və dəqiqəni göstərin (defolt)"</item>
+ <item msgid="3830170141562534721">"Bu piktoqramı göstərməyin"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Faizi həmişə göstərin"</item>
+ <item msgid="2139628951880142927">"Enerji dolan zaman faizi göstərin (defolt)"</item>
+ <item msgid="3327323682209964956">"Bu piktoqramı göstərməyin"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Digər"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Bölünmüş ekran ayırıcısı"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Aşağıya keçin"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Yuxarıya keçin"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Sola köçürün"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Sağa köçürün"</string>
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 3ae995b..3edc805 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -74,7 +74,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Snimak ekrana je napravljen."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Dodirnite da biste videli snimak ekrana."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Nije moguće napraviti snimak ekrana."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Nije moguće snimiti ekran zbog nedovoljne memorije ili to ne dozvoljava aplikacija ili organizacija."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Čuvanje snimka ekrana nije uspelo zbog ograničenog memorijskog prostora."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Aplikacija ili organizacija ne dozvoljavaju pravljenje snimaka ekrana."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Opcije USB prenosa datoteka"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Priključi kao medija plejer (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Priključi kao kameru (PTP)"</string>
@@ -207,6 +208,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Više vremena."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Manje vremena."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Baterijska lampa je isključena."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lampa nije dostupna."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Baterijska lampa je uključena."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Baterijska lampa je isključena."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Baterijska lampa je uključena."</string>
@@ -302,10 +304,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"kačenje ekrana"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"pretraži"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Pokretanje aplikacije <xliff:g id="APP">%s</xliff:g> nije uspelo."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Aplikacija <xliff:g id="APP">%s</xliff:g> je onemogućena u bezbednom režimu."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Istorija"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Obriši"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Ova aplikacija ne podržava režim sa više prozora"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Aplikacija ne podržava režim sa više prozora"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Podeli horizontalno"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Podeli vertikalno"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Prilagođeno deljenje"</string>
@@ -335,8 +338,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Potpuna\ntišina"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Samo\npriorit. prekidi"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Samo\nalarmi"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Sve"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Svi\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Punjenje (pun je za <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Brzo se puni (napuniće se za <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Sporo se puni (napuniće se za <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
@@ -449,39 +450,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Sekunde na satu se prikazuju na statusnoj traci. To može da utiče na trajanje baterije."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Preuredi Brza podešavanja"</string>
<string name="show_brightness" msgid="6613930842805942519">"Prikaži osvetljenost u Brzim podešavanjima"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Omogući ubrzavač za prevlačenje nagore za podeljeni ekran"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Omogući pokret za prevlačenje nagore za podeljeni ekran"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Omogućava pokret za prelazak na podeljeni ekran prevlačenjem nagore od dugmeta Pregled"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimentalno"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Želite li da uključite Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Da biste povezali tastaturu sa tabletom, prvo morate da uključite Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Uključi"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Primeni na obaveštenja o temi <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Primeni na sva obaveštenja iz ove aplikacije"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Prikazuj obaveštenja bez zvuka"</string>
+ <string name="block" msgid="2734508760962682611">"Blokiraj sva obaveštenja"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Ne isključuj zvuk"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Ne isključuju zvuk niti blokiraj"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Prikaži kompletna podešavanja važnosti"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Blokirana"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Veoma mala važnost"</string>
<string name="low_importance" msgid="4109929986107147930">"Mala važnost"</string>
<string name="default_importance" msgid="8192107689995742653">"Uobičajena važnost"</string>
<string name="high_importance" msgid="1527066195614050263">"Velika važnost"</string>
<string name="max_importance" msgid="5089005872719563894">"Važnost: hitno"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Ova obaveštenja se nikada ne prikazuju"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Prikazuju se u dnu liste obaveštenja bez zvuka"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Ova obaveštenja se prikazuju bez zvuka"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Prikazuju se u vrhu liste obaveštenja i emituje se zvuk"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Nakratko se prikazuju na ekranu i emituje se zvuk"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Prikazuju se u dnu liste obaveštenja bez zvuka"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Ova obaveštenja se prikazuju bez zvuka"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Dozvolite da ova obaveštenja emituju zvuk"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Nakratko se prikazuju na ekranu i emituju zvuk"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Prikazuju se u vrhu liste obaveštenja, nakratko se prikazuju na ekranu i emituju zvuk"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Još podešavanja"</string>
<string name="notification_done" msgid="5279426047273930175">"Gotovo"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Normalne boje"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Noćne boje"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Prilagođene boje"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automatski"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Nepoznate boje"</string>
- <string name="color_transform" msgid="6985460408079086090">"Izmena boja"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Prikaži pločicu Brza podešavanja"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Omogući prilagođenu transformaciju"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Boja i izgled"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Noćni režim"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Kalibrišite ekran"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Uključeno"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Isključeno"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Automatski uključi"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Pređite na noćni režim u zavisnosti od lokacije i doba dana"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Kada je noćni režim uključen"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Koristi tamnu temu za Android OS"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Prilagodi senku"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Prilagodi osvetljenost"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Tamna tema se primenjuje na ključne delove Android OS-a koji se obično prikazuju u svetloj temi, poput Podešavanja."</string>
<string name="color_apply" msgid="9212602012641034283">"Primeni"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Potvrdite podešavanja"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Neka podešavanja boja mogu da učine uređaj neupotrebljivim. Kliknite na Potvrdi da biste potvrdili ova podešavanja boja, pošto će se u suprotnom ova podešavanja resetovati nakon 10 sekundi."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Potrošnja baterije"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Ušteda baterije nije dostupna tokom punjenja"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Ušteda baterije"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Smanjuje performanse i pozadinske podatke"</string>
@@ -489,21 +498,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Početni"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Nedavni sadržaj"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Nazad"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Prikaži podešavanje Ne uznemiravaj u dijalogu za jačinu zvuka"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Dozvoljava potpunu kontrolu podešavanja Ne uznemiravaj u dijalogu za jačinu zvuka."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Jačina zvuka i Ne uznemiravaj"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Uđi u režim Ne uznemiravaj kada je zvuk utišan"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Prikaži sa kontrolama jačine zvuka"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ne uznemiravaj"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Prečica za dugmad za jačinu zvuka"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Izađi iz režima Ne uznemiravaj kada je zvuk pojačan"</string>
<string name="battery" msgid="7498329822413202973">"Baterija"</string>
<string name="clock" msgid="7416090374234785905">"Sat"</string>
<string name="headset" msgid="4534219457597457353">"Naglavne slušalice"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Slušalice su povezane"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Naglavne slušalice su povezane"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Omogućite ili onemogućite prikazivanje ikona na statusnoj traci."</string>
<string name="data_saver" msgid="5037565123367048522">"Ušteda podataka"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Ušteda podataka je uključena"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Ušteda podataka je isključena"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Uključeno"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Isključeno"</string>
<string name="nav_bar" msgid="1993221402773877607">"Traka za navigaciju"</string>
<string name="start" msgid="6873794757232879664">"Pokreni"</string>
<string name="center" msgid="4327473927066010960">"Centar"</string>
@@ -526,4 +534,21 @@
<string name="preview" msgid="9077832302472282938">"Pregled"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Prevucite da biste dodali pločice"</string>
<string name="qs_edit" msgid="2232596095725105230">"Izmeni"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Vreme"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Prikaži sate, minute i sekunde"</item>
+ <item msgid="1427801730816895300">"Prikaži sate i minute (podrazumevano)"</item>
+ <item msgid="3830170141562534721">"Ne prikazuj ovu ikonu"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Uvek prikazuj procenat"</item>
+ <item msgid="2139628951880142927">"Prikaži procenat tokom punjenja (podrazumevano)"</item>
+ <item msgid="3327323682209964956">"Ne prikazuj ovu ikonu"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Drugo"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Razdelnik podeljenog ekrana"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Pomeri nadole"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Pomeri nagore"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Pomeri ulevo"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Pomeri udesno"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index f407ac1..84757b7 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Екранната снимка е заснета."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Докоснете, за да видите екранната си снимка."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Екранната снимка не можа да бъде заснета."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Не може да се направи екр. снимка поради недостиг на място или забрана от прилож. или организацията ви."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Екранната снимка не може да се запази поради ограничено място в хранилището."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Правенето на екранни снимки не е разрешено от приложението или организацията ви."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Опции за пренос на файлове чрез USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Свързване като медиен плейър (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Свързване като камера (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Повече време."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"По-малко време."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Фенерчето е изключено."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Няма достъп до фенерчето."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Фенерчето е включено."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Фенерчето е изключено."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Фенерчето е включено."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"фиксиране на екрана"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"търсене"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> не можа да стартира."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Приложението <xliff:g id="APP">%s</xliff:g> е деактивирано в безопасния режим."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"История"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Изчистване"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Това приложение не поддържа няколко прозореца"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Приложението не поддържа няколко прозореца"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Хоризонтално разделяне"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Вертикално разделяне"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Персонализирано разделяне"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Пълна\nтишина"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Само\nс приоритет"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Само\nбудилници"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Всички"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Всички\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Зарежда се бавно (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> до пълно зареждане)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Показване на секундите на часовника в лентата на състоянието. Може да се отрази на живота на батерията."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Пренареждане на бързите настройки"</string>
<string name="show_brightness" msgid="6613930842805942519">"Показване на яркостта от бързите настройки"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Актив. на жеста за разделен екран с прек. на пръст нагоре"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Разделяне на екрана с прекарване на пръст нагоре: Активиране"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Активиране на жеста за влизане в режим на разделен екран чрез прокарване на пръст нагоре от бутона за общ преглед"</string>
<string name="experimental" msgid="6198182315536726162">"Експериментални"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Да се включи ли Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"За да свържете клавиатурата с таблета си, първо трябва да включите Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Включване"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Прилагане за известията на тема „<xliff:g id="TOPIC_NAME">%1$s</xliff:g>“"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Прилагане за всички известия от това приложение"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Показване на известията без звуков сигнал"</string>
+ <string name="block" msgid="2734508760962682611">"Блокиране на всички известия"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Без заглушаване на звуковите сигнали"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Без заглушаване на звуковите сигнали или блокиране"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Показване на пълните настройки за важността"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Блокирано"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Минимална важност"</string>
<string name="low_importance" msgid="4109929986107147930">"Малка важност"</string>
<string name="default_importance" msgid="8192107689995742653">"Нормална важност"</string>
<string name="high_importance" msgid="1527066195614050263">"Голяма важност"</string>
<string name="max_importance" msgid="5089005872719563894">"Неотложна важност"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Тези известия не се показват"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Беззвучно показване най-долу в списъка с известия"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Тези известия се показват без звук"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Показване най-горе в списъка с известия и издаване на звуков сигнал"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Показване на екрана и издаване на звуков сигнал"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Показване без звуков сигнал най-долу в списъка с известия"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Показване на тези известия без звуков сигнал"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Разрешаване при тези известия да се издава звуков сигнал"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Показване на екрана и разрешаване на звуков сигнал"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Показване най-горе в списъка с известия, както и на екрана и разрешаване на звуков сигнал"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Още настройки"</string>
<string name="notification_done" msgid="5279426047273930175">"Готово"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Нормални цветове"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Нощни цветове"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Персонализирани цветове"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Автоматично"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Неизвестни цветове"</string>
- <string name="color_transform" msgid="6985460408079086090">"Промяна на цветовете"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Показване на плочката за бързи настройки"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Активиране на персонализираното трансформиране"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Цвят и облик"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Нощен режим"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Калибриране на дисплея"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Вкл."</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Изкл."</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Автоматично включване"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Превключване към нощен режим според местоположението и часа от денонощието"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"При включен нощен режим"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Ползв. на тъмната тема за опер. с-ма Android"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Коригиране на нюансирането"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Коригиране на яркостта"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Тъмната тема се прилага към основните области на операционната система Android, които обикновено се показват със светла тема, като например настройките."</string>
<string name="color_apply" msgid="9212602012641034283">"Прилагане"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Потвърждаване на настройките"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Някои настройки за цветовете могат да направят това устройство неизползваемо. За да ги потвърдите, кликнете върху „OK“. В противен случай те ще бъдат нулирани след 10 секунди."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Ползв. на батерията"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Режимът за запазване на батерията не е налице при зареждане"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Режим за запазване на батерията"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Намалява ефективността и данните на заден план"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Начало"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Скорошни"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Назад"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Показване на „Не безпокойте“ в прозореца за силата на звука"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Достъп до всички опции за управление на „Не безпокойте“ в диалоговия прозорец за силата на звука."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Сила на звука и „Не безпокойте“"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Вкл. на „Не безпокойте“ при намаляване на силата на звука"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Показване с контролите за силата на звука"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Не безпокойте"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Пряк път към бутоните за силата на звука"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Изкл. на „Не безпокойте“ при увеличаване на силата на звука"</string>
<string name="battery" msgid="7498329822413202973">"Батерия"</string>
<string name="clock" msgid="7416090374234785905">"Часовник"</string>
<string name="headset" msgid="4534219457597457353">"Слушалки"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Слушалките (без микрофон) са свързани"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Слушалките са свързани"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Активиране или деактивиране на показването на икони в лентата на състоянието."</string>
<string name="data_saver" msgid="5037565123367048522">"Икономия на данни"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Функцията „Икономия на данни“ е включена"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Функцията „Икономия на данни“ е изключена"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Вкл."</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Изкл."</string>
<string name="nav_bar" msgid="1993221402773877607">"Лента за навигация"</string>
<string name="start" msgid="6873794757232879664">"Начало"</string>
<string name="center" msgid="4327473927066010960">"Център"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Визуализация"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Преместете с плъзгане, за да добавите плочки"</string>
<string name="qs_edit" msgid="2232596095725105230">"Редактиране"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Час"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Показване на часовете, минутите и секундите"</item>
+ <item msgid="1427801730816895300">"Показване на часовете и минутите (по подразбиране)"</item>
+ <item msgid="3830170141562534721">"Тази икона да не се показва"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Процентът винаги да се показва"</item>
+ <item msgid="2139628951880142927">"Процентът да се показва при зареждане (по подразбиране)"</item>
+ <item msgid="3327323682209964956">"Тази икона да не се показва"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Друго"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Разделител в режима за разделен екран"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Преместване надолу"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Преместване нагоре"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Преместване наляво"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Преместване надясно"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index 988e02e..18f37e6 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"স্ক্রীনশট নেওয়া হযেছে৷"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"আপনার স্ক্রীনশট দেখতে স্পর্শ করুন৷"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"স্ক্রীনশট নেওয়া যায়নি৷"</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"সঞ্চয়স্থান সীমিত হওয়ার ফলে স্ক্রীনশট নেওয়া যাবে না, অথবা এটি অ্যাপ্লিকেশানটি অথবা আপনার প্রতিষ্ঠানের দ্বারা অনুমোদিত নয়৷"</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"সঞ্চয়স্থান সীমিত থাকায় স্ক্রীনশটটি সংরক্ষণ করা যাবে না৷"</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"অ্যাপ্লিকেশান বা আপনার প্রতিষ্ঠান স্ক্রীনশটগুলি নেওয়া অনুমতি দেয়নি৷"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB ফাইল স্থানান্তরের বিকল্পগুলি"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"একটি মিডিয়া প্লেয়ার হিসাবে মাউন্ট করুন (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"একটি ক্যামেরা হিসাবে মাউন্ট করুন (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"বেশি সময়।"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"কম সময়।"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ফ্ল্যাশলাইট বন্ধ আছে।"</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ফ্ল্যাশলাইট অনুপলব্ধ৷"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ফ্ল্যাশলাইট চালু আছে।"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ফ্ল্যাশলাইট বন্ধ হয়েছে।"</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ফ্ল্যাশলাইট চালু হয়েছে।"</string>
@@ -304,6 +306,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"নিরাপদ মোডে <xliff:g id="APP">%s</xliff:g> অক্ষম করা হয়েছে৷"</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"ইতিহাস"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"সাফ করুন"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"এই অ্যাপ্লিকেশানটি মাল্টি-উইন্ডো সমর্থন করে না"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"অ্যাপ্লিকেশানগুলি মাল্টি-উইন্ডো সমর্থন করে না"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"অনুভূমিক স্প্লিট"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"উল্লম্ব স্প্লিট"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"কাস্টম স্প্লিট করুন"</string>
@@ -333,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"একদম\nনিরব"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"শুধুমাত্র\nঅগ্রাধিকার"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"শুধুমাত্র\nঅ্যালার্মগুলি"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"সমস্ত"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"সমস্ত\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"ধীরে ধীরে চার্জ হচ্ছে (পূর্ণ হতে <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> সময় বাকি)"</string>
@@ -447,34 +449,43 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"স্থিতি দন্ডে ঘড়ির সেকেন্ড দেখায়৷ ব্যাটারি লাইফকে প্রভাবিত করতে পারে৷"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"দ্রুত সেটিংসে পুনরায় সাজান"</string>
<string name="show_brightness" msgid="6613930842805942519">"দ্রুত সেটিংসে উজ্জ্বলতা দেখান"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"অ্যাকসেলেটর উপরের দিকে সোয়াইপ করে বিভক্ত-স্ক্রীন সক্ষম করুন"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"উপরের দিকে সোয়াইপ করে বিভক্ত-স্ক্রীনে প্রবেশ করার অঙ্গভঙ্গি সক্ষম করুন"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"\'এক নজরে\' বোতাম থেকে উপরের দিকে সোয়াইপ করে, বিভক্ত-স্ক্রীনে প্রবেশ করতে অঙ্গভঙ্গি সক্ষম করুন"</string>
<string name="experimental" msgid="6198182315536726162">"পরীক্ষামূলক"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth চালু করবেন?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"আপনার ট্যাবলেটের সাথে আপনার কীবোর্ড সংযুক্ত করতে, আপনাকে প্রথমে Bluetooth চালু করতে হবে।"</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"চালু করুন"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> বিজ্ঞপ্তিগুলিতে প্রয়োগ করুন"</string>
- <string name="apply_to_app" msgid="363016783939815960">"এই অ্যাপ্লিকেশনের থেকে সব বিজ্ঞপ্তিতে প্রয়োগ করুন"</string>
+ <string name="show_silently" msgid="6841966539811264192">"নীরবভাবে বিজ্ঞপ্তিগুলি দেখায়"</string>
+ <string name="block" msgid="2734508760962682611">"সমস্ত বিজ্ঞপ্তি অবরুদ্ধ করুন"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"নীরব করবেন না"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"নীরব বা অবরুদ্ধ করবেন না"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"সম্পূর্ণ গুরুত্বপূর্ণ সেটিংস দেখায়"</string>
<string name="blocked_importance" msgid="5198578988978234161">"অবরুদ্ধ"</string>
+ <string name="min_importance" msgid="1901894910809414782">"ন্যূনতম গুরুত্ব"</string>
<string name="low_importance" msgid="4109929986107147930">"কম গুরুত্ব"</string>
<string name="default_importance" msgid="8192107689995742653">"সাধারণ গুরুত্ব"</string>
<string name="high_importance" msgid="1527066195614050263">"বেশি গুরুত্ব"</string>
<string name="max_importance" msgid="5089005872719563894">"জরুরি গুরুত্ব"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"এই বিজ্ঞপ্তিগুলি কখনোই দেখানো হবে না"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"বিজ্ঞপ্তি তালিকার নীচের অংশে নিঃশব্দে দেখানো হয়"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"নিঃশব্দে এই বিজ্ঞপ্তিগুলি দেখানো হয়"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"বিজ্ঞপ্তি তালিকার শীর্ষে দেখানো হয় এবং শব্দ করে"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"স্ক্রীনের উপরে দেখানো হয় এবং শব্দ করে"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"বিজ্ঞপ্তি তালিকার নীচের অংশে নিঃশব্দে দেখানো হয়"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"নিঃশব্দে এই বিজ্ঞপ্তিগুলি দেখানো হয়"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"এই বিজ্ঞপ্তিগুলিকে শব্দ করার মঞ্জুরি দেয়"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"স্ক্রীনের উপরে প্রদর্শিত এবং শব্দ করার মঞ্জুরি দেয়"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"বিজ্ঞপ্তি তালিকার শীর্ষে দেখানো হয় এবং স্ক্রীনের উপরে প্রদর্শিত এবং শব্দ করার মঞ্জুরি দেয়"</string>
<string name="notification_more_settings" msgid="816306283396553571">"আরো সেটিংস"</string>
<string name="notification_done" msgid="5279426047273930175">"সম্পন্ন"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"স্বাভাবিক রঙ"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"রাতের রঙ"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"কাস্টম রঙ"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"স্বয়ংক্রিয়ভাবে"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"অজানা রঙ"</string>
- <string name="color_transform" msgid="6985460408079086090">"রঙ সংশোধন"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"দ্রুত সেটিংস টাইল দেখান"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"কাস্টম রূপান্তর সক্ষম করুন"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"রঙ এবং চেহারা"</string>
+ <string name="night_mode" msgid="3540405868248625488">"রাতের মোড"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"প্রদর্শন ক্যালিব্রেট করুন"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"চালু আছে"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"বন্ধ আছে"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"স্বয়ংক্রিয়ভাবে চালু করুন"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"অবস্থান এবং সময়ের হিসাবে উপযুক্ত রাতের মোডে পাল্টান"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"যখন রাতের মোড চালু থাকবে"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Android OS এর জন্য গাঢ় থিম ব্যবহার করুন"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"টিন্ট সমন্বয় করুন"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"উজ্জ্বলতা সমন্বয় করুন"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Android OS এর মূল অংশগুলিতে গাঢ় থিম প্রয়োগ করা হয়েছে যেটা সাধারণত একটি হালকা থিমে প্রদর্শিত হয়, যেমন সেটিংস৷"</string>
<string name="color_apply" msgid="9212602012641034283">"প্রয়োগ করুন"</string>
<string name="color_revert_title" msgid="4746666545480534663">"সেটিংস নিশ্চিত করুন"</string>
<string name="color_revert_message" msgid="9116001069397996691">"কিছু রঙের সেটিংস এই ডিভাইসকে ব্যবহারের অযোগ্য করে দিতে পারে৷ এই রঙের সেটিংস নিশ্চিত করতে ওকে এ ক্লিক করুন, অন্যথায় ১০ সেকেন্ড পরে এই সেটিংস পুনরায় সেট হবে৷"</string>
@@ -486,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"হোম"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"সাম্প্রতিকগুলি"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"পিছনে"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"ভলিউমে \'বিরক্ত করবেন না\' দেখাবেন না"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"ভলিউম ডায়লগে \"বিরক্ত করবেন না\" এর পূর্ণ নিয়ন্ত্রণের মঞ্জুরি দিন৷"</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"ভলিউম এবং \'বিরক্ত করবেন না\'"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"ভলিউম কমানোর মাধ্যেমে \'বিরক্ত করবেন না\' চালু করুন"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"ভলিউম নিয়ন্ত্রণ সহ দেখান"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"বিরক্ত করবেন না"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"ভলিউম বোতামের শর্টকাট"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"ভলিউম বাড়ানোর মাধ্যেমে \'বিরক্ত করবেন না\' থেকে প্রস্থান করুন"</string>
<string name="battery" msgid="7498329822413202973">"ব্যাটারি"</string>
<string name="clock" msgid="7416090374234785905">"ঘড়ি"</string>
<string name="headset" msgid="4534219457597457353">"হেডসেট"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"হেডফোনগুলি সংযুক্ত হয়েছে"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"হেডসেট সংযুক্ত হয়েছে"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"স্থিতি দন্ডে দেখানোর জন্য আইকনগুলিকে সক্ষম বা অক্ষম করুন৷"</string>
<string name="data_saver" msgid="5037565123367048522">"ডেটা সেভার"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"ডেটা সেভার চালু আছে"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"ডেটা সেভার বন্ধ আছে"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"চালু আছে"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"বন্ধ আছে"</string>
<string name="nav_bar" msgid="1993221402773877607">"নেভিগেশন দন্ড"</string>
<string name="start" msgid="6873794757232879664">"শুরু করুন"</string>
<string name="center" msgid="4327473927066010960">"কেন্দ্র"</string>
@@ -523,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"পূর্বরূপ দেখুন"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"টাইলগুলি যোগ করার জন্য টেনে আনুন"</string>
<string name="qs_edit" msgid="2232596095725105230">"সম্পাদনা করুন"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"সময়"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"ঘন্টা, মিনিট, এবং সেকেন্ড দেখান"</item>
+ <item msgid="1427801730816895300">"ঘন্টা এবং মিনিট দেখান (ডিফল্ট)"</item>
+ <item msgid="3830170141562534721">"এই আইকনটি দেখাবেন না"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"সর্বদা শতাংশ দেখান"</item>
+ <item msgid="2139628951880142927">"চার্জ করার সময় শতাংশ দেখান (ডিফল্ট)"</item>
+ <item msgid="3327323682209964956">"এই আইকনটি দেখাবেন না"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"অন্যান্য"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"বিভক্ত-স্ক্রীন বিভাজক"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"নীচে সরান"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"উপরে সরান"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"বাঁয়ে সরান"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"ডানে সরান"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bs-rBA/strings.xml b/packages/SystemUI/res/values-bs-rBA/strings.xml
index 2be74a0..5666c5f 100644
--- a/packages/SystemUI/res/values-bs-rBA/strings.xml
+++ b/packages/SystemUI/res/values-bs-rBA/strings.xml
@@ -74,7 +74,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Ekran snimljen."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Dodirnite za prikaz snimka ekrana."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Došlo je do greške prilikom snimanja ekrana."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Ekran se ne može snimiti zbog manjka prostora, ili to ne dopuštaju aplikacija ili vaša organizacija."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Snimak ekrana se ne može sačuvati zbog manjka prostora za pohranu."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Aplikacija ili vaša organizacija ne dopuštaju pravljenje snimaka ekrana."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Opcije USB prijenosa fajlova"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Reproduciranje medijskih sadržaja (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Priključiti kao kameru (PTP)"</string>
@@ -207,6 +208,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Više vremena."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Manje vremena."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Svjetiljka isključena."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Svjetiljka nije dostupna."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Svjetiljka uključena."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Svjetiljka je isključena."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Svjetiljka je uključena."</string>
@@ -302,10 +304,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"kačenje ekrana"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"pretraga"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikacija <xliff:g id="APP">%s</xliff:g> nije pokrenuta."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> je onemogućena u sigurnom načinu rada."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Historija"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Obriši"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Ova aplikacija ne podržava rad sa više prozora"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Aplikacija ne podržava rad sa više prozora"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Podjela po horizontali"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Podjela po vertikali"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Prilagođena podjela"</string>
@@ -335,8 +338,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Potpuna\ntišina"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Samo\nprioritetni prekidi"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Samo\nalarmi"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Svi"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Svi \n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Punjenje (do kraja preostalo <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Brzo punjenje (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do pune baterije)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Sporo punjenje (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do pune baterije)"</string>
@@ -449,39 +450,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Prikaži sekunde na statusnoj traci. Može skratiti trajanje baterije."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Preuredi \"Brze postavke\""</string>
<string name="show_brightness" msgid="6613930842805942519">"Prikaži osvjetljenje u opciji \"Brze postavke\""</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Uključi akcelerator za dijeljenje ekrana prevlačenjem nagore"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Omogućiti potez za podjelu ekrana prevlačenjem prema gore"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Uključite pokrete prstima da biste ušli u podijeljeni ekran tako što ćete od dugmeta Pregled prevući prstom prema gore"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimentalno"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Želiti li uključiti Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Da povežete tastaturu sa tabletom, prvo morate uključiti Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Uključi"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Primijeni na obavještenja koja se odnose na temu <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Primijeni na sva obavještenja ove aplikacije"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Nečujno pokaži obavijesti"</string>
+ <string name="block" msgid="2734508760962682611">"Blokiraj sva obavještenja"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Nemoj utišati"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Nemoj utišati ili blokirati"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Pokaži kompletne postavke za određivanje značaja"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Blokirano"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Minimalni značaj"</string>
<string name="low_importance" msgid="4109929986107147930">"Mali značaj"</string>
<string name="default_importance" msgid="8192107689995742653">"Normalan značaj"</string>
<string name="high_importance" msgid="1527066195614050263">"Visok značaj"</string>
<string name="max_importance" msgid="5089005872719563894">"Hitan značaj"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Nikada ne prikazuj ova obavještenja"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Nečujno pokaži na dnu spiska obavještenja"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Nečujno prikaži ova obavještenja"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Pokaži na vrhu spiska obavještanja uz zvuk"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Kratki prikaz na ekranu uz zvuk"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Nečujno pokaži na dnu spiska obavještenja"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Nečujno prikaži ova obavještenja"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Dozvolite zvuk na ovim obavještenjima"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Kratko prikaži na ekranu i dozvoli zvuk i dozvoli zvuk"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Pokaži na vrhu liste obaveštenja, kratko prikaži na ekranu i dozvoli zvuk"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Više postavki"</string>
<string name="notification_done" msgid="5279426047273930175">"Gotovo"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Standardne boje"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Boje za noćni rad"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Prilagođene boje"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automatski"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Nepoznate boje"</string>
- <string name="color_transform" msgid="6985460408079086090">"Izmjena boja"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Prikaži polje \"Brze postavke\""</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Uključi prilagođenu transformaciju"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Boja i izgled"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Noćni način rada"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Kalibracija zaslona"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Uključeno"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Isključeno"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Automatsko uključivanje"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Prebaciti u Noćni način rada u skladu sa lokacijom i dobom dana"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Kada je Noćni režim rada uključen"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Koristiti tamne teme za OS Android"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Prilagođavanje nijanse"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Podešavanje osvijetljenosti"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Tamna tema se primjenjuje na ključna područja OS Android koja se obično prikazuju u svijetloj temi, kao što je meni Postavke."</string>
<string name="color_apply" msgid="9212602012641034283">"Prihvati"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Potvrdi postavke"</string>
<string name="color_revert_message" msgid="9116001069397996691">"S nekim postavkama boja ovaj uređaj može biti neupotrebljiv. Kliknite U redu da biste potvrdili ove postavke boja ili sačekajte 10 sekundi da se postavke vrate na početnu vrijednost."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Upotreba baterije"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Ušteda baterije je isključena prilikom punjenja"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Ušteda baterije"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Ograničava rad i prijenos podataka u pozadini"</string>
@@ -489,21 +498,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Početak"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Nedavni ekrani"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Nazad"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Prikaži režim Ne ometaj u dijalogu za jačinu zvuka."</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Dopusti punu kontrolu režima Ne ometaj u dijalogu za jačinu zvuka."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Jačina zvuka i režim Ne ometaj"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Aktiviraj režim Ne ometaj kada se zvuk utiša"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Prikazati sa kontrolama jačine zvuka"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ne ometaj"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Prečica za dugmad za Jačinu zvuka"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Deaktiviraj režim Ne ometaj kada se zvuk pojača"</string>
<string name="battery" msgid="7498329822413202973">"Baterija"</string>
<string name="clock" msgid="7416090374234785905">"Sat"</string>
<string name="headset" msgid="4534219457597457353">"Slušalice s mikrofonom"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Slušalice su priključene"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Slušalice s mikrofonom su priključene"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Uključite ili isključite prikaz ikona na statusnoj traci."</string>
<string name="data_saver" msgid="5037565123367048522">"Ušteda podataka"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Ušteda podataka je uključena"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Ušteda podataka je isključena"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Uključeno"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Isključi"</string>
<string name="nav_bar" msgid="1993221402773877607">"Navigaciona traka"</string>
<string name="start" msgid="6873794757232879664">"Početak"</string>
<string name="center" msgid="4327473927066010960">"Sredina"</string>
@@ -526,4 +534,21 @@
<string name="preview" msgid="9077832302472282938">"Pregledaj"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Povucite da biste dodali polja"</string>
<string name="qs_edit" msgid="2232596095725105230">"Uredi"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Vrijeme"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Prikaži sate, minute i sekunde"</item>
+ <item msgid="1427801730816895300">"Prikaži sate i minute (zadano)"</item>
+ <item msgid="3830170141562534721">"Ne prikazuj ovu ikonu"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Uvijek prikaži postotak"</item>
+ <item msgid="2139628951880142927">"Pokaži postotak u toku punjenja (zadano)"</item>
+ <item msgid="3327323682209964956">"Ne prikazuj ovu ikonu"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Ostalo"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Razdjelnik ekrana"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Pomjeri dolje"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Pomjeri gore"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Pomjeri lijevo"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Pomjeri desno"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 55ab02a..3747be0 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"S\'ha fet una captura de pantalla."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Toca per veure la captura de pantalla."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"No s\'ha pogut fer una captura de pantalla."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"No es pot fer la captura perquè no hi ha prou espai, o l\'organització o l\'aplicació no ho permet."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"La captura de pantalla no es pot desar perquè no hi ha prou espai d\'emmagatzematge."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"L\'aplicació o l\'organització no permeten fer captures de pantalla."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Opcions transf. fitxers USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Munta com a reproductor multimèdia (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Munta com a càmera (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Més temps"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Menys temps"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Llanterna desactivada"</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"La llanterna no està disponible."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Llanterna activada"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Llanterna desactivada."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Llanterna activada."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixació de pantalla"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"No s\'ha pogut iniciar <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"En mode segur, l\'aplicació <xliff:g id="APP">%s</xliff:g> està desactivada."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Historial"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Esborra"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Aquesta aplicació no admet el mode multifinestra"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"L\'aplicació no admet el mode multifinestra"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisió horitzontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisió vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisió personalitzada"</string>
@@ -334,8 +337,6 @@
<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="interruption_level_all" msgid="1330581184930945764">"Totes"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Totes\n"</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>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra els segons del rellotge a la barra d\'estat. Això pot afectar la durada de la bateria."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Reorganitza Configuració ràpida"</string>
<string name="show_brightness" msgid="6613930842805942519">"Mostra la brillantor a Configuració ràpida"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Activa la pantalla dividida en lliscar amunt"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Activa el gest per dividir la pantalla en lliscar cap amunt"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Activa el gest per entrar al mode de pantalla dividida en lliscar cap amunt des del botó Visió general"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Vols activar el Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Per connectar el teclat amb la tauleta, primer has d\'activar el Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Activa"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Aplica a les notificacions sobre <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Aplica a totes les notificacions d\'aquesta aplicació"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Mostra les notificacions de manera silenciosa"</string>
+ <string name="block" msgid="2734508760962682611">"Bloqueja totes les notificacions"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"No silenciïs"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"No silenciïs ni bloquegis"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Mostra la configuració de la importància completa"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloquejades"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Importància mínima"</string>
<string name="low_importance" msgid="4109929986107147930">"Importància baixa"</string>
<string name="default_importance" msgid="8192107689995742653">"Importància normal"</string>
<string name="high_importance" msgid="1527066195614050263">"Importància alta"</string>
<string name="max_importance" msgid="5089005872719563894">"Importància urgent"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"No mostris mai aquestes notificacions"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Mostra de manera silenciosa a la part inferior de la llista de notificacions"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Mostra aquestes notificacions de manera silenciosa"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Mostra a la part superior de la llista de notificacions i emet un so"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Mostra a la pantalla i emet un so"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Les notificacions es mostren de manera silenciosa al capdavall de la llista"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Mostra aquestes notificacions de manera silenciosa"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Permet que aquestes notificacions emetin sons"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Les notificacions apareixen a la pantalla i poden emetre sons"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Les notificacions es mostren al capdamunt de la llista, apareixen a la pantalla i poden emetre sons"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Més opcions"</string>
<string name="notification_done" msgid="5279426047273930175">"Fet"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Colors normals"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Colors nocturns"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Colors personalitzats"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automàtica"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Colors desconeguts"</string>
- <string name="color_transform" msgid="6985460408079086090">"Modificació del color"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Mostra el mosaic de Configuració ràpida"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Activa la transformació personalitzada"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Color i aparença"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Mode nocturn"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Calibra la pantalla"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Activat"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Desactivat"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Activa automàticament"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Canvia al mode nocturn d\'acord amb la ubicació i l\'hora del dia"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Quan el mode nocturn estigui activat"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Fes servir un tema fosc per a Android OS"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Ajusta el color"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Ajusta la brillantor"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"El tema fosc s\'aplica a les àrees clau d\'Android OS que normalment es mostren amb un tema clar, com ara Configuració."</string>
<string name="color_apply" msgid="9212602012641034283">"Aplica"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirma la configuració"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Algunes opcions de configuració de color poden deixar el dispositiu inservible. Fes clic a D\'acord per confirmar la configuració de color; en cas contrari, la configuració es restablirà al cap de 10 segons."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Ús 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_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>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Inici"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recents"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Enrere"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Mostra el mode No molesteu al volum"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Permet el control complet del mode No molesteu al quadre de diàleg de volum."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Volum i mode No molesteu"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Activa el mode No molesteu abaixant el volum"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostra amb els controls de volum"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"No molesteu"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Drecera per als botons de volum"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Desactiva el mode No molesteu apujant el volum"</string>
<string name="battery" msgid="7498329822413202973">"Bateria"</string>
<string name="clock" msgid="7416090374234785905">"Rellotge"</string>
<string name="headset" msgid="4534219457597457353">"Auriculars"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Auriculars connectats"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Auriculars connectats"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Activa o desactiva les icones a la barra d\'estat."</string>
<string name="data_saver" msgid="5037565123367048522">"Economitzador de dades"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"L\'extensió Economitzador de dades està activada"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"L\'extensió Economitzador de dades està desactivada"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Activat"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Desactivat"</string>
<string name="nav_bar" msgid="1993221402773877607">"Barra de navegació"</string>
<string name="start" msgid="6873794757232879664">"Inici"</string>
<string name="center" msgid="4327473927066010960">"Centre"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Previsualització"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Arrossega per afegir camps"</string>
<string name="qs_edit" msgid="2232596095725105230">"Edita"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Hora"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Mostra les hores, els minuts i els segons"</item>
+ <item msgid="1427801730816895300">"Mostra les hores i els minuts (opció predeterminada)"</item>
+ <item msgid="3830170141562534721">"No mostris aquesta icona"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Mostra sempre el percentatge"</item>
+ <item msgid="2139628951880142927">"Mostra el percentatge quan es carregui (opció predeterminada)"</item>
+ <item msgid="3327323682209964956">"No mostris aquesta icona"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Altres"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Divisor de pantalles"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Mou avall"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Mou amunt"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Mou a l\'esquerra"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Mou a la dreta"</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index a1423cb..48c9c55 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -75,7 +75,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Snímek obrazovky Snímek obrazovky pořízen."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Snímek obrazovky zobrazíte dotykem."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Snímek obrazovky se nepodařilo zachytit."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Snímek obrazovky nelze pořídit kvůli nedostatku místa, nebo to aplikace či vaše organizace zakazuje."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Snímek obrazovky nelze pořídit kvůli nedostatku místa v úložišti."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Aplikace nebo organizace zakazuje pořizování snímků obrazovky."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Možnosti přenosu souborů pomocí rozhraní USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Připojit jako přehrávač médií (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Připojit jako fotoaparát (PTP)"</string>
@@ -208,6 +209,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Delší doba"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Kratší doba"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Svítilna je vypnutá."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Svítilna není k dispozici."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Svítilna je zapnutá."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Svítilna je vypnutá."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Svítilna je zapnutá."</string>
@@ -303,10 +305,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"připnutí obrazovky"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"vyhledat"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikaci <xliff:g id="APP">%s</xliff:g> nelze spustit."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Aplikace <xliff:g id="APP">%s</xliff:g> je v nouzovém režimu zakázána."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Historie"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Vymazat"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Tato aplikace režim v několika oknech nepodporuje"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Aplikace režim v několika oknech nepodporuje"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Vodorovné rozdělení"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikální rozdělení"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Vlastní rozdělení"</string>
@@ -336,8 +339,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Úplné\nticho"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Pouze\nprioritní"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Pouze\nbudíky"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Vše"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Všechna\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Nabíjení (plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Rychlé nabíjení (plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Pomalé nabíjení (plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
@@ -450,39 +451,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Na stavovém řádku se bude zobrazovat sekundová ručička. Může být ovlivněna výdrž baterie."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Změnit uspořádání Rychlého nastavení"</string>
<string name="show_brightness" msgid="6613930842805942519">"Zobrazit jas v Rychlém nastavení"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Aktivovat rozdělenou obrazovku přejetím prstem"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Aktivovat rozdělenou obrazovku přejetím prstem nahoru"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Umožňuje aktivovat rozdělenou obrazovku přejetím prstem nahoru od tlačítka Přehled."</string>
<string name="experimental" msgid="6198182315536726162">"Experimentální"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Zapnout Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Chcete-li klávesnici připojit k tabletu, nejdříve musíte zapnout Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Zapnout"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Použít u oznámení z aplikace <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Použít u všech oznámení z této aplikace"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Zobrazovat oznámení tiše"</string>
+ <string name="block" msgid="2734508760962682611">"Blokovat všechna oznámení"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Bez ztlumení"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Bez ztlumení a blokování"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Zobrazit všechna nastavení důležitosti"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Blokováno"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Minimální důležitost"</string>
<string name="low_importance" msgid="4109929986107147930">"Nízká důležitost"</string>
<string name="default_importance" msgid="8192107689995742653">"Normální důležitost"</string>
<string name="high_importance" msgid="1527066195614050263">"Vysoká důležitost"</string>
<string name="max_importance" msgid="5089005872719563894">"Urgentní důležitost"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Tato oznámení nikdy nezobrazovat"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Tato oznámení zobrazovat na konci seznamu bez zvukového upozornění"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Tato oznámení zobrazovat bez zvukového upozornění"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Tato oznámení zobrazovat na začátku seznamu a upozornit na ně zvukem"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Tato oznámení zobrazovat přímo na obrazovce a upozornit na ně zvukem"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Tato oznámení zobrazovat na konci seznamu bez zvukového upozornění"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Tato oznámení zobrazovat bez zvukového upozornění"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Povolit těmto oznámením vydávat zvuky"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Tato oznámení zobrazovat přímo na obrazovce a upozornit na ně zvukem"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Tato oznámení zobrazovat na začátku seznamu, zobrazit přímo na obrazovce a upozornit na ně zvukem"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Další nastavení"</string>
<string name="notification_done" msgid="5279426047273930175">"Hotovo"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Normální barvy"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Noční barvy"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Vlastní barvy"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automaticky"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Neznámé barvy"</string>
- <string name="color_transform" msgid="6985460408079086090">"Změna barev"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Zobrazit dlaždici Rychlé nastavení"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Umožnit převod na vlastní barvy"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Barva a vzhled"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Noční režim"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Kalibrovat displej"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Zapnuto"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Vypnuto"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Zapnout automaticky"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Přejít do nočního režimu automaticky na základě místa a denní doby"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Když je noční režim zapnutý"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Použít v systému Android tmavý motiv"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Upravit tónování"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Upravit jas"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"V hlavních oblastech systému Android, které jsou běžně zobrazovány ve světlém motivu (například Nastavení), se použije tmavý motiv."</string>
<string name="color_apply" msgid="9212602012641034283">"Použít"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Ověření nastavení"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Některá nastavení barev mohou způsobit, že zařízení nebude použitelné. Kliknutím na OK toto nastavení barev potvrdíte, v opačném případě se nastavení po 10 sekundách resetuje."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Využití baterie"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Spořič baterie při nabíjení není k dispozici."</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Spořič baterie"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Omezuje výkon a data na pozadí"</string>
@@ -490,21 +499,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Plocha"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Poslední"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Zpět"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Zobrazovat panel Nerušit v dialogu Hlasitost"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Umožňuje povolit úplné ovládání režimu Nerušit v dialogu Hlasitost."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Hlasitost a režim Nerušit"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Při snížení hlasitosti přejít do režimu Nerušit"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Zobrazit včetně ovládacích prvků hlasitosti"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Nerušit"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Zkratka tlačítek hlasitosti"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Při zvýšení hlasitosti ukončit režim Nerušit"</string>
<string name="battery" msgid="7498329822413202973">"Baterie"</string>
<string name="clock" msgid="7416090374234785905">"Hodiny"</string>
<string name="headset" msgid="4534219457597457353">"Náhlavní souprava"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Sluchátka připojena"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Náhlavní souprava připojena"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Umožňuje aktivovat nebo deaktivovat zobrazení ikon na stavovém řádku."</string>
<string name="data_saver" msgid="5037565123367048522">"Spořič dat"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Spořič dat je zapnutý"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Spořič dat je vypnutý"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Zapnuto"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Vypnuto"</string>
<string name="nav_bar" msgid="1993221402773877607">"Navigační panel"</string>
<string name="start" msgid="6873794757232879664">"Začátek"</string>
<string name="center" msgid="4327473927066010960">"Střed"</string>
@@ -527,4 +535,21 @@
<string name="preview" msgid="9077832302472282938">"Náhled"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Dlaždice přidáte přetažením"</string>
<string name="qs_edit" msgid="2232596095725105230">"Upravit"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Čas"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Zobrazovat hodiny, minuty a sekundy"</item>
+ <item msgid="1427801730816895300">"Zobrazovat hodiny a minuty (výchozí nastavení)"</item>
+ <item msgid="3830170141562534721">"Tuto ikonu nezobrazovat"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Vždy zobrazovat procento"</item>
+ <item msgid="2139628951880142927">"Zobrazovat procento při nabíjení (výchozí nastavení)"</item>
+ <item msgid="3327323682209964956">"Tuto ikonu nezobrazovat"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Jiné"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Čára rozdělující obrazovku"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Přesunout dolů"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Přesunout nahoru"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Přesunout vlevo"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Přesunout vpravo"</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index b509dfa..50d01ea 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Skærmbilledet er gemt."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Tryk for at se dit skærmbillede."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Skærmbilledet kunne ikke tages."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Skærmbilledet kan ikke tages pga. begrænset lagerplads, eller det tillades ikke af appen eller din organisation."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Skærmbilledet kan ikke gemmes pga. begrænset lagerplads."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Appen eller din organisation tillader ikke, at du tager skærmbilleder."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Muligheder for USB-filoverførsel"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Isæt som en medieafspiller (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Isæt som et kamera (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Mere tid."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Mindre tid."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lommelygten er slået fra."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lommelygten er ikke tilgængelig."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lommelygten er slået til."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Lommelygten er slået fra."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Lommelygten er slået til."</string>
@@ -304,6 +306,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> er deaktiveret i sikker tilstand."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Historik"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Ryd"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Denne app understøtter ikke flere vinduer"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Appen understøtter ikke flere vinduer"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Opdel vandret"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Opdel lodret"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Opdel brugerdefineret"</string>
@@ -333,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Total\nstilhed"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Kun\nprioritet"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Kun\nalarmer"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Alle"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Alle\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Oplader (fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Hurtig opladning (fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Langsom opladning (fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
@@ -447,34 +449,43 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Vis sekunder i statuslinjen. Dette kan påvirke batteriets levetid."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Omarranger Hurtige indstillinger"</string>
<string name="show_brightness" msgid="6613930842805942519">"Vis lysstyrke i Hurtige indstillinger"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Aktivér bevægelsen stryg opad for at dele skærmen"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Aktivér bevægelsen Stryg opad for at dele skærmen"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Aktivér bevægelse for at dele skærmen ved at stryge opad fra knappen Oversigt"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimentel"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Vil du slå Bluetooth til?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Bluetooth skal være slået til, før du kan knytte dit tastatur til din tablet."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Slå til"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Anvend for underretninger vedrørende <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Anvend for alle underretninger fra denne app"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Vis underretninger lydløst"</string>
+ <string name="block" msgid="2734508760962682611">"Bloker alle underretninger"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Skal ikke sættes på lydløs"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Skal ikke sættes på lydløs eller blokeres"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Vis alle indstillinger for vigtighed"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Blokeret"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Min vigtighed"</string>
<string name="low_importance" msgid="4109929986107147930">"Lille vigtighed"</string>
<string name="default_importance" msgid="8192107689995742653">"Normal vigtighed"</string>
<string name="high_importance" msgid="1527066195614050263">"Stor vigtighed"</string>
<string name="max_importance" msgid="5089005872719563894">"Presserende vigtighed"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Vis aldrig disse underretninger"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Vis lydløst nederst på listen over underretninger"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Vis disse underretninger lydløst"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Vis øverst på listen over underretninger, og giv lyd"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Vis på skærmen, og giv lyd"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Vis lydløst nederst på listen over underretninger"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Vis disse underretninger lydløst"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Giv disse underretninger tilladelse til at give lyd"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Vis på skærmen, og tillad lyd"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Vis øverst på listen over underretninger, vis på skærmen, og tillad lyd"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Flere indstillinger"</string>
<string name="notification_done" msgid="5279426047273930175">"Færdig"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Almindelige farver"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Nattefarver"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Tilpassede farver"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automatisk"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Ukendte farver"</string>
- <string name="color_transform" msgid="6985460408079086090">"Farveændring"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Vis feltet Hurtige indstillinger"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Aktivér tilpasset farveændring"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Farve og udseende"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Nattilstand"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Kalibrer skærmen"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Til"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Fra"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Slå automatisk til"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Skift til natfunktion alt efter stedet og tidspunktet"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Når natfunktion er slået til"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Brug mørkt tema til Android OS"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Juster farvetonen"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Juster lysstyrken"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Det mørke tema anvendes på centrale områder i Android OS, der normalt vises med lyst tema, f.eks. Indstillinger."</string>
<string name="color_apply" msgid="9212602012641034283">"Anvend"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Bekræft indstillingerne"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Nogle farveindstillinger kan medføre, at du ikke kan bruge enheden. Klik på OK for at bekræfte disse farveindstillinger. Ellers nulstilles disse indstillinger efter ti sekunder."</string>
@@ -486,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Start"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Seneste"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Tilbage"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Vis Forstyr ikke i Lydstyrke"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Tillad fuld kontrol over Forstyr ikke i dialogboksen Lydstyrke."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Lydstyrke og Forstyr ikke"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Aktivér Forstyr ikke med Lydstyrke ned"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Vis med lydstyrkeregulering"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Forstyr ikke"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Genvej til lydstyrkeknapper"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Afslut Forstyr ikke med Lydstyrke op"</string>
<string name="battery" msgid="7498329822413202973">"Batteri"</string>
<string name="clock" msgid="7416090374234785905">"Ur"</string>
<string name="headset" msgid="4534219457597457353">"Headset"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Hovedtelefoner er tilsluttet"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset er forbundet"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Slå visning af ikoner i statusbjælken til eller fra."</string>
<string name="data_saver" msgid="5037565123367048522">"Datasparefunktion"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Datasparefunktionen er slået til"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Datasparefunktionen er slået fra"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Til"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Fra"</string>
<string name="nav_bar" msgid="1993221402773877607">"Navigationslinje"</string>
<string name="start" msgid="6873794757232879664">"Start"</string>
<string name="center" msgid="4327473927066010960">"I midten"</string>
@@ -523,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Eksempelvisning"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Træk for at tilføje felter"</string>
<string name="qs_edit" msgid="2232596095725105230">"Rediger"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Tid"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Vis timer, minutter og sekunder"</item>
+ <item msgid="1427801730816895300">"Vis timer og minutter (standard)"</item>
+ <item msgid="3830170141562534721">"Vis ikke dette ikon"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Vis altid procent"</item>
+ <item msgid="2139628951880142927">"Vis procent ved opladning (standard)"</item>
+ <item msgid="3327323682209964956">"Vis ikke dette ikon"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Andet"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Adskiller til delt skærm"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Flyt ned"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Flyt op"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Flyt til venstre"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Flyt til højre"</string>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 541f03e..fd8cf89 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot aufgenommen"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Zum Ansehen berühren"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Screenshot konnte nicht aufgenommen werden."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Screenshot nicht möglich. Entweder zu wenig Speicher oder die App/dein Unternehmen lässt dies nicht zu."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Speichern des Screenshots aufgrund von zu wenig Speicher nicht möglich."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Die App oder Ihr Unternehmen lässt das Erstellen von Screenshots nicht zu."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB-Dateiübertragungsoptionen"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Als Medienplayer (MTP) bereitstellen"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Als Kamera (PTP) bereitstellen"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Mehr Zeit"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Weniger Zeit"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Taschenlampe deaktiviert"</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Taschenlampe nicht verfügbar."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Taschenlampe aktiviert"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Die Taschenlampe ist deaktiviert."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Die Taschenlampe ist aktiviert."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Bildschirmfixierung"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"Suche"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> konnte nicht gestartet werden."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ist im abgesicherten Modus deaktiviert."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Verlauf"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Löschen"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Diese App unterstützt den Mehrfenstermodus nicht"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"App unterstützt Mehrfenstermodus nicht"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Geteilte Schaltfläche – horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Geteilte Schaltfläche – vertikal"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Geteilte Schaltfläche – benutzerdefiniert"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Laut-\nlos"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Nur\nwichtige"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Nur\nWecker"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Alle"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Alle\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Wird aufgeladen (voll in <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Wird schnell aufgeladen (voll in <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Wird langsam aufgeladen (voll in <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Uhrsekunden in der Statusleiste anzeigen. Kann sich auf die Akkulaufzeit auswirken."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Schnelleinstellungen neu anordnen"</string>
<string name="show_brightness" msgid="6613930842805942519">"Helligkeit in den Schnelleinstellungen anzeigen"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Teilen des Bildschirms durch Wischen nach oben aktivieren"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Teilen des Bildschirms durch Wischen nach oben aktivieren"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Aktiviert die Bewegung zum Teilen des Bildschirms, bei der von der Schaltfläche \"Übersicht\" nach oben gewischt wird"</string>
<string name="experimental" msgid="6198182315536726162">"Experimentell"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth aktivieren?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Zum Verbinden von Tastatur und Tablet muss Bluetooth aktiviert sein."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Aktivieren"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Für Benachrichtigungen über <xliff:g id="TOPIC_NAME">%1$s</xliff:g> anwenden"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Auf alle Benachrichtigungen dieser App anwenden"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Benachrichtigungen ohne Ton anzeigen"</string>
+ <string name="block" msgid="2734508760962682611">"Alle Benachrichtigungen blockieren"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Nicht stummschalten"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Nicht stummschalten oder blockieren"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Vollständige Wichtigkeitseinstellungen anzeigen"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Blockiert"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Minimum-Wichtigkeit"</string>
<string name="low_importance" msgid="4109929986107147930">"Geringe Wichtigkeit"</string>
<string name="default_importance" msgid="8192107689995742653">"Reguläre Wichtigkeit"</string>
<string name="high_importance" msgid="1527066195614050263">"Hohe Wichtigkeit"</string>
<string name="max_importance" msgid="5089005872719563894">"Sehr hohe Wichtigkeit"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Diese Benachrichtigungen niemals anzeigen"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Ohne Ton am Ende der Benachrichtigungsliste anzeigen"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Diese Benachrichtigungen ohne Ton anzeigen"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Mit Ton ganz oben in der Benachrichtigungsliste anzeigen"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Mit Ton auf dem Display einblenden"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Ohne Ton am Ende der Benachrichtigungsliste anzeigen"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Diese Benachrichtigungen ohne Ton anzeigen"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Für diese Benachrichtigungen Ton zulassen"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Auf dem Display einblenden und Ton zulassen"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Ganz oben in der Benachrichtigungsliste anzeigen, auf dem Display einblenden und Ton zulassen"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Weitere Einstellungen"</string>
<string name="notification_done" msgid="5279426047273930175">"Fertig"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Standardfarben"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Nachtfarben"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Benutzerdefinierte Farben"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automatisch"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Unbekannte Farben"</string>
- <string name="color_transform" msgid="6985460408079086090">"Farben ändern"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Kachel \"Schnelleinstellungen\" anzeigen"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Benutzerdefinierte Anpassung aktivieren"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Farbe und Darstellung"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Nachtmodus"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Bildschirm kalibrieren"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"An"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Aus"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Automatisch aktivieren"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Abhängig von Standort und Tageszeit in den Nachtmodus wechseln"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Bei aktiviertem Nachtmodus"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Dunkles Design unter Android OS verwenden"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Farbton anpassen"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Helligkeit anpassen"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Das dunkle Design wird unter Android OS in allen Hauptbereichen übernommen, die normalerweise hell dargestellt werden, wie beispielsweise Einstellungen."</string>
<string name="color_apply" msgid="9212602012641034283">"Übernehmen"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Einstellungen bestätigen"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Einige Farbeinstellungen können dazu führen, dass das Gerät nicht mehr genutzt werden kann. Klicke auf \"OK\", um diese Farbeinstellungen zu bestätigen. Anderenfalls werden diese Einstellungen in 10 Sekunden zurückgesetzt."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Akkunutzung"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Der Energiesparmodus ist beim Aufladen nicht verfügbar."</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Energiesparmodus"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduzierung der Leistung und Hintergrunddaten"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Startseite"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Letzte"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Zurück"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"\"Bitte nicht stören\" bei der Lautstärkeregelung anzeigen"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Volle Kontrolle von \"Bitte nicht stören\" im kleinen Fenster zur Lautstärkeregelung erlauben."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Lautstärke und \"Bitte nicht stören\""</string>
- <string name="volume_down_silent" msgid="66962568467719591">"\"Bitte nicht stören\" bei \"Leiser\" aktivieren"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Einschließlich Lautstärkeregler anzeigen"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Bitte nicht stören"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Tastenkombination für Lautstärketasten"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"\"Bitte nicht stören\" bei \"Lauter\" deaktivieren"</string>
<string name="battery" msgid="7498329822413202973">"Akku"</string>
<string name="clock" msgid="7416090374234785905">"Uhr"</string>
<string name="headset" msgid="4534219457597457353">"Headset"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Mit Kopfhörer verbunden"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Mit Headset verbunden"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Symbole in der Statusleiste ein- bzw. ausblenden"</string>
<string name="data_saver" msgid="5037565123367048522">"Datenkomprimierung"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Datenkomprimierung aktiviert"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Datenkomprimierung deaktiviert"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"An"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Aus"</string>
<string name="nav_bar" msgid="1993221402773877607">"Navigationsleiste"</string>
<string name="start" msgid="6873794757232879664">"Beim Start"</string>
<string name="center" msgid="4327473927066010960">"Mitte"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Vorschau"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Zum Hinzufügen von Kacheln ziehen"</string>
<string name="qs_edit" msgid="2232596095725105230">"Bearbeiten"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Uhrzeit"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Stunden, Minuten und Sekunden anzeigen"</item>
+ <item msgid="1427801730816895300">"Stunden und Minuten anzeigen (Standardeinstellung)"</item>
+ <item msgid="3830170141562534721">"Dieses Symbol nicht anzeigen"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Prozentwert immer anzeigen"</item>
+ <item msgid="2139628951880142927">"Prozentwert beim Laden anzeigen (Standardeinstellung)"</item>
+ <item msgid="3327323682209964956">"Dieses Symbol nicht anzeigen"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Sonstiges"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Bildschirmteiler"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Nach unten verschieben"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Nach oben verschieben"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Nach links verschieben"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Nach rechts verschieben"</string>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index ca354dc..b5f55d9 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Λήφθηκε το στιγμιότυπο οθόνης ."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Αγγίξτε για να δείτε το στιγμιότυπο οθόνης σας"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Αδύνατη η αποθήκευση του στιγμιότυπου οθόνης."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Αδύνατη λήψη στιγμ. οθόνης λόγω περιορισμένου αποθ.χώρου ή αποκλεισμού από εφαρμογή ή οργανισμό."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Δεν είναι δυνατή η αποθήκευση του στιγμιότυπου οθόνης λόγω περιορισμένου χώρου αποθήκευσης."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Η λήψη στιγμιοτύπων οθόνης δεν επιτρέπεται από την εφαρμογή ή από τον οργανισμό σας."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Επιλογές μεταφοράς αρχείων μέσω USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Προσάρτηση ως μονάδας αναπαραγωγής μέσων (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Προσάρτηση ως κάμερας (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Περισσότερη ώρα."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Λιγότερη ώρα."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Ανενεργός φακός."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Ο φακός δεν είναι διαθέσιμος."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Ενεργός φακός."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Ο φακός απενεργοποιήθηκε."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Ο φακός ενεργοποιήθηκε."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"καρφίτσωμα οθόνης"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"αναζήτηση"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Δεν ήταν δυνατή η εκκίνηση της εφαρμογής <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Η εφαρμογή <xliff:g id="APP">%s</xliff:g> έχει απενεργοποιηθεί στην ασφαλή λειτουργία."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Ιστορικό"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Εκκαθάριση"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Η εφαρμογή αυτή δεν υποστηρίζει τη λειτουργία πολλαπλών παραθύρων"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Η εφαρμογή δεν υποστηρίζει τη λειτουργία πολλαπλών παραθύρων"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Οριζόντιος διαχωρισμός"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Κάθετος διαχωρισμός"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Προσαρμοσμένος διαχωρισμός"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Πλήρης\nσίγαση"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Μόνο\nπροτεραιότητας"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Μόνο\nειδοποιήσεις"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Όλα"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Όλες\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Αργή φόρτιση (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> για πλήρη φόρτιση)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Εμφάνιση δευτερολέπτων ρολογιού στη γραμμή κατάστασης. Ενδέχεται να επηρεάσει τη διάρκεια ζωής της μπαταρίας."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Αναδιάταξη Γρήγορων ρυθμίσεων"</string>
<string name="show_brightness" msgid="6613930842805942519">"Εμφάνιση φωτεινότητας στις Γρήγορες ρυθμίσεις"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Ενεργοποίηση επιτάχυνσης ολίσθησης επάνω για διαχωρισμό οθόνης"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Ενεργοποίηση κίνησης ολίσθησης επάνω για διαχωρισμό οθόνης"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Ενεργοποίηση κίνησης για μετάβαση σε διαχωρισμό οθόνης μέσω ολίσθησης επάνω από το κουμπί \"Επισκόπηση\""</string>
<string name="experimental" msgid="6198182315536726162">"Σε πειραματικό στάδιο"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Ενεργοποίηση Bluetooth;"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Για να συνδέσετε το πληκτρολόγιο με το tablet σας, θα πρέπει πρώτα να ενεργοποιήσετε το Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Ενεργοποίηση"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Να εφαρμοστεί στις ειδοποιήσεις <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Να εφαρμοστεί σε όλες τις ειδοποιήσεις από αυτήν την εφαρμογή"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Εμφάνιση ειδοποιήσεων χωρίς ήχο"</string>
+ <string name="block" msgid="2734508760962682611">"Αποκλεισμός όλων των ειδοποιήσεων"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Χωρίς σίγαση"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Χωρίς σίγαση ή αποκλεισμό"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Εμφάνιση όλων των ρυθμίσεων βαρύτητας"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Αποκλεισμένες"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Ελάχιστη βαρύτητα"</string>
<string name="low_importance" msgid="4109929986107147930">"Μικρής βαρύτητας"</string>
<string name="default_importance" msgid="8192107689995742653">"Κανονικής βαρύτητας"</string>
<string name="high_importance" msgid="1527066195614050263">"Μεγάλης βαρύτητας"</string>
<string name="max_importance" msgid="5089005872719563894">"Επείγουσες"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Να μην εμφανίζονται ποτέ αυτές οι ειδοποιήσεις"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Να εμφανίζονται στο κάτω τμήμα της λίστας ειδοποιήσεων χωρίς τίτλο"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Να εμφανίζονται αυτές οι ειδοποιήσεις χωρίς ήχο"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Να εμφανίζονται στην κορυφή της λίστας ειδοποιήσεων με ήχο"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Να προβάλλονται στην οθόνη και να συνοδεύονται από κάποιον ήχο"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Να εμφανίζονται στο κάτω μέρος της λίστας ειδοποιήσεων χωρίς ήχο"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Να εμφανίζονται αυτές οι ειδοποιήσεις χωρίς ήχο"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Να επιτρέπονται οι ήχοι από αυτές τις ειδοποιήσεις"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Να προβάλλονται στην οθόνη και να επιτρέπεται ο ήχος"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Να εμφανίζονται στην κορυφή της λίστας ειδοποιήσεων, να προβάλλονται στην οθόνη και να επιτρέπεται ο ήχος"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Περισσότερες ρυθμίσεις"</string>
<string name="notification_done" msgid="5279426047273930175">"Τέλος"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Κανονικά χρώματα"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Νυχτερινά χρώματα"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Προσαρμοσμένα χρώματα"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Αυτόματο"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Άγνωστα χρώματα"</string>
- <string name="color_transform" msgid="6985460408079086090">"Τροποποίηση χρωμάτων"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Εμφάνιση πλακιδίου Γρήγορων ρυθμίσεων"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Ενεργοποίηση προσαρμοσμένου μετασχηματισμού"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Χρώμα και εμφάνιση"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Νυχτερινή λειτουργία"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Βαθμονόμηση οθόνης"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Ενεργή"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Ανενεργή"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Αυτόματη ενεργοποίηση"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Αλλαγή σε νυχτερινή λειτουργία όπως απαιτείται βάσει τοποθεσίας και ώρας της ημέρας"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Όταν είναι ενεργή η νυχτερινή λειτουργία"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Χρήση σκοτεινού θέματος για Android OS"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Ρύθμιση απόχρωσης"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Ρύθμιση φωτεινότητας"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Το σκούρο θέμα εφαρμόζεται σε βασικές περιοχές του λειτουργικού συστήματος Android οι οποίες συνήθως εμφανίζονται με φωτεινό θέμα, όπως οι Ρυθμίσεις."</string>
<string name="color_apply" msgid="9212602012641034283">"Εφαρμογή"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Επιβεβαίωση ρυθμίσεων"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Ορισμένες ρυθμίσεις χρωμάτων μπορεί να μην επιτρέπουν τη χρήση αυτής της συσκευής. Κάντε κλικ στην επιλογή OK για να επιβεβαιώσετε αυτές τις ρυθμίσεις χρωμάτων, διαφορετικά θα γίνει επαναφορά αυτών των ρυθμίσεων μετά από 10 δευτερόλεπτα."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Χρήση της μπαταρίας"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Η εξοικονόμηση μπαταρίας δεν είναι διαθέσιμη κατά τη διάρκεια της φόρτισης"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Εξοικονόμηση μπαταρίας"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Μειώνει την απόδοση και τα δεδομένα παρασκηνίου"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Αρχική οθόνη"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Πρόσφατα"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Πίσω"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Εμφάνιση λειτουργίας \"Μην ενοχλείτε\" στην ένταση ήχου"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Να επιτρέπεται ο πλήρης έλεγχος της λειτουργίας \"Μην ενοχλείτε\" στο παράθυρο διαλόγου ελέγχου έντασης."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Ένταση ήχου και λειτουργία \"Μην ενοχλείτε\""</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Ενεργοποίηση λειτουργίας \"Μην ενοχλείτε\" κατά τη μείωση της έντασης ήχου"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Εμφάνιση με στοιχεία ελέγχου έντασης ήχου"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Μην ενοχλείτε"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Συντόμευση κουμπιών έντασης ήχου"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Απενεργοποίηση λειτουργίας \"Μην ενοχλείτε\" κατά την αύξηση της έντασης ήχου"</string>
<string name="battery" msgid="7498329822413202973">"Μπαταρία"</string>
<string name="clock" msgid="7416090374234785905">"Ρολόι"</string>
<string name="headset" msgid="4534219457597457353">"Ακουστικά"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Τα ακουστικά συνδέθηκαν"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Τα ακουστικά συνδέθηκαν"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Ενεργοποίηση ή απενεργοποίηση εμφάνιση εικονιδίων στη γραμμή κατάστασης."</string>
<string name="data_saver" msgid="5037565123367048522">"Εξοικονόμηση δεδομένων"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Η Εξοικονόμηση δεδομένων είναι ενεργοποιημένη"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Η Εξοικονόμηση δεδομένων είναι απενεργοποιημένη"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Ενεργή"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Απενεργοποίηση"</string>
<string name="nav_bar" msgid="1993221402773877607">"Γραμμή πλοήγησης"</string>
<string name="start" msgid="6873794757232879664">"Έναρξη"</string>
<string name="center" msgid="4327473927066010960">"Κέντρο"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Προεπισκόπηση"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Σύρετε για να προσθέσετε πλακίδια"</string>
<string name="qs_edit" msgid="2232596095725105230">"Επεξεργασία"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Ώρα"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Να εμφανίζονται ώρες, λεπτά και δευτερόλεπτα"</item>
+ <item msgid="1427801730816895300">"Να εμφανίζονται ώρες και λεπτά (προεπιλογή)"</item>
+ <item msgid="3830170141562534721">"Να μην εμφανίζεται αυτό το εικονίδιο"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Να εμφανίζεται πάντα ποσοστό"</item>
+ <item msgid="2139628951880142927">"Να εμφανίζεται ποσοστό κατά τη φόρτιση (προεπιλογή)"</item>
+ <item msgid="3327323682209964956">"Να μην εμφανίζεται αυτό το εικονίδιο"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Άλλο"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Διαχωριστικό οθόνης"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Μετακίνηση προς τα κάτω"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Μετακίνηση προς τα επάνω"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Μετακίνηση αριστερά"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Μετακίνηση δεξιά"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 14f9301..cbb1ecf 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot captured."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Touch to view your screenshot."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Couldn\'t capture screenshot."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Can\'t take screenshot due to limited storage space, or it isn\'t allowed by the app or your organisation."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Can\'t save screenshot due to limited storage space."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Taking screenshots is not allowed by the app or your organisation."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB file transfer options"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Mount as a media player (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Mount as a camera (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"More time."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Less time."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Torch off."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Torch unavailable."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Torch on."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Torch turned off."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Torch turned on."</string>
@@ -304,6 +306,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> is disabled in safe-mode."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"History"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Clear"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"This app does not support multi-window"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"App does not support multi-window"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Customised"</string>
@@ -333,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Total\nsilence"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Priority\nonly"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Alarms\nonly"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"All"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"All\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charging (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Charging rapidly (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Charging slowly (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
@@ -447,34 +449,43 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Show clock seconds in the status bar. May impact battery life."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Rearrange Quick Settings"</string>
<string name="show_brightness" msgid="6613930842805942519">"Show brightness in Quick Settings"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Enable split-screen swipe-up accelerator"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Enable split-screen swipe-up gesture"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Enable gesture to enter split-screen by swiping up from the Overview button"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Turn on Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"To connect your keyboard with your tablet, you first have to turn on Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Turn on"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Apply to <xliff:g id="TOPIC_NAME">%1$s</xliff:g> notifications"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Apply to all notifications from this app"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Show notifications silently"</string>
+ <string name="block" msgid="2734508760962682611">"Block all notifications"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Don\'t silence"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Don\'t silence or block"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Show full importance settings"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Blocked"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Min importance"</string>
<string name="low_importance" msgid="4109929986107147930">"Low importance"</string>
<string name="default_importance" msgid="8192107689995742653">"Normal importance"</string>
<string name="high_importance" msgid="1527066195614050263">"High importance"</string>
<string name="max_importance" msgid="5089005872719563894">"Urgent importance"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Never show these notifications"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Silently show at the bottom of the notification list"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Silently show these notifications"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Show at the top of the notifications list and make sound"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Peek onto the screen and make sound"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Silently show at the bottom of the notification list"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Silently show these notifications"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Allow these notifications to make sounds"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Peek on to the screen and allow sound"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Show at the top of the notifications list, peek on to the screen and allow sound"</string>
<string name="notification_more_settings" msgid="816306283396553571">"More settings"</string>
<string name="notification_done" msgid="5279426047273930175">"Finished"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Normal colours"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Night colours"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Customised colours"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Auto"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Unknown colours"</string>
- <string name="color_transform" msgid="6985460408079086090">"Colour modification"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Show Quick Settings tile"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Enable customised transform"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Colour and appearance"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Night mode"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Calibrate display"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"On"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Off"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Turn on automatically"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Switch into Night Mode as appropriate for location and time of day"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"When Night Mode is on"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Use dark theme for Android OS"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Adjust tint"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Adjust brightness"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"The dark theme is applied to core areas of Android OS that are normally displayed in a light theme, such as Settings."</string>
<string name="color_apply" msgid="9212602012641034283">"Apply"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirm Settings"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Some colour settings can make this device unusable. Click OK to confirm these colour settings, otherwise these settings will reset after 10 seconds."</string>
@@ -486,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Home"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recent"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Back"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Show Do Not Disturb in volume"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Allow full control of Do Not Disturb in the volume dialogue."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Volume and Do Not Disturb"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Enter Do Not Disturb on volume down"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Show with volume controls"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Do not disturb"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Volume buttons shortcut"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Exit Do Not Disturb on volume up"</string>
<string name="battery" msgid="7498329822413202973">"Battery"</string>
<string name="clock" msgid="7416090374234785905">"Clock"</string>
<string name="headset" msgid="4534219457597457353">"Headset"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Headphones connected"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset connected"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Enable or disable icons from being shown in the status bar."</string>
<string name="data_saver" msgid="5037565123367048522">"Data Saver"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Data Saver is on"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Data Saver is off"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"On"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Off"</string>
<string name="nav_bar" msgid="1993221402773877607">"Navigation bar"</string>
<string name="start" msgid="6873794757232879664">"Start"</string>
<string name="center" msgid="4327473927066010960">"Centre"</string>
@@ -523,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Preview"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Drag to add tiles"</string>
<string name="qs_edit" msgid="2232596095725105230">"(edit)"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Time"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Show hours, minutes and seconds"</item>
+ <item msgid="1427801730816895300">"Show hours and minutes (default)"</item>
+ <item msgid="3830170141562534721">"Don\'t show this icon"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Always show percentage"</item>
+ <item msgid="2139628951880142927">"Show percentage when charging (default)"</item>
+ <item msgid="3327323682209964956">"Don\'t show this icon"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Other"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Split screen divider"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Move down"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Move up"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Move to the left"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Move to the right"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 14f9301..cbb1ecf 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot captured."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Touch to view your screenshot."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Couldn\'t capture screenshot."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Can\'t take screenshot due to limited storage space, or it isn\'t allowed by the app or your organisation."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Can\'t save screenshot due to limited storage space."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Taking screenshots is not allowed by the app or your organisation."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB file transfer options"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Mount as a media player (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Mount as a camera (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"More time."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Less time."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Torch off."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Torch unavailable."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Torch on."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Torch turned off."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Torch turned on."</string>
@@ -304,6 +306,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> is disabled in safe-mode."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"History"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Clear"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"This app does not support multi-window"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"App does not support multi-window"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Customised"</string>
@@ -333,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Total\nsilence"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Priority\nonly"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Alarms\nonly"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"All"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"All\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charging (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Charging rapidly (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Charging slowly (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
@@ -447,34 +449,43 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Show clock seconds in the status bar. May impact battery life."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Rearrange Quick Settings"</string>
<string name="show_brightness" msgid="6613930842805942519">"Show brightness in Quick Settings"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Enable split-screen swipe-up accelerator"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Enable split-screen swipe-up gesture"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Enable gesture to enter split-screen by swiping up from the Overview button"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Turn on Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"To connect your keyboard with your tablet, you first have to turn on Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Turn on"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Apply to <xliff:g id="TOPIC_NAME">%1$s</xliff:g> notifications"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Apply to all notifications from this app"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Show notifications silently"</string>
+ <string name="block" msgid="2734508760962682611">"Block all notifications"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Don\'t silence"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Don\'t silence or block"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Show full importance settings"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Blocked"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Min importance"</string>
<string name="low_importance" msgid="4109929986107147930">"Low importance"</string>
<string name="default_importance" msgid="8192107689995742653">"Normal importance"</string>
<string name="high_importance" msgid="1527066195614050263">"High importance"</string>
<string name="max_importance" msgid="5089005872719563894">"Urgent importance"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Never show these notifications"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Silently show at the bottom of the notification list"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Silently show these notifications"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Show at the top of the notifications list and make sound"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Peek onto the screen and make sound"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Silently show at the bottom of the notification list"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Silently show these notifications"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Allow these notifications to make sounds"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Peek on to the screen and allow sound"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Show at the top of the notifications list, peek on to the screen and allow sound"</string>
<string name="notification_more_settings" msgid="816306283396553571">"More settings"</string>
<string name="notification_done" msgid="5279426047273930175">"Finished"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Normal colours"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Night colours"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Customised colours"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Auto"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Unknown colours"</string>
- <string name="color_transform" msgid="6985460408079086090">"Colour modification"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Show Quick Settings tile"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Enable customised transform"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Colour and appearance"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Night mode"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Calibrate display"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"On"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Off"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Turn on automatically"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Switch into Night Mode as appropriate for location and time of day"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"When Night Mode is on"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Use dark theme for Android OS"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Adjust tint"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Adjust brightness"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"The dark theme is applied to core areas of Android OS that are normally displayed in a light theme, such as Settings."</string>
<string name="color_apply" msgid="9212602012641034283">"Apply"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirm Settings"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Some colour settings can make this device unusable. Click OK to confirm these colour settings, otherwise these settings will reset after 10 seconds."</string>
@@ -486,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Home"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recent"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Back"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Show Do Not Disturb in volume"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Allow full control of Do Not Disturb in the volume dialogue."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Volume and Do Not Disturb"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Enter Do Not Disturb on volume down"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Show with volume controls"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Do not disturb"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Volume buttons shortcut"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Exit Do Not Disturb on volume up"</string>
<string name="battery" msgid="7498329822413202973">"Battery"</string>
<string name="clock" msgid="7416090374234785905">"Clock"</string>
<string name="headset" msgid="4534219457597457353">"Headset"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Headphones connected"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset connected"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Enable or disable icons from being shown in the status bar."</string>
<string name="data_saver" msgid="5037565123367048522">"Data Saver"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Data Saver is on"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Data Saver is off"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"On"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Off"</string>
<string name="nav_bar" msgid="1993221402773877607">"Navigation bar"</string>
<string name="start" msgid="6873794757232879664">"Start"</string>
<string name="center" msgid="4327473927066010960">"Centre"</string>
@@ -523,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Preview"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Drag to add tiles"</string>
<string name="qs_edit" msgid="2232596095725105230">"(edit)"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Time"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Show hours, minutes and seconds"</item>
+ <item msgid="1427801730816895300">"Show hours and minutes (default)"</item>
+ <item msgid="3830170141562534721">"Don\'t show this icon"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Always show percentage"</item>
+ <item msgid="2139628951880142927">"Show percentage when charging (default)"</item>
+ <item msgid="3327323682209964956">"Don\'t show this icon"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Other"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Split screen divider"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Move down"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Move up"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Move to the left"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Move to the right"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 14f9301..cbb1ecf 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot captured."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Touch to view your screenshot."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Couldn\'t capture screenshot."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Can\'t take screenshot due to limited storage space, or it isn\'t allowed by the app or your organisation."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Can\'t save screenshot due to limited storage space."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Taking screenshots is not allowed by the app or your organisation."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB file transfer options"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Mount as a media player (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Mount as a camera (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"More time."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Less time."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Torch off."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Torch unavailable."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Torch on."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Torch turned off."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Torch turned on."</string>
@@ -304,6 +306,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> is disabled in safe-mode."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"History"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Clear"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"This app does not support multi-window"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"App does not support multi-window"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Customised"</string>
@@ -333,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Total\nsilence"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Priority\nonly"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Alarms\nonly"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"All"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"All\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charging (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Charging rapidly (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Charging slowly (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
@@ -447,34 +449,43 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Show clock seconds in the status bar. May impact battery life."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Rearrange Quick Settings"</string>
<string name="show_brightness" msgid="6613930842805942519">"Show brightness in Quick Settings"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Enable split-screen swipe-up accelerator"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Enable split-screen swipe-up gesture"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Enable gesture to enter split-screen by swiping up from the Overview button"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Turn on Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"To connect your keyboard with your tablet, you first have to turn on Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Turn on"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Apply to <xliff:g id="TOPIC_NAME">%1$s</xliff:g> notifications"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Apply to all notifications from this app"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Show notifications silently"</string>
+ <string name="block" msgid="2734508760962682611">"Block all notifications"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Don\'t silence"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Don\'t silence or block"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Show full importance settings"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Blocked"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Min importance"</string>
<string name="low_importance" msgid="4109929986107147930">"Low importance"</string>
<string name="default_importance" msgid="8192107689995742653">"Normal importance"</string>
<string name="high_importance" msgid="1527066195614050263">"High importance"</string>
<string name="max_importance" msgid="5089005872719563894">"Urgent importance"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Never show these notifications"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Silently show at the bottom of the notification list"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Silently show these notifications"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Show at the top of the notifications list and make sound"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Peek onto the screen and make sound"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Silently show at the bottom of the notification list"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Silently show these notifications"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Allow these notifications to make sounds"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Peek on to the screen and allow sound"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Show at the top of the notifications list, peek on to the screen and allow sound"</string>
<string name="notification_more_settings" msgid="816306283396553571">"More settings"</string>
<string name="notification_done" msgid="5279426047273930175">"Finished"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Normal colours"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Night colours"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Customised colours"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Auto"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Unknown colours"</string>
- <string name="color_transform" msgid="6985460408079086090">"Colour modification"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Show Quick Settings tile"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Enable customised transform"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Colour and appearance"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Night mode"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Calibrate display"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"On"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Off"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Turn on automatically"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Switch into Night Mode as appropriate for location and time of day"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"When Night Mode is on"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Use dark theme for Android OS"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Adjust tint"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Adjust brightness"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"The dark theme is applied to core areas of Android OS that are normally displayed in a light theme, such as Settings."</string>
<string name="color_apply" msgid="9212602012641034283">"Apply"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirm Settings"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Some colour settings can make this device unusable. Click OK to confirm these colour settings, otherwise these settings will reset after 10 seconds."</string>
@@ -486,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Home"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recent"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Back"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Show Do Not Disturb in volume"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Allow full control of Do Not Disturb in the volume dialogue."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Volume and Do Not Disturb"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Enter Do Not Disturb on volume down"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Show with volume controls"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Do not disturb"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Volume buttons shortcut"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Exit Do Not Disturb on volume up"</string>
<string name="battery" msgid="7498329822413202973">"Battery"</string>
<string name="clock" msgid="7416090374234785905">"Clock"</string>
<string name="headset" msgid="4534219457597457353">"Headset"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Headphones connected"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset connected"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Enable or disable icons from being shown in the status bar."</string>
<string name="data_saver" msgid="5037565123367048522">"Data Saver"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Data Saver is on"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Data Saver is off"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"On"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Off"</string>
<string name="nav_bar" msgid="1993221402773877607">"Navigation bar"</string>
<string name="start" msgid="6873794757232879664">"Start"</string>
<string name="center" msgid="4327473927066010960">"Centre"</string>
@@ -523,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Preview"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Drag to add tiles"</string>
<string name="qs_edit" msgid="2232596095725105230">"(edit)"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Time"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Show hours, minutes and seconds"</item>
+ <item msgid="1427801730816895300">"Show hours and minutes (default)"</item>
+ <item msgid="3830170141562534721">"Don\'t show this icon"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Always show percentage"</item>
+ <item msgid="2139628951880142927">"Show percentage when charging (default)"</item>
+ <item msgid="3327323682209964956">"Don\'t show this icon"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Other"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Split screen divider"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Move down"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Move up"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Move to the left"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Move to the right"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 4031204..856c1c1 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Se guardó la captura de pantalla."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Toca para ver tu captura de pantalla."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"No se pudo guardar la captura de pantalla."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Error de captura por almacenamiento limitado o porque la aplicación u organización no lo permiten."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"No se puede guardar la captura de pantalla debido al almacenamiento limitado."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"La app o tu organización no permiten las capturas de pantalla."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Opciones de transferencia de archivos por USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Activar como reproductor de medios (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Activar como cámara (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Más tiempo"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Menos tiempo"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Linterna desactivada"</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"La linterna no está disponible."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Linterna activada"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Linterna desactivada"</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Linterna activada"</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Fijar pantalla"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"No se pudo iniciar <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> está inhabilitada en modo seguro."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Historial"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Borrar"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Esta app no es compatible con el modo multiventana"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"La app no es compatible con el modo multiventana"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"División horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"División vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"División personalizada"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Silencio\ntotal"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Solo\nprioridad"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Solo\nalarmas"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Todo"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Todo\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Cargando (faltan <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para completar)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Carga rápida (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para completar la carga)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Carga lenta (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para completar la carga)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Muestra los segundos del reloj en la barra de estado. Puede afectar la duración de la batería."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar la Configuración rápida"</string>
<string name="show_brightness" msgid="6613930842805942519">"Mostrar el brillo en la Configuración rápida"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Deslizar el dedo hacia arriba para dividir la pantalla"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Habilitar gesto de dedo hacia arriba para dividir pantalla"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Habilita el gesto de deslizar el dedo hacia arriba desde el botón Recientes para acceder al modo de pantalla dividida"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"¿Activar Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Para conectar el teclado con la tablet, primero debes activar Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Activar"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Aplicar a las notificaciones de <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Aplicar a todas las notificaciones de esta app"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Mostrar notificaciones de manera silenciosa"</string>
+ <string name="block" msgid="2734508760962682611">"Bloquear todas las notificaciones"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"No silenciar"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"No silenciar ni bloquear"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Mostrar configuración de importancia"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloqueada"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Importancia mínima"</string>
<string name="low_importance" msgid="4109929986107147930">"Poca importancia"</string>
<string name="default_importance" msgid="8192107689995742653">"Importancia normal"</string>
<string name="high_importance" msgid="1527066195614050263">"Importancia alta"</string>
<string name="max_importance" msgid="5089005872719563894">"Urgente"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"No mostrar nunca estas notificaciones"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Mostrar en la parte inferior de la lista de notificaciones sin emitir sonido"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Mostrar estas notificaciones de manera silenciosa"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Mostrar en la parte superior de la lista de notificaciones y emitir sonido"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Mostrar en la pantalla y emitir sonido"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Mostrar en la parte inferior de la lista de notificaciones sin emitir sonido"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Mostrar estas notificaciones de manera silenciosa"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Permitir que estas notificaciones emitan sonidos"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Ver en la pantalla y permitir sonidos"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Mostrar en la parte superior de la lista de notificaciones, ver en la pantalla y permitir sonidos"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Más opciones de configuración"</string>
<string name="notification_done" msgid="5279426047273930175">"Listo"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Colores normales"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Colores nocturnos"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Colores personalizados"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automático"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Colores desconocidos"</string>
- <string name="color_transform" msgid="6985460408079086090">"Modificación del color"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Mostrar el mosaico de Configuración rápida"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Habilitar la transformación personalizada"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Color y apariencia"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Modo nocturno"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Calibrar pantalla"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Activado"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Desactivado"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Activar automáticamente"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Cambiar a modo nocturno según corresponda en relación con la ubicación y hora del día"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Cuando el modo nocturno está activado"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Usar tema oscuro para el SO Android"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Ajustar tinte"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Ajustar brillo"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"El tema oscuro se aplica en las áreas principales del SO Android que suelen mostrarse con un tema claro, como Configuración."</string>
<string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirmar la configuración"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Algunas opciones de configuración de color pueden provocar que el dispositivo quede inutilizable. Haz clic en Aceptar para confirmar estos parámetros de color. De lo contrario, la configuración se restablecerá en diez segundos."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Uso de la batería"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Ahorro de batería no está disponible durante la carga"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Ahorro de batería"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduce el rendimiento y el uso de datos en segundo plano"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Pantalla principal"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recientes"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Atrás"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Mostrar el panel de control de No interrumpir en el volumen"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Permitir el control total del modo No interrumpir en el cuadro de diálogo de volumen."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Volumen y No interrumpir"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Activar el modo No interrumpir al bajar el volumen"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostrar con controles de volumen"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"No interrumpir"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Combinación de teclas de botones de volumen"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Desactivar el modo No interrumpir al subir el volumen"</string>
<string name="battery" msgid="7498329822413202973">"Batería"</string>
<string name="clock" msgid="7416090374234785905">"Reloj"</string>
<string name="headset" msgid="4534219457597457353">"Auriculares"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Auriculares conectados"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Auriculares conectados"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Habilitar o inhabilitar la visualización de los íconos en la barra de estado"</string>
<string name="data_saver" msgid="5037565123367048522">"Reducir datos"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Reducir datos está activada"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Reducir datos está desactivada"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Activado"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Desactivar"</string>
<string name="nav_bar" msgid="1993221402773877607">"Barra de navegación"</string>
<string name="start" msgid="6873794757232879664">"Iniciar"</string>
<string name="center" msgid="4327473927066010960">"Centro"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Vista previa"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Arrastra los mosaicos para agregarlos"</string>
<string name="qs_edit" msgid="2232596095725105230">"Editar"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Hora"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Mostrar horas, minutos y segundos"</item>
+ <item msgid="1427801730816895300">"Mostrar horas y minutos (predeterminado)"</item>
+ <item msgid="3830170141562534721">"No mostrar este ícono"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Siempre mostrar el porcentaje"</item>
+ <item msgid="2139628951880142927">"Mostrar el porcentaje durante la carga (predeterminado)"</item>
+ <item msgid="3327323682209964956">"No mostrar este ícono"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Otros"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Divisor de pantalla dividida"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Mover hacia abajo"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Mover hacia arriba"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Mover a la izquierda"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Mover a la derecha"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index f531294..b3eda73 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Captura guardada"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Toca para ver la captura de pantalla"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"No se ha podido guardar la captura de pantalla."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Error al hacer captura por límite almacenamiento o porque aplicación u organización no lo permiten."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"No se puede guardar la captura de pantalla porque no hay espacio de almacenamiento suficiente."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"La aplicación o tu organización no permiten que se realicen capturas de pantalla."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Opciones de transferencia de archivos por USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Activar como reproductor de medios (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Activar como cámara (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Más tiempo."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Menos tiempo."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Linterna desactivada."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"La linterna no está disponible."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Linterna activada."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Linterna desactivada."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Linterna activada."</string>
@@ -305,6 +307,8 @@
<skip />
<string name="recents_history_button_label" msgid="5153358867807604821">"Historial"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Borrar"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Esta aplicación no admite el modo multiventana."</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"La aplicación no admite el modo multiventana"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"División horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"División vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"División personalizada"</string>
@@ -334,8 +338,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Silencio\ntotal"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Solo\ncon prioridad"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Solo\nalarmas"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Todo"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Todo\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Cargando (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para completar)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Cargando rápidamente (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hasta completar)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Cargando lentamente (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hasta completar)"</string>
@@ -448,39 +450,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Muestra los segundos del reloj en la barra de estado. Puede afectar a la duración de la batería."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar Ajustes rápidos"</string>
<string name="show_brightness" msgid="6613930842805942519">"Mostrar brillo en Ajustes rápidos"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Habilitar deslizar el dedo hacia arriba para dividir la pantalla"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Habilitar deslizar dedo hacia arriba para dividir pantalla"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Habilita el gesto de deslizar el dedo hacia arriba desde el botón Visión general para acceder al modo de pantalla dividida"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"¿Activar Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Para poder conectar tu teclado a tu tablet, debes activar el Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Activar"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Aplicar a las notificaciones de <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Aplicar a todas las notificaciones de esta aplicación"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Mostrar notificaciones de forma silenciosa"</string>
+ <string name="block" msgid="2734508760962682611">"Bloquear todas las notificaciones"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"No silenciar"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"No silenciar ni bloquear"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Mostrar ajustes de importancia por completo"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloqueado"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Importancia mínima"</string>
<string name="low_importance" msgid="4109929986107147930">"Poco importante"</string>
<string name="default_importance" msgid="8192107689995742653">"Importancia normal"</string>
<string name="high_importance" msgid="1527066195614050263">"Muy importante"</string>
<string name="max_importance" msgid="5089005872719563894">"Urgente"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"No mostrar estas notificaciones"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Mostrar en la parte inferior de la lista de notificaciones de forma silenciosa"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Mostrar estas notificaciones de forma silenciosa"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Mostrar en la parte superior de la lista de notificaciones y emitir sonido"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Mostrar en la pantalla y emitir sonido"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Mostrar en la parte inferior de la lista de notificaciones de forma silenciosa"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Mostrar estas notificaciones de forma silenciosa"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Permitir que estas notificaciones reproduzcan sonidos"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Mostrar en la pantalla y permitir sonido"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Mostrar en la parte superior de la lista de notificaciones, mostrar en la pantalla y permitir sonido"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Más ajustes"</string>
<string name="notification_done" msgid="5279426047273930175">"Listo"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Colores normales"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Colores nocturnos"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Colores personalizados"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automático"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Colores desconocidos"</string>
- <string name="color_transform" msgid="6985460408079086090">"Modificación de colores"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Mostrar mosaico de Ajustes rápidos"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Habilitar transformación personalizada"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Color y aspecto"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Modo nocturno"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Calibrar pantalla"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Sí"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"No"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Activar automáticamente"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Cambiar al modo nocturno cuando proceda según la ubicación y la hora del día"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Cuando el modo nocturno esté activado"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Tema oscuro para sistema operativo Android"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Ajustar tono"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Ajustar brillo"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"El tema oscuro se aplica a las áreas principales del sistema operativo Android que normalmente se muestran con un tema claro, como la aplicación Ajustes."</string>
<string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirmar configuración"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Algunas opciones de configuración de color pueden hacer que el dispositivo no se pueda utilizar. Haz clic en Aceptar para confirmar esta configuración. Si no lo haces, se restablecerá esta configuración cuando transcurran 10 segundos."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Uso de la batería"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Ahorro de batería no disponible mientras se carga el dispositivo"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Ahorro de batería"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduce el rendimiento y las conexiones automáticas"</string>
@@ -488,21 +498,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Inicio"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recientes"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Atrás"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Mostrar el panel de control de No molestar en el volumen"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Permitir un control total del modo No molestar en el cuadro de diálogo de volumen."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Volumen y No molestar"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Activar No molestar al bajar el volumen"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostrar con controles de volumen"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"No molestar"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Combinación de teclas para los botones de volumen"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Salir de No molestar al subir el volumen"</string>
<string name="battery" msgid="7498329822413202973">"Batería"</string>
<string name="clock" msgid="7416090374234785905">"Reloj"</string>
<string name="headset" msgid="4534219457597457353">"Auriculares"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Auriculares conectados"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Auriculares conectados"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Permite mostrar u ocultar iconos en la barra de estado"</string>
<string name="data_saver" msgid="5037565123367048522">"Economizador de datos"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Economizador de datos activado"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Economizador de datos desactivado"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Sí"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"No"</string>
<string name="nav_bar" msgid="1993221402773877607">"Barra de navegación"</string>
<string name="start" msgid="6873794757232879664">"Inicio"</string>
<string name="center" msgid="4327473927066010960">"Centro"</string>
@@ -525,4 +534,21 @@
<string name="preview" msgid="9077832302472282938">"Vista previa"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Arrastrar para añadir mosaicos"</string>
<string name="qs_edit" msgid="2232596095725105230">"Cambiar"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Hora"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Mostrar horas, minutos y segundos"</item>
+ <item msgid="1427801730816895300">"Mostrar horas y minutos (predeterminado)"</item>
+ <item msgid="3830170141562534721">"No mostrar este icono"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Mostrar porcentaje siempre"</item>
+ <item msgid="2139628951880142927">"Mostrar porcentaje durante la carga (predeterminado)"</item>
+ <item msgid="3327323682209964956">"No mostrar este icono"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Otros"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Dividir la pantalla"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Bajar"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Subir"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Mover a la izquierda"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Mover a la derecha"</string>
</resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index a7e34e6..1279a2c 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Ekraanipilt on jäädvustatud."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Puudutage kuvatõmmise vaatamiseks."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Kuvatõmmist ei saanud jäädvustada."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Ekraanipilti ei saa jäädvustada piiratud talletusruumi tõttu või ei luba seda rakendus/organisatsioon."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Piiratud salvestusruumi tõttu ei saa ekraanipilti salvestada."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Rakendus või teie organisatsioon ei luba ekraanipilte jäädvustada."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB-failiedastuse valikud"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Paigalda meediumimängijana (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Paigalda kaamerana (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Pikem aeg."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Lühem aeg."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Taskulamp on väljas."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Taskulamp pole saadaval."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Taskulamp on sees."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Taskulamp on välja lülitatud."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Taskulamp on sisse lülitatud."</string>
@@ -304,6 +306,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"Rakendus <xliff:g id="APP">%s</xliff:g> on turvarežiimis keelatud."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Ajalugu"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Kustuta"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"See rakendus ei toeta mitut akent"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Rakendus ei toeta mitut akent"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Horisontaalne poolitamine"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikaalne poolitamine"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Kohandatud poolitamine"</string>
@@ -333,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Täielik\nvaikus"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Ainult\nprioriteetsed"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Ainult\nalarmid"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Kõik"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Kõik\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Laadimine (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>, kuni seade on täis)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Kiirlaadimine (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>, kuni seade on täis)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Aeglane laadimine (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>, kuni seade on täis)"</string>
@@ -447,34 +449,43 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Olekuribal kella sekundite kuvamine. See võib mõjutada aku kasutusaega."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Korralda kiirseaded ümber"</string>
<string name="show_brightness" msgid="6613930842805942519">"Kuva kiirseadetes heledus"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Luba ülespühkimise kiirendi ekraani poolitamiseks"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Luba ülespühkimise liigutus ekraani poolitamiseks"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Lubab žesti, mis poolitab ekraani, kui kasutaja pühib üles nupul Ülevaade."</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimentaalne"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Kas lülitada Bluetooth sisse?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Klaviatuuri ühendamiseks tahvelarvutiga peate esmalt Bluetoothi sisse lülitama."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Lülita sisse"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Rakenda teema <xliff:g id="TOPIC_NAME">%1$s</xliff:g> märguannete puhul"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Rakenda selle rakenduse kõigi märguannete puhul"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Kuva märguanded vaikselt"</string>
+ <string name="block" msgid="2734508760962682611">"Blokeeri kõik märguanded"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Ära vaigista"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Ära vaigista ega blokeeri"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Kuva täieliku tähtsuse seaded"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Blokeeritud"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Minimaalne tähtsus"</string>
<string name="low_importance" msgid="4109929986107147930">"Madal tähtsuse tase"</string>
<string name="default_importance" msgid="8192107689995742653">"Tavaline tähtsuse tase"</string>
<string name="high_importance" msgid="1527066195614050263">"Kõrge tähtsuse tase"</string>
<string name="max_importance" msgid="5089005872719563894">"Kiireloomuline tähtsuse tase"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Ära kunagi näita neid märguandeid"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Kuva märguannete loendi allosas vaikselt"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Kuva need märguanded vaikselt"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Kuva märguannete loendi ülaosas koos heliga"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Kuva ekraani servas koos heliga"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Kuva märguannete loendi allosas vaikselt"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Kuva need märguanded vaikselt"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Luba nende märguannete puhul heli"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Kuva ekraani servas ja luba heli"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Kuva märguannete loendi ülaservas, kuva ekraani servas ja luba heli"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Rohkem seadeid"</string>
<string name="notification_done" msgid="5279426047273930175">"Valmis"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Tavalised värvid"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Öised värvid"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Kohandatud värvid"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automaatne"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Värvid on teadmata"</string>
- <string name="color_transform" msgid="6985460408079086090">"Värvi muutmine"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Kuva paan Kiirseaded"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Luba kohandatud teisendamine"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Värv ja ilme"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Öörežiim"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Ekraani kalibreerimine"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Sees"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Väljas"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Lülita automaatselt sisse"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Lülita öörežiimile, kui see on asukoha ja kellaaja suhtes sobilik"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Kui öörežiim on sees"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Kasuta Android OS-is tumedat teemat"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Reguleeri tooni"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Reguleeri heledust"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Tume teema rakendatakse Android OS-i põhialadele, mis kuvatakse tavaliselt heleda teemaga (nt seaded)."</string>
<string name="color_apply" msgid="9212602012641034283">"Rakenda"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Seadete kinnitamine"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Mõni värviseade ei saa seadet võib-olla kasutada. Nende värviseadete kinnitamiseks klõpsake OK, muidu lähtestatakse need seaded 10 sekundi pärast."</string>
@@ -486,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Avaekraan"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Hiljutised"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Tagasi"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Kuva helitugevuse juures funktsioon Mitte segada"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Helitugevuse dialoogis lubatakse funktsiooni Mitte segada täielik juhtimine."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Helitugevus ja funktsioon Mitte segada"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Lülita helitugevuse vähendamisel sisse funkt. Mitte segada"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Kuva koos helitugevuse juhtnuppudega"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Mitte segada"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Helitugevuse nuppude otsetee"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Lülita helitugevuse suurendamisel välja funkt. Mitte segada"</string>
<string name="battery" msgid="7498329822413202973">"Aku"</string>
<string name="clock" msgid="7416090374234785905">"Kell"</string>
<string name="headset" msgid="4534219457597457353">"Peakomplekt"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Kõrvaklapid on ühendatud"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Peakomplekt on ühendatud"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Lubatakse või keelatakse ikoonide kuvamine olekuribal."</string>
<string name="data_saver" msgid="5037565123367048522">"Andmemahu säästja"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Andmemahu säästja on sisse lülitatud"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Andmemahu säästja on välja lülitatud"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Sees"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Väljas"</string>
<string name="nav_bar" msgid="1993221402773877607">"Navigeerimisriba"</string>
<string name="start" msgid="6873794757232879664">"Algus"</string>
<string name="center" msgid="4327473927066010960">"Keskkoht"</string>
@@ -523,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Eelvaade"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Lohistage paanide lisamiseks"</string>
<string name="qs_edit" msgid="2232596095725105230">"Muuda"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Kellaaeg"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Kuva tunnid, minutid ja sekundid"</item>
+ <item msgid="1427801730816895300">"Kuva tunnid ja minutid (vaikimisi)"</item>
+ <item msgid="3830170141562534721">"Ära kuva seda ikooni"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Kuva alati protsent"</item>
+ <item msgid="2139628951880142927">"Kuva protsent laadimisel (vaikimisi)"</item>
+ <item msgid="3327323682209964956">"Ära kuva seda ikooni"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Muu"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Ekraanijagaja"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Liigu alla"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Liigu üles"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Liigu vasakule"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Liigu paremale"</string>
</resources>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index dcb8ef9..3f8e844 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Pantaila-argazkia atera da."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Pantaila-argazkia ikusteko, ukitu ezazu."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Ezin izan da pantaila-argazkia atera."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Ezin da atera pantaila-argazkia tokirik geratzen ez delako edo horrelakorik onartzen ez delako."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Ezin da atera pantaila-argazkia ez delako tokirik geratzen."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Aplikazioak edo erakundeak ez du onartzen pantaila-argazkiak ateratzea."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB fitxategiak transferitzeko aukerak"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Muntatu multimedia-erreproduzigailu gisa (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Muntatu kamera gisa (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Denbora gehiago."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Denbora gutxiago."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Flasha desaktibatuta dago."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Linterna ez dago erabilgarri."</string>
<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>
@@ -301,13 +303,14 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pantaila-ainguratzea"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"bilatu"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Ezin izan da hasi <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> desgaituta dago modu seguruan."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Historia"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Garbitu"</string>
- <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Banaketa horizontala"</string>
- <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Banaketa bertikala"</string>
- <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Banaketa pertsonalizatua"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Aplikazioak ez du onartzen leiho bat baino gehiago erabiltzea"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Aplikazioak ez du onartzen leiho bat baino gehiago erabiltzea"</string>
+ <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Zatitze horizontala"</string>
+ <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Zatitze bertikala"</string>
+ <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Zatitze pertsonalizatua"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Kargatuta"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Kargatzen"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> falta zaizkio guztiz kargatzeko"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Isiltasun\nosoa"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Lehentasunezkoak\nsoilik"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Alarmak\nsoilik"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Guztiak"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Guztiak\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Kargatzen (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> guztiz kargatu arte)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Bizkor kargatzen (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> guztiz kargatu arte)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Mantso kargatzen (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> guztiz kargatu arte)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Erakutsi erlojuko segundoak egoera-barran. Baliteke bateria gehiago erabiltzea."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Berrantolatu ezarpen bizkorrak"</string>
<string name="show_brightness" msgid="6613930842805942519">"Erakutsi distira Ezarpen bizkorretan"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Gaitu hatza gora pasatuta pantaila zatitzeko bizkortzailea"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Gaitu pantaila zatitzeko keinua hatza gora pasatuta"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Sakatu Ikuspegi nagusia botoia eta gaitu hatza gora pasatuta pantaila zatitzeko keinua"</string>
<string name="experimental" msgid="6198182315536726162">"Esperimentala"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth eginbidea aktibatu nahi duzu?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Teklatua tabletara konektatzeko, Bluetooth eginbidea aktibatu behar duzu."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Aktibatu"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Aplikatu \"<xliff:g id="TOPIC_NAME">%1$s</xliff:g>\" gaiari buruzko jakinarazpenei"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Aplikatu aplikazio honetako jakinarazpen guztiei"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Erakutsi jakinarazpenak soinurik egin gabe"</string>
+ <string name="block" msgid="2734508760962682611">"Blokeatu jakinarazpen guztiak"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Ez isilarazi"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Ez isilarazi edo blokeatu"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Erakutsi garrantzia handiko jakinarazpenen ezarpenak"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Blokeatuta"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Gutxieneko garrantzia"</string>
<string name="low_importance" msgid="4109929986107147930">"Garrantzi txikia"</string>
<string name="default_importance" msgid="8192107689995742653">"Garrantzi normala"</string>
<string name="high_importance" msgid="1527066195614050263">"Garrantzi handia"</string>
<string name="max_importance" msgid="5089005872719563894">"Premiazkoa"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Ez erakutsi jakinarazpen hauek inoiz"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Erakutsi jakinarazpen hauek zerrendaren behealdean, baina soinurik egin gabe"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Erakutsi jakinarazpen hauek, baina soinurik egin gabe"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Erakutsi jakinarazpen hauek zerrendaren goialdean eta egin soinua"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Agerrarazi jakinarazpen hauek pantailan eta egin soinua"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Erakutsi jakinarazpen hauek zerrendaren behealdean, baina soinurik egin gabe"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Erakutsi jakinarazpen hauek, baina soinurik egin gabe"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Egin soinua jakinarazpen hauek jasotzean"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Agerrarazi jakinarazpen hauek pantailan eta egin soinua"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Erakutsi jakinarazpen hauek zerrendaren goialdean, agerrarazi pantailan eta egin soinua"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Ezarpen gehiago"</string>
<string name="notification_done" msgid="5279426047273930175">"Eginda"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Kolore normalak"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Gaueko koloreak"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Kolore pertsonalizatuak"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automatikoa"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Kolore ezezagunak"</string>
- <string name="color_transform" msgid="6985460408079086090">"Kolore-aldaketa"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Erakutsi ezarpen bizkorren lauza"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Gaitu itxuraldaketa pertsonalizatua"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Kolorea eta itxura"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Gau modua"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Kalibratu pantaila"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Aktibatuta"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Desaktibatuta"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Aktibatu automatikoki"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Aldatu Gau modura, kokapena eta ordua kontuan izanda"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Gau modua aktibatuta dagoenean"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Erabili gai iluna Android sistema eragilean"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Doitu kolorea"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Doitu distira"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Gai iluna Android sistema eragileko eremu nagusietan aplikatzen da. Normalean gai argian bistaratzen dira eremu horiek, adibidez, Ezarpenak atalean."</string>
<string name="color_apply" msgid="9212602012641034283">"Aplikatu"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Berretsi ezarpenak"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Baliteke gailua kolore-ezarpen batzuekin ezin erabili izatea. Kolore-ezarpenak berresteko, sakatu Ados. Bestela, hamar segundoren buruan berrezarriko dira ezarpenak."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Bateriaren erabilera"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Bateria-aurrezlea ez dago erabilgarri gailua kargatzen ari denean"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Bateria-aurrezlea"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Errendimendua eta atzeko planoko datuen erabilera murrizten ditu"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Hasierako pantaila"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Azkenak"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Atzera"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Erakutsi \"Ez molestatu\" aukera bolumenaren leihoan"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Baimendu bolumenaren leihoan \"Ez molestatu\" aukera guztiz kontrolatzea."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Bolumena eta \"Ez molestatu\""</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Sartu \"Ez molestatu\" egoeran bolumena jaistean"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Erakutsi bolumena kontrolatzeko aukerekin"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ez molestatu"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Bolumen-botoietarako lasterbidea"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Irten \"Ez molestatu\" egoeratik bolumena igotzean"</string>
<string name="battery" msgid="7498329822413202973">"Bateria"</string>
<string name="clock" msgid="7416090374234785905">"Erlojua"</string>
<string name="headset" msgid="4534219457597457353">"Mikrofonodun entzungailua"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Aurikularrak konektatu dira"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Mikrofonodun entzungailua konektatu da"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Gaitu edo desgaitu ikonoak egoera-barran erakusteko aukera."</string>
<string name="data_saver" msgid="5037565123367048522">"Datu-aurrezlea"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Aktibatuta dago datu-aurrezlea"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Desaktibatuta dago datu-aurrezlea"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Aktibatuta"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Desaktibatuta"</string>
<string name="nav_bar" msgid="1993221402773877607">"Nabigazio-barra"</string>
<string name="start" msgid="6873794757232879664">"Hasi"</string>
<string name="center" msgid="4327473927066010960">"Erdiratu"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Aurrebista"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Arrastatu lauzak hemen gehitzeko"</string>
<string name="qs_edit" msgid="2232596095725105230">"Editatu"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Ordua"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Erakutsi orduak, minutuak eta segundoak"</item>
+ <item msgid="1427801730816895300">"Erakutsi orduak eta minutuak (balio lehenetsia)"</item>
+ <item msgid="3830170141562534721">"Ez erakutsi ikonoa"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Erakutsi beti ehunekoa"</item>
+ <item msgid="2139628951880142927">"Erakutsi ehunekoa kargatu bitartean (balio lehenetsia)"</item>
+ <item msgid="3327323682209964956">"Ez erakutsi ikonoa"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Beste bat"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Pantaila-zatitzailea"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Eraman behera"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Eraman gora"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Eraman ezkerrera"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Eraman eskuinera"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 851a6cb..cc32518 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"عکس صفحهنمایش گرفته شد."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"برای مشاهده عکس صفحهنمایشتان، لمس کنید."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"عکس صفحهنمایش گرفته نشد."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"به دلیل فضای ذخیرهسازی کم یا عدم اجازه برنامه یا سازمانتان، نمیتوان از صفحه عکس گرفت."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"به دلیل محدود بودن فضای ذخیرهسازی نمیتوانید عکس صفحهنمایش را ذخیره کنید."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"این برنامه یا سازمان شما اجازه نمیدهند عکس صفحهنمایش بگیرید."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"گزینههای انتقال فایل USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"نصب بهعنوان دستگاه پخش رسانه (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"تصب بهعنوان دوربین (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"زمان بیشتر."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"زمان کمتر."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"چراغ قوه خاموش است."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"چراغ قوه در دسترس نیست."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"چراغ قوه روشن است."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"چراغ قوه خاموش شد."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"چراغ قوه روشن شد."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"پین کردن صفحه"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"جستجو"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> شروع نشد."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> در حالت ایمن غیرفعال است."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"سابقه"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"پاک کردن"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"این برنامه از چندپنجره پشتیبانی نمیکند"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"برنامه از چندپنجره پشتیبانی نمیکند"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"تقسیم افقی"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"تقسیم عمودی"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"سفارشی کردن تقسیم"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"سکوت\nکامل"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"فقط\nاولویتدار"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"فقط\nهشدارها"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"همه"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"همه\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"در حال شارژ آهسته (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> تا شارژ کامل)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"ثانیههای ساعت را در نوار وضعیت نشان میدهد. ممکن است بر ماندگاری باتری تأثیر بگذارد."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"ترتیب مجدد در تنظیمات سریع"</string>
<string name="show_brightness" msgid="6613930842805942519">"نمایش روشنایی در تنظیمات سریع"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"فعال کردن شتابدهنده تقسیم صفحه با بالا کشیدن"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"فعال کردن تقسیم صفحه با اشاره بالا کشیدن"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"اشاره ورود به تقسیم صفحه با بالا کشیدن صفحه از دکمه نمای کلی را فعال میکند"</string>
<string name="experimental" msgid="6198182315536726162">"آزمایشی"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"بلوتوث روشن شود؟"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"برای مرتبط کردن صفحهکلید با رایانه لوحی، ابتدا باید بلوتوث را روشن کنید."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"روشن کردن"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"اعمال بر روی اعلانهای <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"اعمال بر روی تمام اعلانهای این برنامه"</string>
+ <string name="show_silently" msgid="6841966539811264192">"نمایش بیصدای اعلانها"</string>
+ <string name="block" msgid="2734508760962682611">"مسدود کردن همه اعلانها"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"ساکت نشود"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"ساکت یا مسدود نشود"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"نمایش تنظیمات کامل اهمیت"</string>
<string name="blocked_importance" msgid="5198578988978234161">"مسدود شده"</string>
+ <string name="min_importance" msgid="1901894910809414782">"کمترین اهمیت"</string>
<string name="low_importance" msgid="4109929986107147930">"اهمیت کم"</string>
<string name="default_importance" msgid="8192107689995742653">"اهمیت معمولی"</string>
<string name="high_importance" msgid="1527066195614050263">"اهمیت زیاد"</string>
<string name="max_importance" msgid="5089005872719563894">"اهمیت فوری"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"هرگز این اعلانها نشان داده نشوند"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"بدون صدا در پایین فهرست اعلان نشان داده شود"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"این اعلانها بیصدا نشان داده شوند"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"در بالای فهرست اعلانها و به همراه صدا نشان داده شود"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"در جلوی صفحه به همراه صدا نشان داده شود"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"بدون صدا در پایین فهرست اعلان نشان داده شود"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"این اعلانها بیصدا نشان داده شوند"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"به این اعلانها اجازه داده شود صدادار باشند"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"در صفحه نشان داده شوند و صدادار باشند"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"در بالای فهرست اعلان نشان داده شوند، در صفحه نشان داده شوند و صدادار باشند"</string>
<string name="notification_more_settings" msgid="816306283396553571">"تنظیمات بیشتر"</string>
<string name="notification_done" msgid="5279426047273930175">"تمام"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"رنگهای عادی"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"رنگهای شب"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"رنگهای سفارشی"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"خودکار"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"رنگهای نامشخص"</string>
- <string name="color_transform" msgid="6985460408079086090">"اصلاح رنگ"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"نمایش کاشی تنظیمات سریع"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"فعال کردن تبدیل سفارشی"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"رنگ و ظاهر"</string>
+ <string name="night_mode" msgid="3540405868248625488">"حالت شب"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"درجهبندی نمایشگر"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"روشن"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"خاموش"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"روشن شدن خودکار"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"تغییر به حالت شب وقتی برای مکان و زمان روز مناسب است"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"وقتی حالت شب روشن است"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"استفاده از زمینه تیره برای سیستمعامل Android"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"تنظیم سایهرنگ"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"تنظیم روشنایی"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"زمینه تیره بر قسمتهای اصلی سیستمعامل Android که بهطور معمول با زمینه روشن نشان داده میشوند (مثل «تنظیمات») اعمال میشود."</string>
<string name="color_apply" msgid="9212602012641034283">"اعمال کردن"</string>
<string name="color_revert_title" msgid="4746666545480534663">"تأیید تنظیمات"</string>
<string name="color_revert_message" msgid="9116001069397996691">"بعضی از تنظیمات رنگ میتوانند این دستگاه را غیرقابل استفاده کنند. برای تأیید این تنظیمات رنگ روی «تأیید» کلیک کنید، در غیر این صورت این تغییرات بعد از ۱۰ ثانیه بازنشانی میشوند."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"مصرف باتری"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"هنگام شارژ شدن، «بهینهسازی باتری» در دسترس نیست"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"بهینهسازی باتری"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"عملکرد و اطلاعات پسزمینه را کاهش میدهد"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"صفحه اصلی"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"موارد اخیر"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"برگشت"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"نمایش «مزاحم نشوید» در میزان صدا"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"به حالت «مزاحم نشوید» اجازه داده میشود در کادر گفتگوی میزان صدا کنترل کامل داشته باشد."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"میزان صدا و «مزاحم نشوید»"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"وارد شدن به حالت «مزاحم نشوید» در میزان صدای پایین"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"نمایش با کنترلهای صدا"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"مزاحم نشوید"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"میانبر دکمههای صدا"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"خارج شدن از حالت «مزاحم نشوید» در میزان صدای بالا"</string>
<string name="battery" msgid="7498329822413202973">"باتری"</string>
<string name="clock" msgid="7416090374234785905">"ساعت"</string>
<string name="headset" msgid="4534219457597457353">"هدست"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"هدفون وصل شد"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"هدست وصل شد"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"فعال یا غیرفعال کردن نمایش نمادها در نوار وضعیت."</string>
<string name="data_saver" msgid="5037565123367048522">"صرفهجویی در مصرف داده"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"صرفهجویی در مصرف داده روشن است"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"صرفهجویی در مصرف داده خاموش است"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"روشن"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"خاموش"</string>
<string name="nav_bar" msgid="1993221402773877607">"نوار پیمایش"</string>
<string name="start" msgid="6873794757232879664">"شروع"</string>
<string name="center" msgid="4327473927066010960">"وسط"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"پیشنمایش"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"کشیدن برای افزودن کاشیها"</string>
<string name="qs_edit" msgid="2232596095725105230">"ویرایش"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"زمان"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"ساعت، دقیقه و ثانیه نشان داده شود"</item>
+ <item msgid="1427801730816895300">"ساعت و دقیقه نشان داده شود (پیشفرض)"</item>
+ <item msgid="3830170141562534721">"این نماد نشان داده نشود"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"همیشه درصد نشان داده شود"</item>
+ <item msgid="2139628951880142927">"هنگام شارژ شدن درصد نشان داده شود (پیشفرض)"</item>
+ <item msgid="3327323682209964956">"این نماد نشان داده نشود"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"موارد دیگر"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"تقسیمکننده صفحه"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"انتقال به پایین"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"انتقال به بالا"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"انتقال به چپ"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"انتقال به راست"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index d44bd75..8b3fb5e 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Kuvakaappaus tallennettu"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Katso kuvakaappaus koskettamalla."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Kuvakaappausta ei voitu tallentaa"</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Kuvakaappaus ei onnistu, koska tila ei riitä tai koska sovellus tai organisaatiosi ei salli sitä."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Kuvakaappauksen tallentaminen epäonnistui, sillä tallennustilaa ei ole riittävästi."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Sovellus tai organisaatiosi ei salli kuvakaappauksien tallentamista."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB-tiedostonsiirtoasetukset"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Käytä mediasoittimena (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Käytä kamerana (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Lisää aikaa."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Vähennä aikaa."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Taskulamppu on pois päältä."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Taskulamppu ei ole käytettävissä."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Taskulamppu on päällä."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Taskulamppu poistettiin käytöstä."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Taskulamppu otettiin käyttöön."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"näytön kiinnitys"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"haku"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Sovelluksen <xliff:g id="APP">%s</xliff:g> käynnistäminen epäonnistui."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> on poistettu käytöstä vikasietotilassa."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Historia"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Tyhjennä"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Tämä sovellus ei tue usean ikkunan tilaa."</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Sovellus ei tue usean ikkunan tilaa."</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Vaakasuuntainen jako"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Pystysuuntainen jako"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Muokattu jako"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Täydellinen\nhiljaisuus"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Vain\ntärkeät"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Vain\nherätykset"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Kaikki"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Kaikki\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Ladataan (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> kunnes täynnä)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Nopea lataus (latausaikaa jäljellä <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Hidas lataus (latausaikaa jäljellä <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Näytä sekunnit tilapalkin kellossa. Tämä voi vaikuttaa akun kestoon."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Järjestä pika-asetukset uudelleen"</string>
<string name="show_brightness" msgid="6613930842805942519">"Näytä kirkkaus pika-asetuksissa"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Ota jaetun näytön tilan pyyhkäisyele käyttöön"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Siirry jaetun näytön tilaan pyyhkäisemällä ylöspäin"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Voit siirtyä jaetun näytön tilaan pyyhkäisemällä Viimeisimmät-painikkeesta ylöspäin."</string>
<string name="experimental" msgid="6198182315536726162">"Kokeellinen"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Otetaanko Bluetooth käyttöön?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Jotta voit yhdistää näppäimistön tablettiisi, sinun on ensin otettava Bluetooth käyttöön."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Ota käyttöön"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Sovella aiheen <xliff:g id="TOPIC_NAME">%1$s</xliff:g> ilmoituksiin"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Sovella kaikkiin tämän sovelluksen ilmoituksiin"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Näytä ilmoitukset hiljennettyinä"</string>
+ <string name="block" msgid="2734508760962682611">"Estä kaikki ilmoitukset"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Älä hiljennä"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Älä hiljennä tai estä"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Näytä kaikki tärkeysasetukset"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Estetyt"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Pienin tärkeys"</string>
<string name="low_importance" msgid="4109929986107147930">"Ei kovin tärkeä"</string>
<string name="default_importance" msgid="8192107689995742653">"Tärkeä"</string>
<string name="high_importance" msgid="1527066195614050263">"Hyvin tärkeä"</string>
<string name="max_importance" msgid="5089005872719563894">"Kiireellinen"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Älä koskaan näytä näitä ilmoituksia"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Näytä huomaamattomasti ilmoitusluettelon alaosassa"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Näytä nämä ilmoitukset huomaamattomasti"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Näytä ilmoitukset luettelon kärjessä ja toista merkkiääni"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Näytä ilmoitus näytöllä ja toista äänimerkki"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Hiljennä ilmoitukset ja näytä ne ilmoitusluettelon alaosassa."</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Näytä nämä ilmoitukset hiljennettyinä."</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Salli näiden ilmoitusten äänet."</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Näytä ilmoitukset näytöllä ja salli niiden äänet."</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Näytä ilmoitukset näytöllä ja ilmoitusluettelon yläosassa ja salli niiden äänet."</string>
<string name="notification_more_settings" msgid="816306283396553571">"Lisäasetukset"</string>
<string name="notification_done" msgid="5279426047273930175">"Valmis"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Tavalliset värit"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Yövärit"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Muokatut värit"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automaattinen"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Tuntemattomat värit"</string>
- <string name="color_transform" msgid="6985460408079086090">"Muokatut värit"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Näytä pika-asetusruutu"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Ota muokatut värit käyttöön"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Väri ja ulkoasu"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Yötila"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Kalibroi näyttö"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Käytössä"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Pois käytöstä"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Ota käyttöön automaattisesti"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Ota yötila käyttöön sijainnin ja kellonajan perusteella."</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Kun yötila on käytössä"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Käytä tummaa teemaa käyttöjärjestelmässä"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Säädä sävytystä"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Säädä kirkkautta"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Tumma teema tulee käyttöön Android-käyttöjärjestelmän ydinosissa, kuten Asetuksissa, joissa käytetään tavallisesti vaaleaa teemaa."</string>
<string name="color_apply" msgid="9212602012641034283">"Käytä"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Vahvista asetukset"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Jotkin väriasetukset voivat häiritä laitteen käyttöä. Vahvista uudet väriasetukset valitsemalla OK. Muussa tapauksessa aiemmat asetukset palautetaan 10 sekunnin kuluttua."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Akun käyttö"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Virransäästö ei ole käytettävissä latauksen aikana."</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Virransäästö"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Rajoittaa suorituskykyä ja taustatiedonsiirtoa."</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Aloitusnäyttö"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Viimeaikaiset"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Takaisin"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Näytä Älä häiritse ‑valinnat äänenvoimakkuudessa"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Näytä kaikki Älä häiritse ‑tilan säädöt äänenvoimakkuusvalinnassa."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Äänenvoimakkuus ja Älä häiritse ‑tila"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Siirry Älä häiritse -tilaan, kun äänenvoimakkuutta lasketaan"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Näytä äänenvoimakkuuden säätimien yhteydessä"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Älä häiritse"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Äänenvoimakkuuspainikkeiden pikanäppäin"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Poistu Älä häiritse -tilasta, kun äänenvoimakkuus nousee"</string>
<string name="battery" msgid="7498329822413202973">"Akku"</string>
<string name="clock" msgid="7416090374234785905">"Kello"</string>
<string name="headset" msgid="4534219457597457353">"Kuulokemikrofoni"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Kuulokkeet liitetty"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Kuulokemikrofoni liitetty"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Ota tilapalkin kuvakkeet käyttöön tai poista ne käytöstä."</string>
<string name="data_saver" msgid="5037565123367048522">"Data Saver"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Data Saver on käytössä."</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Data Saver on pois käytöstä."</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Käytössä"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Pois käytöstä"</string>
<string name="nav_bar" msgid="1993221402773877607">"Navigointipalkki"</string>
<string name="start" msgid="6873794757232879664">"Alussa"</string>
<string name="center" msgid="4327473927066010960">"Keskellä"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Esikatselu"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Lisää osioita vetämällä."</string>
<string name="qs_edit" msgid="2232596095725105230">"Muokkaa"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Aika"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Näytä tunnit, minuutit ja sekunnit"</item>
+ <item msgid="1427801730816895300">"Näytä tunnit ja minuutit (oletus)"</item>
+ <item msgid="3830170141562534721">"Älä näytä tätä kuvaketta"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Näytä prosenttiluku aina"</item>
+ <item msgid="2139628951880142927">"Näytä prosenttiluku latauksen aikana (oletus)"</item>
+ <item msgid="3327323682209964956">"Älä näytä tätä kuvaketta"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Muu"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Näytön jakaja"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Siirrä alaspäin"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Siirrä ylöspäin"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Siirrä vasemmalle"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Siirrä oikealle"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index d34723f..e0beeca 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Capture d\'écran réussie"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Appuyez pour afficher votre capture d\'écran."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Impossible de réaliser une capture d\'écran"</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Imposs. prendre saisie d\'écran : espace stock. limité, ou l\'appli ou votre organisation l\'interdit."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Impossible d\'enregistrer la saisie d\'écran, car l\'espace de stockage est limité."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"L\'application ou votre organisation n\'autorise pas les saisies d\'écran."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Options transfert fichiers USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Installer comme un lecteur multimédia (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Installer comme un appareil photo (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Plus longtemps"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Moins longtemps."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lampe de poche désactivée."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lampe de poche indisponible."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lampe de poche activée."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Lampe de poche désactivée."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Lampe de poche activée."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"épinglage d\'écran"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Impossible de lancer <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> est désactivée en mode sécurisé."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Historique"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Effacer"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Cette application ne prend pas en charge le mode multifenêtre"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"L\'application ne prend pas en charge le mode multifenêtre"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Séparation horizontale"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Séparation verticale"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Séparation personnalisée"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Aucune\ninterruption"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Priorités\nuniquement"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Alarmes\nuniquement"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Tous"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Tous\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charge en cours... (chargée à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Charge rapide en cours... (chargé dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Charge lente en cours... (chargé dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Afficher les secondes sur l\'horloge dans la barre d\'état. Cela peut réduire l\'autonomie de la pile."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Réorganiser les paramètres rapides"</string>
<string name="show_brightness" msgid="6613930842805942519">"Afficher la luminosité dans les paramètres rapides"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Activer l\'accélérateur d\'écr. partagé en balayant vers le haut"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Activer le geste d\'écran partagé en balayant vers le haut"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Activer le geste permettant d\'utiliser l\'écran partagé en balayant l\'écran vers le haut à partir du bouton « Aperçu »"</string>
<string name="experimental" msgid="6198182315536726162">"Fonctions expérimentales"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Activer Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Pour connecter votre clavier à votre tablette, vous devez d\'abord activer la connectivité Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Activer"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Appliquer à <xliff:g id="TOPIC_NAME">%1$s</xliff:g> notifications"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Appliquer à toutes les notifications de cette application"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Afficher les notifications en mode silencieux"</string>
+ <string name="block" msgid="2734508760962682611">"Bloquer toutes les notifications"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Ne pas activer le mode silencieux"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Ne pas activer le mode silencieux ni bloquer"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Afficher les paramètres d\'importance complets"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloquée"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Importance minimale"</string>
<string name="low_importance" msgid="4109929986107147930">"Importance faible"</string>
<string name="default_importance" msgid="8192107689995742653">"Importance normale"</string>
<string name="high_importance" msgid="1527066195614050263">"Importance élevée"</string>
<string name="max_importance" msgid="5089005872719563894">"Importance urgente"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Ne jamais afficher ces notifications"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Afficher en mode silencieux au bas de la liste de notifications"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Afficher ces notifications en mode silencieux"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Afficher en haut de la liste des notifications et émettre un son"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Afficher sur l\'écran et émettre un son"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Afficher en mode silencieux au bas de la liste de notifications"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Afficher ces notifications en mode silencieux"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Autoriser ces notifications à émettre des sons"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Afficher sur l\'écran et émettre un son"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Afficher en haut de la liste des notifications, afficher sur l\'écran et émettre un son"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Plus de paramètres"</string>
<string name="notification_done" msgid="5279426047273930175">"Terminé"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Couleurs normales"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Couleurs nocturnes"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Couleurs personnalisées"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automatique"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Couleurs inconnues"</string>
- <string name="color_transform" msgid="6985460408079086090">"Modifier la couleur"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Afficher la tuile de configuration rapide"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Activer la transformation personnalisée"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Couleur et apparence"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Mode Nuit"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Calibrer l\'affichage"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Activé"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Désactivé"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Activer automatiquement"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Passer en mode Nuit en fonction de la position et de l\'heure de la journée"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Lorsque le mode Nuit est activé"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Utiliser thème foncé pour Android"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Ajuster la coloration"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Régler la luminosité"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Le thème foncé est appliqué à des zones essentielles de la plateforme Android qui sont habituellement affichées dans un thème clair, comme les paramètres."</string>
<string name="color_apply" msgid="9212602012641034283">"Appliquer"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirmer les paramètres"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Certains paramètres de couleurs peuvent rendre cet appareil inutilisable. Cliquez sur « OK » pour valider ces paramètres, sinon ils seront réinitialisés après 10 secondes."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Utilisation de la pile"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Le mode Économie d\'énergie n\'est pas accessible pendant la charge"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Économie d\'énergie"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Réduit les performances et les données en arrière-plan"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Accueil"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Récents"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Précédent"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Fonctionnalité Ne pas déranger dans boîte de dialogue volume"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Autoriser le contrôle de la fonctionnalité Ne pas déranger dans la boîte de dialogue de modification du volume"</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Volume et fonctionnalité Ne pas déranger"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Activer fonctionnalité Ne pas déranger avec bouton Volume -"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Afficher avec les commandes de volume"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ne pas déranger"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Raccourci des boutons de volume"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Désactiver fonctionnalité Ne pas déranger avec bouton Volume +"</string>
<string name="battery" msgid="7498329822413202973">"Pile"</string>
<string name="clock" msgid="7416090374234785905">"Horloge"</string>
<string name="headset" msgid="4534219457597457353">"Écouteurs"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Écouteurs connectés"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Écouteurs connectés"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Activer ou désactiver l\'affichage des icônes dans la barre d\'état"</string>
<string name="data_saver" msgid="5037565123367048522">"Économiseur de données"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"La fonction Économiseur de données est activée"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"La fonction Économiseur de données est désactivée"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Activé"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Désactivé"</string>
<string name="nav_bar" msgid="1993221402773877607">"Barre de navigation"</string>
<string name="start" msgid="6873794757232879664">"Démarrer"</string>
<string name="center" msgid="4327473927066010960">"Centrer"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Aperçu"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Faites glisser des tuiles ici pour les ajouter"</string>
<string name="qs_edit" msgid="2232596095725105230">"Modifier"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Heure"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Afficher les heures, les minutes et les secondes"</item>
+ <item msgid="1427801730816895300">"Afficher les heures et les minutes (par défaut)"</item>
+ <item msgid="3830170141562534721">"Ne pas afficher cette icône"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Toujours afficher le pourcentage"</item>
+ <item msgid="2139628951880142927">"Montrer le pourcentage durant la charge (par défaut)"</item>
+ <item msgid="3327323682209964956">"Ne pas afficher cette icône"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Autre"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Séparateur d\'écran partagé"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Déplacer vers le bas"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Déplacer vers le haut"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Déplacer vers la gauche"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Déplacer vers la droite"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 241d34c..9ef6392 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Capture d\'écran réussie"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Appuyez pour afficher votre capture d\'écran."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Impossible de réaliser une capture d\'écran"</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Capture d\'écran imposs., car espace stockage limité, ou appli ou entreprise ne vous y autorise pas."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Impossible d\'enregistrer la capture d\'écran, car l\'espace de stockage est limité."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Les captures d\'écran ne sont pas autorisées par l\'application ou par votre organisation."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Options transfert fichiers USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Installer en tant que lecteur multimédia (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Installer en tant qu\'appareil photo (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Plus longtemps"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Moins longtemps"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lampe de poche désactivée."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lampe de poche indisponible."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lampe de poche activée."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Lampe de poche désactivée."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Lampe de poche activée."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"épinglage d\'écran"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Impossible de lancer <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"L\'application <xliff:g id="APP">%s</xliff:g> est désactivée en mode sécurisé."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Historique"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Effacer"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Application incompatible avec le mode multifenêtre."</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Application incompatible avec le mode multifenêtre"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Séparation horizontale"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Séparation verticale"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Séparation personnalisée"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Aucune\ninterruption"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Priorité\nuniquement"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Alarmes\nuniquement"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Toujours"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Toutes\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charge en cours… (chargé à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Charge rapide… (chargé à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Charge lente… (chargé à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Afficher les secondes dans la barre d\'état. Cela risque de réduire l\'autonomie de la batterie."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Réorganiser la fenêtre de configuration rapide"</string>
<string name="show_brightness" msgid="6613930842805942519">"Afficher la luminosité dans fenêtre de configuration rapide"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Activer accélérateur écran partagé en balayant vers le haut"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Activer l\'écran partagé en balayant vers le haut"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Activer le geste permettant d\'utiliser l\'écran partagé en balayant l\'écran vers le haut à partir du bouton \"Aperçu\""</string>
<string name="experimental" msgid="6198182315536726162">"Paramètres expérimentaux"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Activer le Bluetooth ?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Pour connecter un clavier à votre tablette, vous devez avoir activé le Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Activer"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Appliquer aux notifications relatives au sujet \"<xliff:g id="TOPIC_NAME">%1$s</xliff:g>\""</string>
- <string name="apply_to_app" msgid="363016783939815960">"Appliquer à toutes les notifications de cette application"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Afficher les notifications en mode silencieux"</string>
+ <string name="block" msgid="2734508760962682611">"Bloquer toutes les notifications"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Ne pas activer le mode silencieux"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Ne pas activer le mode silencieux ni bloquer"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Afficher les paramètres d\'importance complets"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloquées"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Importance minimale"</string>
<string name="low_importance" msgid="4109929986107147930">"Importance faible"</string>
<string name="default_importance" msgid="8192107689995742653">"Importance normale"</string>
<string name="high_importance" msgid="1527066195614050263">"Importance élevée"</string>
<string name="max_importance" msgid="5089005872719563894">"Urgent"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Ne jamais afficher ces notifications"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Afficher au bas de la liste des notifications en mode silencieux"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Afficher ces notifications en mode silencieux"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Afficher en haut de la liste des notifications et émettre un son"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Afficher sur l\'écran et émettre un son"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Afficher au bas de la liste des notifications en mode silencieux"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Afficher ces notifications en mode silencieux"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Autoriser ces notifications à émettre des sons"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Afficher sur l\'écran et émettre un son"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Afficher en haut de la liste des notifications, afficher sur l\'écran et émettre un son"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Plus de paramètres"</string>
<string name="notification_done" msgid="5279426047273930175">"Terminé"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Couleurs normales"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Couleurs nocturnes"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Couleurs personnalisées"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automatique"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Couleurs inconnues"</string>
- <string name="color_transform" msgid="6985460408079086090">"Modification des couleurs"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Afficher la tuile de configuration rapide"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Activer la transformation personnalisée"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Couleur et apparence"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Mode Nuit"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Calibrer l\'affichage"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Activé"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Désactivé"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Activer automatiquement"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Passer en mode Nuit en fonction de la position et de l\'heure de la journée"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Lorsque le mode Nuit est activé"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Utiliser thème foncé pour plate-forme Android"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Ajuster la coloration"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Régler la luminosité"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Le thème foncé est appliqué à des zones essentielles de la plate-forme Android qui sont habituellement affichées dans un thème clair, telles que les paramètres."</string>
<string name="color_apply" msgid="9212602012641034283">"Appliquer"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Vérifier les paramètres"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Certains paramètres de couleurs peuvent rendre cet appareil inutilisable. Cliquez sur \"OK\" pour valider ces paramètres, sans quoi ils seront réinitialisés après 10 secondes."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Utilisation batterie"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"L\'économiseur de batterie n\'est pas disponible lorsque l\'appareil est en charge."</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Économiseur de batterie"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Limite les performances et les données en arrière-plan."</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Accueil"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Récents"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Précédent"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Fonctionnalité Ne pas déranger dans boîte de dialogue volume"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Autoriser le contrôle de la fonctionnalité Ne pas déranger dans la boîte de dialogue de modification du volume"</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Volume et fonctionnalité Ne pas déranger"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Activer fonctionnalité Ne pas déranger via le bouton Volume -"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Afficher avec les commandes de volume"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ne pas déranger"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Raccourci des boutons de volume"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Désactiver fonctionnalité Ne pas déranger via bouton Volume +"</string>
<string name="battery" msgid="7498329822413202973">"Batterie"</string>
<string name="clock" msgid="7416090374234785905">"Horloge"</string>
<string name="headset" msgid="4534219457597457353">"Casque"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Casque connecté"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Casque connecté"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Activer ou désactiver l\'affichage des icônes dans la barre d\'état"</string>
<string name="data_saver" msgid="5037565123367048522">"Économiseur de données"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"L\'économiseur de données est activé."</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"L\'économiseur de données est désactivé."</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Activé"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Désactivé"</string>
<string name="nav_bar" msgid="1993221402773877607">"Barre de navigation"</string>
<string name="start" msgid="6873794757232879664">"Début"</string>
<string name="center" msgid="4327473927066010960">"Centre"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Aperçu"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Faites glisser des tuiles ici pour les ajouter"</string>
<string name="qs_edit" msgid="2232596095725105230">"Modifier"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Heure"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Afficher les heures, les minutes et les secondes"</item>
+ <item msgid="1427801730816895300">"Afficher les heures et les minutes (option par défaut)"</item>
+ <item msgid="3830170141562534721">"Ne plus afficher cette icône"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Toujours afficher le pourcentage"</item>
+ <item msgid="2139628951880142927">"Afficher le pourcentage lorsque l\'appareil est en charge (option par défaut)"</item>
+ <item msgid="3327323682209964956">"Ne plus afficher cette icône"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Autre"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Séparateur d\'écran partagé"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Déplacer vers le bas"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Déplacer vers le haut"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Déplacer vers la gauche"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Déplacer vers la droite"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 75e47a5..bb85708 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Captura de pantalla gardada."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Toca para ver a captura de pantalla."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Non se puido facer a captura de pantalla."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Non se pode realizar a captura de pantalla porque o espazo de almacenamento está limitado ou porque non o admite a aplicación ou a túa empresa."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Non se pode gardar a captura de pantalla porque o espazo de almacenamento é limitado."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"A aplicación ou a túa organización non permite realizar capturas de pantalla."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Opcións de transferencia USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Inserir como reprodutor multimedia (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Inserir como cámara (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Máis tempo."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Menos tempo."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lanterna desactivada."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"A lanterna non está dispoñible."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lanterna activada."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Desactivouse a lanterna."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Activouse a lanterna."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixación de pantalla"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Non foi posible iniciar <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"A aplicación <xliff:g id="APP">%s</xliff:g> está desactivada no modo seguro"</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Historial"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Borrar"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Esta aplicación non é compatible con varias ventás"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"A aplicación non é compatible con varias ventás"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Dividir en horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Dividir en vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Dividir de xeito personalizado"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Silencio\ntotal"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Só\nprioridade"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Só\nalarmas"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Todas"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Todas\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Cargando (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para finalizar a carga)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Cargando rápido (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para rematar a carga)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Cargando lento (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para rematar a carga)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra os segundos do reloxo na barra de estado. Pode influír na duración da batería."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar Configuración rápida"</string>
<string name="show_brightness" msgid="6613930842805942519">"Mostrar brillo en Configuración rápida"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Activar acelerador de pant. div. pasando o dedo cara arriba"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Activar pantalla dividida pasando o dedo cara arriba"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Activa o xesto de pasar o dedo cara arriba desde o botón Visión xeral para acceder ao modo de pantalla dividida"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Queres activar o Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Para conectar o teu teclado co tablet, primeiro tes que activar o Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Activar"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Aplicar ás notificacións de <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Aplicar a todas as notificacións procedentes desta aplicación"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Mostrar notificacións de forma silenciosa"</string>
+ <string name="block" msgid="2734508760962682611">"Bloquear todas as notificacións"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Non silenciar"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Non silenciar nin bloquear"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Mostrar a configuración completa da importancia"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloqueada"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Importancia mínima"</string>
<string name="low_importance" msgid="4109929986107147930">"Importancia baixa"</string>
<string name="default_importance" msgid="8192107689995742653">"Importancia normal"</string>
<string name="high_importance" msgid="1527066195614050263">"Importancia alta"</string>
<string name="max_importance" msgid="5089005872719563894">"Importancia urxente"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Non mostrar nunca estas notificacións"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Mostrar de forma silenciosa na parte inferior da lista de notificacións"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Mostrar estas notificacións de forma silenciosa"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Mostrar na parte superior da lista de notificacións e emitir son"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Mostrar na pantalla e emitir son"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Mostrar de forma silenciosa na parte inferior da lista de notificacións"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Mostrar estas notificacións de forma silenciosa"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Permitir que esta notificación emita son"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Mostrar na pantalla e permitir que emita son"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Mostrar na parte superior da lista de notificacións, amosar na pantalla e permitir que emita son"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Máis opcións"</string>
<string name="notification_done" msgid="5279426047273930175">"Feito"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Cores normais"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Cores nocturnas"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Cores personalizadas"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automático"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Cores descoñecidas"</string>
- <string name="color_transform" msgid="6985460408079086090">"Modificación de cor"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Mostrar mosaico de configuración rápida"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Activar transformación personalizada"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Cor e aspecto"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Modo nocturno"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Calibrar pantalla"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Activado"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Desactivado"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Activar automaticamente"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Cambia ao modo nocturno segundo proceda para a localización e a hora do día"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Cando o modo nocturno está activado"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Usar tema escuro para SO Android"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Axustar ton"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Axustar brillo"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"O tema escuro aplícase ás áreas principais do SO Android que se mostran normalmente nun tema claro, como a configuración."</string>
<string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirmar configuración"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Algunhas opcións de configuración de cor poden facer que este dispositivo sexa inutilizable. Fai clic en Aceptar para confirmar esta configuración de cor; en caso contrario, a configuración restablecerase tras 10 segundos."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Uso de batería"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"A función aforro de batería non está dispoñible durante a carga"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Aforro de batería"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduce o rendemento e os datos en segundo plano"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Inicio"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recentes"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Volver"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Mostrar o modo Non molestar no cadro de diálogo de volume"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Permite o control completo do modo Non molestar no cadro de diálogo de volume."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Volume e modo Non molestar"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Activar o modo Non molestar ao baixar o volume"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostrar cos controis de volume"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Non molestar"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Atallo dos botóns de volume"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Desactivar o modo Non molestar ao subir o volume"</string>
<string name="battery" msgid="7498329822413202973">"Batería"</string>
<string name="clock" msgid="7416090374234785905">"Reloxo"</string>
<string name="headset" msgid="4534219457597457353">"Auriculares"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Conectáronse os auriculares"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Conectáronse os auriculares"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Activa ou desactiva a visualización das iconas na barra de estado."</string>
<string name="data_saver" msgid="5037565123367048522">"Economizador de datos"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"O economizador de datos está activado"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"O economizador de datos está desactivado"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Activar"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Desactivar"</string>
<string name="nav_bar" msgid="1993221402773877607">"Barra de navegación"</string>
<string name="start" msgid="6873794757232879664">"Inicio"</string>
<string name="center" msgid="4327473927066010960">"Centro"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Vista previa"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Arrastrar para engadir mosaicos"</string>
<string name="qs_edit" msgid="2232596095725105230">"Editar"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Hora"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Mostrar horas, minutos e segundos"</item>
+ <item msgid="1427801730816895300">"Mostrar horas e minutos (predeterminado)"</item>
+ <item msgid="3830170141562534721">"Non mostrar esta icona"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Mostrar sempre porcentaxe"</item>
+ <item msgid="2139628951880142927">"Mostrar porcentaxe durante a carga (predeterminado)"</item>
+ <item msgid="3327323682209964956">"Non mostrar esta icona"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Outros"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Divisor de pantalla dividida"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Baixar"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Subir"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Mover á esquerda"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Mover á dereita"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index 45a4eaf..075f023 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"સ્ક્રીનશોટ કેપ્ચર કર્યો."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"તમારો સ્ક્રીનશોટ જોવા માટે ટચ કરો."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"સ્ક્રીનશોટ કેપ્ચર કરી શકાયો નથી."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"મર્યાદિત સંગ્રહ સ્થાનને કારણે સ્ક્રીનશોટ લઈ શકાતો નથી અથવા એપ્લિકેશન અથવા તમારા સંગઠન દ્વારા તેની મંજૂરી નથી."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"મર્યાદિત સંગ્રહ સ્થાનને કારણે સ્ક્રીનશોટ સાચવી શકાતો નથી."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ઍપ્લિકેશન કે તમારી સંસ્થા દ્વારા સ્ક્રીનશોટ્સ લેવાની મંજૂરી નથી."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB ફાઇલ ટ્રાન્સફર વિકલ્પો"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"મીડિયા પ્લેયર તરીકે માઉન્ટ કરો (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"કૅમેરા તરીકે માઉન્ટ કરો (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"વધુ સમય."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"ઓછો સમય."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ફ્લેશલાઇટ બંધ."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ફ્લેશલાઇટ અનુપલબ્ધ."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ફ્લેશલાઇટ ચાલુ."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ફ્લેશલાઇટ બંધ કરી."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ફ્લેશલાઇટ ચાલુ કરી."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"સ્ક્રીન પિનિંગ"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"શોધ"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> પ્રારંભ કરી શકાયું નથી."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"સુરક્ષિત મોડમાં <xliff:g id="APP">%s</xliff:g> અક્ષમ કરેલ છે."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"ઇતિહાસ"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"સાફ કરો"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"આ ઍપ્લિકેશન મલ્ટિ-વિંડોનું સમર્થન કરતી નથી"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"ઍપ્લિકેશન મલ્ટિ-વિંડોનું સમર્થન કરતી નથી"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"આડું વિભક્ત કરો"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ઊભું વિભક્ત કરો"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"કસ્ટમ વિભક્ત કરો"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"સાવ\nશાંતિ"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"ફક્ત\nપ્રાધાન્યતા"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"ફક્ત\nએલાર્મ્સ"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"તમામ"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"બધી\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"ધીમેથી ચાર્જિંગ થઇ રહી છે (પૂર્ણ થવામાં <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> બાકી)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"ઘડિયાળ સેકન્ડ સ્થિતિ બારમાં બતાવો. બૅટરીની આવરદા પર અસર કરી શકે છે."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"ઝડપી સેટિંગ્સને ફરીથી ગોઠવો"</string>
<string name="show_brightness" msgid="6613930842805942519">"ઝડપી સેટિંગ્સમાં તેજ બતાવો"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"સ્પ્લિટ-સ્ક્રીન સ્વાઇપ-અપ ઍક્સલરેટર સક્ષમ કરો"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"સ્પ્લિટ-સ્ક્રીન સ્વાઇપ-અપ હાવભાવ સક્ષમ કરો"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"વિહંગાવલોકન બટનમાંથી સ્વાઇપ કરીને સ્પ્લિટ-સ્ક્રીનમાં દાખલ થવા માટે હાવભાવ સક્ષમ કરો"</string>
<string name="experimental" msgid="6198182315536726162">"પ્રાયોગિક"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth ચાલુ કરવુ છે?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"તમારા ટેબ્લેટ સાથે કીબોર્ડ કનેક્ટ કરવા માટે, તમારે પહેલાં Bluetooth ચાલુ કરવાની જરૂર પડશે."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"ચાલુ કરો"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> સૂચનાઓ પર લાગુ કરો"</string>
- <string name="apply_to_app" msgid="363016783939815960">"આ ઍપ્લિકેશનની તમામ સૂચનાઓ પર લાગુ કરો"</string>
+ <string name="show_silently" msgid="6841966539811264192">"સૂચનાઓ ચુપચાપ બતાવો"</string>
+ <string name="block" msgid="2734508760962682611">"તમામ સૂચનાઓને અવરોધિત કરો"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"ચુપ કરશો નહીં"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"ચુપ કે અવરોધિત કરશો નહીં"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"પૂર્ણ મહત્વ સેટિંગ્સ બતાવો"</string>
<string name="blocked_importance" msgid="5198578988978234161">"અવરોધિત"</string>
+ <string name="min_importance" msgid="1901894910809414782">"ન્યૂનતમ મહત્વ"</string>
<string name="low_importance" msgid="4109929986107147930">"નિમ્ન મહત્વની"</string>
<string name="default_importance" msgid="8192107689995742653">"સામાન્ય મહત્વની"</string>
<string name="high_importance" msgid="1527066195614050263">"ઉચ્ચ મહત્વની"</string>
<string name="max_importance" msgid="5089005872719563894">"તાત્કાલિક મહત્વની"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"આ સૂચનાઓ ક્યારેય બતાવશો નહીં"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"સૂચનાની સૂચિની નીચે ચુપચાપ બતાવો"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"આ સૂચનાઓ ચુપચાપ બતાવો"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"સૂચનાઓની સૂચિની ટોચ પર બતાવો અને અવાજ કરો"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"સ્ક્રીન પર ત્વરિત દ્રષ્ટિ કરો અને અવાજ કરો"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"સૂચનાની સૂચિની નીચે ચુપચાપ બતાવો"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"આ સૂચનાઓ ચુપચાપ બતાવો"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"આ સૂચનાને અવાજ કરવાની મંજૂરી આપો"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"સ્ક્રીન પર ત્વરિત દ્રષ્ટિ કરો અને અવાજને મંજૂરી આપો"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"સૂચનાઓની સૂચિની ટોચ પર બતાવો, સ્ક્રીન પર ત્વરિત દ્રષ્ટિ કરો અને અવાજને મંજૂરી આપો"</string>
<string name="notification_more_settings" msgid="816306283396553571">"વધુ સેટિંગ્સ"</string>
<string name="notification_done" msgid="5279426047273930175">"થઈ ગયું"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"સામાન્ય રંગો"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"રાત્રિ રંગો"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"કસ્ટમ રંગો"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"સ્વતઃ"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"અજાણ્યા રંગો"</string>
- <string name="color_transform" msgid="6985460408079086090">"રંગ સંશોધન"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"ઝડપી સેટિંગ્સ ટાઇલ બતાવો"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"કસ્ટમ રૂપાંતરણને સક્ષમ કરો"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"રંગ અને દેખાવ"</string>
+ <string name="night_mode" msgid="3540405868248625488">"રાત્રિ મોડ"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"પ્રદર્શન કૅલિબ્રેટ કરો"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"ચાલુ"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"બંધ"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"આપમેળે ચાલુ કરો"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"સ્થાન અને દિવસના સમય માટે યોગ્ય હોય તે રાત્રિ મોડ પર સ્વિચ કરો"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"જ્યારે રાત્રિ મોડ ચાલુ હોય"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Android OS માટે ઘાટી થીમનો ઉપયોગ કરો"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"ટિંટ સમાયોજિત કરો"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"તેજ સમાયોજિત કરો"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"ઘાટી થીમને Android OS ના મુખ્ય ક્ષેત્રો પર લાગુ કરે છે જે સામાન્ય રીતે સેટિંગ્સ જેવી લાઇટ થીમમાં પ્રદર્શિત કરવામાં આવે છે."</string>
<string name="color_apply" msgid="9212602012641034283">"લાગુ કરો"</string>
<string name="color_revert_title" msgid="4746666545480534663">"સેટિંગ્સની પુષ્ટિ કરો"</string>
<string name="color_revert_message" msgid="9116001069397996691">"કેટલીક રંગ સેટિંગ્સ આ ઉપકરણને બિનઉપયોગી બનાવી શકે છે. આ રંગ સેટિંગ્સની પુષ્ટિ કરવા માટે ઑકે ક્લિક કરો, અન્યથા 10 સેકંડ પછી આ સેટિંગ્સ ફરીથી સેટ થશે."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"બૅટરી વપરાશ"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"ચાર્જિંગ દરમિયાન બૅટરી બચતકર્તા ઉપલબ્ધ નથી"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"બૅટરી બચતકર્તા"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"પ્રદર્શન અને પૃષ્ઠભૂમિ ડેટા ઘટાડે છે"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"હોમ"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"તાજેતરના"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"પાછળ"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"વૉલ્યૂમમાં ખલેલ પાડશો નહીં બતાવો"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"વૉલ્યૂમ સંવાદમાં ખલેલ પાડશો નહીંના સંપૂર્ણ નિયંત્રણની મંજૂરી આપો."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"વૉલ્યૂમ અને ખલેલ પાડશો નહીં"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"વૉલ્યૂમ ઘટાડવા પર ખલેલ પાડશો નહીંમાં દાખલ થાઓ"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"વૉલ્યૂમ નિયંત્રણ સાથે બતાવો"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"ખલેલ પાડશો નહીં"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"વૉલ્યૂમ બટન્સ શૉર્ટકટ"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"વૉલ્યૂમ વધારવા પર ખલેલ પાડશો નહીંમાંથી બહાર નિકળો"</string>
<string name="battery" msgid="7498329822413202973">"બૅટરી"</string>
<string name="clock" msgid="7416090374234785905">"ઘડિયાળ"</string>
<string name="headset" msgid="4534219457597457353">"હેડસેટ"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"હેડફોન કનેક્ટ કર્યાં"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"હેડસેટ કનેક્ટ કર્યો"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"સ્થિતિ બારમાં બતાવવામાં આવતા આઇકન્સને સક્ષમ અથવા અક્ષમ કરો."</string>
<string name="data_saver" msgid="5037565123367048522">"ડેટા સેવર"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"ડેટા સેવર ચાલુ છે"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"ડેટા સેવર બંધ છે"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"ચાલુ"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"બંધ"</string>
<string name="nav_bar" msgid="1993221402773877607">"નેવિગેશન બાર"</string>
<string name="start" msgid="6873794757232879664">"પ્રારંભ કરો"</string>
<string name="center" msgid="4327473927066010960">"મધ્ય"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"પૂર્વાવલોકન કરો"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"ટાઇલ્સ ઉમેરવા માટે ખેંચો"</string>
<string name="qs_edit" msgid="2232596095725105230">"સંપાદિત કરો"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"સમય"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"કલાક, મિનિટ અને સેકંડ બતાવો"</item>
+ <item msgid="1427801730816895300">"કલાક અને મિનિટ બતાવો (ડિફોલ્ટ)"</item>
+ <item msgid="3830170141562534721">"આ આઇકન બતાવશો નહીં"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"હંમેશાં ટકાવારી બતાવો"</item>
+ <item msgid="2139628951880142927">"ચાર્જ થાય ત્યારે ટકાવારી બતાવો (ડિફોલ્ટ)"</item>
+ <item msgid="3327323682209964956">"આ આઇકન બતાવશો નહીં"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"અન્ય"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"સ્પ્લિટ-સ્ક્રીન વિભાજક"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"નીચે ખસેડો"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"ઉપર ખસેડો"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"ડાબે ખસેડો"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"જમણે ખસેડો"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 7349827..91a5d69 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"स्क्रीनशॉट कैप्चर किया गया."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"अपना स्क्रीनशॉट देखने के लिए स्पर्श करें."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"स्क्रीनशॉट को कैप्चर नहीं किया जा सका."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"सीमित मेमोरी स्थान के कारण स्क्रीनशॉट नहीं ले सकते, या ऐप्स या आपके संगठन द्वारा ऐसा अनुमत नहीं है."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"सीमित मेमोरी स्थान के कारण स्क्रीनशॉट सहेजा नहीं जा सकता."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"आपके ऐप्लिकेशन या आपके संगठन द्वारा स्क्रीनशॉट लेने की अनुमति नहीं है."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB फ़ाइल स्थानांतरण विकल्प"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"मीडिया प्लेयर के रूप में माउंट करें (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"कैमरे के रूप में माउंट करें (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"अधिक समय."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"कम समय."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"फ़्लैशलाइट बंद है."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"फ़्लैशलाइट उपलब्ध नहीं है."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"फ़्लैशलाइट चालू है."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"फ़्लैशलाइट को बंद किया गया."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"फ़्लैशलाइट को चालू किया गया."</string>
@@ -304,6 +306,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> को सुरक्षित-मोड में अक्षम किया गया."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"इतिहास"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"साफ़ करें"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"यह ऐप्लिकेशन एकाधिक विंडो का समर्थन नहीं करता है"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"ऐप्लिकेशन एकाधिक विंडो का समर्थन नहीं करता है"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"क्षैतिज रूप से विभाजित करें"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"लम्बवत रूप से विभाजित करें"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"कस्टम रूप से विभाजित करें"</string>
@@ -333,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"पूरी तरह\nशांत"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"केवल\nप्राथमिकता"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"केवल\nअलार्म"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"सभी"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"सभी\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"धीरे चार्ज हो रहा है (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> में पूरा हो जाएगा)"</string>
@@ -447,34 +449,43 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"स्थिति बार में घड़ी के सेकंड दिखाएं. इससे बैटरी के जीवनकाल पर प्रभाव पड़ सकता है."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"त्वरित सेटिंग को पुन: व्यवस्थित करें"</string>
<string name="show_brightness" msgid="6613930842805942519">"त्वरित सेटिंग में स्क्रीन की रोशनी दिखाएं"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"ऊपर स्वाइप करके स्क्रीन विभाजन की त्वरित सुविधा सक्षम करें"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"ऊपर स्वाइप करके विभाजित स्क्रीन में जाने का जेस्चर सक्षम करें"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"अवलोकन बटन से ऊपर स्वाइप करके स्क्रीन विभाजन में आने का हावभाव सक्षम करें"</string>
<string name="experimental" msgid="6198182315536726162">"प्रयोगात्मक"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"ब्लूटूथ चालू करें?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"अपने कीबोर्ड को अपने टैबलेट से कनेक्ट करने के लिए, आपको पहले ब्लूटूथ चालू करना होगा."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"चालू करें"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> नोटिफिकेशन पर लागू करें"</string>
- <string name="apply_to_app" msgid="363016783939815960">"इस ऐप के सभी नोटिफिकेशन पर लागू करें"</string>
+ <string name="show_silently" msgid="6841966539811264192">"नोटिफिकेशन मौन रूप से दिखाएं"</string>
+ <string name="block" msgid="2734508760962682611">"सभी नोटिफिकेशन अवरुद्ध करें"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"मौन ना करें"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"मौन या अवरुद्ध ना करें"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"पूर्ण महत्व वाली सेटिंग दिखाएं"</string>
<string name="blocked_importance" msgid="5198578988978234161">"अवरोधित"</string>
+ <string name="min_importance" msgid="1901894910809414782">"न्यूनतम महत्व"</string>
<string name="low_importance" msgid="4109929986107147930">"निम्न महत्व"</string>
<string name="default_importance" msgid="8192107689995742653">"सामान्य महत्व"</string>
<string name="high_importance" msgid="1527066195614050263">"उच्च महत्व"</string>
<string name="max_importance" msgid="5089005872719563894">"तत्काल महत्व"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"ये नोटिफिकेशन कभी ना दिखाएं"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"नोटिफिकेशन सूची में सबसे नीचे मौन रूप से दिखाएं"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"ये नोटिफिकेशन मौन रूप से दिखाएं"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"नोटिफिकेशन सूची में सबसे ऊपर दिखाएं और ध्वनि चलाएं"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"स्क्रीन पर एक झलक दिखाएं और ध्वनि चलाएं"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"नोटिफिकेशन सूची में सबसे नीचे मौन रूप से दिखाएं"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"ये नोटिफिकेशन मौन रूप से दिखाएं"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"इन नोटिफिकेशन को ध्वनि करने दें"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"स्क्रीन पर झलक दिखाएं और ध्वनि करें"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"नोटिफिकेशन सूची के शीर्ष पर दिखाएं, स्क्रीन पर झलक दिखाएं और ध्वनि करें"</string>
<string name="notification_more_settings" msgid="816306283396553571">"और सेटिंग"</string>
<string name="notification_done" msgid="5279426047273930175">"हो गया"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"सामान्य रंग"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"रात्रि के रंग"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"कस्टम रंग"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"स्वतः"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"अज्ञात रंग"</string>
- <string name="color_transform" msgid="6985460408079086090">"रंग परिवर्तन"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"त्वरित-सेटिंग टाइल दिखाएं"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"कस्टम रूपांतरण सक्षम करें"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"रंग और दिखावट"</string>
+ <string name="night_mode" msgid="3540405868248625488">"रात्रि मोड"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"स्क्रीन को कैलिब्रेट करें"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"चालू"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"बंद"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"अपने आप चालू करें"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"स्थान और दिन के समय के लिए उपयुक्त रात्रि मोड में बदलें"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"रात्रि मोड के चालू होने पर"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Android OS के लिए गहरी थीम का उपयोग करें"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"टिंट समायोजित करें"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"स्क्रीन की रोशनी समायोजित करें"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"गहरी थीम को Android OS के मुख्य क्षेत्रों पर लागू किया जाता है जिन्हें सामान्यतः सेटिंग जैसी हल्की थीम में प्रदर्शित किया जाता है."</string>
<string name="color_apply" msgid="9212602012641034283">"लागू करें"</string>
<string name="color_revert_title" msgid="4746666545480534663">"सेेटिंग की पुष्टि करें"</string>
<string name="color_revert_message" msgid="9116001069397996691">"कुछ रंग सेटिंग इस डिवाइस को अनुपयोगी बना सकती हैं. इन रंग सेटिंग की पुष्टि करने के लिए ठीक क्लिक करें, अन्यथा 10 सेकंड के बाद ये सेटिंग रीसेट हो जाएंगी."</string>
@@ -486,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"होम"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"हाल ही के"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"वापस जाएं"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"वॉल्यूम में परेशान न करें दिखाएं"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"वॉल्यूम संवाद में परेशान न करें के पूर्ण नियंत्रण की अनुमति दें."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"वॉल्यूम और परेशान न करें"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"वॉल्यूम कम करें पर परेशान न करें डालें"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"वॉल्यूम नियंत्रणों के साथ दिखाएं"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"परेशान न करें"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"वॉल्यूम बटन का शॉर्टकट"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"वॉल्यूम बढ़ाएं पर परेशान न करें से बाहर निकलें"</string>
<string name="battery" msgid="7498329822413202973">"बैटरी"</string>
<string name="clock" msgid="7416090374234785905">"घड़ी"</string>
<string name="headset" msgid="4534219457597457353">"हैडसेट"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"हेडफ़ोन कनेक्ट किए गए"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"हैडसेट कनेक्ट किया गया"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"आइकन को स्थिति बार में दिखाए जाने से सक्षम या अक्षम करें."</string>
<string name="data_saver" msgid="5037565123367048522">"डेटा बचतकर्ता"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"डेटा बचतकर्ता चालू है"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"डेटा बचतकर्ता बंद है"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"चालू"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"बंद"</string>
<string name="nav_bar" msgid="1993221402773877607">"नेविगेशन बार"</string>
<string name="start" msgid="6873794757232879664">"प्रारंभ करें"</string>
<string name="center" msgid="4327473927066010960">"मध्य"</string>
@@ -523,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"पूर्वावलोकन"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"टाइलों को जोड़ने के लिए खींचें"</string>
<string name="qs_edit" msgid="2232596095725105230">"संपादित करें"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"समय"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"घंटे, मिनट और सेकंड दिखाएं"</item>
+ <item msgid="1427801730816895300">"घंटे और मिनट दिखाएं (डिफ़ॉल्ट)"</item>
+ <item msgid="3830170141562534721">"यह आइकन ना दिखाएं"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"हमेशा प्रतिशत दिखाएं"</item>
+ <item msgid="2139628951880142927">"चार्ज होते समय प्रतिशत दिखाएं (डिफ़ॉल्ट)"</item>
+ <item msgid="3327323682209964956">"यह आइकन ना दिखाएं"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"अन्य"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"विभाजित स्क्रीन विभाजक"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"नीचे ले जाएं"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"ऊपर ले जाएं"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"बाएं ले जाएं"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"दाएं ले जाएं"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 06721174..eaa777b 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -74,7 +74,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Zaslon je snimljen."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Dodirnite za prikaz snimke zaslona."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Nije bilo moguće snimiti zaslon."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Zaslon nije snimljen zbog ograničene pohrane ili zato što to ne dopušta aplikacija ili vaša organizacija."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Zaslon nije snimljen zbog ograničenog prostora za pohranu."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Snimanje zaslona ne dopušta aplikacija ili vaša organizacija."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Opcije USB prijenosa datoteka"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Učitaj kao media player (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Učitaj kao fotoaparat (PTP)"</string>
@@ -207,6 +208,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Više vremena."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Manje vremena."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Svjetiljka isključena."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Svjetiljka nije dostupna."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Svjetiljka uključena."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Svjetiljka isključena."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Svjetiljka uključena."</string>
@@ -306,6 +308,8 @@
<skip />
<string name="recents_history_button_label" msgid="5153358867807604821">"Povijest"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Izbriši"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Ta aplikacija ne podržava više prozora"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Aplikacija ne podržava više prozora"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Podijeli vodoravno"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Podijeli okomito"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Podijeli prilagođeno"</string>
@@ -335,8 +339,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Potpuna\ntišina"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Samo\nprioritetno"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Samo\nalarmi"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Sve"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Svi\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Punjenje (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do napunjenosti)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Brzo punjenje (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do napunjenosti)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Sporo punjenje (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do napunjenosti)"</string>
@@ -449,34 +451,43 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Prikazuju se sekunde na satu na traci statusa. Može utjecati na trajanje baterije."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Promijeni raspored Brzih postavki"</string>
<string name="show_brightness" msgid="6613930842805942519">"Prikaži svjetlinu u Brzim postavkama"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Omogući ubrzanje za podijeljen zaslon povlačenjem prema gore"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Omogući pokret povlačenja prema gore za podijeljen zaslon"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Omogućivanje pokreta za otvaranje podijeljenog zaslona tako da se od gumba Pregled prstom prijeđe prema gore"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimentalno"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Želite li uključiti Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Da biste povezali tipkovnicu s tabletom, morate uključiti Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Uključi"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Primijeni na obavijesti za temu <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Primijeni na sve obavijesti ove aplikacije"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Prikaži obavijesti tiho"</string>
+ <string name="block" msgid="2734508760962682611">"Blokiraj sve obavijesti"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Ne utišavaj"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Ne utišavaj i ne blokiraj"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Prikaži potpune postavke važnosti"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Blokirano"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Najmanja važnost"</string>
<string name="low_importance" msgid="4109929986107147930">"Mala važnost"</string>
<string name="default_importance" msgid="8192107689995742653">"Uobičajena važnost"</string>
<string name="high_importance" msgid="1527066195614050263">"Velika važnost"</string>
<string name="max_importance" msgid="5089005872719563894">"Hitno"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Nikad ne prikazuj te obavijesti"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Prikaži tiho pri dnu popisa obavijesti"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Prikaži te obavijesti tiho"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Prikaži na vrhu popisa obavijesti i emitiraj zvučni signal"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Prikaži na zaslonu i emitiraj zvučni signal"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Prikaži tiho pri dnu popisa obavijesti"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Prikaži te obavijesti tiho"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Dopusti obavijestima da emitiraju zvučne signale"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Prikaži na zaslonu i dopusti zvuk"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Prikaži pri vrhu popisa obavijesti, prikaži na zaslonu i dopusti zvuk"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Više postavki"</string>
<string name="notification_done" msgid="5279426047273930175">"Gotovo"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Uobičajene boje"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Noćne boje"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Prilagođene boje"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automatski"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Nepoznate boje"</string>
- <string name="color_transform" msgid="6985460408079086090">"Izmjena boja"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Prikaži pločicu s brzim postavkama"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Omogući prilagođenu preobrazbu"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Boja i izgled"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Noćni način rada"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Kalibriranje zaslona"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Uključeno"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Isključeno"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Uključi automatski"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Prebacivanje na noćni način rada prema lokaciji i dobu dana"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Kada je noćni način rada uključen"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Koristi tamnu temu za OS Android"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Prilagodi nijansu"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Prilagodi svjetlinu"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Tamna se tema primjenjuje na glavna područja OS-a Android, kao što su, primjerice, postavke, koja se inače prikazuju u svijetloj temi."</string>
<string name="color_apply" msgid="9212602012641034283">"Primijeni"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Potvrdite postavke"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Neke postavke boja mogu učiniti uređaj neupotrebljivim. Kliknite U redu da biste potvrdili postavke boja jer će se u suprotnom poništiti za 10 sekundi."</string>
@@ -488,21 +499,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Početni zaslon"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Najnovije"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Natrag"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Prikaži \"Ne uznemiravaj\" u glasnoći"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Dopušta potpunu kontrolu nad načinom \"Ne uznemiravaj\" u dijaloškom okviru glasnoće."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Glasnoća i Ne uznemiravaj"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Pokreni \"Ne uznemiravaj\" kada je zvuk stišan"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Prikaži s kontrolama glasnoće"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ne uznemiravaj"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Prečac tipki za glasnoću"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Zaustavi \"Ne uznemiravaj\" kada je zvuk pojačan"</string>
<string name="battery" msgid="7498329822413202973">"Baterija"</string>
<string name="clock" msgid="7416090374234785905">"Sat"</string>
<string name="headset" msgid="4534219457597457353">"Slušalice"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Slušalice su povezane"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Slušalice su povezane"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Omogućuje ili onemogućuje prikazivanje ikona na traci statusa."</string>
<string name="data_saver" msgid="5037565123367048522">"Ušteda podataka"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Ušteda podataka je uključena"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Ušteda podataka je isključena"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Uključeno"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Isključeno"</string>
<string name="nav_bar" msgid="1993221402773877607">"Navigacijska traka"</string>
<string name="start" msgid="6873794757232879664">"Početak"</string>
<string name="center" msgid="4327473927066010960">"Sredina"</string>
@@ -525,4 +535,21 @@
<string name="preview" msgid="9077832302472282938">"Pregled"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Povucite da biste dodali pločice"</string>
<string name="qs_edit" msgid="2232596095725105230">"Uredi"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Vrijeme"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Prikaži sate, minute i sekunde"</item>
+ <item msgid="1427801730816895300">"Prikaži sate i minute (zadano)"</item>
+ <item msgid="3830170141562534721">"Ne prikazuj tu ikonu"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Uvijek prikazuj postotak"</item>
+ <item msgid="2139628951880142927">"Prikazuj postotak tijekom punjenja (zadano)"</item>
+ <item msgid="3327323682209964956">"Ne prikazuj tu ikonu"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Ostalo"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Razdjelnik podijeljenog zaslona"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Pomakni prema dolje"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Pomakni prema gore"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Pomakni ulijevo"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Pomakni udesno"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 0dd5d45..8e55c78 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Képernyőkép rögzítve."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Megérintésével megtekintheti a képernyőképet."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Nem sikerült rögzíteni a képernyőképet."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Nem készíthet képernyőképet, mert kevés a tárhely, vagy az alkalmazás/szervezet nem engedélyezi azt."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Nem menthet képernyőképet, mert kevés a tárhely."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Az alkalmazás vagy szervezete nem engedélyezi képernyőképek készítését."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB-fájlátvitel beállításai"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Csatlakoztatás médialejátszóként (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Csatlakoztatás kameraként (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Több idő."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Kevesebb idő."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Vaku kikapcsolva."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"A zseblámpa nem áll rendelkezésre"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Vaku bekapcsolva."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Vaku kikapcsolva."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Vaku bekapcsolva."</string>
@@ -304,6 +306,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"A(z) <xliff:g id="APP">%s</xliff:g> csökkentett módban ki van kapcsolva."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Előzmények"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Törlés"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Ez az alkalmazás nem támogatja a többablakos nézetet"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Az alkalmazás nem támogatja a többablakos nézetet"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Osztott vízszintes"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Osztott függőleges"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Osztott egyéni"</string>
@@ -333,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Teljes\nnémítás"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Csak\nprioritás"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Csak\nriasztások"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Összes"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Összes\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Töltés (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> a teljes töltöttségig)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Gyors töltés (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> a teljes töltöttségig)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Lassú töltés (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> a teljes töltöttségig)"</string>
@@ -447,34 +449,43 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Másodpercek megjelenítése az állapotsor óráján. Ez hatással lehet az akkumulátor üzemidejére."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Gyorsbeállítások átrendezése"</string>
<string name="show_brightness" msgid="6613930842805942519">"Fényerő megjelenítése a gyorsbeállításokban"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Osztott képernyő engedélyezése felfelé söpréssel"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Képernyőfelosztó gyors felfelé csúsztatás engedélyezése"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Kézmozdulat engedélyezése osztott képernyős nézet aktiválásához, ha az Áttekintés gombról felfelé húzza az ujját"</string>
<string name="experimental" msgid="6198182315536726162">"Kísérleti"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Engedélyezi a Bluetooth-kapcsolatot?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Ha a billentyűzetet csatlakoztatni szeretné táblagépéhez, először engedélyeznie kell a Bluetooth-kapcsolatot."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Bekapcsolás"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"A következő értesítések esetén: <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Az alkalmazás minden értesítése esetén"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Értesítések megjelenítése hangjelzés nélkül"</string>
+ <string name="block" msgid="2734508760962682611">"Minden értesítés letiltása"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Nincs némítás"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Nincs némítás vagy letiltás"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"A teljes fontossági beállítások megjelenítése"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Letiltva"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Minimális fontosságú"</string>
<string name="low_importance" msgid="4109929986107147930">"Kevésbé fontos"</string>
<string name="default_importance" msgid="8192107689995742653">"Normál"</string>
<string name="high_importance" msgid="1527066195614050263">"Fontos"</string>
<string name="max_importance" msgid="5089005872719563894">"Sürgős"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Soha nem jelennek meg ezek az értesítések"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Hangjelzés nélkül jelennek meg az értesítési lista alján"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Hang nélkül jelennek meg ezek az értesítések"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Az értesítési lista tetején jelennek meg hangjelzéssel"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Az értesítések felugranak a képernyőn hangjelzéssel"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Hangjelzés nélkül jelennek meg az értesítési lista alján"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Ezek az értesítések hangjelzés nélkül jelennek meg"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Hangjelzés engedélyezése ezeknél az értesítéseknél"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Az értesítések felugranak a képernyőn hangjelzéssel"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Az értesítési lista tetején jelennek meg, illetve felugranak a képernyőn hangjelzéssel"</string>
<string name="notification_more_settings" msgid="816306283396553571">"További beállítások"</string>
<string name="notification_done" msgid="5279426047273930175">"Kész"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Hagyományos színek"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Esti színek"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Egyéni színek"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automatikus"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Ismeretlen színek"</string>
- <string name="color_transform" msgid="6985460408079086090">"Színmódosítás"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Gyorsbeállítások mozaikjának megjelenítése"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Egyéni átalakítás engedélyezése"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Szín és megjelenés"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Éjszakai mód"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Kijelző kalibrálása"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Bekapcsolva"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Kikapcsolva"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Automatikus bekapcsolás"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Váltás az Éjszakai módra a helynek és napszaknak megfelelően"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Amikor be van kapcsolva az Éjszakai mód"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Sötét téma használata az Android operációs rendszernél"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Színárnyalat módosítása"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Fényerő módosítása"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Sötét téma látható az Android operációs rendszer olyan alapterületeinél, amelyek normál állapotban világosan jelennek meg (például a Beállítások)."</string>
<string name="color_apply" msgid="9212602012641034283">"Alkalmaz"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Beállítások megerősítése"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Bizonyos színbeállítások használhatatlanná tehetik ezt az eszközt. A színbeállítás megerősítéséhez kattintson az OK lehetőségre, máskülönben a rendszer 10 másodpercen belül visszaáll a korábbira."</string>
@@ -486,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Otthon"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Legutóbbiak"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Vissza"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"A „Ne zavarjanak” funkció megjelenítése a hangvezérlőben"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"A „Ne zavarjanak” funkció teljes körű vezérlésének engedélyezése a hangerővezérlési párbeszédpanelon."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Hangvezérlő és „Ne zavarjanak” funkció"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"„Ne zavarjanak” aktiválása hangerőcsökkentéskor"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Megjelenítés hangerőszabályzóval"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ne zavarjanak"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"A hangerőgombok gyorsbillentyűk"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"„Ne zavarjanak” deaktiválása hangerőnöveléskor"</string>
<string name="battery" msgid="7498329822413202973">"Akkumulátor"</string>
<string name="clock" msgid="7416090374234785905">"Óra"</string>
<string name="headset" msgid="4534219457597457353">"Headset"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Fejhallgató csatlakoztatva"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset csatlakoztatva"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Ikonok megjelenítése és elrejtése az állapotsoron."</string>
<string name="data_saver" msgid="5037565123367048522">"Adatforgalom-csökkentő"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Az adatforgalom-csökkentő be van kapcsolva"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Az Adatforgalom-csökkentő ki van kapcsolva"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Be"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Ki"</string>
<string name="nav_bar" msgid="1993221402773877607">"Navigációs sáv"</string>
<string name="start" msgid="6873794757232879664">"Kezdés"</string>
<string name="center" msgid="4327473927066010960">"Igazítás középre"</string>
@@ -523,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Előnézet"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Húzza csempe hozzáadásához"</string>
<string name="qs_edit" msgid="2232596095725105230">"Szerkesztés"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Idő"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Óra, perc és másodperc megjelenítése"</item>
+ <item msgid="1427801730816895300">"Óra és perc megjelenítése (alapértelmezett)"</item>
+ <item msgid="3830170141562534721">"Ne jelenjen meg ez az ikon"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Százalékos érték mindig látható"</item>
+ <item msgid="2139628951880142927">"Százalékos érték töltés közben látható (alapértelmezett)"</item>
+ <item msgid="3327323682209964956">"Ne jelenjen meg ez az ikon"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Egyéb"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Elválasztó az osztott nézetben"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Mozgatás lefelé"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Mozgatás felfelé"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Mozgatás balra"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Mozgatás jobbra"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 4f4af55..09e7f70b 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Էկրանի հանույթը լուսանկարվել է:"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Հպեք ձեր էկրանի հանույթը տեսնելու համար:"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Չհաջողվեց լուսանկարել էկրանի հանույթը:"</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Չենք կարող պատճենել էկրանը՝ տարածքի սահմանափակման կամ ձեր կազմակերպության կողմից արգելքի պատճառով:"</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Չհաջողվեց պահել էկրանի պատկերը սահմանափակ հիշողության պատճառով:"</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Այս հավելվածը կամ ձեր կազմակերպությունը չի թույլատրում Էկրանի պատկերի ստացումը:"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB ֆայլերի փոխանցման ընտրանքներ"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Միացնել որպես մեդիա նվագարկիչ (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Միացնել որպես ֆոտոխցիկ (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Ավելացնել ժամանակը:"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Պակասեցնել ժամանակը:"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Լապտերն անջատված է:"</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Լապտերն անհասանելի է:"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Լապտերը միացված է:"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Լապտերն անջատվեց:"</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Լապտերը միացավ:"</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"էկրանի ամրակցում"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"որոնել"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Հնարավոր չէ գործարկել <xliff:g id="APP">%s</xliff:g>-ը:"</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> հավելվածը անվտանգ ռեժիմում անջատված է:"</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Պատմություն"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Մաքրել"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Այս հավելվածը չի աջակցում բազմապատուհան ռեժիմը"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Հավելվածը չի աջակցում բազմապատուհան ռեժիմը"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Հորիզոնական տրոհում"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Ուղղահայաց տրոհում"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Հատուկ տրոհում"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Ընդհանուր\nլուռ վիճակը"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Միայն\nկարևորները"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Միայն\nզարթուցիչ"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Բոլորը"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Բոլորը\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Դանդաղ լիցքավորում (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>՝ մինչև ավարտ)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Ցույց տալ ժամացույցի վայրկյանները կարգավիճակի տողում: Կարող է ազդել մարտկոցի աշխատանքի ժամանակի վրա:"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Վերադասավորել Արագ կարգավորումները"</string>
<string name="show_brightness" msgid="6613930842805942519">"Ցույց տալ պայծառությունն Արագ կարգավորումներում"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Միացնել մատը վերև սահեցնելով էկրանը տրոհելու արագացուցիչը"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Ակտիվացնել մատը վերև սահեցնելով էկրանը տրոհելու ժեստը"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Միացնել Համատեսք կոճակից մատը դեպի վերև սահեցնելու միջոցով տրոհված էկրանի ռեժիմ անցնելու ժեստը"</string>
<string name="experimental" msgid="6198182315536726162">"Փորձնական"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Միացնե՞լ Bluetooth-ը:"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Ստեղնաշարը ձեր պլանշետին միացնելու համար նախ անհրաժեշտ է միացնել Bluetooth-ը:"</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Միացնել"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Կիրառել <xliff:g id="TOPIC_NAME">%1$s</xliff:g>-ի ծանուցումների նկատմամբ"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Կիրառել այս հավելվածի բոլոր ծանուցումների նկատմամբ"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Ցույց տալ ծանուցումներն առանց ձայնային ազդանշանի"</string>
+ <string name="block" msgid="2734508760962682611">"Արգելափակել բոլոր ծանուցումները"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Ձայնը չանջատել"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Ձայնը չանջատել և չարգելափակել"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Ցույց տալ կարևորության բոլոր կարգավորումները"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Արգելափակված"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Նվազագույն կարևորություն"</string>
<string name="low_importance" msgid="4109929986107147930">"Ցածր կարևորություն"</string>
<string name="default_importance" msgid="8192107689995742653">"Սովորական կարևորություն"</string>
<string name="high_importance" msgid="1527066195614050263">"Բարձր կարևորություն"</string>
<string name="max_importance" msgid="5089005872719563894">"Հրատապ կարևորություն"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Երբեք չցուցադրել այս ծանուցումները"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Ցուցադրել ծանուցումների ցանկի ներքևում առանց ձայնային ազդանշանի"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Ցուցադրել այս ծանուցումներն առանց ձայնային ազդանշանի"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Ցուցադրել ծանուցումների ցանկի վերևում և հնչեցնել ձայնային ազդանշան"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Ցուցադրել էկրանին և հնչեցնել ձայնային ազդանշան"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Ցուցադրել ծանուցումների ցանկի ներքևում առանց ձայնային ազդանշանի"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Ցուցադրել այս ծանուցումներն առանց ձայնային ազդանշանի"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Թույլ տալ այս ծանուցումներին ձայնային ազդանշան հնչեցնել"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Թռուցիկ ցուցադրել էկրանին և թույլատրել ձայնային ազդանշանը"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Ցույց տալ ծանուցումների ցանկի վերևում, թռուցիկ ցուցադրել էկրանին և թույլատրել ձայնային ազդանշանը"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Այլ կարգավորումներ"</string>
<string name="notification_done" msgid="5279426047273930175">"Պատրաստ է"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Սովորական գույներ"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Գիշերային գույներ"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Հատուկ գույներ"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Ավտոմատ"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Անհայտ գույներ"</string>
- <string name="color_transform" msgid="6985460408079086090">"Գույնի փոփոխում"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Ցույց տալ Արագ կարգավորումների սալիկը"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Միացնել հատուկ գունային անցումը"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Գույնը և արտաքին տեսքը"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Գիշերային ռեժիմ"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Չափաբերել էկրանը"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Միացված է"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Անջատված է"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Միացնել ավտոմատ կերպով"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Անցեք Գիշերային ռեժիմի, եթե դա պահանջում է տեղը և օրվա ժամանակը"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Երբ Գիշերային ռեժիմը միացված է"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Օգտագործել մուգ թեման Android OS-ի համար"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Կարգավորել երանգը"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Կարգավորել պայծառությունը"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Մուգ թեման կիրառվում է Android OS-ի հիմնական հատվածների նկատմամբ, որոնք սովորաբար ցուցադրվում են բաց թեմայում (օրինակ՝ Կարգավորումներ):"</string>
<string name="color_apply" msgid="9212602012641034283">"Կիրառել"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Հաստատել կարգավորումները"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Գունային որոշ կարգավորումները կարող են այս սարքը օգտագործման համար ոչ պիտանի դարձնել: Սեղմեք Լավ կոճակը՝ գունային այս կարգավորումները հաստատելու համար: Հակառակ դեպքում այս կարգավորումները կվերակայվեն 10 վայրկյան հետո:"</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Մարտկոցի օգտագործում"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Մարտկոցի տնտեսումը լիցքավորման ժամանակ հասանելի չէ"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Մարտկոցի տնտեսում"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Նվազեցնում է ծանրաբեռնվածությունը և ֆոնային տվյալները"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Գլխավոր էջ"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Վերջինները"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Հետ"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Ցույց տալ Չխանգարել գործառույթը ձայնի կառավարման պատուհանում"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Թույլատրել Չխանգարել գործառույթի ամբողջական վերահսկումը ձայնի կառավարման պատուհանում:"</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Ձայնի ուժգնություն և Չխանգարել գործառույթ"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Մտնել Չխանգարել գործառույթ ձայնի նվազեցման կոճակը սեղմելիս"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Ցույց տալ ձայնի ուժգնության կառավարման տարրերի հետ"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Չընդհատել"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Ձայնի կոճակների դյուրանցում"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Ելնել Չխանգարել գործառույթից ձայնի ավելացման կոճակը սեղմելիս"</string>
<string name="battery" msgid="7498329822413202973">"Մարտկոց"</string>
<string name="clock" msgid="7416090374234785905">"Ժամացույց"</string>
<string name="headset" msgid="4534219457597457353">"Ականջակալ"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Ականջակալը կապակցված է"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Ականջակալը կապակցված է"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Միացնել կամ անջատել պատկերակների ցուցադրումը կարգավիճակի գոտում:"</string>
<string name="data_saver" msgid="5037565123367048522">"Տվյալների խնայում"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Տվյալների խնայումը միացված է"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Տվյալների խնայումն անջատված է"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Միացնել"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Անջատել"</string>
<string name="nav_bar" msgid="1993221402773877607">"Նավարկման գոտի"</string>
<string name="start" msgid="6873794757232879664">"Սկսել"</string>
<string name="center" msgid="4327473927066010960">"Կենտրոն"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Նախադիտում"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Քաշեք՝ սալիկներ ավելացնելու համար"</string>
<string name="qs_edit" msgid="2232596095725105230">"Փոփոխել"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Ժամ"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Ցույց տալ ժամերը, րոպեները և վայրկյանները"</item>
+ <item msgid="1427801730816895300">"Ցույց տալ ժամերը և րոպեները (կանխադրված է)"</item>
+ <item msgid="3830170141562534721">"Ցույց չտալ այս պատկերակը"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Միշտ ցույց տալ տոկոսը"</item>
+ <item msgid="2139628951880142927">"Ցույց տալ տոկոսը լիցքավորելու ժամանակ (կանխադրված է)"</item>
+ <item msgid="3327323682209964956">"Ցույց չտալ այս պատկերակը"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Այլ"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Տրոհված էկրանի բաժանիչ"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Տեղափոխել ներքև"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Տեղափոխել վերև"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Տեղափոխել ձախ"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Տեղափոխել աջ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index fa359ad..46340a7 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Tangkapan layar diambil."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Sentuh untuk melihat tangkapan layar Anda."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Tidak dapat mengambil tangkapan layar."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Tak bisa mengambil tangkapan layar karena ruang penyimpanan terbatas/tak diizinkan aplikasi/organisasi Anda."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Tidak dapat menyimpan tangkapan layar karena ruang penyimpanan terbatas."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Mengambil tangkapan layar tidak diizinkan oleh aplikasi atau organisasi."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Opsi transfer file USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Pasang sebagai pemutar media (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Pasang sebagai kamera (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Lebih lama."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Lebih cepat."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Senter nonaktif."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Senter tidak tersedia."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Senter aktif."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Senter dinonaktifkan."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Senter diaktifkan."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pin ke layar"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"telusuri"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Tidak dapat memulai <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> dinonaktifkan dalam mode aman."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Riwayat"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Hapus"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Aplikasi ini tidak mendukung multijendela"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Aplikasi tidak mendukung multijendela"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Pisahkan Horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Pisahkan Vertikal"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Pisahkan Khusus"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Senyap\ntotal"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Hanya\nprioritas"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Hanya\nalarm"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Semua"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Semua\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Mengisi daya (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hingga penuh)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Mengisi daya dengan cepat (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hingga penuh)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Mengisi daya dengan lambat (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hingga penuh)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Tampilkan detik jam di bilah status. Dapat memengaruhi masa pakai baterai."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Atur Ulang Setelan Cepat"</string>
<string name="show_brightness" msgid="6613930842805942519">"Tampilkan kecerahan di Setelan Cepat"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Aktifkan akselerator gesek atas untuk layar terpisah"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Aktifkan isyarat gesek atas untuk layar terpisah"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Aktifkan isyarat untuk masuk layar terpisah dengan menggesek tombol Ringkasan ke atas"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimental"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Aktifkan Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Untuk menghubungkan keyboard dengan tablet, terlebih dahulu aktifkan Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Aktifkan"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Terapkan ke notifikasi <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Terapkan untuk semua notifikasi dari aplikasi ini"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Tampilkan notifikasi tanpa suara"</string>
+ <string name="block" msgid="2734508760962682611">"Blokir semua notifikasi"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Jangan bisukan"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Jangan bisukan atau blokir"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Tampilkan setelan lengkap nilai penting"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Diblokir"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Nilai penting min"</string>
<string name="low_importance" msgid="4109929986107147930">"Tingkat kepentingan: rendah"</string>
<string name="default_importance" msgid="8192107689995742653">"Tingkat kepentingan: normal"</string>
<string name="high_importance" msgid="1527066195614050263">"Tingkat kepentingan: tinggi"</string>
<string name="max_importance" msgid="5089005872719563894">"Tingkat kepentingan: darurat"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Jangan pernah tunjukkan notifikasi ini"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Tunjukkan di bawah daftar notifikasi tanpa suara"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Tunjukkan notifikasi ini tanpa suara"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Tunjukkan di bagian atas daftar notifikasi dan bunyikan suara"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Muncul di layar dan bunyikan suara"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Tampilkan di bagian bawah daftar notifikasi tanpa suara"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Tampilkan notifikasi ini tanpa suara"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Izinkan notifikasi ini bersuara"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Muncul di layar dan izinkan suara"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Tampilkan di bagian atas daftar notifikasi, muncul di layar, dan izinkan suara"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Setelan lainnya"</string>
<string name="notification_done" msgid="5279426047273930175">"Selesai"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Warna normal"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Warna malam"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Warna khusus"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Otomatis"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Warna tidak diketahui"</string>
- <string name="color_transform" msgid="6985460408079086090">"Perubahan warna"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Tampilkan ubin Setelan Cepat"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Aktifkan transformasi khusus"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Warna dan tampilan"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Mode malam"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Kalibrasi layar"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Aktif"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Nonaktif"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Aktifkan secara otomatis"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Beralih ke Mode Malam yang sesuai untuk lokasi dan waktu"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Saat Mode Malam aktif"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Gunakan tema gelap untuk OS Android"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Sesuaikan rona"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Sesuaikan kecerahan"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Tema gelap diterapkan ke area inti OS Android yang biasanya ditampilkan di tema terang, seperti Setelan."</string>
<string name="color_apply" msgid="9212602012641034283">"Terapkan"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Konfirmasi setelan"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Beberapa setelan warna dapat membuat perangkat ini tidak dapat digunakan. Klik OKE untuk mengonfirmasi setelan warna ini. Jika tidak, setelan ini akan disetel ulang setelah 10 detik."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Pemakaian baterai"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Penghemat Baterai tidak tersedia selama pengisian daya"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Penghemat Baterai"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Mengurangi performa dan data latar belakang"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Layar Utama"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Terbaru"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Kembali"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Tampilkan mode jangan ganggu di volume"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Izinkan kontrol penuh dari mode jangan mengganggu di dialog volume."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Volume dan mode Jangan ganggu"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Masukkan mode jangan ganggu di tombol kecilkan volume"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Tampilkan dengan kontrol volume"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Jangan ganggu"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Pintasan tombol volume"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Keluar dari mode jangan ganggu di tombol keraskan volume"</string>
<string name="battery" msgid="7498329822413202973">"Baterai"</string>
<string name="clock" msgid="7416090374234785905">"Jam"</string>
<string name="headset" msgid="4534219457597457353">"Headset"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Headphone terhubung"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset terhubung"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Aktifkan atau nonaktifkan ikon yang ditampilkan di bilah status."</string>
<string name="data_saver" msgid="5037565123367048522">"Penghemat Data"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Penghemat Data aktif"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Penghemat Data nonaktif"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Aktif"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Nonaktif"</string>
<string name="nav_bar" msgid="1993221402773877607">"Bilah navigasi"</string>
<string name="start" msgid="6873794757232879664">"Awal"</string>
<string name="center" msgid="4327473927066010960">"Tengah"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Pratinjau"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Seret untuk menambahkan ubin"</string>
<string name="qs_edit" msgid="2232596095725105230">"Edit"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Waktu"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Tampilkan jam, menit, dan detik"</item>
+ <item msgid="1427801730816895300">"Tampilkan jam dan menit (default)"</item>
+ <item msgid="3830170141562534721">"Jangan tampilkan ikon ini"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Selalu tampilkan persentase"</item>
+ <item msgid="2139628951880142927">"Tampilkan persentase saat mengisi daya (default)"</item>
+ <item msgid="3327323682209964956">"Jangan tampilkan ikon ini"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Lainnya"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Pembagi layar terpisah"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Turunkan"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Naikkan"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Pindahkan ke kiri"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Pindahkan ke kanan"</string>
</resources>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 2fca674..89708de 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Skjámynd var tekin."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Snertu til að skoða skjámyndina."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Ekki tókst að taka skjámynd."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Ekki hægt að taka skjámynd vegna takmarkaðs pláss eða forritið eða notendaskipanin leyfir það ekki."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Ekki tókst að vista skjámynd vegna takmarkaðs geymslupláss."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Forritið eða fyrirtækið þitt leyfir ekki að teknar séu skjámyndir."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Valkostir USB-skráaflutnings"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Tengja sem efnisspilara (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Tengja sem myndavél (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Meiri tími."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Minni tími."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Slökkt á vasaljósi."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Vasaljós ekki tiltækt"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Kveikt á vasaljósi."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Slökkt á vasaljósi."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Kveikt á vasaljósi."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"skjáfesting"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"leita"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Ekki var hægt að ræsa <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Slökkt er á <xliff:g id="APP">%s</xliff:g> í öruggri stillingu."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Ferill"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Hreinsa"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Þetta forrit styður ekki marga glugga"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Forritið styður ekki marga glugga"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Lárétt skipting"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Lóðrétt skipting"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Sérsniðin skipting"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Algjör\nþögn"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Aðeins\nforgangur"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Aðeins\nvekjarar"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Allar"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Allar\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Í hleðslu (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> fram að fullri hleðslu)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Í hraðri hleðslu (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> fram að fullri hleðslu)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Í hægri hleðslu (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> fram að fullri hleðslu)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Sýna sekúndur á klukku í stöðustikunni. Getur haft áhrif á endingu rafhlöðu."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Endurraða flýtistillingum"</string>
<string name="show_brightness" msgid="6613930842805942519">"Sýna birtustig í flýtistillingum"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Virkja skjáskiptingu með því að strjúka upp"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Virkja skjáskiptingu með því að strjúka upp"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Virkja skjáskiptingarbendingu með því að strjúka upp frá yfirlitshnappi"</string>
<string name="experimental" msgid="6198182315536726162">"Tilraunastillingar"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Kveikja á Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Til að geta tengt lyklaborðið við spjaldtölvuna þarftu fyrst að kveikja á Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Kveikja"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Láta gilda um tilkynningar varðandi <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Láta gilda um allar tilkynningar frá þessu forriti"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Sýna tilkynningar án hljóðs"</string>
+ <string name="block" msgid="2734508760962682611">"Loka á allar tilkynningar"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Ekki þagga"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Hvorki þagga né útiloka"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Sýna stillingar fyrir mikilvægi"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Útilokuð"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Lítill forgangur"</string>
<string name="low_importance" msgid="4109929986107147930">"Ekki svo mikilvægt"</string>
<string name="default_importance" msgid="8192107689995742653">"Venjulegt mikilvægi"</string>
<string name="high_importance" msgid="1527066195614050263">"Mjög mikilvægt"</string>
<string name="max_importance" msgid="5089005872719563894">"Afar áríðandi"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Aldrei sýna þessar tilkynningar"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Sýna neðst á tilkynningalistanum án hljóðs"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Sýna þessar tilkynningar án hljóðs"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Sýna efst á tilkynningalistanum og spila hljóð"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Birta á skjánum og spila hljóð"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Sýna neðst á tilkynningalistanum án hljóðs"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Sýna þessar tilkynningar án hljóðs"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Leyfa þessum tilkynningum að spila hljóð"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Birta á skjánum og leyfa hljóð"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Sýna efst á tilkynningalistanum, birta á skjánum og leyfa hljóð"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Fleiri stillingar"</string>
<string name="notification_done" msgid="5279426047273930175">"Lokið"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Venjulegir litir"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Næturlitir"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Sérsniðnir litir"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Sjálfvirkt"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Óþekktir litir"</string>
- <string name="color_transform" msgid="6985460408079086090">"Litabreytingar"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Sýna flísar í flýtistillingum"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Kveikja á sérsniðinni umbreytingu"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Litur og útlit"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Næturstilling"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Kvarða skjáinn"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Kveikt"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Slökkt"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Kveikja sjálfkrafa"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Skipta í næturstillingu í samræmi við staðsetningu og tíma dags"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Þegar kveikt er á næturstillingu"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Nota dökkt þema fyrir Android OS"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Stilla litblæ"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Stilla birtustig"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Dökka þemað er notað á þeim aðalsvæðum Android OS sem venjulega eru ljós, s.s. í stillingum."</string>
<string name="color_apply" msgid="9212602012641034283">"Nota"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Staðfesta stillingar"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Sumar litastillingar kunna að bitna á notagildi tækisins. Veldu „Í lagi“ til að staðfesta þessar litastillingar, að öðrum kosti verða litirnir endurstilltir eftir tíu sekúndur."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Rafhlöðunotkun"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Ekki er hægt að nota rafhlöðusparnað meðan á hleðslu stendur"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Rafhlöðusparnaður"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Dregur úr afköstum og bakgrunnsgögnum"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Heim"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Nýlegt"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Til baka"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Sýna „Ónáðið ekki“ í hljóðstyrksvali"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Leyfa fulla stjórn á stillingunni „Ónáðið ekki“ í hljóðstyrksglugganum."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Hljóðstyrkur og „Ónáðið ekki“"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Kveikja á „Ónáðið ekki“ með því að lækka"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Sýna með hljóðstyrksstillingum"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ónáðið ekki"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Flýtihnappar fyrir hljóðstyrk"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Slökkva á „Ónáðið ekki“ með því að hækka"</string>
<string name="battery" msgid="7498329822413202973">"Rafhlaða"</string>
<string name="clock" msgid="7416090374234785905">"Klukka"</string>
<string name="headset" msgid="4534219457597457353">"Höfuðtól"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Heyrnartól tengd"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Höfuðtól tengt"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Birtu eða feldu myndtákn í stöðustikunni."</string>
<string name="data_saver" msgid="5037565123367048522">"Gagnasparnaður"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Kveikt er á gagnasparnaði"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Slökkt er á gagnasparnaði"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Kveikt"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Slökkt"</string>
<string name="nav_bar" msgid="1993221402773877607">"Yfirlitsstika"</string>
<string name="start" msgid="6873794757232879664">"Byrja"</string>
<string name="center" msgid="4327473927066010960">"Miðja"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Forskoðun"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Dragðu til að bæta við reitum"</string>
<string name="qs_edit" msgid="2232596095725105230">"Breyta"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Tími"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Sýna klukkustundir, mínútur og sekúndur"</item>
+ <item msgid="1427801730816895300">"Sýna klukkustundir og mínútur (sjálfgefið)"</item>
+ <item msgid="3830170141562534721">"Ekki sýna þetta tákn"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Sýna alltaf hlutfall"</item>
+ <item msgid="2139628951880142927">"Sýna hlutfall meðan á hleðslu stendur (sjálfgefið)"</item>
+ <item msgid="3327323682209964956">"Ekki sýna þetta tákn"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Annað"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Skjáskipting"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Færa niður"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Færa upp"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Færa til vinstri"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Færa til hægri"</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index c2c05b4..d6622e3 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot acquisito."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Tocca per visualizzare il tuo screenshot."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Impossibile acquisire lo screenshot."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Imposs. acquisire screenshot per spazio archiviazione limitato o perché vietato da organizzazione o app."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Impossibile salvare lo screenshot a causa dello spazio di archiviazione limitato."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"L\'acquisizione di screenshot non è consentita dall\'app o dall\'organizzazione."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Opzioni trasferimento file USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Monta come lettore multimediale (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Monta come videocamera (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Più tempo."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Meno tempo."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Torcia spenta."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Torcia non disponibile."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Torcia accesa."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Torcia disattivata."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Torcia attivata."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"blocco su schermo"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Impossibile avviare <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"L\'app <xliff:g id="APP">%s</xliff:g> è stata disattivata in modalità provvisoria."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Cronologia"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Cancella"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Questa app non supporta la modalità multi-finestra"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"L\'app non supporta la modalità multi-finestra"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisione in orizzontale"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisione in verticale"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisione personalizzata"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Silenzio\ntotale"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Solo con\npriorità"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Solo\nsveglie"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Tutte"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Tutte\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"In carica (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> al termine)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Ricarica veloce (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> al termine)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Ricarica lenta (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> al termine)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra i secondi nell\'orologio nella barra di stato. Ciò potrebbe ridurre la durata della carica della batteria."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Riorganizza Impostazioni rapide"</string>
<string name="show_brightness" msgid="6613930842805942519">"Mostra luminosità in Impostazioni rapide"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Attiva Schermo diviso mediante scorrimento verso l\'alto"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Attiva Schermo diviso mediante scorrimento verso l\'alto"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Consente di attivare la modalità Schermo diviso scorrendo verso l\'alto dal pulsante Panoramica"</string>
<string name="experimental" msgid="6198182315536726162">"Sperimentali"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Attivare il Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Per connettere la tastiera al tablet, devi prima attivare il Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Attiva"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Applica a notifiche <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Applica a tutte le notifiche di quest\'app"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Mostra silenziosamente le notifiche"</string>
+ <string name="block" msgid="2734508760962682611">"Blocca tutte le notifiche"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Non disattivare i suoni"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Non disattivare i suoni e non bloccare"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Mostra impostazioni importanza complete"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloccata"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Importanza min"</string>
<string name="low_importance" msgid="4109929986107147930">"Importanza scarsa"</string>
<string name="default_importance" msgid="8192107689995742653">"Importanza normale"</string>
<string name="high_importance" msgid="1527066195614050263">"Importanza elevata"</string>
<string name="max_importance" msgid="5089005872719563894">"Importanza urgente"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Non mostrare mai queste notifiche"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Mostra silenziosamente nella parte inferiore dell\'elenco delle notifiche"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Mostra silenziosamente queste notifiche"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Mostra nella parte superiore dell\'elenco delle notifiche e riproduci suono"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Apri sullo schermo e riproduci suono"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Mostra silenziosamente nella parte inferiore dell\'elenco delle notifiche"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Mostra silenziosamente queste notifiche"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Attiva i suoni per queste notifiche"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Apri sullo schermo e attiva l\'audio"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Mostra in cima all\'elenco delle notifiche, apri sullo schermo e attiva l\'audio"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Altre impostazioni"</string>
<string name="notification_done" msgid="5279426047273930175">"Fine"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Colori normali"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Colori per la notte"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Colori personalizzati"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automatico"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Colori sconosciuti"</string>
- <string name="color_transform" msgid="6985460408079086090">"Modifica del colore"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Mostra il riquadro Impostazioni rapide"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Attiva la trasformazione personalizzata"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Colore e aspetto"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Modalità notturna"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Calibra display"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Attiva"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Disattivata"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Attiva automaticamente"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Attiva la modalità notturna in base alla località e all\'ora del giorno"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Quando la modalità notturna è attiva"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Utilizza tema scuro per sistema Android"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Regola tinta"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Regola luminosità"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Il tema scuro viene applicato agli elementi fondamentali del sistema operativo Android che vengono generalmente visualizzati con un tema chiaro, ad esempio le impostazioni."</string>
<string name="color_apply" msgid="9212602012641034283">"Applica"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Conferma le impostazioni"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Alcune impostazioni relative ai colori potrebbero rendere inutilizzabile il dispositivo. Fai clic su OK per confermare queste impostazioni; in caso contrario, le impostazioni verranno reimpostate dopo 10 secondi."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Utilizzo batteria"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Risparmio energetico non disponibile durante la ricarica"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Risparmio energetico"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Riduce le prestazioni e i dati in background"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Home"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recenti"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Indietro"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Mostra Non disturbare nella finestra del volume"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Consenti il controllo totale della funzione Non disturbare nella finestra di dialogo del volume."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Volume e Non disturbare"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Attiva Non disturbare all\'abbassamento del volume"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostra con controlli volume"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Non disturbare"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Pulsanti del volume come scorciatoia"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Disattiva Non disturbare all\'aumento del volume"</string>
<string name="battery" msgid="7498329822413202973">"Batteria"</string>
<string name="clock" msgid="7416090374234785905">"Orologio"</string>
<string name="headset" msgid="4534219457597457353">"Auricolare"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Cuffie collegate"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Auricolare collegato"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Consente di attivare o disattivare la visualizzazione delle icone nella barra di stato."</string>
<string name="data_saver" msgid="5037565123367048522">"Risparmio dati"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Risparmio dati attivo"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Risparmio dati disattivato"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Attiva"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Off"</string>
<string name="nav_bar" msgid="1993221402773877607">"Barra di navigazione"</string>
<string name="start" msgid="6873794757232879664">"All\'inizio"</string>
<string name="center" msgid="4327473927066010960">"Al centro"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Anteprima"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Trascina per aggiungere i riquadri"</string>
<string name="qs_edit" msgid="2232596095725105230">"Modifica"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Ora"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Mostra ore, minuti e secondi"</item>
+ <item msgid="1427801730816895300">"Mostra ore e minuti (opzione predefinita)"</item>
+ <item msgid="3830170141562534721">"Non mostrare questa icona"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Mostra sempre la percentuale"</item>
+ <item msgid="2139628951880142927">"Mostra la percentuale quando in carica (opzione predefinita)"</item>
+ <item msgid="3327323682209964956">"Non mostrare questa icona"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Altro"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Strumento per schermo diviso"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Sposta giù"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Sposta su"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Sposta a sinistra"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Sposta a destra"</string>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 2601d36..ed44624 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -75,7 +75,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"צילום המסך בוצע."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"גע כדי להציג את צילום המסך שלך"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"לא ניתן לבצע צילום מסך."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"לא ניתן לצלם את המסך מפני שנפח האחסון מוגבל או מפני שהאפליקציה או הארגון שלך אינם מתירים זאת."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"לא ניתן לשמור צילום מסך עקב שטח אחסון מוגבל."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"האפליקציה, או הארגון שלך, אינם מתירים לבצע צילומי מסך."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"אפשרויות העברת קבצים ב-USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"טען כנגן מדיה (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"טען כמצלמה (PTP)"</string>
@@ -208,6 +209,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"יותר זמן."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"פחות זמן."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"הפנס כבוי."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"פנס אינו זמין."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"הפנס מופעל."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"הפנס נכבה."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"הפנס הופעל."</string>
@@ -303,10 +305,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"הצמדת מסך"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"חפש"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"לא ניתן היה להפעיל את <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> מושבת במצב בטוח."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"היסטוריה"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"נקה"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"אפליקציה זו אינה תומכת בריבוי חלונות"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"האפליקציה אינה תומכת בריבוי חלונות"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"פיצול אופקי"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"פיצול אנכי"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"פיצול מותאם אישית"</string>
@@ -336,8 +339,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"שקט\nמוחלט"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"התראות בעדיפות\nבלבד"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"התראות\nבלבד"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"הכל"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"הכל\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"בטעינה איטית (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> עד למילוי)"</string>
@@ -450,39 +451,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"הצג שניות בשעון בשורת הסטטוס. פעולה זו עשויה להשפיע על אורך חיי הסוללה."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"סידור מחדש של הגדרות מהירות"</string>
<string name="show_brightness" msgid="6613930842805942519">"הצג בהירות בהגדרות מהירות"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"הפעל מאיץ מסך מפוצל על ידי החלקה כלפי מעלה"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"הפעל מסך מפוצל על ידי תנועת החלקה כלפי מעלה"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"הפעל את התנועה לכניסה למסך מפוצל על ידי החלקה כלפי מעלה מלחצן הסקירה"</string>
<string name="experimental" msgid="6198182315536726162">"ניסיוניות"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"האם להפעיל את ה-Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"כדי לחבר את המקלדת לטאבלט, תחילה עליך להפעיל את ה-Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"הפעל"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"החל על הודעות של <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"החל על כל ההודעות מאפליקציה זו"</string>
+ <string name="show_silently" msgid="6841966539811264192">"הצג הודעות בלי להשמיע צליל"</string>
+ <string name="block" msgid="2734508760962682611">"חסום את כל ההודעות"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"לא להשתיק"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"לא להשתיק או לחסום"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"הצג את הגדרות החשיבות במלואן"</string>
<string name="blocked_importance" msgid="5198578988978234161">"חסום"</string>
+ <string name="min_importance" msgid="1901894910809414782">"חשיבות מינימלית"</string>
<string name="low_importance" msgid="4109929986107147930">"חשיבות נמוכה"</string>
<string name="default_importance" msgid="8192107689995742653">"חשיבות רגילה"</string>
<string name="high_importance" msgid="1527066195614050263">"חשיבות גבוהה"</string>
<string name="max_importance" msgid="5089005872719563894">"חשיבות דחופה"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"לעולם אל תציג את ההודעות האלה"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"הצג בחלק התחתון של רשימת ההודעות בלי להשמיע צליל"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"הצג את ההודעות האלה בלי להשמיע צליל"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"הצג בחלק העליון של רשימת ההודעות והשמע צליל"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"הצג לרגע על המסך והשמע צליל"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"הצג בסוף רשימת ההודעות בלי להשמיע צליל"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"הצג את ההודעות האלה בלי להשמיע צליל"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"אשר להודעות אלה להשמיע צליל"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"הצג לרגע על גבי המסך ואשר השמעת צליל"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"הצג בראש רשימת ההודעות, הצג לרגע על גבי המסך ואשר השמעת צליל"</string>
<string name="notification_more_settings" msgid="816306283396553571">"הגדרות נוספות"</string>
<string name="notification_done" msgid="5279426047273930175">"סיום"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"צבעים רגילים"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"צבעי לילה"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"צבעים מותאמים אישית"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"אוטומטי"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"צבעים לא ידועים"</string>
- <string name="color_transform" msgid="6985460408079086090">"שינוי צבע"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"הצגת אריח של הגדרות מהירות"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"הפעל טרנספורמציה מותאמת אישית"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"צבע ומראה"</string>
+ <string name="night_mode" msgid="3540405868248625488">"מצב לילה"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"כיול תצוגה"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"פועל"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"כבוי"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"הפעל אוטומטית"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"החלף למצב לילה בהתאם למיקום ולשעה ביום"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"כאשר מצב לילה מופעל"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"השתמש בעיצוב כהה למערכת ההפעלה של Android."</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"התאמת גוון"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"התאמת בהירות"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"העיצוב הכהה מוחל על התחומים העיקריים במערכת ההפעלה Android שמוצגים בדרך כלל בעיצוב בהיר, כמו \'הגדרות\'."</string>
<string name="color_apply" msgid="9212602012641034283">"החל"</string>
<string name="color_revert_title" msgid="4746666545480534663">"אישור הגדרות"</string>
<string name="color_revert_message" msgid="9116001069397996691">"הגדרות צבע מסוימות עלולות להפוך את המכשיר הזה לבלתי שמיש. לחץ על אישור כדי לאשר את הגדרות הצבע האלה, אחרת הגדרות אלה יתאפסו לאחר 10 שניות."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"שימוש בסוללה"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"תכונת החיסכון בסוללה אינה זמינה בעת טעינת המכשיר"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"חיסכון בסוללה"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"מפחית את רמת הביצועים ואת נתוני הרקע"</string>
@@ -490,21 +499,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"דף הבית"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"אחרונים"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"הקודם"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"הצג את החלונית \'נא לא להפריע\' בעוצמת הקול"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"אפשר שליטה מלאה בחלונית \'נא לא להפריע\' בתיבת הדו-שיח של עוצמת הקול."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"עוצמת הקול והאפשרות \'נא לא להפריע\'"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"היכנס לאפשרות \'נא לא להפריע\' בהחלשת עוצמת הקול"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"הצג עם פקדי עוצמת הקול"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"נא לא להפריע"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"מקש קיצור ללחצני עוצמת קול"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"צא מהאפשרות \'נא לא להפריע\' בהגברת עוצמת הקול"</string>
<string name="battery" msgid="7498329822413202973">"סוללה"</string>
<string name="clock" msgid="7416090374234785905">"שעון"</string>
<string name="headset" msgid="4534219457597457353">"אוזניות"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"אוזניות מחוברות"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"אוזניות מחוברות"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"הפעלה או השבתה של סמלים המוצגים בשורת הסטטוס."</string>
<string name="data_saver" msgid="5037565123367048522">"חוסך הנתונים (Data Saver)"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"חוסך הנתונים (Data Saver) פועל"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"חוסך הנתונים (Data Saver) כבוי"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"פועל"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"כבוי"</string>
<string name="nav_bar" msgid="1993221402773877607">"סרגל ניווט"</string>
<string name="start" msgid="6873794757232879664">"התחלה"</string>
<string name="center" msgid="4327473927066010960">"מרכז"</string>
@@ -527,4 +535,21 @@
<string name="preview" msgid="9077832302472282938">"תצוגה מקדימה"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"גרור כדי להוסיף משבצות"</string>
<string name="qs_edit" msgid="2232596095725105230">"ערוך"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"שעה"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"הצג שעות, דקות ושניות"</item>
+ <item msgid="1427801730816895300">"הצג שעות ודקות (ברירת מחדל)"</item>
+ <item msgid="3830170141562534721">"אל תציג את הסמל הזה"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"הצג תמיד באחוזים"</item>
+ <item msgid="2139628951880142927">"הצג באחוזים בזמן טעינה (ברירת מחדל)"</item>
+ <item msgid="3327323682209964956">"אל תציג את הסמל הזה"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"אחר"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"מחלק מסך מפוצל"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"הזז למטה"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"הזז למעלה"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"הזז שמאלה"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"הזז ימינה"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 27b3854..f104703 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"スクリーンショットを取得しました。"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"タップしてスクリーンショットを表示します。"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"スクリーンショットをキャプチャできませんでした。"</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"空き容量が足りないか、アプリまたは組織によって許可されていないため、スクリーンショットは撮れません。"</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"空き容量が足りないため、スクリーンショットを保存できません。"</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"アプリまたは組織によって許可されていないため、スクリーンショットは撮れません。"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USBファイル転送オプション"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"メディアプレーヤー(MTP)としてマウント"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"カメラ(PTP)としてマウント"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"長くします。"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"短くします。"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ライトがOFFです。"</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ライトを使用できません。"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ライトがONです。"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ライトをOFFにしました。"</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ライトをONにしました。"</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"画面固定"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"検索"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>を開始できません。"</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"「<xliff:g id="APP">%s</xliff:g>」はセーフモードでは無効になります。"</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"履歴"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"消去"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"このアプリはマルチウィンドウに対応していません"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"アプリはマルチウィンドウに対応していません"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"横に分割"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"縦に分割"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"分割(カスタム)"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"サイレント\n"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"重要な\n通知のみ"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"アラーム\nのみ"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"すべて"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"すべて\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"低速充電中(完了まで<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"ステータスバーに時計の秒を表示します。電池使用量に影響する可能性があります。"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"クイック設定を並べ替え"</string>
<string name="show_brightness" msgid="6613930842805942519">"クイック設定に明るさ調整バーを表示する"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"スワイプアップ分割画面アクセラレータを有効にする"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"上にスワイプして分割画面に切り替える操作を有効にする"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"[概要] ボタンから上にスワイプして分割画面に切り替える操作を有効にします"</string>
<string name="experimental" msgid="6198182315536726162">"試験運用版"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"BluetoothをONにしますか?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"タブレットでキーボードに接続するには、最初にBluetoothをONにする必要があります。"</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"ONにする"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"「<xliff:g id="TOPIC_NAME">%1$s</xliff:g>」の通知に適用"</string>
- <string name="apply_to_app" msgid="363016783939815960">"このアプリからのすべての通知に適用"</string>
+ <string name="show_silently" msgid="6841966539811264192">"通知をマナーモードで表示する"</string>
+ <string name="block" msgid="2734508760962682611">"通知をすべてブロックする"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"音声で知らせる"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"音声で知らせる / ブロックしない"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"重要度の設定をすべて表示"</string>
<string name="blocked_importance" msgid="5198578988978234161">"ブロック中"</string>
+ <string name="min_importance" msgid="1901894910809414782">"重要度: 最低"</string>
<string name="low_importance" msgid="4109929986107147930">"重要度: 低"</string>
<string name="default_importance" msgid="8192107689995742653">"重要度: 中"</string>
<string name="high_importance" msgid="1527066195614050263">"重要度: 高"</string>
<string name="max_importance" msgid="5089005872719563894">"重要度: 緊急"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"今後はこの通知を表示しない"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"通知リストの末尾にマナーモードで表示する"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"この通知をマナーモードで表示する"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"通知リストの先頭に表示し、音声でも知らせる"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"画面に数秒間表示し、音声でも知らせる"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"通知リストの末尾にマナーモードで表示する"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"この通知をマナーモードで表示する"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"通知を音声で知らせる"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"画面に数秒間表示し、音声でも知らせる"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"通知リストの先頭に表示し、画面に数秒間表示し、音声でも知らせる"</string>
<string name="notification_more_settings" msgid="816306283396553571">"詳細設定"</string>
<string name="notification_done" msgid="5279426047273930175">"完了"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"標準の色"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"夜間の色"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"カスタムの色"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"自動"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"不明な色"</string>
- <string name="color_transform" msgid="6985460408079086090">"色の変更"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"[クイック設定] タイルの表示"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"カスタム変換の有効化"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"色と表示"</string>
+ <string name="night_mode" msgid="3540405868248625488">"夜間モード"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"表示の調整"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"ON"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"OFF"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"自動的に ON"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"場所や時間に応じて夜間モードに切り替えます"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"夜間モードが ON のとき"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Android OS でダークテーマを使用"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"ティントを調整"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"明るさを調整"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"通常ライトテーマで表示される Android OS の主要領域(設定など)にダークテーマが適用されます。"</string>
<string name="color_apply" msgid="9212602012641034283">"適用"</string>
<string name="color_revert_title" msgid="4746666545480534663">"設定の確認"</string>
<string name="color_revert_message" msgid="9116001069397996691">"一部の色設定を適用すると、この端末を使用できなくなることがあります。この色設定を確認するには、[OK] をクリックしてください。確認しない場合、10 秒後に設定はリセットされます。"</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"電池の使用状況"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"充電中はバッテリー セーバーは利用できません"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"バッテリー セーバー"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"パフォーマンスとバックグラウンド データを制限します"</string>
@@ -488,17 +497,15 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"ホーム"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"最近"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"戻る"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"音量内に [通知を非表示] を表示"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"音量ダイアログでの [通知を非表示] の管理を許可します。"</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"音量と [通知を非表示]"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"音量下げボタンで [通知を非表示] を ON にする"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"音量調節を表示"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"通知の非表示"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"音量ボタンのショートカット"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"音量上げボタンで [通知を非表示] を OFF にする"</string>
<string name="battery" msgid="7498329822413202973">"電池"</string>
<string name="clock" msgid="7416090374234785905">"時計"</string>
<string name="headset" msgid="4534219457597457353">"ヘッドセット"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ヘッドホンを接続しました"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ヘッドセットを接続しました"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"ステータスバーでのアイコンの表示を有効または無効にします。"</string>
<!-- no translation found for data_saver (5037565123367048522) -->
<skip />
<!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
@@ -506,6 +513,7 @@
<!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
<skip />
<string name="switch_bar_on" msgid="1142437840752794229">"ON"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"OFF"</string>
<string name="nav_bar" msgid="1993221402773877607">"ナビゲーション バー"</string>
<string name="start" msgid="6873794757232879664">"最初"</string>
<string name="center" msgid="4327473927066010960">"中央"</string>
@@ -528,4 +536,21 @@
<string name="preview" msgid="9077832302472282938">"プレビュー"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"タイルを追加するにはドラッグしてください"</string>
<string name="qs_edit" msgid="2232596095725105230">"編集"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"時間"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"時間、分、秒を表示"</item>
+ <item msgid="1427801730816895300">"時間、分を表示(デフォルト)"</item>
+ <item msgid="3830170141562534721">"このアイコンを表示しない"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"常に割合を表示"</item>
+ <item msgid="2139628951880142927">"変更時に割合を表示(デフォルト)"</item>
+ <item msgid="3327323682209964956">"このアイコンを表示しない"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"その他"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"分割画面の分割線"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"下に移動"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"上に移動"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"左に移動"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"右に移動"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index dc48079..b365eb3 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"სკრინშოტი გადაღებულია."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"შეეხეთ ეკრანის სურათის სანახავად."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"ვერ მოხერხდა ეკრანის ანაბეჭდის გადაღება."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"ეკრანის ანაბეჭდი ვერ შეიქმნა შეზღუდული სივრცის გამო, ან შეზღუდულია თქვენი ორგანიზაციის აპის მიერ."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ეკრანის ანაბეჭდის შენახვა ვერ მოხერხდა შეზღუდული მეხსიერების გამო."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ეკრანის ანაბეჭდების შექმნა არ არის ნებადართული აპის ან თქვენი ორგანიზაციის მიერ."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB ფაილის ტრანსფერის პარამეტრები"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"მედია-საკრავად (MTP) ჩართვა"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"მიუერთეთ როგორც კამერა (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"მეტი დრო."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"ნაკლები დრო."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ფანარი გამორთულია."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ფანარი მიუწვდომელია."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ფანარი ჩართულია."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ფანარი გამოირთო."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ფანარი ჩაირთო."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ეკრანზე ჩამაგრება"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ძიება"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>-ის გამოძახება ვერ მოხერხდა."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> გათიშულია უსაფრთხო რეჟიმში."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"ისტორია"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"გასუფთავება"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"მრავალი ფანჯრის რეჟიმი არ არის მხარდაჭერილი ამ აპის მიერ"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"მრავალი ფანჯრის რეჟიმი არ არის მხარდაჭერილი აპის მიერ"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ჰორიზონტალური გაყოფა"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ვერტიკალური გაყოფა"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ინდივიდუალური გაყობა"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"სრული\nსიჩუმე"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"მხოლოდ\nპრიორიტეტულები"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"მხოლოდ\nგაფრთხილებები"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"ყველა"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"ყველა\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"იტენება ნელა (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> სრულ დატენვამდე)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"საათის წამების ჩვენება სტატუსის ზოლში. შეიძლება გავლენა იქონიოს ბატარეაზე."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"სწრაფი პარამეტრების გადაწყობა"</string>
<string name="show_brightness" msgid="6613930842805942519">"სიკაშკაშის ჩვენება სწრაფ პარამეტრებში"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"ზემოთ გადაფურცვლისას ეკრანის გაყოფის მაჩქარებლის ჩართვა"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"ზემოთ გადაფურცვლისას ეკრანის გაყოფის ჟესტის ჩართვა"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"მიმოხილვის ღილაკიდან ზემოთ გადაფურცვლისას ეკრანის გაყოფის რეჟიმზე გადასვლის ჟესტის ჩართვა"</string>
<string name="experimental" msgid="6198182315536726162">"ექსპერიმენტული"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"გსურთ Bluetooth-ის ჩართვა?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"კლავიატურის ტაბლეტთან დასაკავშირებლად, ჯერ უნდა ჩართოთ Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"ჩართვა"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"„<xliff:g id="TOPIC_NAME">%1$s</xliff:g>“ ტიპის შეტყობინებებისთვის მისადაგება"</string>
- <string name="apply_to_app" msgid="363016783939815960">"ამ აპის ყველა შეტყობინებისთვის მისადაგება"</string>
+ <string name="show_silently" msgid="6841966539811264192">"შეტყობინებების უხმოდ ჩვენება"</string>
+ <string name="block" msgid="2734508760962682611">"ყველა შეტყობინების დაბლოკვა"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"არ გაჩუმდეს"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"არ გაჩუმდეს ან დაიბლოკოს"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"მნიშვნელობის დონის სრული პარამეტრების ჩვენება"</string>
<string name="blocked_importance" msgid="5198578988978234161">"დაბლოკილი"</string>
+ <string name="min_importance" msgid="1901894910809414782">"მინიმალური"</string>
<string name="low_importance" msgid="4109929986107147930">"დაბალი პრიორიტეტი"</string>
<string name="default_importance" msgid="8192107689995742653">"ჩვეულებრივი პრიორიტეტი"</string>
<string name="high_importance" msgid="1527066195614050263">"მაღალი პრიორიტეტი"</string>
<string name="max_importance" msgid="5089005872719563894">"გადაუდებელი"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"ამ შეტყობინებების ჩვენების შეწყვეტა"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"ამ შეტყობინებების სიის ბოლოში, უხმოდ ჩვენება"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"ამ შეტყობინებების უხმოდ ჩვენება"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"ამ შეტყობინებების სიის თავში, ხმოვან სიგნალთან ერთად ჩვენება"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"ამ შეტყობინებების პირდაპირ ეკრანზე, ხმოვან სიგნალთან ერთად ჩვენება"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"შეტყობინებების სიის ბოლოში, უხმოდ ჩვენება"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"ამ შეტყობინებების უხმოდ ჩვენება"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"ამ შეტყობინებებისთვის ხმის გამოცემის დაშვება"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"შეტყობინებების პირდაპირ ეკრანზე ჩვენება და ხმის დაშვება"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"შეტყობინებების სიის თავში ჩვენება, პირდაპირ ეკრანზე გამოჩენა და ხმის დაშვება"</string>
<string name="notification_more_settings" msgid="816306283396553571">"დამატებითი პარამეტრები"</string>
<string name="notification_done" msgid="5279426047273930175">"მზადაა"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"ჩვეულებრივი ფერები"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"ღამის ფერები"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"მორგებული ფერები"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"ავტომატური"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"უცნობი ფერები"</string>
- <string name="color_transform" msgid="6985460408079086090">"ფერების შეცვლა"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"სწრაფი პარამეტრების მოზაიკის ჩვენება"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"მორგებული გარდაქმნის ჩართვა"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"ფერი და იერსახე"</string>
+ <string name="night_mode" msgid="3540405868248625488">"ღამის რეჟიმი"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"ეკრანის კალიბრაცია"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"ჩართული"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"გამორთული"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"ავტომატურად ჩართვა"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"ღამის რეჟიმზე გადართვა მდებარეობისა და დღე-ღამის მონაკვეთის შესაბამისად."</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"ღამის რეჟიმის ჩართვისას"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Android OS-ისთვის მუქი თემის გამოყენება"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"ელფერის გასწორება"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"სიკაშკაშის გასწორება"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"მუქი თემა მიესადაგება Android OS-ის ძირითად არეებს, რომლებიც, ჩვეულებრივ, ღია თემის მეშვეობით არის ნაჩვენები. მაგალითად, პარამეტრებს."</string>
<string name="color_apply" msgid="9212602012641034283">"გამოყენება"</string>
<string name="color_revert_title" msgid="4746666545480534663">"პარამეტრების დადასტურება"</string>
<string name="color_revert_message" msgid="9116001069397996691">"ფერთა ზოგიერთ პარამეტრს ამ მოწყობილობასთან მუშაობის გართულება შეუძლია. ფერთა ამჟამინდელი პარამეტრების დასადასტურებლად, დააწკაპუნეთ „კარგი“-ზე. წინააღმდეგ შემთხვევაში, პარამეტრები 10 წამის შემდეგ ჩამოიყრება."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"ბატარეის მოხმარება"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"ბატარეის დამზოგი დატენვისას მიწვდომელია"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"ბატარეის დამზოგი"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"ამცირებს წარმადობას და ფონურ მონაცემებს"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"მთავარი"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"ბოლოს გამოყენებული"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"უკან"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"ხმის დიალოგში „არ შემაწუხოთ“ რეჟიმის ჩვენება"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"ხმის დიალოგში „არ შემაწუხოთ“ რეჟიმის სრული კონტროლის დაშვება."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"ხმა და „არ შემაწუხოთ“"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"ხმის დაწევისას „არ შემაწუხოთ“ რეჟიმზე გადასვლა"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"ხმის მართვის საშუალებების ჩვენება"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"არ შემაწუხოთ"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"ხმის ღილაკების მალსახმობი"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"ხმის აწევისას „არ შემაწუხოთ“ რეჟიმიდან გამოსვლა"</string>
<string name="battery" msgid="7498329822413202973">"ბატარეა"</string>
<string name="clock" msgid="7416090374234785905">"საათი"</string>
<string name="headset" msgid="4534219457597457353">"ყურსაცვამი"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ყურსასმენები დაკავშირებულია"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ყურსაცვამი დაკავშირებულია"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"სტატუსის ზოლში ხატულების ჩვენების ჩართვა ან გათიშვა."</string>
<string name="data_saver" msgid="5037565123367048522">"მონაცემთა დამზოგველი"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"მონაცემთა დამზოგველი ჩართულია"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"მონაცემთა დამზოგველი გამორთულია"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"ჩართული"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"გამორთვა"</string>
<string name="nav_bar" msgid="1993221402773877607">"ნავიგაციის ზოლი"</string>
<string name="start" msgid="6873794757232879664">"თავში"</string>
<string name="center" msgid="4327473927066010960">"ცენტრში"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"გადახედვა"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"ფილების დასამატებლად, გადაიტანეთ ჩავლებით"</string>
<string name="qs_edit" msgid="2232596095725105230">"რედაქტირება"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"დრო"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"საათების, წუთებისა და წამების ჩვენება"</item>
+ <item msgid="1427801730816895300">"საათებისა და წუთების ჩვენება (ნაგულისხმევი)"</item>
+ <item msgid="3830170141562534721">"აღარ მაჩვენო ეს ხატულა"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"პროცენტულობის ყოველთვის ჩვენება"</item>
+ <item msgid="2139628951880142927">"პროცენტულობის დატენვისას ჩვენება (ნაგულისხმევი)"</item>
+ <item msgid="3327323682209964956">"აღარ მაჩვენო ეს ხატულა"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"სხვა"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"გაყოფილი ეკრანის რეჟიმის გამყოფი"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"ქვემოთ გადატანა"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"ზემოთ გადატანა"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"მარცხნივ გადატანა"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"მარჯვნივ გადატანა"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 1268e41..f8c54b6 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Скриншот сақталды."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Скриншотты көру үшін түрту."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Скриншот жасалмады."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Шектеулі жад кеңістігіне байланысты скриншот түсіру мүмкін емес немесе бұған қолданба немесе ұйым рұқсат етпейді."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Жадтағы шектеулі бос орынға байланысты скриншотты сақтау мүмкін емес."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Қолданба немесе ұйым скриншоттар түсіруге рұқсат етпейді."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB файлын жіберу опциялары"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Медиа ойнатқыш (MTP) ретінде қосыңыз"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Камера ретінде (PTP) қосыңыз"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Көбірек уақыт."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Азырақ уақыт."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Қол шам өшірулі."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Жарқыл қол жетімді емес."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Қол шам қосулы."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Қол шам өшірілді."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Қол шам қосылды."</string>
@@ -305,6 +307,8 @@
<skip />
<string name="recents_history_button_label" msgid="5153358867807604821">"Тарих"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Тазалау"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Бұл қолданба көп терезені қолдамайды"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Қолданба көп терезені қолдамайды"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Бөлінген көлденең"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Бөлінген тік"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Бөлінген теңшелетін"</string>
@@ -334,8 +338,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Толық\nтыныштық"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Тек\nбасымдық"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Тек\nдабылдар"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Барлығы"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Барлығы\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Баяу зарядталуда (толғанша <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
@@ -448,39 +450,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Күйін көрсету жолағында сағат секундтарын көрсету. Батареяның қызмет көрсету мерзіміне әсер етуі мүмкін."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Жылдам параметрлерді қайта реттеу"</string>
<string name="show_brightness" msgid="6613930842805942519">"Жылдам параметрлерде жарықтықты көрсету"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Бөлінген экранды жоғары қарай жанау жеделдеткішін қосу"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Бөлінген экранда жоғары қарай сырғыту қимылын қосу"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"\"Шолу\" түймесінен жоғары қарай жанау арқылы бөлінген экранға кіру қимылын қосу"</string>
<string name="experimental" msgid="6198182315536726162">"Эксперименттік"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth функциясын қосу керек пе?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Пернетақтаны планшетке қосу үшін алдымен Bluetooth функциясын қосу керек."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Қосу"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> хабарландыруға қолдану"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Осы қолданбаның барлық хабарландыруларына қолдану"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Хабарландыруларды үнсіз көрсету"</string>
+ <string name="block" msgid="2734508760962682611">"Барлық хабарландыруларды бұғаттау"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Үнін өшірмеу"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Үнін өшірмеу немесе бұғаттамау"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Толық маңыздылық параметрлерін көрсету"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Бөгелген"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Ең аз маңыздылық"</string>
<string name="low_importance" msgid="4109929986107147930">"Төмен маңыздылық"</string>
<string name="default_importance" msgid="8192107689995742653">"Қалыпты маңыздылық"</string>
<string name="high_importance" msgid="1527066195614050263">"Жоғары маңыздылық"</string>
<string name="max_importance" msgid="5089005872719563894">"Шұғыл маңыздылық"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Осы хабарландыруларды ешқашан көрсетпеу"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Хабарландырулар тізімнің төменгі жағында үнсіз көрсету"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Осы хабарландыруларды үнсіз көрсету"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Хабарландыруларды тізімінің жоғарғы жағында көрсету және дыбыс шығару"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Экранға бекіту және дыбыс шығару"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Хабарландырулар тізімнің төменгі жағында үнсіз көрсету"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Осы хабарландыруларды үнсіз көрсету"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Осы хабарландыруға дыбыстар шығаруға рұқсат ету"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Экранда көрсету және дыбыс шығаруға рұқсат ету"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Хабарландырулар тізімінің жоғарғы жағында көрсету, экранда көрсету және дыбысқа рұқсат ету"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Қосымша параметрлер"</string>
<string name="notification_done" msgid="5279426047273930175">"Дайын"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Қалыпты түстер"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Түнгі түстер"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Арнаулы түстер"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Авто"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Белгісіз түстер"</string>
- <string name="color_transform" msgid="6985460408079086090">"Түсті өзгерту"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Жылдам параметрлер торын көрсету"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Арнаулы түрлендіруді қосу"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Түс және сыртқы түрі"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Түнгі режим"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Дисплейді калибрлеу"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Қосулы"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Өшірулі"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Автоматты түрде қосу"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Орынға және күн уақытына тиісті түнгі режимге ауысу"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Түнгі режим қосулы кезде"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Android ОЖ үшін күңгірт тақырыпты пайдалану"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Реңкті реттеу"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Жарықтықты реттеу"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Күңгірт тақырып Android операциялық жүйесінің әдетте \"Параметрлер\" сияқты ашық тақырыпта көрсетілетін негізгі аумақтарына қолданылады."</string>
<string name="color_apply" msgid="9212602012641034283">"Қолдану"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Параметрлерді растау"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Кейбір түс параметрлері бұл құрылғыны пайдалану мүмкін емес етуі мүмкін. Бұл түс параметрлерін растау үшін OK түймесін басыңыз, әйтпесе параметрлер 10 секундтан кейін ысырылады."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Батареяны пайдалану"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Зарядтау кезінде Батарея үнемдегіш қол жетімді емес"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Батарея үнемдегіш"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Өнімділікті және фондық деректерді азайтады"</string>
@@ -488,21 +498,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Негізгі бет"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Жақындағылар"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Артқа"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Дыбыс деңгейінде \"Мазаламау\" режимін көрсету"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Дыбыс деңгейі диалогтық терезесінде \"Мазаламау\" режимін толық басқаруға рұқсат ету."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Дыбыс деңгейі және \"Мазаламау\""</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Дыбыс деңгейін төмендеткенде \"Мазаламау\" режиміне кіру"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Дыбыс деңгейін басқару элементтерімен бірге көрсету"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Мазаламау"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Дыбыс деңгейі түймелерінің төте жолы"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Дыбыс деңгейін көтергенде \"Мазаламау\" режимінен шығу"</string>
<string name="battery" msgid="7498329822413202973">"Батарея"</string>
<string name="clock" msgid="7416090374234785905">"Сағат"</string>
<string name="headset" msgid="4534219457597457353">"Құлақаспап жинағы"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Құлақаспап қосылды"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Құлақаспап жинағы қосылды"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Белгішелердің күй жолағында көрсетілуін қосу немесе өшіру"</string>
<string name="data_saver" msgid="5037565123367048522">"Дерек сақтағыш"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Дерек сақтағыш қосулы"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Дерек сақтағышы өшірулі"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Қосулы"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Өшірулі"</string>
<string name="nav_bar" msgid="1993221402773877607">"Шарлау тақтасы"</string>
<string name="start" msgid="6873794757232879664">"Бастау"</string>
<string name="center" msgid="4327473927066010960">"Орталық"</string>
@@ -525,4 +534,21 @@
<string name="preview" msgid="9077832302472282938">"Алдын ала қарау"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Торлар қосу үшін сүйреңіз"</string>
<string name="qs_edit" msgid="2232596095725105230">"Өңдеу"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Уақыт"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Сағаттарды, минуттарды және секундтарды көрсету"</item>
+ <item msgid="1427801730816895300">"Сағаттарды және минуттарды көрсету (әдепкі)"</item>
+ <item msgid="3830170141562534721">"Бұл белгішені көрсетпеу"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Әрқашан пайызды көрсету"</item>
+ <item msgid="2139628951880142927">"Зарядтау кезінде пайызды көрсету (әдепкі)"</item>
+ <item msgid="3327323682209964956">"Бұл белгішені көрсетпеу"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Басқа"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Бөлінген экран бөлгіші"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Төмен қарай жылжыту"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Жоғары қарай жылжыту"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Солға жылжыту"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Оңға жылжыту"</string>
</resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 74b1faf..97772ad 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"បានចាប់យករូបថតអេក្រង់។"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"ប៉ះ ដើម្បីមើលរូបថតអេក្រង់របស់អ្នក។"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"មិនអាចចាប់យករូបថតអេក្រង់។"</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"មិនអាចថតអេក្រង់ដោយសារតែទំហំផ្ទុកមានដែនកំណត់ ឬវាមិនត្រូវបានអនុញ្ញាតដោយកម្មវិធី ឬស្ថាប័នរបស់អ្នក។"</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"មិនអាចរក្សាទុករូបថតអេក្រង់បានទេដោយសារទំហំផ្ទុកមានកម្រិត។"</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ការថតរូបអេក្រង់មិនត្រូវបានអនុញ្ញាតដោយកម្មវិធីនេះ ឬស្ថាប័នរបស់អ្នក។"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"ជម្រើសផ្ទេរឯកសារតាមយូអេសប៊ី"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"ភ្ជាប់ជាកម្មវិធីចាក់មេឌៀ (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"ភ្ជាប់ជាម៉ាស៊ីនថត (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"ច្រើនជាង"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"តិចជាង"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"បិទពិល។"</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ពិលមិនអាចប្រើបានទេ"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"បើកពិល។"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"បានបិទពិល។"</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"បានបើកពិល។"</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ការភ្ជាប់អេក្រង់"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ស្វែងរក"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"មិនអាចចាប់ផ្ដើម <xliff:g id="APP">%s</xliff:g> ទេ។"</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ត្រូវបានបិទដំណើរការក្នុងរបៀបសុវត្ថិភាព"</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"ប្រវត្តិ"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"សម្អាត"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"កម្មវិធីនេះមិនគាំទ្រផ្ទាំងវិដូច្រើនទេ"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"កម្មវិធីមិនគាំទ្រផ្ទាំងវិដូច្រើនទេ"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"បំបែកផ្តេក"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"បំបែកបញ្ឈរ"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"បំបែកផ្ទាល់ខ្លួន"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"ស្ងៀមស្ងាត់\nទាំងស្រុង"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"អាទិភាព\nប៉ុណ្ណោះ"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"សំឡេងរោទ៍\nប៉ុណ្ណោះ"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"ទាំងអស់"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"ទាំងអស់\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"ថ្មកំពុងសាកយឺតៗ (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ទើបពេញ)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"បង្ហាញវិនាទីនៅលើរបារស្ថានភាពអាចនឹងប៉ះពាល់ដល់ថាមពលថ្ម។"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"រៀបចំការកំណត់រហ័សឡើងវិញ"</string>
<string name="show_brightness" msgid="6613930842805942519">"បង្ហាញកម្រិតពន្លឺនៅក្នុងការកំណត់រហ័ស"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"បើកដំណើរការឧបករណ៍បង្កើនល្បឿនការអូសទៅលើដើម្បីបំបែកអេក្រង់"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"បើកដំណើរការកាយវិការអូសទៅលើដើម្បីបំបែកអេក្រង់"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"បើកដំណើរការកាយវិការដើម្បីបំបែកអេក្រង់ដោយអូសទៅលើចាប់ពីប៊ូតុងទិដ្ឋភាព"</string>
<string name="experimental" msgid="6198182315536726162">"ពិសោធន៍"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"បើកប៊្លូធូសឬ?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"ដើម្បីភ្ជាប់ក្តារចុចរបស់អ្នកជាមួយនឹងថេប្លេតរបស់អ្នក អ្នកត្រូវតែបើកប៊្លូធូសជាមុនសិន។"</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"បើក"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"អនុវត្តចំពោះការជូនដំណឹង <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"អនុវត្តចំពោះការជូនដំណឹងទាំងអស់ពីកម្មវិធីនេះ"</string>
+ <string name="show_silently" msgid="6841966539811264192">"បង្ហាញការជូនដំណឹងស្ងាត់ៗ"</string>
+ <string name="block" msgid="2734508760962682611">"រារាំងការជូនដំណឹងទាំងអស់"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"កុំបិទសំឡេង"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"កុំបិទសំឡេង ឬរារាំង"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"បង្ហាញការកំណត់កម្រិតភាពសំខាន់ពេញលេញ"</string>
<string name="blocked_importance" msgid="5198578988978234161">"បានរារាំង"</string>
+ <string name="min_importance" msgid="1901894910809414782">"កម្រិតសំខាន់អប្បបរមា"</string>
<string name="low_importance" msgid="4109929986107147930">"មិនសូវសំខាន់"</string>
<string name="default_importance" msgid="8192107689995742653">"សំខាន់មធ្យម"</string>
<string name="high_importance" msgid="1527066195614050263">"សំខាន់ខ្លាំង"</string>
<string name="max_importance" msgid="5089005872719563894">"សំខាន់ជាបន្ទាន់"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"កុំបង្ហាញការជូនដំណឹងទាំងនេះ"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"បង្ហាញស្ងាត់ៗនៅផ្នែកខាងក្រោមបញ្ជីនៃការជូនដំណឹង"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"បង្ហាញការជូនដំណឹងទាំងនេះស្ងាត់ៗ"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"បង្ហាញនៅផ្នែកខាងលើបញ្ជីនៃការជូនដំណឹង និងបន្លឺសំឡេង"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"លោតបង្ហាញនៅលើអេក្រង់ និងបន្លឺសំឡេង"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"បង្ហាញស្ងាត់ៗនៅផ្នែកខាងក្រោមបញ្ជីនៃការជូនដំណឹង"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"បង្ហាញការជូនដំណឹងទាំងនេះស្ងាត់ៗ"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"អនុញ្ញាតឲ្យការជូនដំណឹងទាំងនេះបន្លឺសំឡេង"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"លោតបង្ហាញនៅលើអេក្រង់ និងអនុញ្ញាតឲ្យបន្លឺសំឡេង"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"បង្ហាញនៅផ្នែកខាងលើបញ្ជីនៃការជូនដំណឹង លោតបង្ហាញនៅលើអេក្រង់ និងអនុញ្ញាតឲ្យបន្លឺសំឡេង"</string>
<string name="notification_more_settings" msgid="816306283396553571">"ការកំណត់ច្រើនទៀត"</string>
<string name="notification_done" msgid="5279426047273930175">"រួចរាល់"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"ពណ៌ធម្មតា"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"ពណ៌ពេលយប់"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"ពណ៌ផ្ទាល់ខ្លួន"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"ស្វ័យប្រវត្តិ"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"ពណ៌មិនស្គាល់"</string>
- <string name="color_transform" msgid="6985460408079086090">"ការកែសម្រួលពណ៌"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"បង្ហាញផ្ទាំងប្រអប់ការកំណត់រហ័ស"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"បើកដំណើរការផ្លាស់ប្តូរផ្ទាល់ខ្លួន"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"ពណ៌ និងរូបរាង"</string>
+ <string name="night_mode" msgid="3540405868248625488">"របៀបពេលយប់"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"ការបង្ហាញក្រិត"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"បើក"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"បិទ"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"បើកដោយស្វ័យប្រវត្តិ"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"ប្តូរទៅជារបៀបពេលយប់ដែលសមស្របទៅតាមទីកន្លែង និងពេលវេលា"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"នៅពេលបើករបៀបពេលយប់"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"ប្រើធីមងងឹតសម្រាប់ប្រព័ន្ធប្រតិបត្តិការ Android"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"កែសម្រួលពណ៌ព្រឿងៗ"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"កែសម្រួលពន្លឺ"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"ធីមងងឹតត្រូវបានប្រើសម្រាប់ចំណុចស្នូលនៃប្រព័ន្ធប្រតិបត្តិការ Android ដែលជាទូទៅត្រូវបានបង្ហាញជាធីមភ្លឺ ដូចជាការកំណត់ជាដើម។"</string>
<string name="color_apply" msgid="9212602012641034283">"អនុវត្ត"</string>
<string name="color_revert_title" msgid="4746666545480534663">"បញ្ជាក់ការកំណត់"</string>
<string name="color_revert_message" msgid="9116001069397996691">"ការកំណត់ពណ៌មួយចំនួនអាចធ្វើឲ្យឧបករណ៍នេះមិនអាចប្រើបាន។ សូមចុច យល់ព្រម ដើម្បីបញ្ជាក់ការកំណត់ពណ៌ទាំងនេះ បើមិនដូច្នេះទេការកំណត់ទាំងនេះនឹងកំណត់ឡើងវិញក្នុងរយៈពេល 10 វិនាទីបន្ទាប់។"</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"ការប្រើប្រាស់ថ្ម"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"កម្មវិធីសន្សំថ្មមិនអាចប្រើបានអំឡុងពេលសាកថ្មទេ"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"កម្មវិធីសន្សំថ្ម"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"កាត់បន្ថយប្រតិបត្តិការ និងទិន្នន័យផ្ទៃខាងក្រោយ"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"ដើម"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"ថ្មីៗ"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"ថយក្រោយ"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"បង្ហាញមុខងារកុំរំខាននៅក្នុងកម្រិតសំឡេង"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"អនុញ្ញាតឲ្យមានការគ្រប់គ្រងពេញលេញចំពោះមុខងារកុំរំខាននៅក្នុងប្រអប់កម្រិតសំឡេង។"</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"កម្រិតសំឡេង និងមុនងារកុំរំខាន"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"ចូលមុខងារកុំរំខាននៅពេលបន្ថយសំឡេង"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"បង្ហាញជាមួយការគ្រប់គ្រងកម្រិតសំឡេង"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"កុំរំខាន"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"ផ្លូវកាត់ប៊ូតុងកម្រិតសំឡេង"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"ចាកចេញពីមុខងារកុំរំខាននៅពេលបង្កើនសំឡេង"</string>
<string name="battery" msgid="7498329822413202973">"ថ្ម"</string>
<string name="clock" msgid="7416090374234785905">"នាឡិកា"</string>
<string name="headset" msgid="4534219457597457353">"កាស"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"បានភ្ជាប់កាស"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"បានភ្ជាប់កាស"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"បើក ឬបិទដំណើរការបង្ហាញរូបតំណាងនៅលើរបារស្ថានភាព"</string>
<string name="data_saver" msgid="5037565123367048522">"កម្មវិធីសន្សំសំចៃទិន្នន័យ"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"កម្មវិធីសន្សំសំចៃទិន្នន័យបានបើក"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"កម្មវិធីសន្សំសំចៃទិន្នន័យបានបិទ"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"បើក"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"បិទ"</string>
<string name="nav_bar" msgid="1993221402773877607">"របាររុករក"</string>
<string name="start" msgid="6873794757232879664">"ចាប់ផ្ដើម"</string>
<string name="center" msgid="4327473927066010960">"កណ្តាល"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"មើលជាមុន"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"អូសដើម្បីបន្ថែមចំណងជើង"</string>
<string name="qs_edit" msgid="2232596095725105230">"កែសម្រួល"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"ម៉ោង"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"បង្ហាញម៉ោង នាទី និងវិនាទី"</item>
+ <item msgid="1427801730816895300">"បង្ហាញម៉ោង នាទី (លំនាំដើម)"</item>
+ <item msgid="3830170141562534721">"កុំបង្ហាញរូបតំណាងនេះ"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"បង្ហាញភាគរយជានិច្ច"</item>
+ <item msgid="2139628951880142927">"បង្ហាញភាគរយនៅពេលសាកថ្ម (លំនាំដើម)"</item>
+ <item msgid="3327323682209964956">"កុំបង្ហាញរូបតំណាងនេះ"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"ផ្សេងៗ"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"កម្មវិធីចែកអេក្រង់បំបែក"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"ផ្លាស់ទីចុះក្រោម"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"ផ្លាស់ទីឡើងលើ"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"ផ្លាស់ទីទៅឆ្វេង"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"ផ្លាស់ទីទៅស្តាំ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 5ab6e31..481b918c 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಸೆರೆಹಿಡಿಯಲಾಗಿದೆ."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ಶಾಟ್ ವೀಕ್ಷಿಸಲು ಸ್ಪರ್ಶಿಸಿ."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಸೆರೆಹಿಡಿಯಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"ಪರಿಮಿತ ಸಂಗ್ರಹಣೆ ಸ್ಥಳ, ಅಥವಾ ಅಪ್ಲಿಕೇಶನ್ ಅಥವಾ ನಿಮ್ಮ ಸಂಸ್ಥೆಯಿಂದ ಅನುಮತಿಯಿಲ್ಲದಿರುವ ಕಾರಣ ಸ್ಕ್ರೀನ್ಶಾಟ್ ತೆಗೆಯಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ಪರಿಮಿತ ಸಂಗ್ರಹಣೆ ಸ್ಥಳದ ಕಾರಣದಿಂದಾಗಿ ಸ್ಕ್ರೀನ್ಶಾಟ್ ಉಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ಸ್ಕ್ರೀನ್ಶಾಟ್ಗಳನ್ನು ತೆಗೆದುಕೊಳ್ಳುವುದನ್ನು ಅಪ್ಲಿಕೇಶನ್ ಅಥವಾ ನಿಮ್ಮ ಸಂಸ್ಥೆ ಅನುಮತಿಸುವುದಿಲ್ಲ."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB ಫೈಲ್ ವರ್ಗಾವಣೆ ಆಯ್ಕೆಗಳು"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"ಮೀಡಿಯಾ ಪ್ಲೇಯರ್ ರೂಪದಲ್ಲಿ ಅಳವಡಿಸಿ (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"ಕ್ಯಾಮರಾ ರೂಪದಲ್ಲಿ ಅಳವಡಿಸಿ (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"ಹೆಚ್ಚು ಸಮಯ."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"ಕಡಿಮೆ ಸಮಯ."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ಫ್ಲ್ಯಾಶ್ಲೈಟ್ ಆಫ್ ಆಗಿದೆ."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ಫ್ಲ್ಯಾಶ್ಲೈಟ್ ಲಭ್ಯವಿಲ್ಲ."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ಫ್ಲ್ಯಾಶ್ಲೈಟ್ ಆನ್ ಆಗಿದೆ."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ಫ್ಲ್ಯಾಶ್ಲೈಟ್ ಆಫ್ ಮಾಡಲಾಗಿದೆ."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ಫ್ಲ್ಯಾಶ್ಲೈಟ್ ಆನ್ ಮಾಡಲಾಗಿದೆ."</string>
@@ -304,6 +306,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ಅನ್ನು ಸುರಕ್ಷಿತ ಮೋಡ್ನಲ್ಲಿ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"ಇತಿಹಾಸ"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"ತೆರವುಗೊಳಿಸು"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಬಹು-ವಿಂಡೊಗಳನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"ಅಪ್ಲಿಕೇಶನ್ ಬಹು-ವಿಂಡೊಗಳನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ಅಡ್ಡಲಾಗಿ ವಿಭಜಿಸಿದ"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ಲಂಬವಾಗಿ ವಿಭಜಿಸಿದ"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ಕಸ್ಟಮ್ ವಿಭಜಿಸಿದ"</string>
@@ -333,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"ಸಂಪೂರ್ಣ\nನಿಶ್ಯಬ್ಧ"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"ಆದ್ಯತೆ\nಮಾತ್ರ"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"ಅಲಾರಮ್ಗಳು\nಮಾತ್ರ"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"ಎಲ್ಲ"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"ಎಲ್ಲಾ\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"ನಿಧಾನ ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ (ಪೂರ್ಣಗೊಳ್ಳಲು <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
@@ -447,34 +449,43 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯಲ್ಲಿ ಗಡಿಯಾರ ಸೆಕೆಂಡುಗಳನ್ನು ತೋರಿಸು. ಇದಕ್ಕೆ ಬ್ಯಾಟರಿ ಬಾಳಿಕೆಯು ಪರಿಣಾಮಬೀರಬಹುದು."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಮರುಹೊಂದಿಸಿ"</string>
<string name="show_brightness" msgid="6613930842805942519">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ಪ್ರಖರತೆಯನ್ನು ತೋರಿಸಿ"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಸ್ವೈಪ್-ಅಪ್ ವೇಗವರ್ಧಕವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"ಸ್ಪ್ಲಿಟ್-ಸ್ಕ್ರೀನ್ ಸ್ವೈಪ್-ಅಪ್ ಗೆಶ್ಚರ್ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"ಸಮಗ್ರ ನೋಟದ ಬಟನ್ನಿಂದ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ ಸ್ಪ್ಲಿಟ್-ಸ್ಕ್ರೀನ್ ನಮೂದಿಸಲು ಗೆಸ್ಚರ್ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
<string name="experimental" msgid="6198182315536726162">"ಪ್ರಾಯೋಗಿಕ"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"ಬ್ಲೂಟೂತ್ ಆನ್ ಮಾಡುವುದೇ?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"ನಿಮ್ಮ ಕೀಬೋರ್ಡ್ ಅನ್ನು ಟ್ಯಾಬ್ಲೆಟ್ಗೆ ಸಂಪರ್ಕಿಸಲು, ನೀವು ಮೊದಲು ಬ್ಲೂಟೂತ್ ಆನ್ ಮಾಡಬೇಕಾಗುತ್ತದೆ."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"ಆನ್ ಮಾಡು"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> ಅಧಿಸೂಚನೆಗಳಿಗೆ ಅನ್ವಯಿಸಿ"</string>
- <string name="apply_to_app" msgid="363016783939815960">"ಈ ಅಪ್ಲಿಕೇಶನ್ನಿಂದ ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳಿಗೆ ಅನ್ವಯಿಸಿ"</string>
+ <string name="show_silently" msgid="6841966539811264192">"ಸ್ಥಬ್ಧವಾಗಿ ಅಧಿಸೂಚನೆಗಳನ್ನು ತೋರಿಸಿ"</string>
+ <string name="block" msgid="2734508760962682611">"ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳನ್ನು ನಿರ್ಬಂಧಿಸಿ"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"ಮೌನವಾಗಿಸಬೇಡಿ"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"ಸ್ಥಬ್ದ ಅಥವಾ ನಿರ್ಬಂಧಿಸಬೇಡಿ"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"ಪೂರ್ಣ ಪ್ರಾಮುಖ್ಯತೆ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ತೋರಿಸಿ"</string>
<string name="blocked_importance" msgid="5198578988978234161">"ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string>
+ <string name="min_importance" msgid="1901894910809414782">"ಕನಿಷ್ಟ ಪ್ರಾಮುಖ್ಯತೆ"</string>
<string name="low_importance" msgid="4109929986107147930">"ಕಡಿಮೆ ಪ್ರಾಮುಖ್ಯತೆ"</string>
<string name="default_importance" msgid="8192107689995742653">"ಸಾಮಾನ್ಯ ಪ್ರಾಮುಖ್ಯತೆ"</string>
<string name="high_importance" msgid="1527066195614050263">"ಉನ್ನತ ಪ್ರಾಮುಖ್ಯತೆ"</string>
<string name="max_importance" msgid="5089005872719563894">"ತುರ್ತು ಪ್ರಾಮುಖ್ಯತೆ"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ಎಂದಿಗೂ ತೋರಿಸಬೇಡ"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"ಅಧಿಸೂಚನೆ ಪಟ್ಟಿಯ ಕೆಳಭಾಗದಲ್ಲಿ ಸ್ಥಬ್ಧವಾಗಿ ತೋರಿಸು"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ಸ್ಥಬ್ಧವಾಗಿ ತೋರಿಸು"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"ಅಧಿಸೂಚನೆಗಳ ಪಟ್ಟಿಯ ಮೇಲ್ಭಾಗದಲ್ಲಿ ತೋರಿಸು ಮತ್ತು ಧ್ವನಿ ಮಾಡು"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"ಪರದೆಯನ್ನು ವೀಕ್ಷಿಸಿ ಮತ್ತು ಧ್ವನಿ ಮಾಡು"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"ಅಧಿಸೂಚನೆ ಪಟ್ಟಿಯ ಕೆಳಭಾಗದಲ್ಲಿ ಸ್ಥಬ್ಧವಾಗಿ ತೋರಿಸು"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ಸ್ಥಬ್ಧವಾಗಿ ತೋರಿಸು"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"ಈ ಅಧಿಸೂಚನೆಯು ಧ್ವನಿಗಳನ್ನು ಮಾಡಲು ಅನುಮತಿಸಿ"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"ಪರದೆಯನ್ನು ವೀಕ್ಷಿಸಿ ಮತ್ತು ಧ್ವನಿ ಅನುಮತಿಸಿ ಮತ್ತು ಧ್ವನಿ ಅನುಮತಿಸಿ"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"ಅಧಿಸೂಚನೆಗಳ ಪಟ್ಟಿಯ ಮೇಲ್ಭಾಗದಲ್ಲಿ ತೋರಿಸು, ಪರದೆಯನ್ನು ವೀಕ್ಷಿಸಿ ಮತ್ತು ಧ್ವನಿ ಅನುಮತಿಸಿ"</string>
<string name="notification_more_settings" msgid="816306283396553571">"ಹೆಚ್ಚಿನ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="notification_done" msgid="5279426047273930175">"ಮುಗಿದಿದೆ"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"ಸಾಮಾನ್ಯ ಬಣ್ಣಗಳು"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"ರಾತ್ರಿ ಬಣ್ಣಗಳು"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"ಕಸ್ಟಮ್ ಬಣ್ಣಗಳು"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"ಸ್ವಯಂ"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"ಅಪರಿಚಿತ ಬಣ್ಣಗಳು"</string>
- <string name="color_transform" msgid="6985460408079086090">"ಬಣ್ಣ ಬದಲಾವಣೆ"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳ ಟೈಲ್ ತೋರಿಸು"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"ಕಸ್ಟಮ್ ಪರಿವರ್ತನೆಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"ಬಣ್ಣ ಮತ್ತು ಗೋಚರತೆ"</string>
+ <string name="night_mode" msgid="3540405868248625488">"ರಾತ್ರಿ ಮೋಡ್"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"ಅಣಿಗೊಳಿಸುವ ಪ್ರದರ್ಶನ"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"ಆನ್"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"ಆಫ್"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಆನ್ ಮಾಡು"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"ಸ್ಥಳ ಮತ್ತು ದಿನದ ಸಮಯಕ್ಕೆ ಸೂಕ್ತವಾಗುವಂತೆ ರಾತ್ರಿ ಮೋಡ್ ಅನ್ನು ಬದಲಾಯಿಸಿ"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"ರಾತ್ರಿ ಮೋಡ್ ಆನ್ ಆಗಿರುವಾಗ"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Android OS ಗೆ ಕಪ್ಪು ಥೀಮ್ ಬಳಸಿ"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"ಟಿಂಟ್ ಸರಿಹೊಂದಿಸು"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"ಪ್ರಖರತೆಯನ್ನು ಸರಿಹೊಂದಿಸು"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"ಕಪ್ಪು ಥೀಮ್ ಅನ್ನು Android OS ನ ಕೋರ್ ಪ್ರದೇಶಗಳಿಗೆ ಅನ್ವಯಿಸಲಾಗಿರುತ್ತದೆ. ಇದನ್ನು ಸೆಟ್ಟಿಂಗ್ಗಳಂತಹ ತಿಳಿಯಾದ ಥೀಮ್ನಲ್ಲಿ ಸಾಮಾನ್ಯವಾಗಿ ಪ್ರದರ್ಶಿಸಲಾಗುತ್ತದೆ."</string>
<string name="color_apply" msgid="9212602012641034283">"ಅನ್ವಯಿಸು"</string>
<string name="color_revert_title" msgid="4746666545480534663">"ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಖಚಿತಪಡಿಸಿ"</string>
<string name="color_revert_message" msgid="9116001069397996691">"ಕೆಲವು ಬಣ್ಣ ಸೆಟ್ಟಿಂಗ್ಗಳು ಈ ಸಾಧನವನ್ನು ಅನುಪಯುಕ್ತಗೊಳಿಸಬಹುದು. ಈ ಬಣ್ಣ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಖಚಿತಪಡಿಸಲು ಸರಿ ಕ್ಲಿಕ್ ಮಾಡಿ, ಇಲ್ಲವಾದರೆ ಈ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು 10 ಸೆಕೆಂಡುಗಳ ನಂತರ ಮರುಹೊಂದಿಸಿ."</string>
@@ -486,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"ಮುಖಪುಟ"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"ಇತ್ತೀಚಿನವುಗಳು"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"ಹಿಂದೆ"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"ವಾಲ್ಯೂಮ್ನಲ್ಲಿ \"ಅಡಚಣೆ ಮಾಡಬೇಡಿ\" ಅನ್ನು ತೋರಿಸಿ"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"ವಾಲ್ಯೂಮ್ ಸಂವಾದದಲ್ಲಿ \"ಅಡಚಣೆ ಮಾಡಬೇಡಿ\"ಯ ಸಂಪೂರ್ಣ ನಿಯಂತ್ರಣವನ್ನು ಅನುಮತಿಸಿ."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"ವಾಲ್ಯೂಮ್ ಮತ್ತು ಅಡಚಣೆ ಮಾಡಬೇಡಿ"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"ವಾಲ್ಯೂಮ್ ಕಡಿಮೆಯಲ್ಲಿ \"ಅಡಚಣೆ ಮಾಡಬೇಡಿ\" ನಮೂದಿಸಿ"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"ವಾಲ್ಯೂಮ್ ನಿಯಂತ್ರಣಗಳ ಜೊತೆಗೆ ತೋರಿಸು"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"ವಾಲ್ಯೂಮ್ ಬಟನ್ಗಳ ಶಾರ್ಟ್ಕಟ್"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"ವಾಲ್ಯೂಮ್ ಹೆಚ್ಚಳದಲ್ಲಿ \"ಅಡಚಣೆ ಮಾಡಬೇಡಿ\"ಯನ್ನು ತೊರೆಯಿರಿ"</string>
<string name="battery" msgid="7498329822413202973">"ಬ್ಯಾಟರಿ"</string>
<string name="clock" msgid="7416090374234785905">"ಗಡಿಯಾರ"</string>
<string name="headset" msgid="4534219457597457353">"ಹೆಡ್ಸೆಟ್"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ಹೆಡ್ಫೋನ್ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ಹೆಡ್ಸೆಟ್ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯಲ್ಲಿ ಐಕಾನ್ಗಳು ತೋರಿಸುವುದನ್ನು ಸಕ್ರಿಯ ಅಥವಾ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ."</string>
<string name="data_saver" msgid="5037565123367048522">"ಡೇಟಾ ಉಳಿಸುವಿಕೆ"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"ಡೇಟಾ ಉಳಿಸುವಿಕೆ ಆನ್ ಆಗಿದೆ"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"ಡೇಟಾ ಉಳಿಸುವಿಕೆ ಆಫ್ ಆಗಿದೆ"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"ಆನ್"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"ಆಫ್"</string>
<string name="nav_bar" msgid="1993221402773877607">"ನ್ಯಾವಿಗೇಷನ್ ಬಾರ್"</string>
<string name="start" msgid="6873794757232879664">"ಪ್ರಾರಂಭ"</string>
<string name="center" msgid="4327473927066010960">"ಮಧ್ಯ"</string>
@@ -523,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"ಪೂರ್ವವೀಕ್ಷಣೆ"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"ಟೈಲ್ಗಳನ್ನು ಸೇರಿಸಲು ಡ್ರ್ಯಾಗ್ ಮಾಡಿ"</string>
<string name="qs_edit" msgid="2232596095725105230">"ಸಂಪಾದಿಸು"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"ಸಮಯ"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"ಗಂಟೆಗಳು, ನಿಮಿಷಗಳು, ಸೆಕೆಂಡುಗಳನ್ನು ತೋರಿಸು"</item>
+ <item msgid="1427801730816895300">"ಗಂಟೆಗಳು ಮತ್ತು ನಿಮಿಷಗಳನ್ನು ತೋರಿಸು (ಡಿಫಾಲ್ಟ್)"</item>
+ <item msgid="3830170141562534721">"ಈ ಐಕಾನ್ ತೋರಿಸಬೇಡ"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"ಯಾವಾಗಲೂ ಪ್ರತಿಶತವನ್ನು ತೋರಿಸು"</item>
+ <item msgid="2139628951880142927">"ಚಾರ್ಜ್ ಮಾಡುವಾಗ ಪ್ರತಿಶತವನ್ನು ತೋರಿಸು (ಡಿಫಾಲ್ಟ್)"</item>
+ <item msgid="3327323682209964956">"ಈ ಐಕಾನ್ ತೋರಿಸಬೇಡ"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"ಇತರ"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"ಸ್ಪ್ಲಿಟ್-ಪರದೆ ಡಿವೈಡರ್"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"ಕೆಳಗೆ ಸರಿಸಿ"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"ಮೇಲೆ ಸರಿಸಿ"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"ಎಡಕ್ಕೆ ಸರಿಸಿ"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"ಬಲಕ್ಕೆ ಸರಿಸಿ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 5e6f65a..a3f4ff1 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"캡쳐화면 저장됨"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"캡쳐화면을 보려면 터치하세요."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"캡쳐화면을 캡쳐하지 못했습니다."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"저장 공간이 부족하거나 앱 또는 소속 조직에서 허용하지 않아 스크린샷을 찍을 수 없습니다."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"저장용량이 부족하여 스크린샷을 저장할 수 없습니다."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"앱이나 조직에서 스크린샷 촬영을 허용하지 않습니다."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB 파일 전송 옵션"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"미디어 플레이어로 마운트(MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"카메라로 마운트(PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"시간 늘리기"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"시간 줄이기"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"손전등: 사용 중지"</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"손전등을 사용할 수 없습니다."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"손전등: 사용"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"손전등이 사용 중지되었습니다."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"손전등을 사용합니다."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"화면 고정"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"검색"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>을(를) 시작할 수 없습니다."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g>은(는) 안전 모드에서 사용 중지됩니다."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"기록"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"삭제"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"이 앱은 다중 창을 지원하지 않습니다."</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"앱이 다중 창을 지원하지 않습니다."</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"수평 분할"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"수직 분할"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"맞춤 분할"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"모두\n차단"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"중요 알림만\n허용"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"알람만\n"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"모두 수신"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"모두\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"저속 충전 중(<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> 후 충전 완료)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"상태 표시줄에 시계 초 단위를 표시합니다. 배터리 수명에 영향을 줄 수도 있습니다."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"빠른 설정 재정렬"</string>
<string name="show_brightness" msgid="6613930842805942519">"빠른 설정에서 밝기 표시"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"위로 스와이프하여 창 분할하기 사용 설정"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"화면 분할 위로 스와이프 동작 사용"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"최근 사용 버튼에서 위로 스와이프하기 동작으로 창 분할 모드를 사용 설정합니다."</string>
<string name="experimental" msgid="6198182315536726162">"베타"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"블루투스를 켜시겠습니까?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"키보드를 태블릿에 연결하려면 먼저 블루투스를 켜야 합니다."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"사용"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> 알림에 적용"</string>
- <string name="apply_to_app" msgid="363016783939815960">"이 앱의 전체 알림에 적용"</string>
+ <string name="show_silently" msgid="6841966539811264192">"무음으로 알림 표시"</string>
+ <string name="block" msgid="2734508760962682611">"모든 알림 차단"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"무음 모드 사용 안함"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"무음 모드 또는 차단 사용 안함"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"전체 중요도 설정 표시"</string>
<string name="blocked_importance" msgid="5198578988978234161">"차단됨"</string>
+ <string name="min_importance" msgid="1901894910809414782">"중요도 최소"</string>
<string name="low_importance" msgid="4109929986107147930">"중요도 낮음"</string>
<string name="default_importance" msgid="8192107689995742653">"중요도 보통"</string>
<string name="high_importance" msgid="1527066195614050263">"중요도 높음"</string>
<string name="max_importance" msgid="5089005872719563894">"중요도 긴급"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"알림 다시 표시 안함"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"알림 목록 하단에 무음으로 표시"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"무음으로 알림 표시"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"알림 목록 상단에 표시하고 소리로 알림"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"화면에 표시하고 소리로 알림"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"알림 목록 맨 아래에 무음으로 표시"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"무음으로 알림 표시"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"알림을 소리로 알리도록 허용"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"화면에 표시하고 소리로 알림"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"알림 목록 맨 위에 표시, 화면에 표시하고 소리로 알림"</string>
<string name="notification_more_settings" msgid="816306283396553571">"설정 더보기"</string>
<string name="notification_done" msgid="5279426047273930175">"완료"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"일반 색상"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"야간 색상"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"맞춤 색상"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"자동"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"알 수 없는 색상"</string>
- <string name="color_transform" msgid="6985460408079086090">"색상 수정"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"빠른 설정 타일 표시"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"맞춤 변환 사용"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"색상 및 모양"</string>
+ <string name="night_mode" msgid="3540405868248625488">"야간 모드"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"디스플레이 보정"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"사용"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"사용 안함"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"자동으로 사용 설정"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"위치 및 시간대에 맞게 야간 모드로 전환"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"야간 모드 사용 중일 때"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Android OS용 어두운 테마 사용"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"농담 효과 조정"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"밝기 조정"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"설정 등 밝은 테마에서 일반적으로 표시되는 Android OS의 핵심 영역에 어두운 테마가 적용됩니다."</string>
<string name="color_apply" msgid="9212602012641034283">"적용"</string>
<string name="color_revert_title" msgid="4746666545480534663">"설정 확인"</string>
<string name="color_revert_message" msgid="9116001069397996691">"일부 색상 설정으로 인해 이 기기를 사용하지 못할 수 있습니다. 확인을 클릭하여 이러한 색상 설정을 확인하지 않으면 10초 후에 설정이 초기화됩니다."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"배터리 사용량"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"충전하는 동안 배터리 세이버는 사용할 수 없습니다."</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"배터리 세이버"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"성능 및 백그라운드 데이터를 줄입니다."</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"홈"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"최근"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"뒤로"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"볼륨에 알림 일시중지 표시"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"볼륨 대화상자에서 알림 일시중지에 대한 전체 컨트롤을 허용합니다."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"볼륨 및 알림 일시중지"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"볼륨 작게 시 알림 일시중지 사용"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"볼륨 컨트롤과 함께 표시"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"알림 일시중지"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"볼륨 버튼 단축키"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"볼륨 크게 시 알림 일시중지 종료"</string>
<string name="battery" msgid="7498329822413202973">"배터리"</string>
<string name="clock" msgid="7416090374234785905">"시계"</string>
<string name="headset" msgid="4534219457597457353">"헤드셋"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"헤드폰 연결됨"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"헤드셋 연결됨"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"아이콘이 상태 표시줄에 표시되도록 사용 설정 또는 중지합니다."</string>
<string name="data_saver" msgid="5037565123367048522">"데이터 세이버"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"데이터 세이버 사용"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"데이터 세이버 사용 안함"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"사용"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"사용 안함"</string>
<string name="nav_bar" msgid="1993221402773877607">"탐색 메뉴"</string>
<string name="start" msgid="6873794757232879664">"시작"</string>
<string name="center" msgid="4327473927066010960">"중앙"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"미리보기"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"드래그하여 타일 추가"</string>
<string name="qs_edit" msgid="2232596095725105230">"수정"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"시간"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"시간, 분, 초 표시"</item>
+ <item msgid="1427801730816895300">"시간, 분 표시(기본값)"</item>
+ <item msgid="3830170141562534721">"이 아이콘 표시 안함"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"항상 퍼센트 표시"</item>
+ <item msgid="2139628951880142927">"충전할 때 퍼센트 표시(기본값)"</item>
+ <item msgid="3327323682209964956">"이 아이콘 표시 안함"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"기타"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"화면 분할기"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"아래로 이동"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"위로 이동"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"왼쪽으로 이동"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"오른쪽으로 이동"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index 7819f40..66a34f0 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Скриншот тартылды."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Тийип, скриншотту көрүңүз."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Скриншот кылынбай жатат."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Сактагыч орду чектелүү болгондуктан скриншот тарта албайт, же буга колдонмо же ишканаңыз тарабынан уруксат жок."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Сактагычта бош орун аз болгондуктан скриншот сакталбай жатат."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Скриншот тартууга колдонмо же ишканаңыз уруксат бербейт."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB менен файл өткөрүү мүмкүнчүлүктөрү"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Медиа ойноткуч катары кошуу (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Камера катары кошуу (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Көбүрөөк убакыт."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Азыраак убакыт."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Колчырак өчүк."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Кол чырак жок."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Колчырак күйүк."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Колчырак өчүрүлдү."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Колчырак күйгүзүлдү."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"экран кадоо"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"издөө"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> баштай алган жок."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> коопсуз режиминде өчүрүлдү."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Таржымал"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Тазалоо"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Бул колдонмодо бир нече терезе режими колдоого алынбайт"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Колдонмодо бир нече терезе режими колдоого алынбайт"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Туурасынан бөлүү"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Тигинен бөлүү"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Ыңгайлаштырылган бөлүү"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Тым-\nтырс"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Артыкчылыктуу\nгана"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Ойготкучтар\nгана"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Бардыгы"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Бардык\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Жай кубатталууда (толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> калды)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Абал тилкесинен сааттын секунддары көрсөтүлсүн. Батареянын кубаты көбүрөөк сарпталышы мүмкүн."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Ыкчам жөндөөлөрдү кайра коюу"</string>
<string name="show_brightness" msgid="6613930842805942519">"Ыкчам жөндөөлөрдөн жарык деңгээлин көрсөтүү"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Өйдө серпип экранды бөлгүчтү иштетүү"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Өйдө серпип экранды бөлүү жаңсоосун иштетүү"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Сереп баскычынан өйдө серпип, экранды бөлүү режимин киргизүү үчүн жаңсоону иштетиңиз"</string>
<string name="experimental" msgid="6198182315536726162">"Сынамык"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth күйгүзүлсүнбү?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Баскычтобуңузду планшетиңизге туташтыруу үчүн, адегенде Bluetooth\'ту күйгүзүшүңүз керек."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Күйгүзүү"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> эскертмелерине колдонулсун"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Ушул колдонмодон алынган бардык эскертмелерге колдонулсун"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Эскертмелер үнсүз көрсөтүлсүн"</string>
+ <string name="block" msgid="2734508760962682611">"Бардык эскертмелерди бөгөттөө"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Үнсүз кылынбасын"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Үнсүз кылынып же бөгөттөлбөсүн"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Маанилүүлүк жөндөөлөрү толук көрсөтүлсүн"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Бөгөттөлгөн"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Маанилүүлүгү эң төмөн"</string>
<string name="low_importance" msgid="4109929986107147930">"Маанилүүлүгү төмөн"</string>
<string name="default_importance" msgid="8192107689995742653">"Маанилүүлүгү орточо"</string>
<string name="high_importance" msgid="1527066195614050263">"Маанилүүлүгү жогору"</string>
<string name="max_importance" msgid="5089005872719563894">"Маанилүүлүгү шашылыш"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Бул эскертмелер эч качан көрсөтүлбөсүн"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Эскертмелер тизмесинин эң ылдыйында үнсүз көрсөтүлсүн"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Бул эскертмелер үнсүз көрсөтүлсүн"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Эскертмелер тизмесинин эң жогорусунда үн чыгарып көрсөтүлсүн"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Үн менен коштолуп, экранга чыгарылсын"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Эскертмелер тизмесинин соңунда үнсүз көрсөтүлсүн"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Бул эскертмелер үнсүз көрсөтүлсүн"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Бул эскертмелер добуш чыгарышына уруксат берилсин"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Үн менен коштолуп, экранга чыгарылсын"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Эскертмелер тизмесинин эң башында көрсөтүлүп, үн менен коштолуп, экранга чыгарылсын"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Дагы жөндөөлөр"</string>
<string name="notification_done" msgid="5279426047273930175">"Аткарылды"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Кадимки түстөр"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Түнкү түстөр"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Ыңгайлаштырылган түстөр"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Авто"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Белгисиз түстөр"</string>
- <string name="color_transform" msgid="6985460408079086090">"Түсүн өзгөртүү"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Ыкчам жөндөөлөр тактасын көрсөтүү"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Ыңгайлаштырылган өзгөртүүнү иштетүү"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Түсү жана көрүнүшү"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Түнкү режим"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Дисплейди калибрлөө"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Күйүк"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Өчүк"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Автоматтык түрдө күйгүзүү"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Жайгашкан жерге жана убакытка жараша түнкү режимге которулуңуз"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Түнкү режим күйүп турганда"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Android OS үчүн караңгы тема колдонуу"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Кошумча түсүн тууралоо"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Жарыктыгын тууралоо"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Адатта жарык темада көрсөтүлүүчү Android тутумунун негизги элементтерине (Жөндөөлөр сыяктуу) колдонула турган караңгы тема."</string>
<string name="color_apply" msgid="9212602012641034283">"Колдонуу"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Жөндөөлөрдү ырастоо"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Айрым түс жөндөөлөрү бул түзмөктү колдонулгус кылып коюшу мүмкүн. Бул түс жөндөөлөрүн ырастоо үчүн OK баскычын чыкылдатыңыз, болбосо бул жөндөөлөр 10 секунддан кийин баштапкы абалына келтирилет."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Батарея колдонулушу"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Батареяны үнөмдөгүч түзмөк кубатталып жатканда иштебейт"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Батареяны үнөмдөгүч"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Иштин майнаптуулугун начарлатып, фондук дайындарды чектейт"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Башкы бет"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Акыркылар"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Артка"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"\"Тынчымды алба\" режимин үн көзөмөлдөгүчүндө көрсөтүү"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Үндү катуулатып/акырындатуу диалогунда \"Тынчымды алба\" режимин толук көзөмөлдөөгө уруксат берүү."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Үн көзөмөлдөгүчү жана \"Тынчымды алба\" режими"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Үн акырындатылганда \"Тынчымды алба\" режимине кирүү"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Үн көзөмөлдөгүчтөрү менен көрсөтүлсүн"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Тынчымды алба"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Үндү көзөмөлдөөчү баскычтардын кыска жолдору"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Үн катуулатылганда \"Тынчымды алба\" режиминен чыгуу"</string>
<string name="battery" msgid="7498329822413202973">"Батарея"</string>
<string name="clock" msgid="7416090374234785905">"Саат"</string>
<string name="headset" msgid="4534219457597457353">"Гарнитура"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Гарнитуралар туташкан"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Гарнитура туташты"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Абал тилкесиндеги сүрөтчөнү иштетүү же өчүрүү."</string>
<string name="data_saver" msgid="5037565123367048522">"Дайындарды үнөмдөгүч"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Дайындарды үнөмдөгүч күйүк"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Дайындарды үнөмдөгүч өчүрүлгөн"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Күйүк"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Өчүк"</string>
<string name="nav_bar" msgid="1993221402773877607">"Чабыттоо тилкеси"</string>
<string name="start" msgid="6873794757232879664">"Баштоо"</string>
<string name="center" msgid="4327473927066010960">"Экрандын ортосунда"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Алдын ала көрүү"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Керектүү нерселерди сүйрөп кошуңуз"</string>
<string name="qs_edit" msgid="2232596095725105230">"Түзөтүү"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Убакыт"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Сааттар, мүнөттөр жана секунддар көрсөтүлсүн"</item>
+ <item msgid="1427801730816895300">"Сааттар жана мүнөттөр көрсөтүлсүн (демейки)"</item>
+ <item msgid="3830170141562534721">"Бул сөлөкөт көрсөтүлбөсүн"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Ар дайым пайызы көрсөтүлсүн"</item>
+ <item msgid="2139628951880142927">"Кубаттоо учурунда пайызы көрсөтүлсүн (демейки)"</item>
+ <item msgid="3327323682209964956">"Бул сөлөкөт көрсөтүлбөсүн"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Башка"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Экранды бөлгүч"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Төмөн жылдыруу"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Жогору жылдыруу"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Солго жылдыруу"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Оңго жылдыруу"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 622e1e5..8000621f 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"ຖ່າຍຮູບໜ້າຈໍແລ້ວ"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"ແຕະເພື່ອເບິ່ງພາບໜ້າຈໍຂອງທ່ານ."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"ບໍ່ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້"</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"ບໍ່ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້ເນື່ອງຈາກບ່ອນຈັດເກັບຂໍ້ມູນທີ່ຈຳກັດ ຫຼືແອັບຯ ຫຼືອົງກອນຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ເຮັດໄດ້."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ບໍ່ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້ເນື່ອງຈາກພື້ນທີ່ຈັດເກັບຂໍ້ມູນມີຈຳກັດ."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ແອັບ ຫຼື ອົງກອນຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ມີການຖ່າຍຮູບໜ້າຈໍ."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB ໂຕເລືອກການຍ້າຍໄຟລ໌"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"ເຊື່ອມຕໍ່ເປັນ media player (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"ເຊື່ອມຕໍ່ເປັນກ້ອງຖ່າຍຮູບ (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"ເພີ່ມເວລາ."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"ຫຼຸດເວລາ."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ໄຟສາຍປິດ."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ບໍ່ສາມາດໃຊ້ໄຟສາຍໄດ້"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ໄຟສາຍເປີດ."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ປິດໄຟສາຍແລ້ວ."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ເປີດໄຟສາຍແລ້ວ."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ການປັກໝຸດໜ້າຈໍ"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ຊອກຫາ"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"ບໍ່ສາມາດເລີ່ມ <xliff:g id="APP">%s</xliff:g> ໄດ້."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ຖືກປິດໃຊ້ໃນໂໝດຄວາມມປອດໄພ."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"ປະຫວັດ"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"ລຶບ"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"ແອັບນີ້ບໍ່ຮອງຮັບຫຼາຍໜ້າຈໍ"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"ແອັບບໍ່ຮອງຮັບຫຼາຍໜ້າຈໍ"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ການແຍກລວງຂວາງ"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ການແຍກລວງຕັ້ງ"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ການແຍກກຳນົດເອງ"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"ຄວາມງຽບ\nທັງໝົດ"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"ບຸລິມະສິດ\nເທົ່ານັ້ນ"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"ໂມງປຸກ\nເທົ່ານັ້ນ"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"ທັງໝົດ"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"ທັງໝົດ\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"ກຳລັງສາກໄຟ (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ກວ່າຈະເຕັມ)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"ສະແດງວິນາທີໂມງຢູ່ໃນແຖບສະຖານະ. ອາດຈະມີຜົນກະທົບຕໍ່ອາຍຸແບັດເຕີຣີ."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"ຈັດວາງການຕັ້ງຄ່າດ່ວນຄືນໃໝ່"</string>
<string name="show_brightness" msgid="6613930842805942519">"ສະແດງຄວາມແຈ້ງຢູ່ໃນການຕັ້ງຄ່າດ່ວນ"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"ເປີດໃຊ້ຕົວເລັ່ງຄວາມໄວການປັດຂຶ້ນຂອງໜ້າຈໍແບບແຍກກັນ"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"ເປີດໃຊ້ທ່າທາງການປັດຂຶ້ນເພື່ອເຂົ້າສູ່ໜ້າຈໍແບບແຍກກັນ"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"ເປີດໃຊ້ທ່າທາງເພື່ອເຂົ້າສູ່ໜ້າຈໍແບບແຍກກັນ ໂດຍການປັດຂຶ້ນຈາກປຸ່ມພາບຮວມ"</string>
<string name="experimental" msgid="6198182315536726162">"ຍັງຢູ່ໃນການທົດລອງ"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"ເປີດໃຊ້ Bluetooth ບໍ່?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"ເພື່ອເຊື່ອມຕໍ່ແປ້ນພິມຂອງທ່ານກັບແທັບເລັດຂອງທ່ານ, ກ່ອນອື່ນໝົດທ່ານຕ້ອງເປີດ Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"ເປີດ"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"ນຳໃຊ້ກັບການແຈ້ງເຕືອນ <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"ນຳໃຊ້ກັບທຸກການແຈ້ງເຕືອນຈາກແອັບນີ້"</string>
+ <string name="show_silently" msgid="6841966539811264192">"ສະແດງການແຈ້ງເຕືອນແບບບໍ່ມີສຽງ"</string>
+ <string name="block" msgid="2734508760962682611">"ບລັອກການແຈ້ງເຕືອນທັງໝົດ"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"ຢ່າງຽບ"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"ຢ່າງຽບ ຫຼື ບລັອກ"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"ສະແດງການຕັ້ງຄ່າຄວາມສຳຄັນແບບເຕັມ"</string>
<string name="blocked_importance" msgid="5198578988978234161">"ບລັອກໄວ້ແລ້ວ"</string>
+ <string name="min_importance" msgid="1901894910809414782">"ຄວາມສຳຄັນໜ້ອຍສຸດ"</string>
<string name="low_importance" msgid="4109929986107147930">"ຄວາມສໍາຄັນຕໍ່າ"</string>
<string name="default_importance" msgid="8192107689995742653">"ຄວາມສຳຄັນປົກກະຕິ"</string>
<string name="high_importance" msgid="1527066195614050263">"ຄວາມສໍາຄັນສູງ"</string>
<string name="max_importance" msgid="5089005872719563894">"ຄວາມສໍາຄັນຮີບດ່ວນ"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"ຢ່າສະແດງການແຈ້ງເຕືອນເຫຼົ່ານີ້"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"ສະແດງຢູ່ສ່ວນລຸ່ມຂອງລາຍການແຈ້ງເຕືອນແບບມີບໍ່ສຽງ"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"ສະແດງການແຈ້ງເຕືອນເຫຼົ່ານີ້ແບບບໍ່ມີສຽງ"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"ສະແດງຢູ່ສ່ວນເທິງຂອງລາຍການແຈ້ງເຕືອນ ແລະສົ່ງສຽງດັງ"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"ເດັ້ງຂຶ້ນເທິງຫນ້າຈໍ ແລະສົ່ງສຽງດັງ"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"ສະແດງຢູ່ລຸ່ມສຸດຂອງລາຍການແຈ້ງເຕືອນແບບມີບໍ່ສຽງ"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"ສະແດງການແຈ້ງເຕືອນເຫຼົ່ານີ້ແບບບໍ່ມີສຽງ"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"ອະນຸຍາດໃຫ້ການແຈ້ງເຕືອນເຫຼົ່ານີ້ໃຊ້ສຽງໄດ້"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"ແຈ້ງໄປໜ້າຈໍ ແລະ ອະນຸຍາດໃຫ້ໃຊ້ສຽງໄດ້"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"ສະແດງຢູ່ເທິງສຸດຂອງລາຍການແຈ້ງເຕືອນ, ແຈ້ງໄປໜ້າຈໍ ແລະ ອະນຸຍາດໃຫ້ໃຊ້ສຽງໄດ້"</string>
<string name="notification_more_settings" msgid="816306283396553571">"ການຕັ້ງຄ່າເພີ່ມເຕີມ"</string>
<string name="notification_done" msgid="5279426047273930175">"ສຳເລັດແລ້ວ"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"ສີປົກກະຕິ"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"ສີຕອນກາງຄືນ"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"ສີແບບກຳນົດເອງ"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"ອັດຕະໂນມັດ"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"ສີທີ່ບໍ່ຮູ້ຈັກ"</string>
- <string name="color_transform" msgid="6985460408079086090">"ການດັດແປງສີ"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"ສະແດງໄທລ໌ການຕັ້ງຄ່າດ່ວນ"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"ເປີດໃຊ້ການປ່ຽນສີແບບກຳນົດເອງ"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"ສີ ແລະ ລັກສະນະ"</string>
+ <string name="night_mode" msgid="3540405868248625488">"ໂໝດກາງຄືນ"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"ປັບໜ້າຈໍ"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"ເປີດ"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"ປິດ"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"ເປີດໃຊ້ອັດຕະໂນມັດ"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"ສະລັບໄປໃຊ້ໂໝດກາງຄືນຕາມຄວາມເໝາະສົມກັບສະຖານທີ່ ແລະ ເວລາໃນແຕ່ລະມື້"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"ເມື່ອເປີດໂໝດກາງຄືນ"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"ໃຊ້ຮູບແບບສີສັນແບບມືດສຳລັບ Android OS"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"ປັບແຕ່ງໂທນສີ"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"ປັບແຕ່ງຄວາມສະຫວ່າງ"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"ຮູບແບບສີສັນມືດແມ່ນນຳໃຊ້ກັບພື້ນທີ່ຫຼັກຂອງ Android OS ທີ່ປົກກະຕິຈະສະແດງເປັນຮູບແບບສີສັນແຈ້ງ ເຊັ່ນ: ການຕັ້ງຄ່າ."</string>
<string name="color_apply" msgid="9212602012641034283">"ນຳໃຊ້"</string>
<string name="color_revert_title" msgid="4746666545480534663">"ຢືນຢັນການຕັ້ງຄ່າ"</string>
<string name="color_revert_message" msgid="9116001069397996691">"ບາງການຕັ້ງຄ່າສີສາມາດເຮັດໃຫ້ອຸປະກອນນີ້ບໍ່ສາມາດໃຊ້ໄດ້. ຄລິກ ຕົກລົງ ເພື່ອຢືນຢັນການຕັ້ງຄ່າສີເຫຼົ່ານີ້, ຖ້າບໍ່ດັ່ງນັ້ນ ການຕັ້ງຄ່າເຫຼົ່ານີ້ຈະຕັ້ງຄືນໃໝ່ ຫຼັງຈາກ 10 ວິນາທີ."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"ການໃຊ້ແບັດເຕີຣີ"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"ຕົວປະຢັດແບັດເຕີຣີບໍ່ມີໃຫ້ນຳໃຊ້ໃນລະຫວ່າງການສາກ"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"ຕົວປະຢັດແບັດເຕີຣີ"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"ຫຼຸດປະສິທິພາບການໃຊ້ງານ ແລະ ຂໍ້ມູນພື້ນຫຼັງ"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"ໜ້າຫຼັກ"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"ຫາກໍໃຊ້"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"ກັບຄືນ"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"ສະແດງ ຫ້າມລົບກວນ ໃນລະດັບສຽງ"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"ອະນຸຍາດການຄວບຄຸມເຕັມສ່ວນຂອງ ຫ້າມລົບກວນ ໃນກ່ອງປັບລະດັບສຽງ."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"ລະດັບສຽງ ແລະ ຫ້າມລົບກວນ"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"ເປີດໃຊ້ໂໝດ ຫ້າມລົບກວນ ເມື່ອປັບສຽງໃຫ້ຄ່ອຍລົງ"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"ສະແດງສ່ວນຄວບຄຸມສຽງ"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"ຫ້າມລົບກວນ"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"ທາງລັດປຸ່ມສຽງ"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"ອອກຈາກໂໝດ ຫ້າມລົບກວນ ເມື່ອປັບສຽງໃຫ້ດັງຂຶ້ນ"</string>
<string name="battery" msgid="7498329822413202973">"ແບັດເຕີຣີ"</string>
<string name="clock" msgid="7416090374234785905">"ໂມງ"</string>
<string name="headset" msgid="4534219457597457353">"ຊຸດຫູຟັງ"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ເຊື່ອມຕໍ່ຊຸດຫູຟັງແລ້ວ"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ເຊື່ອມຕໍ່ຊຸດຫູຟັງແລ້ວ"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"ເປີດ ຫຼື ປິດໄອຄອນຕ່າງໆຈາກການສະແດງໃນແຖບສະຖານະ."</string>
<string name="data_saver" msgid="5037565123367048522">"ຕົວປະຢັດຂໍ້ມູນ"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"ຕົວປະຢັດຂໍ້ມູນເປີດຢູ່"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"ຕົວປະຢັດຂໍ້ມູນປິດຢູ່"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"ເປີດ"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"ປິດ"</string>
<string name="nav_bar" msgid="1993221402773877607">"ແຖບນຳທາງ"</string>
<string name="start" msgid="6873794757232879664">"ເລີ່ມຕົ້ນ"</string>
<string name="center" msgid="4327473927066010960">"ເຄິ່ງກາງ"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"ສະແດງຕົວຢ່າງ"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"ລາກເພື່ອເພີ່ມໄທລ໌"</string>
<string name="qs_edit" msgid="2232596095725105230">"ແກ້ໄຂ"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"ເວລາ"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"ສະແດງຊົ່ວໂມງ, ນາທີ ແລະ ວິນາທີ"</item>
+ <item msgid="1427801730816895300">"ສະແດງຊົ່ວໂມງ ແລະ ນາທີ (ຄ່າເລີ່ມຕົ້ນ)"</item>
+ <item msgid="3830170141562534721">"ຢ່າສະແດງໄອຄອນນີ້"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"ສະແດງເປີເຊັນຕະຫຼອດເວລາ"</item>
+ <item msgid="2139628951880142927">"ສະແດງເປີເຊັນເມື່ອກຳລັງສາກໄຟ (ຄ່າເລີ່ມຕົ້ນ)"</item>
+ <item msgid="3327323682209964956">"ຢ່າສະແດງໄອຄອນນີ້"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"ອື່ນໆ"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"ຕົວຂັ້ນການແບ່ງໜ້າຈໍ"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"ເລື່ອນລົງ"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"ເລື່ອນຂຶ້ນ"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"ເລື່ອນຊ້າຍ"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"ເລື່ອນຂວາ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 34decce7..bb49c39 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -75,7 +75,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Ekrano kopija užfiksuota."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Palieskite, kad peržiūrėtumėte ekrano kopiją."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Nepavyko užfiksuoti ekrano kopijos."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Neg. daryti ekr. kopijų dėl ribotos saugyklos vietos arba to atlikti neleidžia progr. ar organiz."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Negalima išsaugoti ekrano kopijos dėl ribotos saugyklos vietos."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Jūsų organizacijoje arba naudojant šią programą neleidžiama daryti ekrano kopijų"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB failo perdavimo parinktys"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Įmontuoti kaip medijos leistuvę (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Įmontuoti kaip fotoaparatą (PTP)"</string>
@@ -208,6 +209,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Daugiau laiko."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Mažiau laiko."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Blykstė išjungta."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Blykstė nepasiekiama."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Blykstė įjungta."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Blykstė išjungta."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Blykstė įjungta."</string>
@@ -303,10 +305,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekrano prisegimas"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"paieška"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Nepavyko paleisti <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Programa „<xliff:g id="APP">%s</xliff:g>“ išjungta saugos režimu."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Istorija"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Išvalyti"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Ši programa nepalaiko kelių langų režimo"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Programa nepalaiko kelių langų režimo"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Horizontalus skaidymas"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikalus skaidymas"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Tinkintas skaidymas"</string>
@@ -336,8 +339,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Visiška\ntyla"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Tik\nprioritetiniai"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Tik\nsignalai"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Visi"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Visi\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Kraunama (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> iki visiško įkrovimo)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Greitai kraunama (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> iki visiško įkrovimo)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Lėtai kraunama (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> iki visiško įkrovimo)"</string>
@@ -450,39 +451,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Rodyti laikrodžio sekundes būsenos juostoje. Tai gali paveikti akumuliatoriaus naudojimo laiką."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Pertvarkyti sparčiuosius nustatymus"</string>
<string name="show_brightness" msgid="6613930842805942519">"Rodyti skaistį sparčiuosiuose nustatymuose"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Įgalinti skaidyto ekrano perbrauk. aukštyn spartinimo įrankį"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Įgalinti ekrano skaidymo perbraukimo aukštyn gestą"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Įgalinti gestą, kuriuo galima įjungti skaidytą ekraną, perbraukiant aukštyn nuo apžvalgos mygtuko"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimentinė versija"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Įjungti „Bluetooth“?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Kad galėtumėte prijungti klaviatūrą prie planšetinio kompiuterio, pirmiausia turite įjungti „Bluetooth“."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Įjungti"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Taikyti „<xliff:g id="TOPIC_NAME">%1$s</xliff:g>“ pranešimams"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Taikyti visiems pranešimams iš šios programos"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Tyliai rodyti pranešimus"</string>
+ <string name="block" msgid="2734508760962682611">"Blokuoti visus pranešimus"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Netylėti"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Netylėti arba blokuoti"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Rodyti visos svarbos nustatymus"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Užblokuota"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Min. svarba"</string>
<string name="low_importance" msgid="4109929986107147930">"Maža svarba"</string>
<string name="default_importance" msgid="8192107689995742653">"Įprasta svarba"</string>
<string name="high_importance" msgid="1527066195614050263">"Didelė svarba"</string>
<string name="max_importance" msgid="5089005872719563894">"Skubi svarba"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Niekada nerodyti šių pranešimų"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Tyliai rodyti pranešimų sąrašo apačioje"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Tyliai rodyti šiuos pranešimus"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Rodyti pranešimų sąrašo viršuje ir skambėti"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Rodyti ekrane ir skambėti"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Tyliai rodyti pranešimų sąrašo apačioje"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Tyliai rodyti šiuos pranešimus"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Leisti šiems pranešimams skambėti"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Rodyti ekrane ir leisti skambėti"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Rodyti pranešimų sąrašo viršuje, rodyti ekrane ir leisti skambėti"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Daugiau nustatymų"</string>
<string name="notification_done" msgid="5279426047273930175">"Atlikta"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Įprastos spalvos"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Nakties spalvos"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Tinkintos spalvos"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automatinis"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Nežinomos spalvos"</string>
- <string name="color_transform" msgid="6985460408079086090">"Spalvų keitimas"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Rodyti Sparčiųjų nustatymų išklotinės elementą"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Įgalinti tinkintą transformavimą"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Spalva ir išvaizda"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Naktinis režimas"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Kalibruoti ekraną"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Įjungta"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Išjungta"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Įjungti automatiškai"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Perjungti į naktinį režimą pagal vietovę ir dienos laiką"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Kai įjungtas naktinis režimas"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Naudoti tamsią „Android“ OS temą"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Koreguoti atspalvį"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Koreguoti šviesumą"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Pagrindinėms „Android“ OS dalims, kurioms paprastai taikoma šviesi tema, pvz., skilčiai „Nustatymai“, bus pritaikyta tamsi tema."</string>
<string name="color_apply" msgid="9212602012641034283">"Taikyti"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Nustatymų patvirtinimas"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Dėl kai kurių spalvų nustatymų įrenginys gali būti netinkamas naudoti. Spustelėkite „Gerai“, kad patvirtintumėte šiuos spalvų nustatymus. Kitaip šie nustatymai bus nustatyti iš naujo po 10 sekundžių."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Akum. energ. vartoj."</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Akumuliatoriaus tausojimo priemonė nepasiekiama įkraunant"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Akumuliatoriaus tausojimo priemonė"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Sumažinamas našumas ir foninių duomenų naudojimas"</string>
@@ -490,21 +499,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Pagrindinis ekranas"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Naujausios veiklos ekranas"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Atgal"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Rodyti netrukdymo režimą garsumo dialogo lange"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Leisti visiškai valdyti netrukdymo režimą garsumo dialogo lange."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Garsumas ir netrukdymo režimas"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Įjungti netrukdymo režimą mažinant garsumą"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Rodyti su garsumo valdikliais"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Netrukdymo režimas"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Garsumo mygtukų spartusis klavišas"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Išjungti netrukdymo režimą didinant garsumą"</string>
<string name="battery" msgid="7498329822413202973">"Akumuliatorius"</string>
<string name="clock" msgid="7416090374234785905">"Laikrodis"</string>
<string name="headset" msgid="4534219457597457353">"Ausinės"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Ausinės prijungtos"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Ausinės prijungtos"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Įgalinti arba išjungti piktogramų rodymą būsenos juostoje."</string>
<string name="data_saver" msgid="5037565123367048522">"Duomenų taupymo priemonė"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Duomenų taupymo priemonė įjungta"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Duomenų taupymo priemonė išjungta"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Įjungti"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Išjungta"</string>
<string name="nav_bar" msgid="1993221402773877607">"Naršymo juosta"</string>
<string name="start" msgid="6873794757232879664">"Pradėti"</string>
<string name="center" msgid="4327473927066010960">"Centre"</string>
@@ -527,4 +535,21 @@
<string name="preview" msgid="9077832302472282938">"Peržiūrėti"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Nuvilkite, kad pridėtumėte išklotinės elementų"</string>
<string name="qs_edit" msgid="2232596095725105230">"Redaguoti"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Laikas"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Rodyti valandas, minutes ir sekundes"</item>
+ <item msgid="1427801730816895300">"Rodyti valandas ir minutes (numatytasis nustatymas)"</item>
+ <item msgid="3830170141562534721">"Nerodyti šios piktogramos"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Visada rodyti procentus"</item>
+ <item msgid="2139628951880142927">"Rodyti procentus kraunant (numatytasis nustatymas)"</item>
+ <item msgid="3327323682209964956">"Nerodyti šios piktogramos"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Kita"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Skaidyto ekrano daliklis"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Perkelti žemyn"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Perkelti aukštyn"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Perkelti kairėn"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Perkelti dešinėn"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index c667f35..574889e 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -74,7 +74,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Ekrānuzņēmums ir uzņemts."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Pieskarieties, lai skatītu ekrānuzņēmumu."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Nevarēja uzņemt ekrānuzņēmumu."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Nevar veikt ekrānuzņēmumu (krātuvē nepietiek vietas, vai to neļauj lietotne vai jūsu organizācija)."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Nevar saglabāt ekrānuzņēmumu, jo krātuvē nepietiek vietas."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Lietotne vai jūsu organizācija neatļauj veikt ekrānuzņēmumus."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB failu pārsūtīšanas opcijas"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Pievienot kā multivides atskaņotāju (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Pievienot kā kameru (PTP)"</string>
@@ -207,6 +208,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Vairāk laika."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Mazāk laika."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Apgaismojums ir izslēgts."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Zibspuldze nav pieejama."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Apgaismojums ir ieslēgts."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Apgaismojums ir izslēgts."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Apgaismojums ir ieslēgts."</string>
@@ -302,10 +304,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Piespraust ekrānu"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"Meklēt"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Nevarēja palaist lietotni <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Lietotne <xliff:g id="APP">%s</xliff:g> ir atspējota drošajā režīmā."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Vēsture"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Notīrīt"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Šajā lietotnē netiek atbalstīts vairāku logu režīms."</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Lietotnē netiek atbalstīts vairāku logu režīms"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Horizontāls dalījums"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikāls dalījums"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Pielāgots dalījums"</string>
@@ -335,8 +338,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Pilnīgs\nklusums"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Tikai\nprioritārie"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Tikai\nsignāli"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Visi"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Visi\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Notiek uzlāde (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> līdz pilnīgai uzlādei)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Ātra uzlāde (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> līdz pilnīgai uzlādei)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Lēna uzlāde (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> līdz pilnīgai uzlādei)"</string>
@@ -449,39 +450,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Statusa joslā rādīt pulksteņa sekundes. Var ietekmēt akumulatora darbības laiku."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Pārkārtot ātros iestatījumus"</string>
<string name="show_brightness" msgid="6613930842805942519">"Rādīt spilgtumu ātrajos iestatījumos"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Iespējot ekrāna sadalīšanu, izmantojot vilkšanu augšup"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Iespējot vilkšanu augšup, lai sadalītu ekrānu"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Iespējot žestu ekrāna sadalīšanai, velkot augšup no pogas Pārskats"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimentāli"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Vai ieslēgt Bluetooth savienojumu?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Lai pievienotu tastatūru planšetdatoram, vispirms ir jāieslēdz Bluetooth savienojums."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Ieslēgt"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Lietot paziņojumiem “<xliff:g id="TOPIC_NAME">%1$s</xliff:g>”"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Lietot visiem šīs lietotnes paziņojumiem"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Rādīt paziņojumus bez skaņas signāla"</string>
+ <string name="block" msgid="2734508760962682611">"Bloķēt visus paziņojumus"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Neizslēgt skaņu"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Neizslēgt skaņu vai nebloķēt"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Rādīt ļoti svarīgu paziņojumu iestatījumus"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloķēts"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Minimāls svarīguma līmenis"</string>
<string name="low_importance" msgid="4109929986107147930">"Nav svarīgs"</string>
<string name="default_importance" msgid="8192107689995742653">"Parasts"</string>
<string name="high_importance" msgid="1527066195614050263">"Ļoti svarīgs"</string>
<string name="max_importance" msgid="5089005872719563894">"Steidzams"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Nekad nerādīt šos paziņojumus"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Rādīt paziņojumu saraksta apakšdaļā bez skaņas signāla"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Rādīt šos paziņojumus bez skaņas signāla"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Rādīt paziņojumu saraksta augšdaļā un ar skaņas signālu"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Rādīt ekrānā ar skaņas signālu"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Rādīt paziņojumu saraksta apakšdaļā bez skaņas signāla"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Rādīt šos paziņojumus bez skaņas signāla"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Atļaut skaņas signālu šiem paziņojumiem"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Rādīt ekrānā un atļaut skaņas signālu"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Rādīt paziņojumu saraksta augšdaļā, rādīt ekrānā ar skaņas signālu"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Citi iestatījumi"</string>
<string name="notification_done" msgid="5279426047273930175">"Gatavs"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Parastas krāsas"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Nakts krāsas"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Pielāgotas krāsas"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automātiski"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Nezināmas krāsas"</string>
- <string name="color_transform" msgid="6985460408079086090">"Krāsu pārveidošana"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Ātro iestatījumu elementa rādīšana"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Pielāgotās pārveidošanas iespējošana"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Krāsas un izskats"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Nakts režīms"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Ekrāna kalibrēšana"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Ieslēgts"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Izslēgts"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Ieslēgt automātiski"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Pārslēgt uz nakts režīmu atbilstoši atrašanās vietai un diennakts laikam"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Ja ir ieslēgts nakts režīms"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Izmantot tumšo motīvu operētājsistēmai Android"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Regulēt toni"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Regulēt spilgtumu"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Tumšais motīvs tiek lietots galvenajos operētājsistēmas Android elementos, kas parasti tiek rādīti ar gaišu motīvu, piemēram, lietotnē Iestatījumi."</string>
<string name="color_apply" msgid="9212602012641034283">"Lietot"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Iestatījumu apstiprināšana"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Noteiktu krāsu iestatījumu dēļ šī ierīce var kļūt nelietojama. Lai apstiprinātu šos krāsu iestatījumus, noklikšķiniet uz Labi. Ja to neizdarīsiet, pēc 10 sekundēm šie iestatījumi tiks atiestatīti."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Akumulatora lietojums"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Akumulatora jaudas taupīšanas režīms uzlādes laikā nav pieejams."</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Akumulatora jaudas taupīšanas režīms"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Samazina veiktspēju un fona datus."</string>
@@ -489,21 +498,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Sākums"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Pēdējie"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Atpakaļ"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Rādīt režīmu “Netraucēt” skaļuma regulēšanas dialoglodziņā"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Atļaujiet pilnu režīma “Netraucēt” kontroli skaļuma regulēšanas dialoglodziņā."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Skaļums un režīms “Netraucēt”"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Ieslēgt režīmu “Netraucēt”, samazinot skaļumu"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Rādīt ar skaļuma vadīklām"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Netraucēt"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Skaļuma pogu saīsne"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Izslēgt režīmu “Netraucēt”, palielinot skaļumu"</string>
<string name="battery" msgid="7498329822413202973">"Akumulators"</string>
<string name="clock" msgid="7416090374234785905">"Pulkstenis"</string>
<string name="headset" msgid="4534219457597457353">"Austiņas"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Austiņas ir pievienotas"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Austiņas ar mikrofonu ir pievienotas"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Iespējojiet vai atspējojiet ikonu rādīšanu statusa joslā."</string>
<string name="data_saver" msgid="5037565123367048522">"Datu lietojuma samazinātājs"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Datu lietojuma samazinātājs ieslēgts"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Datu lietojuma samazinātājs ir izslēgts."</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Ieslēgts"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Izslēgts"</string>
<string name="nav_bar" msgid="1993221402773877607">"Navigācijas josla"</string>
<string name="start" msgid="6873794757232879664">"Sākums"</string>
<string name="center" msgid="4327473927066010960">"Centrs"</string>
@@ -526,4 +534,21 @@
<string name="preview" msgid="9077832302472282938">"Priekšskatījums"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Velciet elementus, lai tos pievienotu"</string>
<string name="qs_edit" msgid="2232596095725105230">"Rediģēt"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Laiks"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Rādīt stundas, minūtes un sekundes"</item>
+ <item msgid="1427801730816895300">"Rādīt stundas un minūtes (noklusējums)"</item>
+ <item msgid="3830170141562534721">"Nerādīt šo ikonu"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Vienmēr rādīt procentuālo vērtību"</item>
+ <item msgid="2139628951880142927">"Rādīt procentuālo vērtību uzlādes laikā (noklusējums)"</item>
+ <item msgid="3327323682209964956">"Nerādīt šo ikonu"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Citi"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Ekrāna sadalītājs"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Pārvietot uz leju"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Pārvietot uz augšu"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Pārvietot pa kreisi"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Pārvietot pa labi"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index 8051ec0..58b7b75 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Сликата на екранот е снимена."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Допрете за да ја видите сликата на екранот."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Сликата на екранот не можеше да се сними."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Не може да направи слика на екран поради огран. простор или не дозволува аплика. или организацијата."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Сликата од екранот не може да се зачува поради ограничена меморија."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Апликацијата или вашата организација не дозволува создавање слики од екранот."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Пренос на датотека со УСБ"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Монтирај како мултимедијален плеер (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Монтирај како фотоапарат (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Повеќе време."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Помалку време."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Блицот е исклучен."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Светилката е недостапна."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Блицот е вклучен."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Блицот е исклучен."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Блицот е вклучен."</string>
@@ -304,6 +306,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> е оневозможен во безбеден режим."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Историја"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Исчисти"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Апликацијава не поддржува повеќе прозорци"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Апликацијата не поддржува повеќе прозорци"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Раздели хоризонтално"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Раздели вертикално"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Раздели прилагодено"</string>
@@ -333,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Целосна\nтишина"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Само\nприоритетни"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Само\nаларми"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Сѐ"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Сите\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Бавно полнење (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> додека не се наполни)"</string>
@@ -447,34 +449,43 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Прикажи ги секундите на часовникот на статусната лента. Може да влијае на траењето на батеријата."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Преуредете ги Брзи поставки"</string>
<string name="show_brightness" msgid="6613930842805942519">"Прикажете ја осветленоста во Брзи поставки"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Овозможете забрзувач за повлекување нагоре поделен екран"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Овозможи го гестот повлекување нагоре за поделен екран"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Овозможете гест за отворање поделен екран со повлекување нагоре од копчето Краток преглед"</string>
<string name="experimental" msgid="6198182315536726162">"Експериментално"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Да се вклучи Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"За да ја поврзете тастатурата со таблетот, најпрво треба да вклучите Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Вклучи"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Важи за известувањата за <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Важи за сите известувања од оваа апликација"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Тивко прикажувај ги известувањата"</string>
+ <string name="block" msgid="2734508760962682611">"Блокирај ги сите известувања"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Не стишувај"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Не стишувај или блокирај"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Прикажи ги поставките со целосна важност"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Блокирано"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Минимална важност"</string>
<string name="low_importance" msgid="4109929986107147930">"Мала важност"</string>
<string name="default_importance" msgid="8192107689995742653">"Нормална важност"</string>
<string name="high_importance" msgid="1527066195614050263">"Голема важност"</string>
<string name="max_importance" msgid="5089005872719563894">"Итна важност"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Никогаш не ги прикажувај известувањава"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Тивко прикажувај ги на дното на списокот со известувања"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Тивко прикажувај ги известувањава"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Прикажувај ги на врвот на списокот со известувања и дај звучен сигнал"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Појави се на екранот и дај звучен сигнал"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Тивко прикажувај ги на дното на списокот со известувања"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Тивко прикажувај ги известувањава"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Овозможи им на известувањава да прават звуци"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Ѕиркање на екранот и овозможен звук и овозможен звук"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Прикажувај ги на врвот на списокот со известувања, ѕиркање на екранот и овозможи звук"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Повеќе поставки"</string>
<string name="notification_done" msgid="5279426047273930175">"Готово"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Нормални бои"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Ноќни бои"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Приспособени бои"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Автоматски"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Непознати бои"</string>
- <string name="color_transform" msgid="6985460408079086090">"Промена на бојата"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Прикажи плочка Брзи поставки"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Овозможи приспособено трансформирање"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Боја и изглед"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Ноќен режим"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Калибрирај го екранот"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Вклучено"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Исклучено"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Вклучи автоматски"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Префрли во Ноќен режим како што е соодветно за локацијата и времето во денот"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Кога Ноќниот режим е вклучен"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Користете ја темната тема за ОС Android"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Приспособи ја бојата"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Приспособи ја осветленоста"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Темната тема се применува на основните области на Android OS што обично се прикажуваат во светла тема, како Поставки."</string>
<string name="color_apply" msgid="9212602012641034283">"Примени"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Потврдете ги поставките"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Некои поставки на боите може да го направат уредот неупотреблив. Кликнете на Во ред за да ги потврдите овие поставки на боите, инаку тие поставки ќе се ресетираат по 10 секунди."</string>
@@ -486,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Почетна страница"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Неодамнешни"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Назад"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Прикажи „Не вознемирувај“ во јачината на звукот"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Дозволете целосна контрола на „Не вознемирувај“ во дијалогот за јачина на звукот."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Јачина на звук и „Не вознемирувај“"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Премини во „Не вознемирувај“ при намалена јачина на звукот"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Прикажи со контроли за јачина на звук"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Не вознемирувај"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Кратенка за копчињата за јачина на звук"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Излези од „Не вознемирувај“ при зголемена јачина на звукот"</string>
<string name="battery" msgid="7498329822413202973">"Батерија"</string>
<string name="clock" msgid="7416090374234785905">"Часовник"</string>
<string name="headset" msgid="4534219457597457353">"Слушалки"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Слушалките се поврзани"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Слушалките се поврзани"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Овозможете или оневозможете прикажување на иконите во статусната лента."</string>
<string name="data_saver" msgid="5037565123367048522">"Штедач на интернет"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Штедачот на интернет е вклучен"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Штедачот на интернет е исклучен"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Вклучено"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Исклучено"</string>
<string name="nav_bar" msgid="1993221402773877607">"Лента за навигација"</string>
<string name="start" msgid="6873794757232879664">"Почеток"</string>
<string name="center" msgid="4327473927066010960">"Центар"</string>
@@ -523,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Преглед"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Повлечете за додавање плочки"</string>
<string name="qs_edit" msgid="2232596095725105230">"Уреди"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Време"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Прикажи часови, минути и секунди"</item>
+ <item msgid="1427801730816895300">"Прикажи часови и минути (стандардно)"</item>
+ <item msgid="3830170141562534721">"Не прикажувај ја иконава"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Секогаш прикажувај процент"</item>
+ <item msgid="2139628951880142927">"Прикажи процент кога се полни (стандардно)"</item>
+ <item msgid="3327323682209964956">"Не прикажувај ја иконава"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Друго"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Разделник на поделен екран"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Преместете надолу"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Преместете нагоре"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Преместете налево"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Преместете надесно"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index 4cb8c2e..6627645 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"സ്ക്രീൻഷോട്ട് എടുത്തു."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"നിങ്ങളുടെ സ്ക്രീൻഷോട്ട് കാണാനായി സ്പർശിക്കുക."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"സ്ക്രീൻഷോട്ട് എടുക്കാൻ കഴിഞ്ഞില്ല."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"സംഭരണ ഇടം പരിമിതമായതിനാൽ സ്ക്രീൻഷോട്ട് എടുക്കാനാകില്ല, അല്ലെങ്കിൽ ഇത് അപ്ലിക്കേഷനോ നിങ്ങളുടെ ഓർഗനൈസേഷനോ അനുവദിക്കുന്നില്ല."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"സ്റ്റോറേജ് ഇടം പരിമിതമായതിനാൽ സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കാൻ കഴിയില്ല."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"സ്ക്രീൻഷോട്ടുകൾ എടുക്കുന്നത് ആപ്പോ നിങ്ങളുടെ സ്ഥാപനമോ അനുവദിക്കുന്നില്ല."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB ഫയൽ കൈമാറൽ ഓപ്ഷനുകൾ"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"ഒരു മീഡിയ പ്ലേയറായി (MTP) മൗണ്ടുചെയ്യുക"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"ഒരു ക്യാമറയായി (PTP) മൗണ്ടുചെയ്യുക"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"കൂടുതൽ സമയം."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"സമയം കുറയ്ക്കുക."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ടോർച്ച് ഓഫാണ്."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ടോർച്ച് ലഭ്യമല്ല."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ടോർച്ച് ഓണാണ്."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ടോർച്ച് ഓഫാക്കി."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ടോർച്ച് ഓണാക്കി."</string>
@@ -304,6 +306,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"സുരക്ഷിത മോഡിൽ <xliff:g id="APP">%s</xliff:g> പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"ചരിത്രം"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"മായ്ക്കുക"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"ഒന്നിലധികം വിൻഡോകളെ ഈ ആപ്പ് പിന്തുണയ്ക്കുന്നില്ല"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"ഒന്നിലധികം വിൻഡോകളെ ആപ്പ് പിന്തുണയ്ക്കുന്നില്ല"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"തിരശ്ചീനമായി വേർതിരിക്കുക"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ലംബമായി വേർതിരിക്കുക"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ഇഷ്ടാനുസൃതമായി വേർതിരിക്കുക"</string>
@@ -333,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"പൂർണ്ണ\nനിശബ്ദത"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"മുൻഗണന\nമാത്രം"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"അലാറങ്ങൾ\nമാത്രം"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"എല്ലാം"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"എല്ലാം\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"പതുക്കെ ചാർജുചെയ്യുന്നു (പൂർണ്ണമാകാൻ <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
@@ -447,34 +449,43 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"സ്റ്റാറ്റസ് ബാറിൽ ക്ലോക്ക് സെക്കൻഡ് കാണിക്കുന്നത് ബാറ്ററിയുടെ ലൈഫിനെ ബാധിക്കാം."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"ദ്രുത ക്രമീകരണം പുനഃസജ്ജീകരിക്കുക"</string>
<string name="show_brightness" msgid="6613930842805942519">"ദ്രുത ക്രമീകരണത്തിൽ തെളിച്ചം കാണിക്കുക"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"സ്പ്ലിറ്റ്-സ്ക്രീൻ സ്വൈപ്പ്-അപ്പ് ആക്സിലറേറ്റർ പ്രവർത്തനക്ഷമമാക്കൂ"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"സ്പ്ലിറ്റ്-സ്ക്രീൻ സ്വൈപ്പ്-അപ്പ് ജെസ്റ്റർ പ്രവർത്തനക്ഷമമാക്കുക"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"ചുരുക്കവിവരണ ബട്ടണിൽ നിന്ന് മുകളിലേക്ക് സ്വൈപ്പുചെയ്തുകൊണ്ട് സ്പ്ലിറ്റ്-സ്ക്രീനിലേക്ക് പ്രവേശിക്കാൻ ജെസ്റ്റർ പ്രവർത്തനക്ഷമമാക്കുക"</string>
<string name="experimental" msgid="6198182315536726162">"പരീക്ഷണാത്മകം!"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth ഓണാക്കണോ?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"നിങ്ങളുടെ ടാബ്ലെറ്റുമായി കീബോർഡ് കണക്റ്റുചെയ്യുന്നതിന്, ആദ്യം Bluetooth ഓണാക്കേണ്ടതുണ്ട്."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"ഓണാക്കുക"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> അറിയിപ്പുകളിലേക്ക് പ്രയോഗിക്കുക"</string>
- <string name="apply_to_app" msgid="363016783939815960">"ഈ ആപ്പിൽ നിന്നുള്ള എല്ലാ അറിയിപ്പുകളിലേക്കും പ്രയോഗിക്കുക"</string>
+ <string name="show_silently" msgid="6841966539811264192">"അറിയിപ്പുകൾ നിശ്ശബ്ദമായി കാണിക്കുക"</string>
+ <string name="block" msgid="2734508760962682611">"എല്ലാ അറിയിപ്പുകളും ബ്ലോക്കുചെയ്യുക"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"നിശബ്ദമാക്കരുത്"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"നിശബ്ദമാക്കുകയോ ബ്ലോക്കുചെയ്യുകയോ അരുത്"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"പൂർണ്ണ പ്രാധാന്യ ക്രമീകരണം കാണിക്കുക"</string>
<string name="blocked_importance" msgid="5198578988978234161">"ബ്ലോക്കുചെയ്തു"</string>
+ <string name="min_importance" msgid="1901894910809414782">"കുറഞ്ഞ പ്രാധാന്യം"</string>
<string name="low_importance" msgid="4109929986107147930">"താഴ്ന്ന പ്രാധാന്യം"</string>
<string name="default_importance" msgid="8192107689995742653">"സാധാരണ പ്രാധാന്യം"</string>
<string name="high_importance" msgid="1527066195614050263">"ഉയർന്ന പ്രാധാന്യം"</string>
<string name="max_importance" msgid="5089005872719563894">"അടിയന്തര പ്രാധാന്യം"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"ഈ അറിയിപ്പുകൾ ഒരിക്കലും കാണിക്കരുത്"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"അറിയിപ്പ് ലിസ്റ്റിന്റെ താഴെ ശബ്ദമുണ്ടാക്കാതെ കാണിക്കുക"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"ഈ അറിയിപ്പുകൾ നിശബ്ദമായി കാണിക്കുക"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"അറിയിപ്പ് ലിസ്റ്റിന്റെ ഏറ്റവും മുകളിൽ കാണിക്കുക, ശബ്ദമുണ്ടാക്കുക"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"സ്ക്രീനിൽ ദൃശ്യമാക്കുക, ശബ്ദമുണ്ടാക്കുക"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"അറിയിപ്പ് ലിസ്റ്റിന്റെ താഴെ ശബ്ദമുണ്ടാക്കാതെ കാണിക്കുക"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"ഈ അറിയിപ്പുകൾ നിശബ്ദമായി കാണിക്കുക"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"ശബ്ദമുണ്ടാക്കാൻ ഈ അറിയിപ്പുകളെ അനുവദിക്കുക"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"സ്ക്രീനിൽ ദൃശ്യമാക്കുക, ശബ്ദമുണ്ടാക്കുക"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"അറിയിപ്പ് ലിസ്റ്റിന്റെ ഏറ്റവും മുകളിൽ കാണിക്കുക, ശബ്ദമുണ്ടാക്കുക"</string>
<string name="notification_more_settings" msgid="816306283396553571">"കൂടുതൽ ക്രമീകരണം"</string>
<string name="notification_done" msgid="5279426047273930175">"പൂർത്തിയായി"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"സാധാരണ വര്ണ്ണങ്ങൾ"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"രാത്രി വര്ണ്ണങ്ങൾ"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"ഇഷ്ടാനുസൃത വര്ണ്ണങ്ങൾ"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"യാന്ത്രികം"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"തിരിച്ചറിയാനാകാത്ത വർണ്ണങ്ങൾ"</string>
- <string name="color_transform" msgid="6985460408079086090">"വർണ്ണ പരിഷ്കരണം"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"ദ്രുത ക്രമീകരണ ടൈൽ കാണിക്കുക"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"ഇഷ്ടാനുസൃത പരിവർത്തനം പ്രവർത്തനക്ഷമമാക്കുക"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"വർണ്ണവും രൂപഭാവവും"</string>
+ <string name="night_mode" msgid="3540405868248625488">"നൈറ്റ് മോഡ്"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"ഡിസ്പ്ലേ കാലിബ്രേറ്റുചെയ്യുക"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"ഓൺ"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"ഓഫ്"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"സ്വയമേവ ഓണാക്കുക"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"ലൊക്കേഷനും ദിവസത്തിലെ സമയത്തിനും അനുയോജ്യമായ തരത്തിൽ നൈറ്റ് മോഡിലേക്ക് സ്വിച്ചുചെയ്യുക"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"നൈറ്റ് മോഡ് ഓണായിരിക്കുമ്പോൾ"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Android OS-നുള്ള ഇരുണ്ട തീം ഉപയോഗിക്കുക"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"ടിന്റ് ക്രമപ്പെടുത്തുക"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"തെളിച്ചം ക്രമപ്പെടുത്തുക"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"ക്രമീകരണം പോലെയുള്ള, ഒരു ലൈറ്റ് തീമിൽ സാധാരണ ഗതിയിൽ പ്രദർശിപ്പിക്കപ്പെടുന്ന Android OS-ന്റെ അടിസ്ഥാന ഇടങ്ങളിലേക്ക്, ഇരുണ്ട തീം പ്രയോഗിക്കുന്നു."</string>
<string name="color_apply" msgid="9212602012641034283">"ബാധകമാക്കുക"</string>
<string name="color_revert_title" msgid="4746666545480534663">"ക്രമീകരണം സ്ഥിരീകരിക്കുക"</string>
<string name="color_revert_message" msgid="9116001069397996691">"ചില വർണ്ണ ക്രമീകരണത്തിന് ഈ ഉപകരണത്തെ ഉപയോഗരഹിതമാക്കാനാകും. ഈ വർണ്ണ ക്രമീകരണം സ്ഥിരീകരിക്കുന്നതിന് ശരി എന്നതിൽ ക്ലിക്കുചെയ്യുക, അല്ലെങ്കിൽ 10 സെക്കൻഡിന് ശേഷം ഈ ക്രമീകരണം പുനഃക്രമീകരിക്കപ്പെടും."</string>
@@ -486,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"വീട്"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"പുതിയവ"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"മടങ്ങുക"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"വോളിയത്തിൽ \'ശല്യപ്പെടുത്തരുത്\' കാണിക്കുക"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"വോളിയം ഡയലോഗിൽ \'ശല്യപ്പെടുത്തരുത്\' എന്നത് പൂർണ്ണമായി നിയന്ത്രിക്കാൻ അനുവദിക്കുക."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"വോളിയവും \'ശല്യപ്പെടുത്തരുത്\' എന്നതും"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"വോളിയം താഴുമ്പോൾ \'ശല്യപ്പെടുത്തരുത്\' പ്രവർത്തിപ്പിക്കുക"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"വോളിയം നിയന്ത്രണങ്ങളോടൊപ്പം കാണിക്കുക"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"ശല്യപ്പെടുത്തരുത്"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"വോളിയം ബട്ടൺ കുറുക്കുവഴി"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"വോളിയം ഉയരുമ്പോൾ \'ശല്യപ്പെടുത്തരുത്\' നിർത്തുക"</string>
<string name="battery" msgid="7498329822413202973">"ബാറ്ററി"</string>
<string name="clock" msgid="7416090374234785905">"ക്ലോക്ക്"</string>
<string name="headset" msgid="4534219457597457353">"ഹെഡ്സെറ്റ്"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ഹെഡ്ഫോണുകൾ കണക്റ്റുചെയ്തു"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ഹെഡ്സെറ്റ് കണക്റ്റുചെയ്തു"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"സ്റ്റാറ്റസ് ബാറിൽ കാണിക്കുന്നതിൽ നിന്ന് ഐക്കണുകളെ പ്രവർത്തനക്ഷമമാക്കുകയോ പ്രവർത്തനരഹിതമാക്കുകയോ ചെയ്യുക"</string>
<string name="data_saver" msgid="5037565123367048522">"ഡാറ്റ സേവർ"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"ഡാറ്റാ സേവർ ഓണാണ്"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"ഡാറ്റാ സേവർ ഓഫാണ്"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"ഓൺ"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"ഓഫ്"</string>
<string name="nav_bar" msgid="1993221402773877607">"നാവിഗേഷൻ ബാർ"</string>
<string name="start" msgid="6873794757232879664">"ആരംഭിക്കൂ"</string>
<string name="center" msgid="4327473927066010960">"മധ്യം"</string>
@@ -523,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"പ്രിവ്യു നടത്തുക"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"ടൈലുകൾ ചേർക്കുന്നതിന് വലിച്ചിടുക"</string>
<string name="qs_edit" msgid="2232596095725105230">"എഡിറ്റുചെയ്യുക"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"സമയം"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"മണിക്കൂറും മിനിറ്റും സെക്കൻഡും കാണിക്കുക"</item>
+ <item msgid="1427801730816895300">"മണിക്കൂറും മിനിറ്റും കാണിക്കുക (ഡിഫോൾട്ട്)"</item>
+ <item msgid="3830170141562534721">"ഈ ഐക്കൺ കാണിക്കരുത്"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"എല്ലായ്പ്പോഴും ശതമാനം കാണിക്കുക"</item>
+ <item msgid="2139628951880142927">"ചാർജ്ജുചെയ്യുമ്പോൾ ശതമാനം കാണിക്കുക (ഡിഫോൾട്ട്)"</item>
+ <item msgid="3327323682209964956">"ഈ ഐക്കൺ കാണിക്കരുത്"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"മറ്റുള്ളവ"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"സ്പ്ലിറ്റ്-സ്ക്രീൻ ഡിവൈഡർ"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"താഴേക്ക് നീക്കുക"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"മുകളിലേക്ക് നീക്കുക"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"ഇടത്തേക്ക് നീക്കുക"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"വലത്തേക്ക് നീക്കുക"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index f22e315..a69be1f 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -71,7 +71,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Дэлгэцийн агшинг авсан."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Дэлгэцийн агшныг харах бол хүрнэ үү."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Дэлгэцийн агшинг авч чадсангүй."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Хадгалах сан хязгаартай эсхүл таны байгууллага буюу апп-с зөвшөөрөөгүй учир дэлгэцийн зургийг авах боломжгүй."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Хадгалах сангийн багтаамж бага байгаа тул дэлгэцийн авсан зургийг хадгалах боломжгүй байна."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Дэлгэцийн зураг авахыг апп эсвэл танай байгууллагаас зөвшөөрөөгүй байна."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB файл шилжүүлэх сонголт"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Медиа тоглуулагч(MTP) болгон залгах"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Камер болгон(PTP) залгах"</string>
@@ -204,6 +205,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Хугацаа нэмэх."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Хугацаа хасах."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Флаш гэрэл унтарсан."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Гэрэлтүүлэгч боломжгүй байна."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Флаш гэрэл ассан."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Флаш гэрлийг унтраасан."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Флаш гэрлийг асаасан."</string>
@@ -299,10 +301,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"дэлгэц тогтоох"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"хайх"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>-г эхлүүлж чадсангүй."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g>-г аюулгүй горимд идэвхгүй болгосон."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Түүх"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Устгах"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Энэ апп олон цонхыг дэмждэггүй"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Апп олон цонхыг дэмждэггүй"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Хэвтээ чиглэлд хуваах"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Босоо чиглэлд хуваах"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Хүссэн хэлбэрээр хуваах"</string>
@@ -332,8 +335,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Дуугүй\nболгох"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Зөвхөн\nхамгийн чухлыг"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Зөвхөн\nсэрүүлэг"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Бүгд"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Бүх\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Цэнэглэж байна (дүүргэхэд <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> шаардлагатай)"</string>
@@ -446,39 +447,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Статус талбарт цагийн секундыг харуулах. Энэ нь тэжээлийн цэнэгт нөлөөлж болно."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Түргэн тохиргоог дахин засварлах"</string>
<string name="show_brightness" msgid="6613930842805942519">"Түргэн тохиргоонд гэрэлтүүлэг харах"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Дэлгэц хуваах дээш шудрах хурдасгуурыг идэвхжүүлэх"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Дэлгэц хуваах дээш шудрах дохиог идэвхжүүлэх"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Тойм товчлуурыг дээш шударч, хуваагдсан дэлгэцэд зангаагаар орох тохиргоог идэвхжүүлэх"</string>
<string name="experimental" msgid="6198182315536726162">"Туршилтын"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth-г асаах уу?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Компьютерийн гараа таблетад холбохын тулд эхлээд Bluetooth-г асаана уу."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Асаах"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> мэдэгдэлд хэрэгжүүлэх"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Энэ апп-н бүх мэдэгдэлд хэрэгжүүлэх"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Мэдэгдлийг чимээгүй харуулах"</string>
+ <string name="block" msgid="2734508760962682611">"Бүх мэдэгдлийг блоклох"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Дуугүй болгох хэрэггүй"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Дууг нь хаах эсвэл блоклох хэрэггүй"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Бүрэн ач холбогдлын тохиргоог харуулах"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Блоклосон"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Хамгийн бага ач холбогдол"</string>
<string name="low_importance" msgid="4109929986107147930">"Бага ач холбогдолтой"</string>
<string name="default_importance" msgid="8192107689995742653">"Энгийн ач холбогдолтой"</string>
<string name="high_importance" msgid="1527066195614050263">"Өндөр ач холбогдолтой"</string>
<string name="max_importance" msgid="5089005872719563894">"Яаралтай ач холбогдолтой"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Эдгээр мэдэгдлийг хэзээ ч харуулахгүй"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Мэдэгдлийг жагсаалтын доод хэсэгт дуугүй харуулах"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Эдгээр мэдэгдлийг дуугүй харуулах"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Мэдэгдлийг жагсаалтын эхэнд дуутай харуулах"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Дэлгэцэнд яаралтайгаар дуутай гаргах"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Мэдэгдлийг жагсаалтын доод хэсэгт дуугүй харуулах"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Эдгээр мэдэгдлийг дуугүй харуулах"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Эдгээр мэдэгдлийг дуу гаргахыг зөвшөөрөх"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Дэлгэцэд яаралтайгаар дуутай гаргах"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Мэдэгдлийг жагсаалтын эхэнд яаралтай дуутай харуулах"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Бусад тохиргоо"</string>
<string name="notification_done" msgid="5279426047273930175">"Дууссан"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Хэвийн өнгө"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Шөнийн өнгө"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Өгөгдмөл өнгө"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Автомат"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Үл мэдэгдэх өнгө"</string>
- <string name="color_transform" msgid="6985460408079086090">"Өнгөний өөрчлөлт"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Түргэн тохиргооны хэсгийг харуулах"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Өгөгдмөл өөрчлөлтийг идэвхжүүлэх"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Өнгө, харагдах байдал"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Шөнийн горим"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Дэлгэцийг тохируулах"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Идэвхтэй"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Идэвхгүй"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Автоматаар асаах"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Тухайн өдрийн байршил, цагийн тохиромжтой үед Шөнийн горимд шилжүүлэх"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Шөнийн горим идэвхтэй үед"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Android-н үйлдлийн системд бараан загварыг ашиглах"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Өнгөний нягтаршилыг тохируулах"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Гэрэлтүүлгийг тохируулах"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Тохиргоо зэрэг тогтмол цайвар загварт харуулдаг Android үйлдлийн системийн гол хэсгийг бараан загварт харуулна."</string>
<string name="color_apply" msgid="9212602012641034283">"Хэрэгжүүлэх"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Тохиргоог баталгаажуулах"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Зарим өнгөний тохиргоо энэ төхөөрөмжийг ашиглах боломжгүй болгож болзошгүй. OK товчлуурыг дарж эдгээр өнгөний тохиргоог зөвшөөрөхгүй бол энэ тохиргоо нь 10 секундын дараа шинэчлэгдэх болно."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Тэжээл ашиглалт"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Цэнэглэх үед тэжээл хэмнэгч ажиллахгүй"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Тэжээл хэмнэгч"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Гүйцэтгэл болон дэвсгэрийн датаг багасгадаг"</string>
@@ -486,21 +495,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Нүүр хуудас"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Саяхны"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Буцах"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Бүү саад бол тохиргоог дууны түвшинд харуулах"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Бүү саад бол тохиргооны бүрэн хяналтыг дууны түвшний харилцах цонхонд зөвшөөрнө үү."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Дууны түвшин болон бүү саад бол тохиргоо"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Бүү саад бол тохиргоог оруулахын тулд дууны түвшинг бууруулах"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Түвшний хяналттай харуулах"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Бүү саад бол"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Түвшний товчлуурын товчлол"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Бүү саад бол тохиргооноос гарахын тулд дууны түвшинг нэмэх"</string>
<string name="battery" msgid="7498329822413202973">"Зай"</string>
<string name="clock" msgid="7416090374234785905">"Цаг"</string>
<string name="headset" msgid="4534219457597457353">"Чихэвч"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Чихэвч холбогдсон"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Чихэвч холбогдсон"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Статусын самбарт харагдах дүрс тэмдгийг идэвхжүүлэх эсвэл идэвхгүй болгоно уу."</string>
<string name="data_saver" msgid="5037565123367048522">"Өгөгдөл хамгаалагч"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Өгөгдөл хамгаалагчийг асаасан байна"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Өгөгдөл хамгаалагчийг унтраасан байна"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Идэвхтэй"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Идэвхгүй"</string>
<string name="nav_bar" msgid="1993221402773877607">"Навигацийн самбар"</string>
<string name="start" msgid="6873794757232879664">"Эхлэх"</string>
<string name="center" msgid="4327473927066010960">"Гол хэсэг"</string>
@@ -523,4 +531,21 @@
<string name="preview" msgid="9077832302472282938">"Урьдчилж харах"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Дөрвөлж нэмэхийн тулд чирнэ үү"</string>
<string name="qs_edit" msgid="2232596095725105230">"Засах"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Цаг"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Цаг, минут, секундийг харуулах"</item>
+ <item msgid="1427801730816895300">"Цаг, минутыг харуулах (өгөгдмөл)"</item>
+ <item msgid="3830170141562534721">"Энэ дүрс тэмдгийг бүү үзүүл"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Хувийг тогтмол харуулах"</item>
+ <item msgid="2139628951880142927">"Цэнэглэх үед хувийг тогтмол харуулах (өгөгдмөл)"</item>
+ <item msgid="3327323682209964956">"Энэ дүрс тэмдгийг бүү үзүүл"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Бусад"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"\"Дэлгэц хуваах\" хуваагч"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Доош зөөх"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Дээш зөөх"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Зүүн тийш зөөх"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Баруун тийш зөөх"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index ff36be2..d99678c 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"स्क्रीनशॉट कॅप्चर केला."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"आपला स्क्रीनशॉट पाहण्यासाठी स्पर्श करा."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"स्क्रीनशॉट कॅप्चर करू शकलो नाही."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"मर्यादित संचयन स्थानामुळे किंवा अॅपद्वारे किंवा आपल्या संस्थेद्वारे त्याची अनुमती नसल्यामुळे स्क्रीनशॉट घेऊ शकत नाही."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"मर्यादित संचय जागेमुळे स्क्रीनशॉट जतन करू शकत नाही."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"अॅप किंवा आपल्या संस्थेद्वारे स्क्रीनशॉट घेण्यास अनुमती नाही."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB फाईल स्थानांतरण पर्याय"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"मीडिया प्लेअर म्हणून माउंट करा (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"कॅमेरा म्हणून माउंट करा (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"अधिक वेळ."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"कमी वेळ."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"फ्लॅशलाइट बंद."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"फ्लॅशलाइट अनुपलब्ध आहे."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"फ्लॅशलाइट चालू."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"फ्लॅशलाइट बंद केला."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"फ्लॅशलाइट चालू केला."</string>
@@ -304,6 +306,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> सुरक्षित-मोडमध्ये अक्षम केला आहे."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"इतिहास"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"साफ करा"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"हा अॅप एकाधिक-विंडोला समर्थन देत नाही"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"अॅप एकाधिक-विंडोला समर्थन देत नाही"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"क्षैतिज विभाजित करा"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"अनुलंब विभाजित करा"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"सानुकूल विभाजित करा"</string>
@@ -333,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"संपूर्ण\nशांतता"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"केवळ\nप्राधान्य"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"केवळ\nअलार्म"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"सर्व"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"सर्व\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"(<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> पूर्ण होईपर्यंत) हळूहळू चार्ज होत आहे"</string>
@@ -447,34 +449,43 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"स्टेटस बारमध्ये घड्याळ सेकंद दर्शवा. कदाचित बॅटरी आयुष्य प्रभावित होऊ शकते."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"द्रुत सेटिंग्जची पुनर्रचना करा"</string>
<string name="show_brightness" msgid="6613930842805942519">"द्रुत सेटिंग्जमध्ये चमक दर्शवा"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"विभाजित-स्क्रीन स्वाइप-अप त्वरक सक्षम करा"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"विभाजित-स्क्रीन स्वाइप-अप जेश्चर सक्षम करा"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"विहंगावलोकन बटणावरून वर स्वाइप करून विभाजित-स्क्रीन प्रविष्ट करण्यासाठी जेश्चर सक्षम करा"</string>
<string name="experimental" msgid="6198182315536726162">"प्रायोगिक"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"ब्लूटुथ सुरू करायचे?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"आपला कीबोर्ड आपल्या टॅब्लेटसह कनेक्ट करण्यासाठी, आपल्याला प्रथम ब्लूटुथ चालू करणे आवश्यक आहे."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"चालू करा"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> सूचनांवर लागू करा"</string>
- <string name="apply_to_app" msgid="363016783939815960">"या अॅपमधील सर्व सूचनांवर लागू करा"</string>
+ <string name="show_silently" msgid="6841966539811264192">"सूचना शांतपणे दर्शवा"</string>
+ <string name="block" msgid="2734508760962682611">"सर्व सूचना अवरोधित करा"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"शांत करू नका"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"शांत किंवा अवरोधित करू नका"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"पूर्ण महत्त्व सेटिंग्ज दर्शवा"</string>
<string name="blocked_importance" msgid="5198578988978234161">"अवरोधित केले"</string>
+ <string name="min_importance" msgid="1901894910809414782">"किमान महत्त्व"</string>
<string name="low_importance" msgid="4109929986107147930">"कमी महत्त्व"</string>
<string name="default_importance" msgid="8192107689995742653">"सामान्य महत्त्व"</string>
<string name="high_importance" msgid="1527066195614050263">"सर्वाधिक महत्व"</string>
<string name="max_importance" msgid="5089005872719563894">"त्वरित महत्त्व"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"या सूचना कधीही दर्शवू नका"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"सूचना सूचीच्या तळाशी शांतपणे दर्शवा"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"या सूचना शांतपणे दर्शवा"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"सूचना सूचीच्या शीर्षस्थानी दर्शवा आणि ध्वनी चालू करा"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"स्क्रीनवर डोकावून पहा आणि ध्वनी चालू करा"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"सूचना सूचीच्या तळाशी शांतपणे दर्शवा"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"या सूचना शांतपणे दर्शवा"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"या सूचनांना ध्वनी चालू करण्याची अनुमती द्या"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"स्क्रीनवर पहा आणि ध्वनीस अनुमती द्या ध्वनीस अनुमती द्या"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"सूचनांच्या शीर्षस्थानी दर्शवा, स्क्रीनवर पहा आणि ध्वनीस अनुमती द्या"</string>
<string name="notification_more_settings" msgid="816306283396553571">"अधिक सेटिंग्ज"</string>
<string name="notification_done" msgid="5279426047273930175">"पूर्ण झाले"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"सामान्य रंग"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"रात्रीचे रंग"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"सानुकूल रंग"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"स्वयं"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"अज्ञात रंग"</string>
- <string name="color_transform" msgid="6985460408079086090">"रंग सुधारणा"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"द्रुत सेटिंग्ज टाइल दर्शवा"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"सानुकूल रूपांतरण सक्षम करा"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"रंग आणि स्वरूप"</string>
+ <string name="night_mode" msgid="3540405868248625488">"रात्र मोड"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"प्रदर्शनाचे मापन करा"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"चालू"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"बंद"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"स्वयंचलितपणे चालू करा"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"स्थान आणि दिवसाच्या वेळेसाठी योग्य असल्यानुसार रात्र मोड मध्ये स्विच करा"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"रात्र मोड चालू असताना"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Android OS साठी गडद थीमचा वापर करा"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"रंगाची छटा समायोजित करा"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"चकाकी समायोजित करा"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"सेटिंग्ज सारख्या प्रकाश थीममध्ये प्रदर्शित केल्या जाणाऱ्या Android OS च्या मुख्य क्षेत्रांवर गडद थीम लागू केली जाते."</string>
<string name="color_apply" msgid="9212602012641034283">"लागू करा"</string>
<string name="color_revert_title" msgid="4746666545480534663">"सेटिंग्जची पुष्टी करा"</string>
<string name="color_revert_message" msgid="9116001069397996691">"काही रंग सेटिंग्ज या डिव्हाइसला निरुपयोगी करू शकतात. या रंग सेटिंग्जची पुष्टी करण्यासाठी ठीक आहे दाबा अन्यथा या सेटिंग्ज 10 सेकंदांनंतर रीसेट होतील."</string>
@@ -486,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"मुख्यपृष्ठ"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"अलीकडील"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"परत"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"आवाजामध्ये व्यत्यय आणू नका दर्शवा"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"आवाज संवादामधील व्यत्यय आणू नका च्या पूर्ण नियंत्रणास अनुमती द्या."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"आवाज आणि व्यत्यय आणू नका"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"आवाज कमी केल्यावर व्यत्यय आणू नका प्रविष्ट करा"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"आवाज नियंत्रणांसह दर्शवा"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"व्यत्यय आणू नका"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"आवाजाच्या बटणांचा शार्टकट"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"आवाज वाढविल्यावर व्यत्यय आणू नका मधून बाहेर पडा"</string>
<string name="battery" msgid="7498329822413202973">"बॅटरी"</string>
<string name="clock" msgid="7416090374234785905">"घड्याळ"</string>
<string name="headset" msgid="4534219457597457353">"हेडसेट"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"हेडफोन कनेक्ट केले"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"हेडसेट कनेक्ट केला"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"चिन्हे स्टेटस बारमध्ये दर्शविले जाण्यापासून प्रतिबंधित करण्यासाठी ती सक्षम किंवा अक्षम करा."</string>
<string name="data_saver" msgid="5037565123367048522">"डेटा बचतकर्ता"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"डेटा बचतकर्ता चालू आहे"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"डेटा बचतकर्ता बंद आहे"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"चालू"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"बंद"</string>
<string name="nav_bar" msgid="1993221402773877607">"नॅव्हिगेशन बार"</string>
<string name="start" msgid="6873794757232879664">"प्रारंभ"</string>
<string name="center" msgid="4327473927066010960">"मध्यवर्ती"</string>
@@ -523,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"पूर्वावलोकन"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"टाइल जोडण्यासाठी ड्रॅग करा"</string>
<string name="qs_edit" msgid="2232596095725105230">"संपादित करा"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"वेळ"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"तास, मिनिटे आणि सेकंद दर्शवा"</item>
+ <item msgid="1427801730816895300">"तास आणि मिनिटे दर्शवा (डीफॉल्ट)"</item>
+ <item msgid="3830170141562534721">"हे चिन्ह दर्शवू नका"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"नेहमी टक्केवारी दर्शवा"</item>
+ <item msgid="2139628951880142927">"चार्ज करताना टक्केवारी दर्शवा (डीफॉल्ट)"</item>
+ <item msgid="3327323682209964956">"हे चिन्ह दर्शवू नका"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"अन्य"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"विभाजित-स्क्रीन विभाजक"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"खाली हलवा"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"वर हलवा"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"डावीकडे हलवा"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"उजवीकडे हलवा"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 13a1f00..a716eef 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Tangkapan skrin ditangkap."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Sentuh untuk melihat tangkapan skrin anda."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Tidak dapat menangkap tangkapan skrin."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Tdk dpt mngmbil tgkapn skrin krn ruang storan trhad atau tdk dibenarkn olh apl atau organisasi anda."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Tidak dapat menyimpan tangkapan skrin kerana ruang storan terhad."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Apl atau organisasi anda tidak membenarkan pengambilan tangkapan skrin."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Pilihan pemindahan fail USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Lekapkan sebagai pemain media (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Lekapkan sebagai kamera (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Lagi masa."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Kurang masa."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lampu suluh dimatikan."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lampu suluh tidak tersedia."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lampu suluh dihidupkan."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Lampu suluh dimatikan."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Lampu suluh dihidupkan."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"penyematan skrin"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"cari"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Tidak dapat memulakan <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> dilumpuhkan dalam mod selamat."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Sejarah"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Kosongkan"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Apl ini tidak menyokong berbilang tetingkap"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Apl tidak menyokong berbilang tetingkap"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Mendatar Terpisah"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Menegak Terpisah"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Tersuai Terpisah"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Senyap\nsepenuhnya"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Keutamaan\nsahaja"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Penggera\nsahaja"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Semua"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Semua\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Mengecas (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> sehingga penuh)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Mengecas cepat (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> sehingga penuh)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Mengecas perlahan (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> sehingga penuh)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Tunjukkan saat jam dalam bar status. Mungkin menjejaskan hayat bateri."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Susun Semula Tetapan Pantas"</string>
<string name="show_brightness" msgid="6613930842805942519">"Tunjukkan kecerahan dalam Tetapan Pantas"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Dayakan pemecut leret ke atas untuk memasuki skrin terpisah"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Dayakan gerak isyarat leret ke atas utk masuk skrin terpisah"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Dayakan gerak isyarat untuk memasuki skrin terpisah dengan meleret ke atas daripada butang Ikhtisar"</string>
<string name="experimental" msgid="6198182315536726162">"Percubaan"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Hidupkan Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Untuk menyambungkan papan kekunci anda dengan tablet, anda perlu menghidupkan Bluetooth terlebih dahulu."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Hidupkan"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Gunakan untuk pemberitahuan <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Gunakan untuk semua pemberitahuan daripada apl ini"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Tunjukkan pemberitahuan secara senyap"</string>
+ <string name="block" msgid="2734508760962682611">"Sekat semua pemberitahuan"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Jangan senyapkan"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Jangan senyapkan atau sekat"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Tunjukkan tetapan kepentingan penuh"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Disekat"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Kurang penting"</string>
<string name="low_importance" msgid="4109929986107147930">"Kepentingan rendah"</string>
<string name="default_importance" msgid="8192107689995742653">"Kepentingan biasa"</string>
<string name="high_importance" msgid="1527066195614050263">"Kepentingan tinggi"</string>
<string name="max_importance" msgid="5089005872719563894">"Kepentingan segera"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Jangan sekali-kali tunjukkan pemberitahuan ini"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Tunjukkan pada bahagian bawah senarai pemberitahuan secara senyap"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Tunjukkan pemberitahuan ini secara senyap"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Tunjukkan pada bahagian atas senarai pemberitahuan dan bunyikan"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Intai pada skrin dan bunyikan"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Tunjukkan pada bahagian bawah senarai pemberitahuan secara senyap"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Tunjukkan pemberitahuan ini secara senyap"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Benarkan pemberitahuan ini berbunyi"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Intai pada skrin dan benarkan bunyi"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Tunjukkan pada bahagian atas senarai pemberitahuan, intai pada skrin dan benarkan bunyi"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Lagi tetapan"</string>
<string name="notification_done" msgid="5279426047273930175">"Selesai"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Warna biasa"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Warna malam"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Warna tersuai"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Auto"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Warna tidak diketahui"</string>
- <string name="color_transform" msgid="6985460408079086090">"Pengubahsuaian warna"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Tunjukkan jubin Tetapan Pantas"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Dayakan jelmaan tersuai"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Warna dan penampilan"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Mod malam"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Tentukur paparan"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Hidup"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Mati"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Hidupkan secara automatik"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Beralih ke Mod Malam sebagaimana sesuai untuk lokasi dan masa"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Apabila Mod Malam dihidupkan"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Gunakan tema gelap untuk OS Android"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Laraskan seri warna"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Laraskan kecerahan"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Tema gelap digunakan pada bahagian teras OS Android yang biasanya dipaparkan dalam tema cerah, seperti Tetapan."</string>
<string name="color_apply" msgid="9212602012641034283">"Gunakan"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Sahkan tetapan"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Sesetengah tetapan warna boleh menjadikan peranti ini tidak dapat digunakan. Klik OK untuk mengesahkan tetapan warna ini, jika tidak, tetapan ini akan ditetapkan semula selepas 10 saat."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Penggunaan bateri"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Penjimat Bateri tidak tersedia semasa mengecas"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Penjimat Bateri"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Mengurangkan prestasi dan data latar belakang"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Skrin Utama"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Terbaharu"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Kembali"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Tunjukkan jangan ganggu dalam kelantangan"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Benarkan kawalan penuh jangan ganggu dalam dialog kelantangan."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Kelantangan dan Jangan Ganggu"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Masuki mod jangan ganggu apabila kelantangan direndahkan"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Tunjukkan dengan kawalan kelantangan"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Jangan ganggu"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Pintasan butang kelantangan"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Keluar drp mod jangan ganggu apabila kelantangan ditinggikan"</string>
<string name="battery" msgid="7498329822413202973">"Bateri"</string>
<string name="clock" msgid="7416090374234785905">"Jam"</string>
<string name="headset" msgid="4534219457597457353">"Set Kepala"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Fon kepala disambungkan"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Set kepala disambungkan"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Dayakan atau lumpuhkan ikon daripada dipaparkan dalam bar status."</string>
<string name="data_saver" msgid="5037565123367048522">"Penjimat Data"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Penjimat Data dihidupkan"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Penjimat Data dimatikan"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Hidup"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Mati"</string>
<string name="nav_bar" msgid="1993221402773877607">"Bar navigasi"</string>
<string name="start" msgid="6873794757232879664">"Mula"</string>
<string name="center" msgid="4327473927066010960">"Tengah"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Pratonton"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Seret untuk menambahkan jubin"</string>
<string name="qs_edit" msgid="2232596095725105230">"Edit"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Masa"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Tunjukkan jam, minit dan saat"</item>
+ <item msgid="1427801730816895300">"Tunjukkan jam dan minit (lalai)"</item>
+ <item msgid="3830170141562534721">"Jangan tunjukkan ikon ini"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Sentiasa tunjukkan peratusan"</item>
+ <item msgid="2139628951880142927">"Tunjukkan peratusan semasa mengecas (lalai)"</item>
+ <item msgid="3327323682209964956">"Jangan tunjukkan ikon ini"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Lain-lain"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Pembahagi skrin pisah"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Alih ke bawah"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Alih ke atas"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Alih ke kiri"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Alih ke kanan"</string>
</resources>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 60e2812..503b91f 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"ဖန်သားပြင်ဓါတ်ပုံရိုက်ခြင်းအား ဖမ်းယူပြီး"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"သင့်ဖန်သားပြင်ဓါတ်ပုံရိုက်ခြင်းအား ကြည့်ရှုရန် ထိပါ"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"ဖန်သားပြင်ဓါတ်ပုံရိုက်ခြင်းအား မဖမ်းစီးနိုင်ပါ"</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"မျက်နှာပြင်လျှပ်တပြက်ပုံကို မရုက်နိုင်ခဲ့ပါ၊ သိုလှောင်မှု နေရာ အကန့်အသတ် ရှိနေ၍ သို့မဟုတ် app သို့မဟုတ် သင်၏ အဖွဲ့အစည်းက ခွင့်မပြု၍ ဖြစ်နိုင်သည်။"</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"သိုလှောင်ခန်းနေရာ အကန့်အသတ်ရှိသောကြောင့် ဖန်သားပြင်ဓာတ်ပုံကို သိမ်းဆည်း၍မရပါ။"</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ဖန်သားပြင်ဓာတ်ပုံရိုက်ကူးခြင်းကို အက်ပ်မှ သို့မဟုတ် သင့်အဖွဲ့အစည်းမှ ခွင့်မပြုပါ။"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB ဖိုင်ပြောင်း ရွေးမှုများ"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"မီဒီယာပလေရာအနေဖြင့် တပ်ဆင်ရန် (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"ကင်မရာအနေဖြင့် တပ်ဆင်ရန် (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"အချိန် တိုး"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"အချိန် လျှော့"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ဖလက်ရှမီး ပိတ်ထား"</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ဓာတ်မီးမရသေးပါ။"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ဖလက်ရှမီး ဖွင့်ထား။"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ဖလက်ရှမီး ပိတ်ထားသည်။"</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ဖလက်ရှမီး ဖွင့်ထားသည်။"</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"မျက်နှာပြင် ပင်ထိုးမှု"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ရှာဖွေရန်"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ကို မစနိုင်ပါ။"</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ကို ဘေးကင်းလုံခြုံသည့်မုဒ်တွင် ပိတ်ထားပါသည်။"</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"မှတ်တမ်း"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"ရှင်းလင်းပါ"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"ဤအက်ပ်သည် ဝင်းဒိုးများစွာဖွင့်ခြင်းကို ပံ့ပိုးမထားပါ"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"အက်ပ်သည် ဝင်းဒိုးများစွာဖွင့်ခြင်းကို ပံ့ပိုးမထားပါ"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ရေပြင်ညီ ပိုင်းမည်"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ဒေါင်လိုက်ပိုင်းမည်"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"စိတ်ကြိုက် ပိုင်းမည်"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"လုံးဝ\nတိတ်ဆိတ်ခြင်း"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"ဦးစားပေးမှု\nသာ"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"နှိုးစက်များ\nသာ"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"အားလုံး"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"အားလုံး\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"နှေးကွေးစွာ အားသွင်းခြင်း (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ပြည့်သည်အထိ)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"အခြေအနေပြနေရာမှာ နာရီ စက္ကန့်များကို ပြပါ။ ဘက်ထရီ သက်တမ်းကို အကျိုးသက်ရောက်နိုင်တယ်။"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"အမြန် ဆက်တင်များကို ပြန်စီစဉ်ရန်"</string>
<string name="show_brightness" msgid="6613930842805942519">"အမြန် ဆက်တင်များထဲက တောက်ပမှုကို ပြရန်"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"မျက်နှာပြင်ခွဲကြည့်ရန် အပေါ်သို့ပွတ်ဆွဲခြင်း လုပ်ဆောင်ချက်ကိုဖွင့်ပါ"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"မျက်နှာပြင်ခွဲကြည့်ရန် အပေါ်သို့ပွတ်ဆွဲခြင်း အမူအရာကိုဖွင့်ပါ"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"ခြုံကြည့်သည့်ခလုတ်မှ အပေါ်သို့ပွတ်ဆွဲခြင်းဖြင့် မျက်နှာပြင်ခွဲကြည့်ရန် လက်ဟန်ကိုဖွင့်ပါ"</string>
<string name="experimental" msgid="6198182315536726162">"စမ်းသပ်ရေး"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"ဘလူးတုသ် ဖွင့်ရမလား။"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"ကီးဘုတ်ကို တပ်ဘလက်နှင့် ချိတ်ဆက်ရန်၊ ပမထဦးစွာ ဘလူးတုသ်ကို ဖွင့်ပါ။"</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"ဖွင့်ပါ"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"သတိပေးချက် <xliff:g id="TOPIC_NAME">%1$s</xliff:g> ခုသို့သက်ရောက်စေပါ"</string>
- <string name="apply_to_app" msgid="363016783939815960">"ဤအက်ပ်မှ သတိပေးချက်များအားလုံးသို့ သက်ရောက်စေပါ"</string>
+ <string name="show_silently" msgid="6841966539811264192">"သတိပေးချက်များကို တိတ်ဆိတ်စွာပြပါ"</string>
+ <string name="block" msgid="2734508760962682611">"သတိပေးချက်များအားလုံးကို ပိတ်ဆို့ပါ"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"အသံ မတိတ်ပါနှင့်"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"အသံ မတိတ်ပါနှင့် သို့မဟုတ် မပိတ်ဆို့ပါနှင့်"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"အပြည့်အဝအရေးပါသည့် ဆက်တင်များကိုပြပါ"</string>
<string name="blocked_importance" msgid="5198578988978234161">"ပိတ်ဆို့ထားသည်"</string>
+ <string name="min_importance" msgid="1901894910809414782">"အနည်းဆုံး အရေးပါမှု"</string>
<string name="low_importance" msgid="4109929986107147930">"အနည်းငယ်သာ အရေးပါသည်"</string>
<string name="default_importance" msgid="8192107689995742653">"သာမန်သာ အရေးပါသည်"</string>
<string name="high_importance" msgid="1527066195614050263">"အလွန်အရေးပါသည်"</string>
<string name="max_importance" msgid="5089005872719563894">"အရေးတကြီး အရေးပါသည်"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"ဤသတိပေးချက်များကို ဘယ်တော့မှမပြပါနှင့်"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"သတိပေးချက်စာရင်း၏ အောက်ဆုံးတွင် တိတ်တဆိတ်ပြပါ"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"ဤသတိပေးချက်များကို တိတ်တဆိတ်ပြပါ"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"သတိပေးချက်စာရင်းများ၏ ထိပ်တွင်ပြကာ အသံဖွင့်ပါ"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"မျက်နှာပြင်ပေါ်သို့ ဖော်ပြကာ အသံဖွင့်ပါ"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"သတိပေးချက်စာရင်း၏ အောက်ဆုံးတွင် တိတ်ဆိတ်စွာပြပါ"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"ဤသတိပေးချက်များကို တိတ်ဆိတ်စွာပြပါ"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"ဤသတိပေးချက်များကို အသံထွက်ခွင့်ပြုပါ"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"ဖန်သားပြင်ပေါ်တွင် ပေါ်စေပြီး အသံထွက်ခွင့်ပြုပါ"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"သတိပေးချက်စာရင်း၏ ထိပ်ဆုံးတွင်ပြပြီး ဖန်သားပြင်ပေါ်တွင် ပေါ်စေကာ အသံထွက်ခွင့်ပြုပါ"</string>
<string name="notification_more_settings" msgid="816306283396553571">"နောက်ထပ် ဆက်တင်များ"</string>
<string name="notification_done" msgid="5279426047273930175">"ပြီးပါပြီ"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"ပုံမှန် အရောင်များ"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"ည အရောင်များ"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"စိတ်ကြိုက် အရောင်များ"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"အလိုအလျောက်"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"မသိသည့် အရောင်များ"</string>
- <string name="color_transform" msgid="6985460408079086090">"အရောင် မွမ်းမံမှု"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"အမြန် ဆက်တင် လေးထောင့်ကွက်ကို ပြပါ"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"စိတ်ကြိုက် ပြောင်းလဲမှုကို ဖွင့်ပါ"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"အရောင်နှင့် အပြင်အဆင်"</string>
+ <string name="night_mode" msgid="3540405868248625488">"ညသုံးမုဒ်"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"ပြသမှုအချိန်အဆကို ညှိပါ"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"ဖွင့်ပါ"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"ပိတ်ပါ"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"အလိုအလျောက် ဖွင့်ပါ"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"တည်နေရာနှင့် တစ်ရက်တာအချိန်နှင့် သင့်လျော်သလို ညသုံးမုဒ်သို့ ပြောင်းပါ"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"ညသုံမုဒ်ဖွင့်ထားစဉ်"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Android OS အတွက်အရောင်ရင့်အပြင်အဆင်ကို သုံးပါ"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"အရောင်မွဲမှုကို ချိန်ပါ"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"အလင်းအမှောင်ချိန်ပါ"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"အရောင်ရင့်အပြင်အဆင်သည် ဆက်တင်များကဲ့သို့ ပုံမှန်အားဖြင့် အရောင်ဖျော့အပြင်အဆင်အဖြစ်ရှိသည့် Android OS ၏အဓိကနေရာများကို ပြောင်းလဲပေးပါသည်။"</string>
<string name="color_apply" msgid="9212602012641034283">"အသုံးပြုပါ"</string>
<string name="color_revert_title" msgid="4746666545480534663">"ဆက်တင်များကို အတည်ပြုပါ"</string>
<string name="color_revert_message" msgid="9116001069397996691">"အချို့သော အရောင်ဆက်တက်များက ဤကိရိယာကို သုံးမရအောင် လုပ်ပစ်နိုင်ပါသည်။ ဤအရောင် ဆက်တင်များကို အတည်ပြုရန် အိုကေကို နှိပ်ပါ၊ သို့မဟုတ် ဤဆက်တင်များကို ၁၀ စက္ကန့် အကြာတွင် ပြန်ညှိလိုက်ပါမည်။"</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"ဘက်ထရီ အသုံးပြုမှု"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"အားသွင်းနေချိန်မှာ Battery Saver ကို သုံးမရပါ"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Battery Saver"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"လုပ်ဆောင်မှု နှင့် နောက်ခံ ဒေတာကို လျော့နည်းစေပါသည်"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"ပင်မ"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"မကြာသေးခင်က"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"နောက်သို့"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"အသံအတိုးအလျှော့တွင် မနှောက်ယှက်ရကို ပြပါ"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"အသံအတိုးအလျှော့အကွက်ထဲတွင် မနှောက်ယှက်ရကို အပြည့်အဝထိန်းချုပ်ခွင့် ပြုပါ။"</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"အသံအတိုးအလျှော့နှင့် မနှောက်ယှက်ရ"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"အသံလျှော့သည်နှင့် မနှောက်ယှက်ရသို့ ပြောင်းလဲပါ"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"အသံထိန်းချုပ်သည့်ခလုတ်များဖြင့် ပြပါ"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"မနှောက်ယှက်ပါနှင့်"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"အသံထိန်းချုပ်သည့်ခလုတ် ဖြတ်လမ်း"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"အသံချဲ့သည်နှင့် မနှောက်ယှက်ရမှ ထွက်ပါ"</string>
<string name="battery" msgid="7498329822413202973">"ဘတ်ထရီ"</string>
<string name="clock" msgid="7416090374234785905">"နာရီ"</string>
<string name="headset" msgid="4534219457597457353">"မိုက်ခွက်ပါနားကြပ်"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"နားကြပ်တပ်ဆင်ပြီးပါပြီ"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"မိုက်ခွက်ပါနားကြပ်တပ်ဆင်ပြီးပါပြီ"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"အခြေအနေဘားတန်းတွင် သင်္ကေတပုံပြခြင်းကို ဖွင့်ရန် သို့မဟုတ် ပိတ်ရန်"</string>
<string name="data_saver" msgid="5037565123367048522">"ဒေတာချွေတာမှု"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"ဒေတာချွေတာမှု ဖွင့်ထားသည်"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"ဒေတာချွေတာမှု ပိတ်ထားသည်"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"ဖွင့်ပါ"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"ပိတ်ပါ"</string>
<string name="nav_bar" msgid="1993221402773877607">"ရွှေ့လျားရန်ဘားတန်း"</string>
<string name="start" msgid="6873794757232879664">"စတင်ပါ"</string>
<string name="center" msgid="4327473927066010960">"ဌာန"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"အစမ်းကြည့်ပါ"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"အချပ်များကိုထည့်ရန် ဖိဆွဲပါ"</string>
<string name="qs_edit" msgid="2232596095725105230">"တည်းဖြတ်ပါ"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"အချိန်"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"နာရီ၊ မိနစ်နှင့် စက္ကန့်ကိုပြပါ"</item>
+ <item msgid="1427801730816895300">"နာရီနှင့် မိနစ်ကိုပြပါ (ပုံသေ)"</item>
+ <item msgid="3830170141562534721">"ဤသင်္ကေတပုံကို မပြပါနှင့်"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"ရာခိုင်နှုန်းကို အမြဲတမ်းပြပါ"</item>
+ <item msgid="2139628951880142927">"အားသွင်းနေစဉ်တွင် ရာခိုင်နှုန်းကိုပြပါ (ပုံသေ)"</item>
+ <item msgid="3327323682209964956">"ဤသင်္ကေတပုံကို မပြပါနှင့်"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"အခြား"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"မျက်နှာပြင်ခွဲခြမ်း ပိုင်းခြားပေးသည့်စနစ်"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"အောက်သို့ရွှေ့ပါ"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"အပေါ်သို့ရွှေ့ပါ"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"ဘယ်ဘက်သို့ရွှေ့ပါ"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"ညာဘက်သို့ရွှေ့ပါ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index f326a01..b3de239 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Skjermdumpen er lagret."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Trykk for å se skjermdumpen."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Kan ikke lagre skjermdumpen."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Kan ikke ta skjermdump grunnet plassbegrensning, app- eller organisasjonstillatelser."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Kan ikke lagre skjermdumpen på grunn av begrenset lagringsplass."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Appen eller organisasjonen din tillater ikke at du tar skjermdumper."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Altern. for USB-filoverføring"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Sett inn som mediespiller (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Sett inn som kamera (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Mer tid."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Mindre tid."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lommelykten er av."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lommelykt er ikke tilgjengelig."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lommelykten er på."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Lommelykten er slått av."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Lommelykten er slått på."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"én-appsmodus"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"Søk"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Kunne ikke starte <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> er slått av i sikker modus."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Logg"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Tøm"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Denne appen har ikke støtte for flervindusmodus"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Appen har ikke støtte for flervindusmodus"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Del horisontalt"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Del vertikalt"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Del tilpasset"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Total\nstillhet"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Bare\nPrioritet"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Bare\nalarmer"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Alle"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Alle\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Lader (fulladet om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Lader raskt (fulladet om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Lader sakte (fulladet om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Vis sekunder i statusfeltet på klokken. Det kan påvirke batteritiden."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Omorganiser hurtiginnstillingene"</string>
<string name="show_brightness" msgid="6613930842805942519">"Vis lysstyrke i hurtiginnstillingene"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Slå på delt skjerm ved å sveipe opp med akseleratoren"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Slå på delt skjerm ved å sveipe opp"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Slå på bevegelsen for å åpne delt skjerm ved å sveipe opp fra Oversikt-knappen"</string>
<string name="experimental" msgid="6198182315536726162">"På forsøksstadiet"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Vil du slå på Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"For å koble tastaturet til nettbrettet ditt må du først slå på Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Slå på"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Bruk for varsler for <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Bruk for alle varslene fra denne appen"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Vis varsler uten lyd"</string>
+ <string name="block" msgid="2734508760962682611">"Blokkér alle varsler"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Ikke slå av lyden"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Ikke slå av lyden eller blokkér anrop"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Vis alle viktighetsinnstillingene"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Blokkert"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Laveste prioritet"</string>
<string name="low_importance" msgid="4109929986107147930">"Lav viktighet"</string>
<string name="default_importance" msgid="8192107689995742653">"Vanlig viktighet"</string>
<string name="high_importance" msgid="1527066195614050263">"Høy viktighet"</string>
<string name="max_importance" msgid="5089005872719563894">"Svært høy viktighet"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Aldri vis disse varslene"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Vis nederst på varsellisten uten lyd"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Vis disse varslene uten lyd"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Vis øverst på varsellisten med lyd"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Vis fort på skjermen med lyd"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Vis nederst på varsellisten uten lyd"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Vis disse varslene uten lyd"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Tillat at disse varslene vises med lyd"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Vis fort på skjermen og tillat lyd"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Vis øverst på varsellisten, vis fort på skjermen og tillat lyd"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Flere innstillinger"</string>
<string name="notification_done" msgid="5279426047273930175">"Ferdig"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Normale farger"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Nattfarger"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Spesialtilpassede farger"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automatisk"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Ukjente farger"</string>
- <string name="color_transform" msgid="6985460408079086090">"Fargemodifisering"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Vis ruten for hurtiginnstillinger"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Slå på spesialtilpasset forvandling"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Farge og utseende"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Nattmodus"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Kalibrer skjermen"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"På"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Av"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Slå på automatisk"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Bytt til nattmodus avhengig av tid og sted"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Når nattmodus er på"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Bruk et mørkt tema for Android OS"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Juster fargen"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Juster lysstyrken"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Det mørke temaet brukes på kjerneområdene i Android OS som vanligvis vises i et lyst tema, for eksempel Innstillinger."</string>
<string name="color_apply" msgid="9212602012641034283">"Bruk"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Bekreft innstillingene"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Noen fargeinnstillinger kan gjøre denne enheten ubrukelig. Klikk på OK for å bekrefte disse fargeinnstillingene, ellers blir de tilbakestilt etter ti sekunder."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Batteribruk"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Batterisparing er ikke tilgjengelig under lading"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Batterisparing"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduserer ytelsen og begrenser bakgrunnsdataene"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Startside"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Nylige"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Tilbake"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Vis «Ikke forstyrr» i volumkontrollene"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Tillat full kontroll over «Ikke forstyrr» i volumdialogen."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Volum og «Ikke forstyrr»"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Åpne «Ikke forstyrr» med volum ned-knappen"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Vis med volumkontrollene"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ikke forstyrr"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Hurtigtast for volumknappene"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Lukk «Ikke forstyrr» med volum opp-knappen"</string>
<string name="battery" msgid="7498329822413202973">"Batteri"</string>
<string name="clock" msgid="7416090374234785905">"Klokke"</string>
<string name="headset" msgid="4534219457597457353">"Hodetelefoner"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Øretelefoner er tilkoblet"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Hodetelefoner er tilkoblet"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Vis eller skjul ikoner i statusfeltet."</string>
<string name="data_saver" msgid="5037565123367048522">"Datasparing"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Datasparing er på"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Datasparing er av"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"På"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Av"</string>
<string name="nav_bar" msgid="1993221402773877607">"Navigasjonsrad"</string>
<string name="start" msgid="6873794757232879664">"Start"</string>
<string name="center" msgid="4327473927066010960">"Midtstilt"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Forhåndsvisning"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Dra for å legge til fliser"</string>
<string name="qs_edit" msgid="2232596095725105230">"Endre"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Tid"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Vis timer, minutter og sekunder"</item>
+ <item msgid="1427801730816895300">"Vis timer og minutter (standard)"</item>
+ <item msgid="3830170141562534721">"Ikke vis dette ikonet"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Vis alltid prosentandel"</item>
+ <item msgid="2139628951880142927">"Vis prosentandel under lading (standard)"</item>
+ <item msgid="3327323682209964956">"Ikke vis dette ikonet"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Annet"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Skilleelement for delt skjerm"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Flytt ned"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Flytt opp"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Flytt mot venstre"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Flytt mot høyre"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 9b67d9c..4b78552 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"स्क्रिनसट क्याप्चर गरियो।"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"तपाईँको स्क्रिनसट हेर्न छुनुहोस्।"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"स्क्रिनसट क्याप्चर गर्न सकिएन।"</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"सीमित भण्डारण ठाउँको कारणले स्क्रिनसट लिन सकिएन, वा यो अनुप्रयोग वा आफ्नो संगठन द्वारा अनुमति छैन।"</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"सीमित भण्डारण स्थान उपलब्ध रहेको हुनाले स्क्रिनसटलाई सुरक्षित गर्न सकिँदैन।"</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"अनुप्रयोग वा तपाईँको संगठनले स्क्रिनसट लिन अनुमति दॅिंदैन।"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB फाइल सार्ने विकल्पहरू"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"मिडिया प्लेयर(MTP)को रूपमा माउन्ट गर्नुहोस्"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"क्यामेराको रूपमा माउन्ट गर्नुहोस् (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"थप समय।"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"कम समय।"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"टर्च बन्द छ।"</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"फ्ल्यासलाइट उपलब्ध छैन।"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"टर्च खुला छ।"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"टर्च बन्द गरियो।"</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"टर्च खुला गरियो।"</string>
@@ -305,6 +307,8 @@
<skip />
<string name="recents_history_button_label" msgid="5153358867807604821">"इतिहास"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"मेटाउनुहोस्"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"यस अनुप्रयोगले बहु-विन्डोलाई समर्थन गर्दैन"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"अनुप्रयोगले बहु-विन्डोलाई समर्थन गर्दैन"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"तेर्सो रूपमा विभाजन गर्नुहोस्"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ठाडो रूपमा विभाजन गर्नुहोस्"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"अनुकूलन विभाजन गर्नुहोस्"</string>
@@ -334,8 +338,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"पूरै\nशान्त"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"प्राथमिकता \nमात्र"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"अलार्महरू \nमात्र"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"सबै"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"सबै\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"बिस्तारै चार्ज हुँदै (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> पूर्ण नभएसम्म)"</string>
@@ -448,38 +450,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"वस्तुस्थिति पट्टीको घडीमा सेकेन्ड देखाउनुहोस्। ब्याट्री आयु प्रभावित हुन सक्छ।"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"द्रुत सेटिङहरू पुनः व्यवस्थित गर्नुहोस्"</string>
<string name="show_brightness" msgid="6613930842805942519">"द्रुत सेटिङहरूमा उज्यालो देखाउनुहोस्"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"विभाजित-स्क्रिनको स्वाइप-अप एक्सेलेटर सक्रिय गर्नुहोस्"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"विभाजित-स्क्रिन स्वाइप-अप इशारा सक्षम गर्नुहोस्"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"परिदृश्य बटनदेखि माथि स्वाइप गरी विभाजित-स्क्रिन प्रविष्ट गर्न इसारालाई सक्रिय गर्नुहोस्"</string>
<string name="experimental" msgid="6198182315536726162">"प्रयोगात्मक"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"ब्लुटुथ सक्रिय पार्ने हो?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"आफ्नो ट्याब्लेटसँग किबोर्ड जोड्न, पहिले तपाईँले ब्लुटुथ सक्रिय गर्नुपर्छ।"</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"सक्रिय पार्नुहोस्"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> सूचनाहरूमा लागू गर्नुहोस्"</string>
- <string name="apply_to_app" msgid="363016783939815960">"यो अनुप्रयोगका सबै सूचनाहरूमा लागू गर्नुहोस्"</string>
+ <string name="show_silently" msgid="6841966539811264192">"सूचनाहरूलाई बिना आवाज देखाउनुहोस्"</string>
+ <string name="block" msgid="2734508760962682611">"सबै सूचनाहरूलाई रोक्नुहोस्"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"मौन नगर्नुहोस्"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"मौन नगर्नुहोस् वा नरोक्नुहोस्"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"पूर्ण महत्त्व सेटिङहरू देखाउनुहोस्"</string>
<string name="blocked_importance" msgid="5198578988978234161">"रोकियो"</string>
+ <string name="min_importance" msgid="1901894910809414782">"न्यूनतम महत्त्व"</string>
<string name="low_importance" msgid="4109929986107147930">"न्यून महत्त्व"</string>
<string name="default_importance" msgid="8192107689995742653">"सामान्य महत्त्व"</string>
<string name="high_importance" msgid="1527066195614050263">"उच्च महत्त्व"</string>
<string name="max_importance" msgid="5089005872719563894">"जरूरी महत्त्व"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"यी सूचनाहरू कहिल्यै नदेखाउनुहोस्"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"सूचीको फेदमा बिना आवाज देखाउनुहोस्"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"यी सूचनाहरू बिना आवाज देखाउनुहोस्"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"सूचना सूचीको शीर्षमा देखाउनुहोस् र आवाज निकाल्नुहोस्"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"स्क्रिनमा हेर्नुहोस् र आवाज निकाल्नुहोस्"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"सूचना सूचीको फेदमा बिना आवाज देखाउने"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"यी सूचनाहरूलाई बिना आवाज देखाउने"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"यी सूचनाहरूलाई ध्वनि निकाल्न अनुमति दिने"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"स्क्रिनमा चियाउने र ध्वनि निकाल्न अनुमति दिने"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"सूचना सूचीको शीर्षमा देखाउने, स्क्रिनमा चियाउने र ध्वनि निकाल्न अनुमति दिने"</string>
<string name="notification_more_settings" msgid="816306283396553571">"थप सेटिङहरू"</string>
<string name="notification_done" msgid="5279426047273930175">"सम्पन्न भयो"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"सामान्य रङहरू"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"रात्री रङहरू"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"अनुकूलन रङहरू"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"स्वतः"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"अज्ञात रङहरू"</string>
- <string name="color_transform" msgid="6985460408079086090">"रङ परिमार्जन"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"द्रुत सेटिङ टाइल देखाउनुहोस्"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"अनुकूलन रूपान्तरण सक्रिय गर्नुहोस्"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"रंग र रूप"</string>
+ <string name="night_mode" msgid="3540405868248625488">"रात्री मोड"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"प्रदर्शनको स्तर मिलाउनुहोस्"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"सक्रिय"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"निष्क्रिय"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"स्वतः सक्रिय पार्नुहोस्"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"स्थान र दिनको समयको लागि उपयुक्त रात्री मोडमा स्विच गर्नुहोस्"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"रात्री मोड सक्रिय हुँदा"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Android OS का लागि गाढा रंगको विषयवस्तु प्रयोग गर्नुहोस्"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"रङ्गलाई समायोजन गर्नुहोस्"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"चमकलाई समायोजन गर्नुहोस्"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"गहिरो रंगको विषयवस्तुलाई Android OS का त्यस्ता मुख्य क्षेत्रहरूमा लागू गरिन्छ जसलाई सामान्यतया हल्का रंगमा देखाइन्छ, जस्तै सेटिङहरू।"</string>
<string name="color_apply" msgid="9212602012641034283">"लागू गर्नुहोस्"</string>
<string name="color_revert_title" msgid="4746666545480534663">"सेटिङहरूको पुष्टि गर्नुहोस्"</string>
<string name="color_revert_message" msgid="9116001069397996691">"केही रङ सेटिङहरूले यस यन्त्रलाई अनुपयोगी बनाउन सक्छन्। यी रङ सेटिङहरू पुष्टि गर्न ठीक छ मा क्लिक गर्नुहोस्, अन्यथा यी सेटिङहरू १० सेकेण्डपछि रिसेट हुनेछन्।"</string>
- <string name="battery_panel_title" msgid="7944156115535366613">"ब्याट्रि उपयोग"</string>
+ <string name="battery_panel_title" msgid="7944156115535366613">"ब्याट्री उपयोग"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"चार्ज गर्ने समयमा ब्याट्री सेभर उपलब्ध छैन"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"ब्याट्री सेभर"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"कार्यसम्पादन र पृष्ठभूमि डेटा घटाउँछ"</string>
@@ -487,21 +498,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"गृह"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"हालैका"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"पछाडि"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"भोल्युममा बाधा नपुर्याउनुहोस् देखाउनुहोस्"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"भोल्युमको संवादमा बाधा नपुर्याउनुहोस् को पूर्ण नियन्त्रणलाई अनुमति दिनुहोस्"</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"भोल्युम र बाधा नपुर्याउनुहोस्"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"भोल्युम कम गर्नेमा बाधा नपुर्याउनुहोस् प्रविष्ट गर्नुहोस्"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"भोल्युम नियन्त्रणसहित देखाउनुहोस्"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"बाधा नपुर्याउनुहोस्"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"भोल्युम बटनका सर्टकट"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"भोल्युम बढाउनेमा बाधा नपुर्याउनुहोस् प्रविष्ट गर्नुहोस्"</string>
<string name="battery" msgid="7498329822413202973">"ब्याट्री"</string>
<string name="clock" msgid="7416090374234785905">"घडी"</string>
<string name="headset" msgid="4534219457597457353">"हेडसेट"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"हेडफोनहरू जडान गरियो"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"हेडसेट जडान गरियो"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"वस्तुस्थिति पट्टीमा देखाइनको लागि आइकनहरू सक्रिय वा निष्क्रिय गर्नुहोस्।"</string>
<string name="data_saver" msgid="5037565123367048522">"डेटा सेभर"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"डेटा सेभर अन छ"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"डेटा सेभर बन्द छ"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"सक्रिय गर्नुहोस्"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"निष्क्रिय"</string>
<string name="nav_bar" msgid="1993221402773877607">"नेभिगेशन पट्टी"</string>
<string name="start" msgid="6873794757232879664">"सुरु गर्नुहोस्"</string>
<string name="center" msgid="4327473927066010960">"केन्द्र"</string>
@@ -524,4 +534,21 @@
<string name="preview" msgid="9077832302472282938">"पूर्वावलोकन"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"टाइलहरू थप्न तान्नुहोस्"</string>
<string name="qs_edit" msgid="2232596095725105230">"सम्पादन गर्नुहोस्"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"समय"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"घण्टा, मिनेट, र सेकेन्ड देखाउनुहोस्"</item>
+ <item msgid="1427801730816895300">"घण्टा र मिनेट (पूर्वनिर्धारित) देखाउनुहोस्"</item>
+ <item msgid="3830170141562534721">"यो आइकन नदेखाउनुहोस्"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"सधैं प्रतिशत देखाउनुहोस्"</item>
+ <item msgid="2139628951880142927">"चार्ज गर्दा प्रतिशत देखाउनुहोस् (पूर्वनिर्धारित)"</item>
+ <item msgid="3327323682209964956">"यो आइकन नदेखाउनुहोस्"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"अन्य"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"विभाजित-स्क्रिन छुट्याउने"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"तल सार्नुहोस्"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"माथि सार्नुहोस्"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"बाँया सार्नुहोस्"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"दायाँ सार्नुहोस्"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 23455d8..9698cdf 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot gemaakt."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Raak aan om je screenshot te bekijken."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Screenshot is niet gemaakt."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Kan geen screenshot maken wegens beperkte opslagruimte of omdat de app of je organisatie dit niet toestaat."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Kan screenshot niet opslaan vanwege beperkte opslagruimte."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Het maken van screenshots wordt niet toegestaan door de app of je organisatie."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Opties voor USB-bestandsoverdracht"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Koppelen als mediaspeler (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Koppelen als camera (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Meer tijd."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Minder tijd."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Zaklamp uit."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Zaklamp niet beschikbaar."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Zaklamp aan."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Zaklamp uitgeschakeld."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Zaklamp ingeschakeld."</string>
@@ -304,6 +306,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> is uitgeschakeld in de veilige modus"</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Geschiedenis"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Wissen"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Deze app ondersteunt de modus voor meerdere vensters niet"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"App ondersteunt meerdere vensters niet"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Horizontaal splitsen"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Verticaal splitsen"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Aangepast splitsen"</string>
@@ -333,8 +337,6 @@
<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>
- <string name="interruption_level_all" msgid="1330581184930945764">"Alle"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Alle\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Opladen (vol over <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Snel opladen (vol over <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Langzaam opladen (vol over <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
@@ -447,34 +449,43 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Klokseconden op de statusbalk weergeven. Kan van invloed zijn op de accuduur."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Snelle instellingen opnieuw indelen"</string>
<string name="show_brightness" msgid="6613930842805942519">"Helderheid weergeven in Snelle instellingen"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Omhoog vegen voor gesplitst scherm inschakelen"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Omhoog vegen voor gesplitst scherm inschakelen"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Gebaar inschakelen om gesplitst scherm te openen door vanaf de knop Overzicht omhoog te vegen"</string>
<string name="experimental" msgid="6198182315536726162">"Experimenteel"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth inschakelen?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Als je je toetsenbord wilt verbinden met je tablet, moet je eerst Bluetooth inschakelen."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Inschakelen"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Toepassen op meldingen voor <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Toepassen op alle meldingen van deze app"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Meldingen zonder geluid weergeven"</string>
+ <string name="block" msgid="2734508760962682611">"Alle meldingen blokkeren"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Niet zonder geluid weergeven"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Niet zonder geluid weergeven of blokkeren"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Volledige instellingen voor belang weergeven"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Geblokkeerd"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Minimaal belang"</string>
<string name="low_importance" msgid="4109929986107147930">"Klein belang"</string>
<string name="default_importance" msgid="8192107689995742653">"Normaal belang"</string>
<string name="high_importance" msgid="1527066195614050263">"Groot belang"</string>
<string name="max_importance" msgid="5089005872719563894">"Urgent belang"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Deze meldingen nooit weergeven"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Onder aan de lijst met meldingen weergeven zonder geluid"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Deze meldingen zonder geluid weergeven"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Boven aan de lijst met meldingen weergeven en geluid laten horen"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Op het scherm weergeven en geluid laten horen"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Onder aan de lijst met meldingen weergeven zonder geluid"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Deze meldingen zonder geluid weergeven"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Toestaan dat deze meldingen geluid laten horen"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Op het scherm weergeven en geluid toestaan"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Boven aan de lijst met meldingen weergeven, op het scherm weergeven en geluid toestaan"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Meer instellingen"</string>
<string name="notification_done" msgid="5279426047273930175">"Gereed"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Normale kleuren"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Nachtkleuren"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Aangepaste kleuren"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automatisch"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Onbekende kleuren"</string>
- <string name="color_transform" msgid="6985460408079086090">"Kleuraanpassing"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Tegel voor \'Snelle instellingen\' weergeven"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Aangepast transformeren inschakelen"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Kleur en uiterlijk"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Nachtmodus"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Display kalibreren"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Aan"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Uit"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Automatisch inschakelen"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Overschakelen naar nachtmodus indien van toepassing voor locatie en tijd van de dag"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Als nachtmodus is ingeschakeld"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Donker thema gebruiken voor Android OS"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Tint aanpassen"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Helderheid aanpassen"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Het donkere thema wordt toegepast op kerngedeelten van het Android-besturingssysteem die normaal gesproken worden weergegeven met een licht thema, zoals Instellingen."</string>
<string name="color_apply" msgid="9212602012641034283">"Toepassen"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Instellingen bevestigen"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Bij sommige kleurinstellingen kan het apparaat onbruikbaar worden. Klik op OK om deze kleurinstellingen te bevestigen, anders worden deze instellingen na tien seconden gereset."</string>
@@ -486,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Startpagina"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recent"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Terug"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"\'Niet storen\' weergeven in volume"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Volledig beheer van \'Niet storen\' in het volumedialoogvenster toestaan."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Volume en \'Niet storen\'"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"\'Niet storen\' activeren bij volume omlaag"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Weergeven met volumeknoppen"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Niet storen"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Volumeknoppen als sneltoets"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"\'Niet storen\' afsluiten bij volume omhoog"</string>
<string name="battery" msgid="7498329822413202973">"Accu"</string>
<string name="clock" msgid="7416090374234785905">"Klok"</string>
<string name="headset" msgid="4534219457597457353">"Headset"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Hoofdtelefoon aangesloten"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset aangesloten"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"De weergave van pictogrammen in de statusbalk in- of uitschakelen."</string>
<string name="data_saver" msgid="5037565123367048522">"Databesparing"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Databesparing is ingeschakeld"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Databesparing is uitgeschakeld"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Aan"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Uit"</string>
<string name="nav_bar" msgid="1993221402773877607">"Navigatiebalk"</string>
<string name="start" msgid="6873794757232879664">"Begin"</string>
<string name="center" msgid="4327473927066010960">"Midden"</string>
@@ -523,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Voorbeeld"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Sleep om tegels toe te voegen"</string>
<string name="qs_edit" msgid="2232596095725105230">"Bewerken"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Tijd"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Uren, minuten en seconden weergeven"</item>
+ <item msgid="1427801730816895300">"Uren en minuten weergeven (standaard)"</item>
+ <item msgid="3830170141562534721">"Dit pictogram niet weergeven"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Percentage altijd weergeven"</item>
+ <item msgid="2139628951880142927">"Percentage weergeven tijdens opladen (standaard)"</item>
+ <item msgid="3327323682209964956">"Dit pictogram niet weergeven"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Overig"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Scheiding voor gesplitst scherm"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Omlaag"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Omhoog"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Naar links"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Naar rechts"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index 0d8ab19..6fb2c70 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"ਸਕ੍ਰੀਨਸ਼ੌਟ ਕੈਪਚਰ ਕੀਤਾ।"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"ਆਪਣਾ ਸਕ੍ਰੀਨਸ਼ੌਟ ਦੇਖਣ ਲਈ ਛੋਹਵੋ।"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"ਸਕ੍ਰੀਨਸ਼ੌਟ ਕੈਪਚਰ ਨਹੀਂ ਕਰ ਸਕਿਆ।"</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"ਸੀਮਿਤ ਸਟੋਰੇਜ ਸਪੇਸ ਦੇ ਕਾਰਨ ਸਕ੍ਰੀਨਸ਼ੌਟ ਨਹੀਂ ਲੈ ਸਕਦਾ ਜਾਂ ਐਪ ਜਾਂ ਤੁਹਾਡੀ ਕੰਪਨੀ ਵੱਲੋਂ ਇਸਦੀ ਆਗਿਆ ਨਹੀਂ ਹੈ।"</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ਸੀਮਿਤ ਸਟੋਰੇਜ ਥਾਂ ਦੇ ਕਾਰਨ ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਸਕਦਾ।"</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ਐਪ ਜਾਂ ਤੁਹਾਡੀ ਸੰਸਥਾ ਦੁਆਰਾ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲੈਣ ਦੀ ਮਨਜ਼ੂਰੀ ਨਹੀਂ ਹੈ।"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ ਚੋਣਾਂ"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"ਇੱਕ ਮੀਡੀਆ ਪਲੇਅਰ (MTP) ਦੇ ਤੌਰ ਤੇ ਮਾਊਂਟ ਕਰੋ"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"ਇੱਕ ਕੈਮਰੇ (PTP) ਦੇ ਤੌਰ ਤੇ ਮਾਊਂਟ ਕਰੋ"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"ਹੋਰ ਸਮਾਂ।"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"ਘੱਟ ਸਮਾਂ।"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ਫਲੈਸ਼ਲਾਈਟ ਬੰਦ।"</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ਫਲੈਸ਼ਲਾਈਟ ਉਪਲਬਧ ਨਹੀਂ ਹੈ।"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ਫਲੈਸ਼ਲਾਈਟ ਚਾਲੂ।"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ਫਲੈਸ਼ਲਾਈਟ ਬੰਦ ਕੀਤਾ।"</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ਫਲੈਸ਼ਲਾਈਟ ਚਾਲੂ ਕੀਤੀ।"</string>
@@ -304,6 +306,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ਨੂੰ ਸੁਰੱਖਿਅਤ-ਮੋਡ ਵਿੱਚ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ।"</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"ਇਤਿਹਾਸ"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"ਸਾਫ਼ ਕਰੋ"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"ਇਹ ਐਪ ਮਲਟੀ-ਵਿੰਡੋ ਨੂੰ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੀ"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"ਐਪ ਮਲਟੀ-ਵਿੰਡੋ ਨੂੰ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੀ"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ਹੌਰੀਜ਼ੌਂਟਲ ਸਪਲਿਟ"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ਵਰਟੀਕਲ ਸਪਲਿਟ"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ਕਸਟਮ ਸਪਲਿਟ"</string>
@@ -333,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"ਕੁਲ \n ਚੁੱਪੀ"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"ਕੇਵਲ\nਤਰਜੀਹੀ"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"ਕੇਵਲ\nਅਲਾਰਮ"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"ਸਭ"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"ਸਾਰੀਆਂ\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"ਹੌਲੀ-ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ਪੂਰੀ ਹੋਣ ਤੱਕ)"</string>
@@ -447,34 +449,43 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"ਸਥਿਤੀ ਬਾਰ ਵਿੱਚ ਘੜੀ ਸਕਿੰਟ ਦਿਖਾਓ। ਬੈਟਰੀ ਸਮਰੱਥਾ ਤੇ ਅਸਰ ਪੈ ਸਕਦਾ ਹੈ।"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਨੂੰ ਦੁਬਾਰਾ ਕ੍ਰਮ ਦਿਓ"</string>
<string name="show_brightness" msgid="6613930842805942519">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਚਮਕ ਦਿਖਾਓ"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਸਵਾਈਪ-ਅੱਪ ਐਕਸੇਲਰੇਟਰ ਨੂੰ ਯੋਗ ਬਣਾਓ"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਸਵਾਈਪ-ਅੱਪ ਸੰਕੇਤ ਨੂੰ ਯੋਗ ਬਣਾਓ"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"ਰੂਪ-ਰੇਖਾ ਬਟਨ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰਨ ਦੁਆਰਾ ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਵਿੱਚ ਦਾਖਲ ਹੋਣ ਲਈ ਸੰਕੇਤ ਨੂੰ ਯੋਗ ਬਣਾਓ"</string>
<string name="experimental" msgid="6198182315536726162">"ਪ੍ਰਯੋਗਾਤਮਿਕ"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth ਚਾਲੂ ਕਰੋ?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"ਆਪਣੇ ਟੈਬਲੇਟ ਨਾਲ ਆਪਣਾ ਕੀ-ਬੋਰਡ ਕਨੈਕਟ ਕਰਨ ਲਈ, ਤੁਹਾਨੂੰ ਪਹਿਲਾਂ Bluetooth ਚਾਲੂ ਕਰਨ ਦੀ ਜ਼ਰੂਰਤ ਹੈ।"</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"ਚਾਲੂ ਕਰੋ"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> ਸੂਚਨਾਵਾਂ \'ਤੇ ਲਾਗੂ ਕਰੋ"</string>
- <string name="apply_to_app" msgid="363016783939815960">"ਇਸ ਐਪ ਦੀਆਂ ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ \'ਤੇ ਲਾਗੂ ਕਰੋ"</string>
+ <string name="show_silently" msgid="6841966539811264192">"ਸੂਚਨਾਵਾਂ ਚੁੱਪਚਾਪ ਢੰਗ ਨਾਲ ਵਿਖਾਓ"</string>
+ <string name="block" msgid="2734508760962682611">"ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਬਲੌਕ ਕਰੋ"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"ਚੁੱਪ ਨਾ ਕਰਵਾਓ"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"ਚੁੱਪ ਨਾ ਕਰਵਾਓ ਜਾਂ ਬਲੌਕ ਨਾ ਕਰੋ"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"ਪੂਰੀ ਮਹੱਤਤਾ ਵਾਲੀਆਂ ਸੈਟਿੰਗਾਂ ਨੂੰ ਵਿਖਾਓ"</string>
<string name="blocked_importance" msgid="5198578988978234161">"ਬਲੌਕ ਕੀਤਾ"</string>
+ <string name="min_importance" msgid="1901894910809414782">"ਨਿਊਨਤਮ ਮਹੱਤਤਾ"</string>
<string name="low_importance" msgid="4109929986107147930">"ਘੱਟ ਮਹੱਤਤਾ"</string>
<string name="default_importance" msgid="8192107689995742653">"ਸਧਾਰਨ ਮਹੱਤਤਾ"</string>
<string name="high_importance" msgid="1527066195614050263">"ਵੱਧ ਮਹੱਤਤਾ"</string>
<string name="max_importance" msgid="5089005872719563894">"ਜ਼ਰੂਰੀ ਮਹੱਤਤਾ"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"ਇਹਨਾਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਕਦੇ ਨਾ ਵਿਖਾਓ"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"ਸੂਚਨਾ ਸੂਚੀ ਦੇ ਹੇਠਾਂ ਚੁੱਪਚਾਪ ਢੰਗ ਨਾਲ ਵਿਖਾਓ"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"ਇਹਨਾਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਚੁੱਪਚਾਪ ਢੰਗ ਨਾਲ ਵਿਖਾਓ"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"ਸੂਚਨਾਵਾਂ ਸੂਚੀ ਦੇ ਸਿਖਰ \'ਤੇ ਵਿਖਾਓ ਅਤੇ ਆਵਾਜ਼ ਕਰੋ"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"ਸਕਰੀਨ \'ਤੇ ਝਾਤੀ ਮਾਰੋ ਅਤੇ ਆਵਾਜ਼ ਕਰੋ"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"ਸੂਚਨਾ ਸੂਚੀ ਦੇ ਹੇਠਾਂ ਚੁੱਪਚਾਪ ਢੰਗ ਨਾਲ ਵਿਖਾਓ"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"ਇਹਨਾਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਚੁੱਪਚਾਪ ਢੰਗ ਨਾਲ ਵਿਖਾਓ"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"ਇਹਨਾਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਧੁਨੀ ਪੈਦਾ ਕਰਨ ਦੀ ਮਨਜ਼ੂਰੀ ਦਿਓ"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"ਸਕ੍ਰੀਨ \'ਤੇ ਝਲਕ ਵਿਖਾਉਣ ਅਤੇ ਧੁਨੀ ਦੀ ਮਨਜ਼ੂਰੀ ਦਿਓ"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"ਸੂਚਨਾਵਾਂ ਸੂਚੀ ਦੇ ਸਿਖਰ \'ਤੇ ਵਿਖਾਓ, ਸਕ੍ਰੀਨ \'ਤੇ ਝਲਕ ਵਿਖਾਉਣ ਅਤੇ ਧੁਨੀ ਦੀ ਮਨਜ਼ੂਰੀ ਦਿਓ"</string>
<string name="notification_more_settings" msgid="816306283396553571">"ਹੋਰ ਸੈਟਿੰਗਾਂ"</string>
<string name="notification_done" msgid="5279426047273930175">"ਹੋ ਗਿਆ"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"ਸਧਾਰਨ ਰੰਗ"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"ਰਾਤ ਦੇ ਰੰਗ"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"ਕਸਟਮ ਰੰਗ"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"ਸਵੈ"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"ਅਗਿਆਤ ਰੰਗ"</string>
- <string name="color_transform" msgid="6985460408079086090">"ਰੰਗ ਸੋਧ"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਟਾਇਲ ਵਿਖਾਓ"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"ਕਸਟਮ ਤਬਦੀਲੀ ਯੋਗ ਬਣਾਓ"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"ਰੰਗ ਅਤੇ ਵਿਖਾਲਾ"</string>
+ <string name="night_mode" msgid="3540405868248625488">"ਰਾਤ ਮੋਡ"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"ਡਿਸਪਲੇ ਨੂੰ ਕੈਲੀਬ੍ਰੇਟ ਕਰੋ"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"ਚਾਲੂ"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"ਬੰਦ"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"ਸਵੈਚਾਲਿਤ ਤੌਰ \'ਤੇ ਚਾਲੂ ਕਰੋ"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"ਟਿਕਾਣੇ ਅਤੇ ਦਿਨ ਦੇ ਸਮੇਂ ਲਈ ਢੁਕਵੇਂ ਰਾਤ ਮੋਡ \'ਤੇ ਸਵਿੱਚ ਕਰੋ"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"ਜਦੋਂ ਰਾਤ ਮੋਡ ਚਾਲੂ ਹੋਵੇ"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Android OS ਲਈ ਗੂੜ੍ਹੇ ਥੀਮ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"ਟਿੰਟ ਨੂੰ ਵਿਵਸਥਿਤ ਕਰੋ"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"ਚਮਕ ਨੂੰ ਵਿਵਸਥਿਤ ਕਰੋ"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"ਗੂੜ੍ਹੇ ਥੀਮ ਨੂੰ Android OS ਦੇ ਉਹਨਾਂ ਮੁੱਖ ਖੇਤਰਾਂ \'ਤੇ ਲਾਗੂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ ਜੋ ਆਮ ਤੌਰ \'ਤੇ ਇੱਕ ਹਲਕੇ ਥੀਮ ਵਿੱਚ ਵਿਖਾਏ ਜਾਂਦੇ ਹਨ, ਜਿਵੇਂ ਕਿ ਸੈਟਿੰਗਾਂ।"</string>
<string name="color_apply" msgid="9212602012641034283">"ਲਾਗੂ ਕਰੋ"</string>
<string name="color_revert_title" msgid="4746666545480534663">"ਸੈਟਿੰਗਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ"</string>
<string name="color_revert_message" msgid="9116001069397996691">"ਕੁਝ ਰੰਗ ਸੈਟਿੰਗਾਂ ਇਸ ਡੀਵਾਈਸ ਨੂੰ ਬੇਕਾਰ ਕਰ ਸਕਦੀਆਂ ਹਨ। ਇਹਨਾਂ ਰੰਗ ਸੈਟਿੰਗਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰਨ ਲਈ ਠੀਕ \'ਤੇ ਕਲਿੱਕ ਕਰੋ, ਨਹੀਂ ਤਾਂ ਇਹ ਸੈਟਿੰਗਾਂ 10 ਸਕਿੰਟ ਬਾਅਦ ਮੁੜ-ਸੈੱਟ ਹੋ ਜਾਣਗੀਆਂ।"</string>
@@ -486,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"ਮੁੱਖ ਸਕ੍ਰੀਨ"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"ਹਾਲੀਆ"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"ਪਿੱਛੇ"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"ਵੌਲਯੂਮ ਵਿੱਚ ਮੈਨੂੰ ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ ਵਿਖਾਓ"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"ਵੌਲਯੂਮ ਡਾਇਲੌਗ ਵਿੱਚ ਮੈਨੂੰ ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ ਦੇ ਪੂਰੇ ਨਿਯੰਤ੍ਰਣ ਦੀ ਮਨਜ਼ੂਰੀ ਦਿਓ।"</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"ਵੌਲਯੂਮ ਅਤੇ ਮੈਨੂੰ ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"ਵੌਲਯੂਮ ਘੱਟ ਹੋਣ \'ਤੇ ਮੈਨੂੰ ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ ਵਿੱਚ ਦਾਖਲ ਹੋਵੋ"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"ਵੌਲਯੂਮ ਕੰਟਰੋਲਾਂ ਨਾਲ ਵਿਖਾਓ"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"ਮੈਨੂੰ ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"ਵੌਲਯੂਮ ਬਟਨ ਸ਼ਾਰਟਕੱਟ"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"ਵੌਲਯੂਮ ਉੱਚੀ ਹੋਣ \'ਤੇ ਮੈਨੂੰ ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ ਤੋਂ ਬਾਹਰ ਜਾਓ"</string>
<string name="battery" msgid="7498329822413202973">"ਬੈਟਰੀ"</string>
<string name="clock" msgid="7416090374234785905">"ਘੜੀ"</string>
<string name="headset" msgid="4534219457597457353">"ਹੈੱਡਸੈੱਟ"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ਹੈੱਡਫੋਨਾਂ ਨੂੰ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ਹੈੱਡਸੈੱਟ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"ਚਿੰਨ੍ਹਾਂ ਦੇ ਸਥਿਤੀ ਪੱਟੀ ਵਿੱਚ ਵਿਖਾਏ ਜਾਣ ਨੂੰ ਯੋਗ ਜਾਂ ਅਯੋਗ ਬਣਾਓ।"</string>
<string name="data_saver" msgid="5037565123367048522">"ਡੈਟਾ ਸੇਵਰ"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"ਡੈਟਾ ਸੇਵਰ ਚਾਲੂ ਹੈ"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"ਡੈਟਾ ਸੇਵਰ ਬੰਦ ਹੈ"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"ਚਾਲੂ"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"ਬੰਦ"</string>
<string name="nav_bar" msgid="1993221402773877607">"ਆਵਾਗੌਣ ਪੱਟੀ"</string>
<string name="start" msgid="6873794757232879664">"ਸ਼ੁਰੂ ਕਰੋ"</string>
<string name="center" msgid="4327473927066010960">"ਕੇਂਦਰ"</string>
@@ -523,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"ਝਲਕ"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"ਟਾਇਲਾਂ ਨੂੰ ਸ਼ਾਮਲ ਕਰਨ ਲਈ ਘਸੀਟੋ"</string>
<string name="qs_edit" msgid="2232596095725105230">"ਸੰਪਾਦਨ ਕਰੋ"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"ਸਮਾਂ"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"ਘੰਟੇ, ਮਿੰਟ, ਅਤੇ ਸਕਿੰਟ ਵਿਖਾਓ"</item>
+ <item msgid="1427801730816895300">"ਘੰਟੇ ਅਤੇ ਮਿੰਟ ਵਿਖਾਓ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item>
+ <item msgid="3830170141562534721">"ਇਸ ਚਿੰਨ੍ਹ ਨੂੰ ਨਾ ਵਿਖਾਓ"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"ਹਮੇਸ਼ਾਂ ਪ੍ਰਤੀਸ਼ਤਤਾ ਵਿਖਾਓ"</item>
+ <item msgid="2139628951880142927">"ਚਾਰਜਿੰਗ ਦੌਰਾਨ ਪ੍ਰਤੀਸ਼ਤਤਾ ਵਿਖਾਓ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item>
+ <item msgid="3327323682209964956">"ਇਸ ਚਿੰਨ੍ਹ ਨੂੰ ਨਾ ਵਿਖਾਓ"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"ਹੋਰ"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਡਿਵਾਈਡਰ"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"ਹੇਠਾਂ ਲੈ ਜਾਓ"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"ਉੱਪਰ ਲੈ ਜਾਓ"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"ਖੱਬੇ ਲੈ ਜਾਓ"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"ਸੱਜੇ ਲੈ ਜਾਓ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 2eae56a..974685c 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -75,7 +75,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Wykonano zrzut ekranu."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Dotknij, aby wyświetlić zrzut ekranu."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Nie udało się wykonać zrzutu ekranu."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Nie można wykonać zrzutu ekranu, bo brak miejsca albo nie zezwala na to aplikacja lub Twoja organizacja."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Nie można zapisać zrzutu ekranu, bo brakuje miejsca w pamięci."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Nie możesz wykonać zrzutu ekranu, bo nie zezwala na to aplikacja lub Twoja organizacja."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB – opcje przesyłania plików"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Podłącz jako odtwarzacz multimedialny (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Podłącz jako aparat (PTP)"</string>
@@ -208,6 +209,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Więcej czasu."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Mniej czasu."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Latarka wyłączona."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Latarka niedostępna."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Latarka włączona."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Latarka została wyłączona."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Latarka została włączona."</string>
@@ -276,7 +278,7 @@
<string name="quick_settings_cast_title" msgid="7709016546426454729">"Przesyłanie"</string>
<string name="quick_settings_casting" msgid="6601710681033353316">"Przesyłam"</string>
<string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Urządzenie bez nazwy"</string>
- <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Wszystko gotowe do przesyłania"</string>
+ <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Gotowy do działania"</string>
<string name="quick_settings_cast_detail_empty_text" msgid="311785821261640623">"Brak dostępnych urządzeń"</string>
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Jasność"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATYCZNA"</string>
@@ -303,10 +305,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"przypinanie ekranu"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"szukaj"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Nie udało się uruchomić aplikacji <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Aplikacja <xliff:g id="APP">%s</xliff:g> została wyłączona w trybie bezpiecznym."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Historia"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Wyczyść"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Ta aplikacja nie obsługuje trybu wielu okien"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Aplikacja nie obsługuje trybu wielu okien"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Podziel poziomo"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Podziel pionowo"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Podziel niestandardowo"</string>
@@ -336,8 +339,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Całkowita\ncisza"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Tylko\npriorytetowe"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Tylko\nalarmy"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Wszystkie"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Wszystkie\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Ładuje się (pełne naładowanie za <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Szybkie ładowanie (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do końca)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Wolne ładowanie (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do końca)"</string>
@@ -450,39 +451,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Pokaż sekundy na zegarku na pasku stanu. Może mieć wpływ na czas pracy baterii."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Uporządkuj Szybkie ustawienia"</string>
<string name="show_brightness" msgid="6613930842805942519">"Pokaż jasność w Szybkich ustawieniach"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Włącz przyspieszenie dzielenia ekranu przesunięciem w górę"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Włącz dzielenie ekranu gestem przesunięcia w górę"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Włącz dzielenie ekranu po wykonaniu gestu przesunięcia palcem w górę od przycisku Przegląd"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperymentalne"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Włączyć Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Aby połączyć klawiaturę z tabletem, musisz najpierw włączyć Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Włącz"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Zastosuj do powiadomień typu <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Zastosuj do wszystkich powiadomień z tej aplikacji"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Pokazuj powiadomienia bez sygnału dźwiękowego"</string>
+ <string name="block" msgid="2734508760962682611">"Blokuj wszystkie powiadomienia"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Nie ignoruj"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Nie ignoruj ani nie blokuj"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Pokaż pełne ustawienia ważności"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Zablokowane"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Najmniejsza ważność"</string>
<string name="low_importance" msgid="4109929986107147930">"Mało ważne"</string>
<string name="default_importance" msgid="8192107689995742653">"Ważne"</string>
<string name="high_importance" msgid="1527066195614050263">"Bardzo ważne"</string>
<string name="max_importance" msgid="5089005872719563894">"Pilne"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Nigdy nie pokazuj tych powiadomień"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Pokazuj na dole listy powiadomień bez sygnału dźwiękowego"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Pokazuj te powiadomienia bez sygnału dźwiękowego"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Pokazuj na górze listy powiadomień i sygnalizuj dźwiękiem"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Wyświetlaj na ekranie i odtwarzaj dźwięk"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Pokazuj na końcu listy powiadomień bez sygnału dźwiękowego"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Pokazuj te powiadomienia bez sygnału dźwiękowego"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Zezwól na sygnalizowanie tych powiadomień dźwiękiem"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Wyświetlaj na ekranie i sygnalizuj dźwiękiem"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Pokazuj na początku listy powiadomień, wyświetlaj na ekranie i sygnalizuj dźwiękiem"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Więcej ustawień"</string>
<string name="notification_done" msgid="5279426047273930175">"Gotowe"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Kolory standardowe"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Kolory nocne"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Kolory niestandardowe"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automatycznie"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Nieznane kolory"</string>
- <string name="color_transform" msgid="6985460408079086090">"Zmiana koloru"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Pokazuj kafelek szybkich ustawień"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Włącz przekształcenie niestandardowe"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Kolor i wygląd"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Tryb nocny"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Kalibracja wyświetlacza"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Wł."</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Wył."</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Włącz automatycznie"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Przełączaj na tryb nocny odpowiednio do lokalizacji i pory dnia"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Gdy jest włączony tryb nocny"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Użyj motywu ciemnego dla Androida"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Dostosuj odcień"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Dostosuj jasność"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Motyw ciemny zostanie zastosowany do głównych obszarów Androida, które normalnie są jasne, takich jak Ustawienia."</string>
<string name="color_apply" msgid="9212602012641034283">"Zastosuj"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Potwierdź ustawienia"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Niektóre ustawienia kolorów mogą utrudniać korzystanie z urządzenia. Kliknij OK, by potwierdzić te ustawienia kolorów. Jeśli tego nie zrobisz, zostaną one zresetowane po 10 sekundach."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Wykorzystanie baterii"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Oszczędzanie baterii nie jest dostępne podczas ładowania"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Oszczędzanie baterii"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Zmniejsza wydajność i ogranicza dane w tle"</string>
@@ -490,21 +499,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Ekran główny"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Ostatnie"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Wstecz"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Pokaż panel Nie przeszkadzać w oknie sterowania głośnością"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Pokaż cały panel Nie przeszkadzać w oknie sterowania głośnością."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Głośność i tryb Nie przeszkadzać"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Włącz tryb Nie przeszkadzać przy zmniejszaniu głośności"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Pokazuj z regulacją głośności"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Nie przeszkadzać"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Wł./wył. przyciskami głośności"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Wyłącz tryb Nie przeszkadzać przy zwiększaniu głośności"</string>
<string name="battery" msgid="7498329822413202973">"Bateria"</string>
<string name="clock" msgid="7416090374234785905">"Zegar"</string>
<string name="headset" msgid="4534219457597457353">"Zestaw słuchawkowy"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Słuchawki są podłączone"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Zestaw słuchawkowy jest podłączony"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Włącz lub wyłącz wyświetlanie ikon na pasku stanu."</string>
<string name="data_saver" msgid="5037565123367048522">"Oszczędzanie danych"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Oszczędzanie danych jest włączone"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Oszczędzanie danych jest wyłączone"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Wł."</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Wył."</string>
<string name="nav_bar" msgid="1993221402773877607">"Pasek nawigacji"</string>
<string name="start" msgid="6873794757232879664">"Na początku"</string>
<string name="center" msgid="4327473927066010960">"Na środku"</string>
@@ -527,4 +535,21 @@
<string name="preview" msgid="9077832302472282938">"Podgląd"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Przeciągnij, aby dodać kafelki"</string>
<string name="qs_edit" msgid="2232596095725105230">"Edytuj"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Godzina"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Pokazuj godziny, minuty i sekundy"</item>
+ <item msgid="1427801730816895300">"Pokazuj godziny i minuty (domyślnie)"</item>
+ <item msgid="3830170141562534721">"Nie pokazuj tej ikony"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Zawsze pokazuj procent"</item>
+ <item msgid="2139628951880142927">"Pokazuj procent podczas ładowania (domyślnie)"</item>
+ <item msgid="3327323682209964956">"Nie pokazuj tej ikony"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Inne"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Linia dzielenia ekranu"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Przesuń w dół"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Przesuń w górę"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Przesuń w lewo"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Przesuń w prawo"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 5219454..3797adc 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Captura de tela obtida."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Toque para visualizar a captura de tela."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Não foi possível obter a captura de tela."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Não é possível capturar a tela porque não há espaço suficiente ou o app ou organização não permite."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Não é possível salvar a captura de tela, porque não há espaço suficiente."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Capturas de tela não são permitidas pelo app ou por sua organização."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Opções transf. arq. por USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Conectar como media player (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Montar como uma câmera (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Mais tempo."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Menos tempo."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lanterna desativada."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lanterna indisponível."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lanterna ativada."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"A lanterna foi desativada."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"A lanterna foi ativada."</string>
@@ -305,6 +307,8 @@
<skip />
<string name="recents_history_button_label" msgid="5153358867807604821">"Histórico"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Limpar"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Este app não é compatível com o modo de várias janelas"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"O app não é compatível com o modo de várias janelas"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisão horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisão vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisão personalizada"</string>
@@ -334,8 +338,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Silêncio\ntotal"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Somente\nprioridade"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Somente\nalarmes"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Tudo"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Todas\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Carregando (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> até concluir)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Carregando rapidamente (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para conclusão)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Carregando lentamente (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para conclusão)"</string>
@@ -448,39 +450,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Mostrar segundos do relógio na barra de status. Pode afetar a duração da bateria."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar \"Configurações rápidas\""</string>
<string name="show_brightness" msgid="6613930842805942519">"Mostrar brilho nas \"Configurações rápidas\""</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Ativar acelerador para dividir a tela ao deslizar para cima"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Ativar gesto para dividir a tela ao deslizar para cima"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Ativa o gesto para entrar no modo de tela dividida deslizando a partir do botão \"Visão geral\""</string>
<string name="experimental" msgid="6198182315536726162">"Experimentais"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Ativar o Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Para conectar o teclado ao tablet, é preciso primeiro ativar o Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Ativar"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Aplicar a notificações de <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Aplicar a todas as notificações deste app"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Mostrar notificações de forma silenciosa"</string>
+ <string name="block" msgid="2734508760962682611">"Bloquear todas as notificações"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Não silenciar"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Não silenciar ou bloquear"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Mostrar todas as configurações de importância"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloqueadas"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Importância mínima"</string>
<string name="low_importance" msgid="4109929986107147930">"Importância baixa"</string>
<string name="default_importance" msgid="8192107689995742653">"Importância normal"</string>
<string name="high_importance" msgid="1527066195614050263">"Importância elevada"</string>
<string name="max_importance" msgid="5089005872719563894">"Importância urgente"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Nunca mostrar essas notificações"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Mostrar na parte inferior da lista de notificações de forma silenciosa"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Mostrar essas notificações de forma silenciosa"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Mostrar na parte superior da lista de notificações e emitir som"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Mostrar parcialmente na tela e emitir som"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Mostrar na parte inferior da lista de notificações de forma silenciosa"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Mostrar essas notificações de forma silenciosa"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Permitir que essas notificações emitam sons"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Mostrar parcialmente na tela e permitir som"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Mostrar na parte superior da lista de notificações, mostrar parcialmente na tela e permitir sons"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Mais configurações"</string>
<string name="notification_done" msgid="5279426047273930175">"Concluído"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Cores normais"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Cores noturnas"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Cores personalizadas"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automáticas"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Cores desconhecidas"</string>
- <string name="color_transform" msgid="6985460408079086090">"Modificação de cor"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Mostrar bloco de configurações rápidas"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Ativar transformação personalizada"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Cor e aparência"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Modo noturno"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Calibrar tela"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Ativado"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Desativado"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Ativar automaticamente"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Alternar para o modo noturno conforme apropriado para o local e hora do dia"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Quando o modo noturno está ativado"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Usar o tema escuro para o SO Android"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Ajustar tonalidade"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Ajustar brilho"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"O tema escuro é aplicado a áreas centrais do sistema operacional Android que normalmente são exibidas em um tema claro, como as configurações."</string>
<string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirmar configurações"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Algumas configurações de cor podem tornar o dispositivo inutilizável. Clique em \"OK\" para confirmar essas configurações de cor; caso contrário, essas configurações serão redefinidas após 10 segundos."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Uso da bateria"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"A Economia de bateria não fica disponível durante o carregamento"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Economia de bateria"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduz o desempenho e os dados em segundo plano"</string>
@@ -488,21 +498,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Início"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recentes"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Voltar"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Mostrar \"Não perturbe\" nas opções de volume"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Permitir controle total do recurso \"Não perturbe\" na caixa de diálogo de volume."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Volume e \"Não perturbe\""</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Entre no modo \"Não perturbe\" abaixando o volume"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostrar com controles de volume"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Não perturbe"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Atalho de botões de volume"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Saia do modo \"Não perturbe\" aumentando o volume"</string>
<string name="battery" msgid="7498329822413202973">"Bateria"</string>
<string name="clock" msgid="7416090374234785905">"Relógio"</string>
<string name="headset" msgid="4534219457597457353">"Fone de ouvido"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Fones de ouvido conectados"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Fone de ouvido conectado"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Ativar ou desativar a exibição de ícones na barra de status."</string>
<string name="data_saver" msgid="5037565123367048522">"Economia de dados"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Economia de dados ativada"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"A Economia de dados está desativada"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Ativado"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Desativado"</string>
<string name="nav_bar" msgid="1993221402773877607">"Barra de navegação"</string>
<string name="start" msgid="6873794757232879664">"Iniciar"</string>
<string name="center" msgid="4327473927066010960">"Centralizar"</string>
@@ -525,4 +534,21 @@
<string name="preview" msgid="9077832302472282938">"Visualização"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Arraste para adicionar blocos"</string>
<string name="qs_edit" msgid="2232596095725105230">"Editar"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Horas"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Mostrar horas, minutos e segundos"</item>
+ <item msgid="1427801730816895300">"Mostrar horas e minutos (padrão)"</item>
+ <item msgid="3830170141562534721">"Não mostrar este ícone"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Sempre mostrar porcentagem"</item>
+ <item msgid="2139628951880142927">"Mostrar porcentagem durante o carregamento (padrão)"</item>
+ <item msgid="3327323682209964956">"Não mostrar este ícone"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Outros"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Divisor de tela"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Mover para baixo"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Mover para cima"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Mover para a esquerda"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Mover para a direita"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 064e565..7ee2554 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Captura de ecrã efetuada"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Toque para ver a captura de ecrã"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Não foi possível obter captura de ecrã."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Imp. tirar capt. ecrã devido ao espaço de armaz. limit. ou isso não é permitido pela aplic. da sua ent."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Não é possível guardar a captura de ecrã devido a espaço de armazenamento limitado."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"A aplicação ou a sua entidade não tem autorização para tirar capturas de ecrã."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Opções de transm. de fich. USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Montar como leitor de multimédia (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Montar como câmara (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Mais tempo."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Menos tempo."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lanterna desligada."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lanterna indisponível."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lanterna ligada."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Lanterna desligada."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Lanterna ligada."</string>
@@ -304,6 +306,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"O <xliff:g id="APP">%s</xliff:g> está desativado no modo de segurança."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Histórico"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Limpar"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Esta aplicação não é compatível com várias janelas"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"A aplicação não é compatível com várias janelas"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisão horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisão vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisão personalizada"</string>
@@ -333,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Silêncio\ntotal"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Apenas\nprioridade"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Apenas\nalarmes"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Tudo"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Todas\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"A carregar (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> até à carga máxima)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"A carregar rapid. (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> até à carga máxima)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"A carregar lentam. (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> até à carga máxima)"</string>
@@ -447,34 +449,43 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Mostrar segundos do relógio na barra de estado. Pode afetar a autonomia da bateria."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar as Definições rápidas"</string>
<string name="show_brightness" msgid="6613930842805942519">"Mostrar luminosidade nas Definições rápidas"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Ativar acelerador de deslize ráp. para cima do ecrã dividido"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Ativar gesto de deslize rápido para cima do ecrã dividido"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Ativar o gesto para aceder ao ecrã dividido ao deslizar rapidamente para cima a partir do botão Vista geral"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Pretende ativar o Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Para ligar o teclado ao tablet, tem de ativar primeiro o Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Ativar"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Aplicar a notificações de <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Aplicar a todas as notificações desta aplicação"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Mostrar notificações sem som"</string>
+ <string name="block" msgid="2734508760962682611">"Bloquear todas as notificações"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Não silenciar"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Não silenciar nem bloquear"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Mostrar definições de importância completas"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloqueado"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Importância mín."</string>
<string name="low_importance" msgid="4109929986107147930">"Importância baixa"</string>
<string name="default_importance" msgid="8192107689995742653">"Importância normal"</string>
<string name="high_importance" msgid="1527066195614050263">"Importância alta"</string>
<string name="max_importance" msgid="5089005872719563894">"Urgente"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Nunca mostrar estas notificações"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Mostrar na parte inferior da lista de notificações sem som"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Mostrar estas notificações sem som"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Mostrar na parte superior da lista de notificações e emitir som"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Mostrar no ecrã e emitir som"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Mostrar na parte inferior da lista de notificações sem som"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Mostrar estas notificações sem som"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Permitir que estas notificações emitam sons"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Mostrar no ecrã e permitir som"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Mostrar na parte superior da lista de notificações, mostrar no ecrã e permitir som"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Mais definições"</string>
<string name="notification_done" msgid="5279426047273930175">"Concluído"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Cores normais"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Cores noturnas"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Cores personalizadas"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automáticas"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Cores desconhecidas"</string>
- <string name="color_transform" msgid="6985460408079086090">"Modificação de cor"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Mostrar o mosaico de Definições rápidas"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Ativar transformação personalizada"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Cor e aspeto"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Modo noturno"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Calibrar ecrã"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Ativado"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Desativado"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Ligar automaticamente"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Alternar para o Modo noturno consoante a localização e a hora do dia"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Quando o Modo noturno está ativado"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Utilizar o tema escuro para o SO Android"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Ajustar tonalidade"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Ajustar brilho"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"O tema escuro é aplicado a áreas essenciais do SO Android que são normalmente apresentadas num tema claro, como as Definições."</string>
<string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirmar as definições"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Algumas definições de cor podem tornar este dispositivo instável. Clique em OK para confirmar estas definições de cor. Caso contrário, estas definições serão repostas após 10 segundos."</string>
@@ -486,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Página inicial"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recentes"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Anterior"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Mostrar Não incomodar no volume"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Permitir o controlo total de Não incomodar na caixa de diálogo do volume."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Volume e Não incomodar"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Ativar Não incomodar ao diminuir o volume"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostrar com controlos de volume"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Não incomodar"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Atalho dos botões de volume"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Desativar Não incomodar ao aumentar o volume"</string>
<string name="battery" msgid="7498329822413202973">"Bateria"</string>
<string name="clock" msgid="7416090374234785905">"Relógio"</string>
<string name="headset" msgid="4534219457597457353">"Ausc. com microfone integrado"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Auscultadores ligados"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Auscultadores com microfone integrado ligados"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Ativar ou desativar a apresentação de ícones na barra de estado."</string>
<string name="data_saver" msgid="5037565123367048522">"Poupança de dados"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Poupança de dados ativada"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Poupança de dados desativada"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Ativado"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Desativado"</string>
<string name="nav_bar" msgid="1993221402773877607">"Barra de navegação"</string>
<string name="start" msgid="6873794757232879664">"Início"</string>
<string name="center" msgid="4327473927066010960">"Centro"</string>
@@ -523,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Pré-visualizar"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Arraste para adicionar mosaicos"</string>
<string name="qs_edit" msgid="2232596095725105230">"Editar"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Hora"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Mostrar horas, minutos e segundos"</item>
+ <item msgid="1427801730816895300">"Mostrar horas e minutos (predefinição)"</item>
+ <item msgid="3830170141562534721">"Não mostrar este ícone"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Mostrar sempre a percentagem"</item>
+ <item msgid="2139628951880142927">"Mostrar a percentagem durante o carregamento (predefinição)"</item>
+ <item msgid="3327323682209964956">"Não mostrar este ícone"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Outro"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Divisor do ecrã dividido"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Mover para baixo"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Mover para cima"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Mover para a esquerda"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Mover para a direita"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 5219454..3797adc 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Captura de tela obtida."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Toque para visualizar a captura de tela."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Não foi possível obter a captura de tela."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Não é possível capturar a tela porque não há espaço suficiente ou o app ou organização não permite."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Não é possível salvar a captura de tela, porque não há espaço suficiente."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Capturas de tela não são permitidas pelo app ou por sua organização."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Opções transf. arq. por USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Conectar como media player (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Montar como uma câmera (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Mais tempo."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Menos tempo."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lanterna desativada."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lanterna indisponível."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lanterna ativada."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"A lanterna foi desativada."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"A lanterna foi ativada."</string>
@@ -305,6 +307,8 @@
<skip />
<string name="recents_history_button_label" msgid="5153358867807604821">"Histórico"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Limpar"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Este app não é compatível com o modo de várias janelas"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"O app não é compatível com o modo de várias janelas"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisão horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisão vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisão personalizada"</string>
@@ -334,8 +338,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Silêncio\ntotal"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Somente\nprioridade"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Somente\nalarmes"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Tudo"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Todas\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Carregando (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> até concluir)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Carregando rapidamente (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para conclusão)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Carregando lentamente (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para conclusão)"</string>
@@ -448,39 +450,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Mostrar segundos do relógio na barra de status. Pode afetar a duração da bateria."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar \"Configurações rápidas\""</string>
<string name="show_brightness" msgid="6613930842805942519">"Mostrar brilho nas \"Configurações rápidas\""</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Ativar acelerador para dividir a tela ao deslizar para cima"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Ativar gesto para dividir a tela ao deslizar para cima"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Ativa o gesto para entrar no modo de tela dividida deslizando a partir do botão \"Visão geral\""</string>
<string name="experimental" msgid="6198182315536726162">"Experimentais"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Ativar o Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Para conectar o teclado ao tablet, é preciso primeiro ativar o Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Ativar"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Aplicar a notificações de <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Aplicar a todas as notificações deste app"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Mostrar notificações de forma silenciosa"</string>
+ <string name="block" msgid="2734508760962682611">"Bloquear todas as notificações"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Não silenciar"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Não silenciar ou bloquear"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Mostrar todas as configurações de importância"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloqueadas"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Importância mínima"</string>
<string name="low_importance" msgid="4109929986107147930">"Importância baixa"</string>
<string name="default_importance" msgid="8192107689995742653">"Importância normal"</string>
<string name="high_importance" msgid="1527066195614050263">"Importância elevada"</string>
<string name="max_importance" msgid="5089005872719563894">"Importância urgente"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Nunca mostrar essas notificações"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Mostrar na parte inferior da lista de notificações de forma silenciosa"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Mostrar essas notificações de forma silenciosa"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Mostrar na parte superior da lista de notificações e emitir som"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Mostrar parcialmente na tela e emitir som"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Mostrar na parte inferior da lista de notificações de forma silenciosa"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Mostrar essas notificações de forma silenciosa"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Permitir que essas notificações emitam sons"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Mostrar parcialmente na tela e permitir som"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Mostrar na parte superior da lista de notificações, mostrar parcialmente na tela e permitir sons"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Mais configurações"</string>
<string name="notification_done" msgid="5279426047273930175">"Concluído"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Cores normais"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Cores noturnas"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Cores personalizadas"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automáticas"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Cores desconhecidas"</string>
- <string name="color_transform" msgid="6985460408079086090">"Modificação de cor"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Mostrar bloco de configurações rápidas"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Ativar transformação personalizada"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Cor e aparência"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Modo noturno"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Calibrar tela"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Ativado"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Desativado"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Ativar automaticamente"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Alternar para o modo noturno conforme apropriado para o local e hora do dia"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Quando o modo noturno está ativado"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Usar o tema escuro para o SO Android"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Ajustar tonalidade"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Ajustar brilho"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"O tema escuro é aplicado a áreas centrais do sistema operacional Android que normalmente são exibidas em um tema claro, como as configurações."</string>
<string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirmar configurações"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Algumas configurações de cor podem tornar o dispositivo inutilizável. Clique em \"OK\" para confirmar essas configurações de cor; caso contrário, essas configurações serão redefinidas após 10 segundos."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Uso da bateria"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"A Economia de bateria não fica disponível durante o carregamento"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Economia de bateria"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduz o desempenho e os dados em segundo plano"</string>
@@ -488,21 +498,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Início"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recentes"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Voltar"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Mostrar \"Não perturbe\" nas opções de volume"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Permitir controle total do recurso \"Não perturbe\" na caixa de diálogo de volume."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Volume e \"Não perturbe\""</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Entre no modo \"Não perturbe\" abaixando o volume"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostrar com controles de volume"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Não perturbe"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Atalho de botões de volume"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Saia do modo \"Não perturbe\" aumentando o volume"</string>
<string name="battery" msgid="7498329822413202973">"Bateria"</string>
<string name="clock" msgid="7416090374234785905">"Relógio"</string>
<string name="headset" msgid="4534219457597457353">"Fone de ouvido"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Fones de ouvido conectados"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Fone de ouvido conectado"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Ativar ou desativar a exibição de ícones na barra de status."</string>
<string name="data_saver" msgid="5037565123367048522">"Economia de dados"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Economia de dados ativada"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"A Economia de dados está desativada"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Ativado"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Desativado"</string>
<string name="nav_bar" msgid="1993221402773877607">"Barra de navegação"</string>
<string name="start" msgid="6873794757232879664">"Iniciar"</string>
<string name="center" msgid="4327473927066010960">"Centralizar"</string>
@@ -525,4 +534,21 @@
<string name="preview" msgid="9077832302472282938">"Visualização"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Arraste para adicionar blocos"</string>
<string name="qs_edit" msgid="2232596095725105230">"Editar"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Horas"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Mostrar horas, minutos e segundos"</item>
+ <item msgid="1427801730816895300">"Mostrar horas e minutos (padrão)"</item>
+ <item msgid="3830170141562534721">"Não mostrar este ícone"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Sempre mostrar porcentagem"</item>
+ <item msgid="2139628951880142927">"Mostrar porcentagem durante o carregamento (padrão)"</item>
+ <item msgid="3327323682209964956">"Não mostrar este ícone"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Outros"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Divisor de tela"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Mover para baixo"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Mover para cima"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Mover para a esquerda"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Mover para a direita"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 1af5b42..c2bec08 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -21,10 +21,10 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7164937344850004466">"UI sistem"</string>
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Ștergeți"</string>
- <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Eliminaţi din listă"</string>
+ <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Eliminați din listă"</string>
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Informații despre aplicație"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Ecranele dvs. recente apar aici"</string>
- <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Renunţaţi la aplicațiile recente"</string>
+ <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Renunțați la aplicațiile recente"</string>
<plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
<item quantity="few">%d ecrane în Recente</item>
<item quantity="other">%d de ecrane în Recente</item>
@@ -36,7 +36,7 @@
<string name="battery_low_title" msgid="6456385927409742437">"Bateria este aproape descărcată"</string>
<string name="battery_low_percent_format" msgid="2900940511201380775">"Procent rămas din baterie: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"Procent rămas din baterie: <xliff:g id="PERCENTAGE">%s</xliff:g>. Economisirea bateriei este activată."</string>
- <string name="invalid_charger" msgid="4549105996740522523">"Încărcarea USB nu este acceptată. \nUtilizaţi numai încărcătorul furnizat."</string>
+ <string name="invalid_charger" msgid="4549105996740522523">"Încărcarea USB nu este acceptată. \nUtilizați numai încărcătorul furnizat."</string>
<string name="invalid_charger_title" msgid="3515740382572798460">"Încărcarea prin USB nu este acceptată."</string>
<string name="invalid_charger_text" msgid="5474997287953892710">"Utilizați numai încărcătorul furnizat."</string>
<string name="battery_low_why" msgid="4553600287639198111">"Setări"</string>
@@ -50,16 +50,16 @@
<string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTOM."</string>
<string name="status_bar_settings_notifications" msgid="397146176280905137">"Notificări"</string>
<string name="bluetooth_tethered" msgid="7094101612161133267">"Conectat prin tethering prin Bluetooth"</string>
- <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Setaţi metode introducere text"</string>
+ <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Setați metode introducere text"</string>
<string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Tastatură fizică"</string>
<string name="usb_device_permission_prompt" msgid="834698001271562057">"Permiteți aplicației <xliff:g id="APPLICATION">%1$s</xliff:g> să acceseze dispozitivul USB?"</string>
<string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Permiteți aplicației <xliff:g id="APPLICATION">%1$s</xliff:g> să acceseze accesoriul USB?"</string>
- <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Deschideţi <xliff:g id="ACTIVITY">%1$s</xliff:g> la conectarea acestui dispozitiv USB?"</string>
- <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"Deschideţi <xliff:g id="ACTIVITY">%1$s</xliff:g> la conectarea acestui accesoriu USB?"</string>
- <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Aplic. instal. nu funcţ. cu acest acces. USB. Aflați despre acest accesoriu la <xliff:g id="URL">%1$s</xliff:g>"</string>
+ <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Deschideți <xliff:g id="ACTIVITY">%1$s</xliff:g> la conectarea acestui dispozitiv USB?"</string>
+ <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"Deschideți <xliff:g id="ACTIVITY">%1$s</xliff:g> la conectarea acestui accesoriu USB?"</string>
+ <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Aplic. instal. nu funcț. cu acest acces. USB. Aflați despre acest accesoriu la <xliff:g id="URL">%1$s</xliff:g>"</string>
<string name="title_usb_accessory" msgid="4966265263465181372">"Accesoriu USB"</string>
<string name="label_view" msgid="6304565553218192990">"Afișați"</string>
- <string name="always_use_device" msgid="1450287437017315906">"Utilizaţi în mod prestabilit pt. acest dispoz. USB"</string>
+ <string name="always_use_device" msgid="1450287437017315906">"Utilizați în mod prestabilit pt. acest dispoz. USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Utiliz. în mod prestabilit pt. acest accesoriu USB"</string>
<string name="usb_debugging_title" msgid="4513918393387141949">"Permiteți depanarea USB?"</string>
<string name="usb_debugging_message" msgid="2220143855912376496">"Amprenta digitală din cheia RSA a computerului este:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
@@ -74,10 +74,11 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Captură de ecran realizată."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Atingeți pentru a vedea captura de ecran."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Captura de ecran nu a putut fi realizată."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Captură de ecran impos. de realizat: spațiu de stoc. limitat sau nu este permisă de apl. sau de organiz."</string>
- <string name="usb_preference_title" msgid="6551050377388882787">"Opţiuni pentru transferul de fișiere prin USB"</string>
- <string name="use_mtp_button_title" msgid="4333504413563023626">"Montaţi ca player media (MTP)"</string>
- <string name="use_ptp_button_title" msgid="7517127540301625751">"Montaţi drept cameră foto (PTP)"</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Captura de ecran nu poate fi salvată din cauza spațiului de stocare limitat."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Crearea capturilor de ecran nu este permisă de aplicație sau de organizația dvs."</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Opțiuni pentru transferul de fișiere prin USB"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Montați ca player media (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Montați drept cameră foto (PTP)"</string>
<string name="installer_cd_button_title" msgid="2312667578562201583">"Instal. aplic. Transfer de fișiere Android pt. Mac"</string>
<string name="accessibility_back" msgid="567011538994429120">"Înapoi"</string>
<string name="accessibility_home" msgid="8217216074895377641">"Ecranul de pornire"</string>
@@ -97,7 +98,7 @@
<string name="recents_caption_resize" msgid="3517056471774958200">"Selectați noul aspect pentru activitate"</string>
<string name="cancel" msgid="6442560571259935130">"Anulați"</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Buton zoom pentru compatibilitate."</string>
- <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Faceţi zoom de la o imagine mai mică la una mai mare."</string>
+ <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Faceți zoom de la o imagine mai mică la una mai mare."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Conectat prin Bluetooth."</string>
<string name="accessibility_bluetooth_disconnected" msgid="7416648669976870175">"Deconectat de la Bluetooth."</string>
<string name="accessibility_no_battery" msgid="358343022352820946">"Nu există baterie."</string>
@@ -157,7 +158,7 @@
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Notificări."</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Ștergeți notificarea."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS activat."</string>
- <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Se obţine GPS."</string>
+ <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Se obține GPS."</string>
<string name="accessibility_tty_enabled" msgid="4613200365379426561">"TeleTypewriter activat."</string>
<string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Vibrare sonerie."</string>
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"Sonerie silențioasă."</string>
@@ -207,6 +208,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Mai mult timp."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Mai puțin timp."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lanterna este dezactivată."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lanterna nu este disponibilă."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lanterna este activată."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Lanterna este dezactivată."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Lanterna este activată."</string>
@@ -302,10 +304,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixare pe ecran"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"căutare"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> nu a putut porni."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Aplicația <xliff:g id="APP">%s</xliff:g> este dezactivată în modul sigur."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Istoric"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Ștergeți"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Această aplicație nu acceptă ferestre multiple"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Aplicația nu acceptă ferestre multiple"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divizare pe orizontală"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divizare pe verticală"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divizare personalizată"</string>
@@ -315,8 +318,8 @@
<string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"Nu se încarcă"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Rețeaua poate\nfi monitorizată"</string>
<string name="description_target_search" msgid="3091587249776033139">"Căutați"</string>
- <string name="description_direction_up" msgid="7169032478259485180">"Glisaţi în sus pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="description_direction_left" msgid="7207478719805562165">"Glisaţi spre stânga pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <string name="description_direction_up" msgid="7169032478259485180">"Glisați în sus pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+ <string name="description_direction_left" msgid="7207478719805562165">"Glisați spre stânga pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="zen_priority_introduction" msgid="3070506961866919502">"Nu veți fi deranjat(ă) de sunete și vibrații, exceptând alarmele, mementourile, evenimentele și apelanții pe care îi menționați."</string>
<string name="zen_priority_customize_button" msgid="7948043278226955063">"Personalizați"</string>
<string name="zen_silence_introduction_voice" msgid="2284540992298200729">"Această opțiune blochează TOATE sunetele și vibrațiile, inclusiv cele ale alarmelor, muzicii, videoclipurilor și jocurilor. Totuși, veți putea iniția apeluri."</string>
@@ -335,8 +338,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Niciun\nsunet"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Numai\ncu prioritate"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Numai\nalarme"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Toate"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Toate\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Se încarcă (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> până la finalizare)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Se încarcă rapid (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> până la finalizare)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Se încarcă lent (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> până la finalizare)"</string>
@@ -449,39 +450,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Afișează secundele pe ceas în bara de stare. Poate afecta autonomia bateriei."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Rearanjați Setările rapide"</string>
<string name="show_brightness" msgid="6613930842805942519">"Afișați luminozitatea în Setările rapide"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Activați acceleratorul pentru accesarea ecranului împărțit prin glisarea în sus"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Activați gestul de accesare a ecranului împărțit prin glisare în sus"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Activați gestul de accesare a ecranului împărțit prin glisarea în sus de la butonul Recente"</string>
<string name="experimental" msgid="6198182315536726162">"Experimentale"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Activați Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Pentru a conecta tastatura la tabletă, mai întâi trebuie să activați Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Activați"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Aplicați notificărilor de tip <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Aplicați tuturor notificărilor de la această aplicație"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Notificările se afișează fără a se emite un sunet"</string>
+ <string name="block" msgid="2734508760962682611">"Blocați toate notificările"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Nu dezactivați sunetul"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Nu dezactivați sunetul și nu blocați"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Afișați toate setările privind importanța"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Blocate"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Importanță minimă"</string>
<string name="low_importance" msgid="4109929986107147930">"Importanță redusă"</string>
<string name="default_importance" msgid="8192107689995742653">"Importanță normală"</string>
<string name="high_importance" msgid="1527066195614050263">"Importanță ridicată"</string>
<string name="max_importance" msgid="5089005872719563894">"Importanță: urgente"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Aceste notificări nu se afișează niciodată"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Se afișează în partea de jos a listei cu notificări fără a se emite un sunet"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Aceste notificări se afișează fără a se emite un sunet"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Se afișează în partea de sus a listei cu notificări și se emite un sunet"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Se afișează pentru o scurtă durată pe ecran și se emite un sunet"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Se afișează în partea de jos a listei cu notificări fără a se emite un sunet"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Aceste notificări se afișează fără a se emite un sunet"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Permiteți acestor notificări să emită sunete"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Se afișează pentru o scurtă durată pe ecran și se permite un sunet"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Apar în partea de sus a listei cu notificări, se afișează pentru scurt timp pe ecran și se permite un sunet"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Mai multe setări"</string>
<string name="notification_done" msgid="5279426047273930175">"Terminat"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Culori normale"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Culori de noapte"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Culori personalizate"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automat"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Culori necunoscute"</string>
- <string name="color_transform" msgid="6985460408079086090">"Modificarea culorilor"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Afișați caseta cu Setările rapide"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Activați transformarea personalizată"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Culoare și aspect"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Modul Noapte"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Calibrați afișarea"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Activat"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Dezactivat"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Activați automat"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Comutați la modul Noapte în funcție de locație și de momentul zilei"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Când modul Noapte este activat"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Folosiți tema întunecată pentru SO Android"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Ajustați culoarea"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Ajustați luminozitatea"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Tema întunecată se aplică zonelor principale ale sistemului de operare Android care sunt de obicei afișate cu o temă deschisă la culoare, cum ar fi Setările."</string>
<string name="color_apply" msgid="9212602012641034283">"Aplicați"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirmați setările"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Unele setări pentru culori pot face dispozitivul să nu mai funcționeze. Dați clic pe OK pentru a confirma aceste setări pentru culori. În caz contrar, acestea se vor reseta după 10 secunde."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Utilizarea bateriei"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Economisirea bateriei nu este disponibilă pe durata încărcării"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Economisirea bateriei"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduce performanța și datele de fundal"</string>
@@ -489,21 +498,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Ecran de pornire"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recente"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Înapoi"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Afișați opțiunile pentru Nu deranjați în dialogul de volum"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Permiteți controlul complet al modului Nu deranjați din dialogul pentru volum."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Volumul și Nu deranjați"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Accesați Nu deranjați la reducerea volumului"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Afișează cu comenzile de volum"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Nu deranja"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Comandă rapidă din butoanele de volum"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Ieșiți din Nu deranjați la creșterea volumului"</string>
<string name="battery" msgid="7498329822413202973">"Baterie"</string>
<string name="clock" msgid="7416090374234785905">"Ceas"</string>
<string name="headset" msgid="4534219457597457353">"Set căști-microfon"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Căștile sunt conectate"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Setul căști-microfon este conectat"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Activați sau dezactivați afișarea pictogramelor în bara de stare."</string>
<string name="data_saver" msgid="5037565123367048522">"Economizor de date"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Economizorul de date este activat"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Economizorul de date este dezactivat"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Activați"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Dezactivați"</string>
<string name="nav_bar" msgid="1993221402773877607">"Bară de navigare"</string>
<string name="start" msgid="6873794757232879664">"La început"</string>
<string name="center" msgid="4327473927066010960">"În centru"</string>
@@ -513,7 +521,7 @@
<string name="select_button" msgid="1597989540662710653">"Selectați butonul de adăugat"</string>
<string name="add_button" msgid="4134946063432258161">"Adăugați un buton"</string>
<string name="save" msgid="2311877285724540644">"Salvați"</string>
- <string name="reset" msgid="2448168080964209908">"Resetaţi"</string>
+ <string name="reset" msgid="2448168080964209908">"Resetați"</string>
<string name="no_home_title" msgid="1563808595146071549">"Nu s-a găsit niciun buton Ecran de pornire"</string>
<string name="no_home_message" msgid="5408485011659260911">"Pentru a naviga pe acest dispozitiv este necesar un buton Ecran de pornire. Adăugați un buton Ecran de pornire înainte să salvați."</string>
<string name="adjust_button_width" msgid="6138616087197632947">"Ajustați lățimea butonului"</string>
@@ -526,4 +534,21 @@
<string name="preview" msgid="9077832302472282938">"Previzualizare"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Trageți pentru a adăuga sectoare"</string>
<string name="qs_edit" msgid="2232596095725105230">"Editați"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Oră"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Afișează orele, minutele și secundele"</item>
+ <item msgid="1427801730816895300">"Afișează orele și minutele (prestabilit)"</item>
+ <item msgid="3830170141562534721">"Nu afișa această pictogramă"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Afișează întotdeauna procentajul"</item>
+ <item msgid="2139628951880142927">"Afișează procentajul când se încarcă (prestabilit)"</item>
+ <item msgid="3327323682209964956">"Nu afișa această pictogramă"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Altele"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Separator pentru ecranul împărțit"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Mutați în jos"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Mutați în sus"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Mutați spre stânga"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Mutați spre dreapta"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index ba1373f..8ece7fa 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -75,7 +75,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Скриншот сохранен"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Нажмите, чтобы просмотреть"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Не удалось сохранить скриншот."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Не удается сделать скриншот: не хватает памяти или нет разрешения от приложения или организации."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Не удалось сохранить скриншот: недостаточно места."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Не удалось сделать скриншот: нет разрешения от приложения или организации."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Параметры передачи через USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Подключить как мультимедийный проигрыватель (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Установить как камеру (PTP)"</string>
@@ -208,6 +209,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Увеличить время."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Уменьшить время."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Фонарик отключен."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Фонарик недоступен."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Фонарик включен."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Фонарик отключен."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Фонарик включен."</string>
@@ -303,10 +305,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Заблокировать в приложении"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"поиск"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Не удалось запустить приложение \"<xliff:g id="APP">%s</xliff:g>\""</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Приложение \"<xliff:g id="APP">%s</xliff:g>\" отключено в безопасном режиме."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Журнал"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Очистить"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Приложение не поддерживает многооконный режим"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Приложение не поддерживает многооконный режим"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Разделить по горизонтали"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Разделить по вертикали"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Разделить по-другому"</string>
@@ -336,8 +339,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Полная\nтишина"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Только\nважные"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Только\nбудильник"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Все"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Все\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Медленная зарядка (осталось <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
@@ -450,39 +451,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Показывать в строке состояния время с точностью до секунды (заряд батареи может расходоваться быстрее)."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Изменить порядок Быстрых настроек"</string>
<string name="show_brightness" msgid="6613930842805942519">"Добавить яркость в Быстрые настройки"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Разделять экран пролистыванием вверх"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Разделять экран пролистыванием вверх"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Включить разделение экрана пролистыванием вверх с кнопки \"Обзор\""</string>
<string name="experimental" msgid="6198182315536726162">"Экспериментальная функция"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Подключение по Bluetooth"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Чтобы подключить клавиатуру к планшету, включите Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Включить"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Применить к уведомлениям на тему \"<xliff:g id="TOPIC_NAME">%1$s</xliff:g>\""</string>
- <string name="apply_to_app" msgid="363016783939815960">"Применить ко всем уведомлениям этого приложения"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Показывать без звука"</string>
+ <string name="block" msgid="2734508760962682611">"Блокировать все уведомления"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Показывать со звуком"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Не блокировать, показывать со звуком"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Показывать все настройки важности"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Блокировка"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Наименьшая важность"</string>
<string name="low_importance" msgid="4109929986107147930">"Низкая важность"</string>
<string name="default_importance" msgid="8192107689995742653">"Средняя важность"</string>
<string name="high_importance" msgid="1527066195614050263">"Высокая важность"</string>
<string name="max_importance" msgid="5089005872719563894">"Крайняя важность"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Не показывать эти уведомления."</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Показывать без звука в конце списка уведомлений."</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Показывать уведомления без звука."</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Показывать со звуком в начале списка уведомлений."</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Показывать со звуком поверх всех окон."</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Показывать без звука в конце списка уведомлений"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Показывать без звука"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Показывать со звуком"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Показывать со звуком поверх всех окон"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Показывать со звуком в начале списка уведомлений и поверх всех окон"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Другие настройки"</string>
<string name="notification_done" msgid="5279426047273930175">"Готово"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Обычные цвета"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Ночные цвета"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Собственные цвета"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Авто"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Неизвестные цвета"</string>
- <string name="color_transform" msgid="6985460408079086090">"Цветовые настройки"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Показывать панель быстрых настроек"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Включить собственные настройки"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Цвета и стиль"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Ночной режим"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Калибровка дисплея"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Включен"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Отключен"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Включать автоматически"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Включать ночной режим с учетом местоположения и времени суток"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"В ночном режиме"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Использовать темное оформление для Android"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Изменять оттенок"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Яркость"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Темное оформление применяется к основным элементам системы Android (таким, как приложение \"Настройки\"), которые обычно показываются в светлом."</string>
<string name="color_apply" msgid="9212602012641034283">"Применить"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Подтвердите настройки"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Некоторые цветовые настройки могут затруднить работу с устройством. Чтобы применить выбранные параметры, нажмите \"ОК\". В противном случае они будут сброшены через 10 секунд."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Уровень заряда"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Режим энергосбережения нельзя включить во время зарядки"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Режим энергосбережения"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Ограничивает производительность и фоновую передачу данных"</string>
@@ -490,21 +499,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Главный экран"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Недавние"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Назад"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Показать панель \"Не беспокоить\" в окне регулировки звука"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Позволяет управлять режимом \"Не беспокоить\" в окне регулировки громкости."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Регулировка громкости и режим \"Не беспокоить\""</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Включать режим \"Не беспокоить\" при уменьшении громкости"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Показывать при нажатии кнопок регулировки громкости"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Не беспокоить"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Кнопки регулировки громкости"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Отключать режим \"Не беспокоить\" при увеличении громкости"</string>
<string name="battery" msgid="7498329822413202973">"Батарея"</string>
<string name="clock" msgid="7416090374234785905">"Часы"</string>
<string name="headset" msgid="4534219457597457353">"Гарнитура"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Наушники подключены"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Гарнитура подключена"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Включение и отключение показа значков в строке состояния"</string>
<string name="data_saver" msgid="5037565123367048522">"Экономия трафика"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Режим экономии трафика включен"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Режим экономии трафика отключен"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Включено"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Отключено"</string>
<string name="nav_bar" msgid="1993221402773877607">"Панель навигации"</string>
<string name="start" msgid="6873794757232879664">"Вверху"</string>
<string name="center" msgid="4327473927066010960">"В центре"</string>
@@ -527,4 +535,21 @@
<string name="preview" msgid="9077832302472282938">"Просмотр"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Перетащите нужные элементы"</string>
<string name="qs_edit" msgid="2232596095725105230">"Изменить"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Время"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Часы, минуты и секунды"</item>
+ <item msgid="1427801730816895300">"Часы и минуты (по умолчанию)"</item>
+ <item msgid="3830170141562534721">"Не показывать этот значок"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Всегда показывать процент заряда"</item>
+ <item msgid="2139628951880142927">"Показывать процент во время зарядки (по умолчанию)"</item>
+ <item msgid="3327323682209964956">"Не показывать этот значок"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Другое"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Разделитель экрана"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Опустить"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Поднять"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Сдвинуть влево"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Сдвинуть вправо"</string>
</resources>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index b15137e..b485320 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"තිර රුව ග්රහණය කරන ලදි."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"ඔබගේ තිර රුව බැලීමට ස්පර්ශ කරන්න."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"තිර රුව ග්රහණය කිරීමට නොහැකි විය."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"සීමිත ආචයනය ඉඩ හේතුවෙන් තිර රුව ලබාගත නොහැක, හෝ ඔබගේ යෙදුම හෝ ඔබගේ සංවිධානය විසින් එය ඉඩ නොදී තිබේ."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"සීමිත ගබඩා ඉඩ නිසා තිර රුව සුරැකිය නොහැකිය."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"තිර රූ ගැනීමට යෙදුම හෝ ඔබගේ සංවිධානය ඉඩ නොදේ."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB ගොනු හුවමාරු විකල්ප"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"මධ්ය ධාවකයක් (MTP) ලෙස සවි කරන්න"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"කැමරාවක් (PTP) ලෙස සවි කරන්න"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"වේලාව වැඩියෙන්."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"වේලාව අඩුවෙන්."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"සැණෙළි ආලෝකය අක්රිය කරන ලදි."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"සැණෙළි ආලෝකය ලබා ගත නොහැකිය."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"සැණෙළි ආලෝකය සක්රිය කරන ලදි."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"සැණෙළි ආලෝකය අක්රිය කරන ලදි."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"සැණෙළි ආලෝකය සක්රිය කරන ලදි."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"තිර ඇමිණීම"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"සෙවීම"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ආරම්භ කළ නොහැක."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ආරක්ෂිත ප්රකාරය තුළ අබලයි."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"ඉතිහාසය"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"හිස් කරන්න"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"මෙම යෙදුම බහු-කවුළුව සඳහා සහාය නොදක්වයි"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"යෙදුම බහු-කවුළුව සඳහා සහාය නොදක්වයි"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"තිරස්ව වෙන් කරන්න"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"සිරස්ව වෙන් කරන්න"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"අභිමත ලෙස වෙන් කරන්න"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"සම්පූර්ණ\nනිහඬතාව"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"ප්රමුඛතා\nපමණි"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"ඇඟවීම්\nපමණි"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"සියලු"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"සියලු\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"සෙමින් ආරෝපණය වෙමින් (සම්පුර්ණ වන තෙක් <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"තත්ත්ව තීරුවෙහි ඔරලෝසු තත්පර පෙන්වන්න. බැටරි ආයු කාලයට බලපෑමට හැකිය."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"ඉක්මන් සැකසීම් යළි පිළිවෙළට සකසන්න"</string>
<string name="show_brightness" msgid="6613930842805942519">"ඉක්මන් සැකසීම්වල දීප්තිය පෙන්වන්න"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"බෙදුම්-තිර ඉහළට-ස්වයිප් කිරීමේ ත්වරකය සබල කරන්න"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"බෙදුම්-තිරය ඉහළට-ස්වයිප් කිරීමේ අභිනය සබල කරන්න"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"දළ විශ්ලේෂණ බොත්තම හරහා ඉහළට ස්වයිප් කිරීමෙන් බෙදුම් තිරයට ඇතුළු වීමට ඉඟිය සබල කිරීම"</string>
<string name="experimental" msgid="6198182315536726162">"පරීක්ෂණාත්මක"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"බ්ලූටූත් ක්රියාත්මක කරන්නද?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"ඔබේ යතුරු පුවරුව ඔබේ ටැබ්ලට් පරිගණකයට සම්බන්ධ කිරීමට, ඔබ පළමුව බ්ලූටූත් ක්රියාත්මක කළ යුතුය."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"ක්රියාත්මක කරන්න"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> දැනුම්දීම් වෙත යොදන්න"</string>
- <string name="apply_to_app" msgid="363016783939815960">"මෙම යෙදුම වෙතින් වන සියලු දැනුම්දීම් සඳහා යොදන්න"</string>
+ <string name="show_silently" msgid="6841966539811264192">"නිශ්ශබ්දව දැනුම්දීම් පෙන්වන්න"</string>
+ <string name="block" msgid="2734508760962682611">"සියලු දැනුම්දීම් අවහිර කරන්න"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"නිශ්ශබ්ද නොකරන්න"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"නිශ්ශබ්ද හෝ අවහිර නොකරන්න"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"පූර්ණ වැදගත්කම් සැකසීම් පෙන්වන්න"</string>
<string name="blocked_importance" msgid="5198578988978234161">"අවහිර කරන ලදි"</string>
+ <string name="min_importance" msgid="1901894910809414782">"අවම වැදගත්කම"</string>
<string name="low_importance" msgid="4109929986107147930">"අඩු වැදගත්කම"</string>
<string name="default_importance" msgid="8192107689995742653">"සාමාන්ය වැදගත්කම"</string>
<string name="high_importance" msgid="1527066195614050263">"වැඩි වැදගත්කම"</string>
<string name="max_importance" msgid="5089005872719563894">"හදිසි වැදගත්කම"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"මෙම දැනුම්දීම් කිසිදා නොපෙන්වන්න"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"දැනුම්දීම් ලැයිස්තුවෙහි පහළින්ම නිශ්ශබ්දව පෙන්වන්න"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"නිශ්ශබ්දව මෙම දැනුම්දීම් පෙන්වන්න"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"දැනුම්දීම් ලැයිස්තුවෙහි ඉහළින්ම පෙන්වන්න සහ ශබ්ද කරන්න"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"තිරයට පැමිණ ශබ්ද කරන්න"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"දැනුම්දීම් ලැයිස්තුවෙහි පහළින්ම නිශ්ශබ්දව පෙන්වන්න"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"නිශ්ශබ්දව මෙම දැනුම්දීම් පෙන්වන්න"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"මෙම දැනුම්දීම්වලට ශබ්ද නැගීමට ඉඩ දෙන්න"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"තිරයට එබිකම් කර ශබ්දයට ඉඩ දෙන්න සහ ශබ්දයට ඉඩ දෙන්න"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"දැනුම්දීම් ලැයිස්තුවෙහි ඉහළින්ම පෙන්වන්න, තිරයට එබිකම් කර ශබ්දයට ඉඩ දෙන්න"</string>
<string name="notification_more_settings" msgid="816306283396553571">"තව සැකසීම්"</string>
<string name="notification_done" msgid="5279426047273930175">"නිමයි"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"සාමාන්ය වර්ණ"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"රාත්රී වර්ණ"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"අභිරුචි වර්ණ"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"ස්වයංක්රිය"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"නොදන්නා වර්ණ"</string>
- <string name="color_transform" msgid="6985460408079086090">"වර්ණ වෙනස් කිරීම"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"ඉක්මන් සැකසීම් ටයිලය පෙන්වන්න"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"අභිරුචි පරිවර්තනය සබල කරන්න"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"වර්ණය සහ පෙනුම"</string>
+ <string name="night_mode" msgid="3540405868248625488">"රාත්රී ප්රකාරය"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"සංදර්ශකය ක්රමාංකනය කරන්න"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"ක්රියාත්මකයි"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"ක්රියාවිරහිතයි"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"ස්වයංක්රියව ක්රියාත්මක කරන්න"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"ස්ථානය සහ දවසේ වේලාවට ගැළපෙන ලෙස රාත්රී ප්රකාරයට මාරු වන්න"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"රාත්රී ප්රකාරය ක්රියාත්මක විට"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Android OS සඳහා අඳුරු තේමාව භාවිත කරන්න"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"පැහැය සීරුමාරු කරන්න"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"දීප්තිය සීරුමාරු කරන්න"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"සැකසීම් වැනි, සාමාන්යයෙන් ලා පැහැ තේමාවක සංදර්ශනය වන Android OS හි මූලික ප්රදේශවලට අඳුරු තේමාව යෙදේ."</string>
<string name="color_apply" msgid="9212602012641034283">"යොදන්න"</string>
<string name="color_revert_title" msgid="4746666545480534663">"සැකසීම් තහවුරු කරන්න"</string>
<string name="color_revert_message" msgid="9116001069397996691">"සමහර වර්ණ සැකසීම් මෙම උපාංගය භාවිත කළ නොහැකි තත්ත්වයට පත් කළ හැකිය. මෙම වර්ණ සැකසීම් තහවුරු කිරීමට හරි ක්ලික් කරන්න, නැතහොත් මෙම සැකසීම් තත්පර 10කට පසුව යළි සකසනු ඇත."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"බැටරි භාවිතය"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"ආරෝපණය අතරතුර බැටරි සුරැකුම ලබා ගත නොහැකිය."</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"බැටරි සුරැකුම"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"ක්රියාකාරිත්වය සහ පසුබිම් දත්ත අඩු කරන්න"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"මුල් පිටුව"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"මෑත"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"ආපසු"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"හඩ පරිමාව තුළ බාධා නොකරන්න පුවරුව පෙන්වන්න"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"හඬ පරිමා සංවාදය තුළ බාධා නොකරන්න පුවරුවට පූර්ණ පාලනය ඉඩ දෙන්න."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"හඬ පරිමාව සහ බාධා නොකරන්න"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"හඬ පරිමාව අඩු කරන්න මත බාධා නොකරන්න වෙත ඇතුළු වන්න"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"හඩ පරිමා පාලන සහිතව පෙන්වන්න"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"බාධා නොකරන්න"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"හඩ පරිමා බොත්තම් කෙටිමග"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"හඬ පරිමාව වැඩි කරන්න මත බාධා නොකරන්න වෙතින් ඉවත් වන්න"</string>
<string name="battery" msgid="7498329822413202973">"බැටරිය"</string>
<string name="clock" msgid="7416090374234785905">"ඔරලෝසුව"</string>
<string name="headset" msgid="4534219457597457353">"හෙඩ්සෙට්"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"හෙඩ්ෆෝන් සම්බන්ධ කළ"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"හෙඩ්සෙට් සම්බන්ධ කළ"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"තත්ත්ව තීරුව මත අයිකන පෙන්වීම සබල හෝ අබල කරන්න."</string>
<string name="data_saver" msgid="5037565123367048522">"දත්ත සුරැකුම"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"දත්ත සුරැකුම ක්රියාත්මකයි"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"දත්ත සුරැකුම ක්රියාවිරහිතයි"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"ක්රියාත්මකයි"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"ක්රියාවිරහිතයි"</string>
<string name="nav_bar" msgid="1993221402773877607">"සංචලන තීරුව"</string>
<string name="start" msgid="6873794757232879664">"ආරම්භ කරන්න"</string>
<string name="center" msgid="4327473927066010960">"මධ්ය"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"පෙරදසුන"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"ටයිල් එක් කිරීමට අදින්න"</string>
<string name="qs_edit" msgid="2232596095725105230">"සංස්කරණය කරන්න"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"වේලාව"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"පැය, මිනිත්තු, සහ තත්පර පෙන්වන්න"</item>
+ <item msgid="1427801730816895300">"පැය සහ මිනිත්තු පෙන්වන්න (පෙරනිමි)"</item>
+ <item msgid="3830170141562534721">"මෙම නිරූපකය නොපෙන්වන්න"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"සෑම විටම ප්රතිශතය පෙන්වන්න"</item>
+ <item msgid="2139628951880142927">"ආරෝපණය වන විට ප්රතිශතය පෙන්වන්න (පෙරනිමි)"</item>
+ <item msgid="3327323682209964956">"මෙම නිරූපකය නොපෙන්වන්න"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"වෙනත්"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"බෙදුම්-තිර වෙන්කරණය"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"පහළට ගෙන යන්න"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"ඉහළට ගෙන යන්න"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"වමට ගෙන යන්න"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"දකුණට ගෙන යන්න"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 199bd90..40daf19 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -75,7 +75,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Snímka obrazovky bola zaznamenaná."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Snímku obrazovky zobrazíte dotykom."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Snímku obrazovky sa nepodarilo zachytiť."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Nie je možné vytvoriť viac sním. obraz. pre obmedz. úlož. priestor alebo to nie je povolené apl. či vašou organiz."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Snímku obrazovky nie je možné vytvoriť z dôvodu nedostatku miesta v úložisku."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Vytváranie snímok obrazovky je zakázané aplikáciou alebo vašou organizáciou."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Možnosti prenosu súborov USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Pripojiť ako prehrávač médií (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Pripojiť ako fotoaparát (PTP)"</string>
@@ -208,6 +209,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Dlhší čas"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Kratší čas"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Svietidlo je vypnuté."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Svietidlo nie je k dispozícii."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Svietidlo je zapnuté."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Svietidlo je vypnuté."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Svietidlo je zapnuté."</string>
@@ -303,10 +305,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pripnutie k obrazovke"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"hľadať"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikáciu <xliff:g id="APP">%s</xliff:g> sa nepodarilo spustiť"</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Aplikácia <xliff:g id="APP">%s</xliff:g> je v núdzovom režime zakázaná."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"História"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Vymazať"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Táto aplikácia nepodporuje režim viacerých okien"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Aplikácia nepodporuje režim viacerých okien"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Rozdeliť vodorovné"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Rozdeliť zvislé"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Rozdeliť vlastné"</string>
@@ -336,8 +339,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Úplné\nticho"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Iba\nprioritné"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Iba\nbudíky"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Všetky"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Všetky\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Nabíja sa (úplné nabitie o <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Nabíja sa rýchlo (úplné nabitie o <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Nabíja sa pomaly (úplné nabitie o <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
@@ -450,39 +451,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Zobrazí sekundy v stavovom riadku. Môže to ovplyvňovať výdrž batérie."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Zmeniť usporiadanie Rýchlych nastavení"</string>
<string name="show_brightness" msgid="6613930842805942519">"Zobraziť jas v Rýchlych nastaveniach"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Aktivovať rozdelenú obrazovku prejdením prstom"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Aktivovať rozdelenú obrazovku prejdením prstom"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Umožňuje aktivovať rozdelenú obrazovku prejdením prstom nahor od tlačidla Prehľad"</string>
<string name="experimental" msgid="6198182315536726162">"Experimentálne"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Zapnúť Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Ak chcete klávesnicu pripojiť k tabletu, najprv musíte zapnúť Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Zapnúť"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Použiť na upozornenia týkajúce sa témy <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Použiť na všetky upozornenia z tejto aplikácie"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Zobrazovať upozornenia bez zvukového signálu"</string>
+ <string name="block" msgid="2734508760962682611">"Blokovať všetky upozornenia"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Nestíšiť"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Nestíšiť ani neblokovať"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Zobraziť nastavenia vysokej dôležitosti"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Zablokované"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Minimálna dôležitosť"</string>
<string name="low_importance" msgid="4109929986107147930">"Nízka dôležitosť"</string>
<string name="default_importance" msgid="8192107689995742653">"Normálna dôležitosť"</string>
<string name="high_importance" msgid="1527066195614050263">"Vysoká dôležitosť"</string>
<string name="max_importance" msgid="5089005872719563894">"Neodkladná dôležitosť"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Tieto upozornenia nikdy nezobrazovať"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Zobrazovať v dolnej časti zoznamu upozornení bez zvukového signálu"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Tieto upozornenia zobrazovať bez zvukového signálu"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Zobrazovať v hornej časti zoznamu upozornení so zvukovým signálom"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Zobrazovať cez obrazovku so zvukovým signálom"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Zobrazovať v dolnej časti zoznamu upozornení bez zvukového signálu"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Tieto upozornenia zobrazovať bez zvukového signálu"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Umožniť týmto upozorneniam vydávať zvukové signály"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Zobrazovať cez obrazovku a povoliť zvukový signál"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Zobrazovať v hornej časti zoznamu upozornení, zobrazovať cez obrazovku a povoliť zvukový signál"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Ďalšie nastavenia"</string>
<string name="notification_done" msgid="5279426047273930175">"Hotovo"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Normálne farby"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Nočné farby"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Vlastné farby"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automatické"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Neznáme farby"</string>
- <string name="color_transform" msgid="6985460408079086090">"Úprava farieb"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Zobraziť dlaždicu Rýchle nastavenia"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Povoliť vlastnú transformáciu"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Farba a vzhľad"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Nočný režim"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Kalibrovať obrazovku"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Zapnutý"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Vypnutý"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Zapínať automaticky"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Prepnúť do Nočného režimu podľa miesta a času dňa"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Keď je zapnutý Nočný režim"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Použiť tmavý motív pre systém Android OS"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Upraviť tónovanie"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Upraviť jas"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"V hlavných oblastiach systému Android OS (ako sú Nastavenia), ktoré sú obyčajne zobrazené vo svetlom motíve, je použitý tmavý motív."</string>
<string name="color_apply" msgid="9212602012641034283">"Použiť"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Potvrdenie nastavení"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Niektoré nastavenia farieb môžu toto zariadenie znefunkčniť. Tieto nastavenia farieb potvrdíte kliknutím na tlačidlo OK, ináč sa tieto nastavenia o 10 sekúnd obnovia."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Využitie batérie"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Počas nabíjania nie je Šetrič batérie k dispozícii"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Šetrič batérie"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Obmedzí výkonnosť a údaje na pozadí"</string>
@@ -490,21 +499,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Domovská stránka"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Nedávne"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Späť"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Zobrazovať panel Nerušiť v dialógu Hlasitosť"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Umožňuje povoliť úplné ovládanie režimu nerušiť v dialógu Hlasitosť."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Hlasitosť a režim Nerušiť"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Pri znížení hlasitosti prejsť do režimu Nerušiť"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Zobrazovať s ovládacími prvkami hlasitosti"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Nerušiť"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Skratka tlačidiel hlasitosti"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Pri zvýšení hlasitosti ukončiť režim Nerušiť"</string>
<string name="battery" msgid="7498329822413202973">"Batéria"</string>
<string name="clock" msgid="7416090374234785905">"Hodiny"</string>
<string name="headset" msgid="4534219457597457353">"Náhlavná súprava"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Slúchadlá pripojené"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Náhlavná súprava pripojená"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Umožňuje aktivovať alebo deaktivovať zobrazenie ikon v stavovom riadku."</string>
<string name="data_saver" msgid="5037565123367048522">"Šetrič dát"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Šetrič dát je zapnutý"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Šetrič dát je vypnutý"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Zapnuté"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Vypnuté"</string>
<string name="nav_bar" msgid="1993221402773877607">"Navigačný panel"</string>
<string name="start" msgid="6873794757232879664">"Začiatok"</string>
<string name="center" msgid="4327473927066010960">"Stred"</string>
@@ -527,4 +535,21 @@
<string name="preview" msgid="9077832302472282938">"Ukážka"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Dlaždice pridáte presunutím"</string>
<string name="qs_edit" msgid="2232596095725105230">"Upraviť"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Čas"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Zobrazovať hodiny, minúty a sekundy"</item>
+ <item msgid="1427801730816895300">"Zobrazovať hodiny a minúty (predvolené)"</item>
+ <item msgid="3830170141562534721">"Nezobrazovať túto ikonu"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Vždy zobrazovať percentá"</item>
+ <item msgid="2139628951880142927">"Zobrazovať percentá počas nabíjania (predvolené)"</item>
+ <item msgid="3327323682209964956">"Nezobrazovať túto ikonu"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Ďalšie"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Rozdeľovač obrazovky"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Posunúť nadol"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Posunúť nahor"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Posunúť doľava"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Posunúť doprava"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 9ebb19d..756c43d 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -75,7 +75,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Posnetek zaslona je shranjen."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Dotaknite se, če si želite ogledati posnetek zaslona."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Posnetka zaslona ni bilo mogoče shraniti."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Izdelava posnetka zaslona ni mogoča zaradi omejenega prostora za shranjevanje ali pa tega ne dovoli aplikacija ali vaša organizacija."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Shranjevanje posnetka zaslona ni mogoče zaradi omejenega prostora za shranjevanje."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Aplikacija ali organizacija ne dovoljuje posnetkov zaslona."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Možnosti prenosa datotek prek USB-ja"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Vpni kot predvajalnik (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Vpni kot fotoaparat (PTP)"</string>
@@ -208,6 +209,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Daljši čas."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Krajši čas."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Svetilka je izklopljena."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Svetilka ni na voljo."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Svetilka je vklopljena."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Svetilka je izklopljena."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Svetilka je vklopljena."</string>
@@ -306,6 +308,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"Aplikacija <xliff:g id="APP">%s</xliff:g> je v varnem načinu onemogočena."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Zgodovina"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Izbriši"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Ta aplikacija ne podpira načina z več okni"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Aplikacija ne podpira načina z več okni"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Razdeli vodoravno"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Razdeli navpično"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Razdeli po meri"</string>
@@ -335,8 +339,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Popolna\ntišina"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Samo\nprednostno"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Samo\nalarmi"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Vse"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Vse\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Polnjenje (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do napolnjenosti)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Hitro polnjenje (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do napolnjenosti)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Počasno polnjenje (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do napolnjenosti)"</string>
@@ -449,34 +451,43 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Prikaže sekunde pri uri v vrstici stanja. To lahko vpliva na čas delovanja pri akumulatorskem napajanju."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Preuredi hitre nastavitve"</string>
<string name="show_brightness" msgid="6613930842805942519">"Prikaz svetlosti v hitrih nastavitvah"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Omogočanje vklopa razdeljenega zaslona z vlečenjem navzgor"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Omogočanje poteze za razdeljen zaslon z vlečenjem navzgor"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Omogočanje poteze za vklop razdeljenega zaslona, tako da uporabnik od gumba za pregled povleče s prstom navzgor"</string>
<string name="experimental" msgid="6198182315536726162">"Poskusno"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Želite vklopiti Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Če želite povezati tipkovnico in tablični računalnik, vklopite Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Vklop"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Uporabi za obvestila za temo <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Uporabi za vsa obvestila za to aplikacijo"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Prikaži obvestila brez zvoka"</string>
+ <string name="block" msgid="2734508760962682611">"Blokiraj vsa obvestila"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Ne utišaj"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Ne utišaj ali blokiraj"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Prikaz celotnih nastavitev za pomembnost"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Blokirano"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Najmanjša pomembnost"</string>
<string name="low_importance" msgid="4109929986107147930">"Nizka pomembnost"</string>
<string name="default_importance" msgid="8192107689995742653">"Običajna pomembnost"</string>
<string name="high_importance" msgid="1527066195614050263">"Visoka pomembnost"</string>
<string name="max_importance" msgid="5089005872719563894">"Nujna pomembnost"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Nikoli ne prikaži teh obvestil"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Prikaži na dnu seznama obvestil brez zvoka"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Prikaži ta obvestila brez zvoka"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Prikaži na vrhu seznama obvestil in predvajaj zvok"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Za hip pokaži predogled na zaslonu in predvajaj zvok"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Prikaži na dnu seznama obvestil brez zvoka"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Prikaži ta obvestila brez zvoka"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Dovoli zvoke za ta obvestila"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Za hip pokaži predogled na zaslonu in dovoli zvok"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Prikaži na vrhu seznama obvestil, za hip pokaži predogled na zaslonu in dovoli zvok"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Več nastavitev"</string>
<string name="notification_done" msgid="5279426047273930175">"Dokončano"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Običajne barve"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Nočne barve"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Barve po meri"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Samodejno"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Neznane barve"</string>
- <string name="color_transform" msgid="6985460408079086090">"Spreminjanje barv"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Prikaz ploščice s hitrimi nastavitvami"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Omogočanje spremembe po meri"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Barva in videz"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Nočni način"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Umerjanje zaslona"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Vklopljeno"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Izklopljeno"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Samodejni vklop"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Preklop v nočni način, kot je ustrezno glede na lokacijo in uro v dnevu"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Ko je vklopljen nočni način"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Uporaba temne teme za sistem Android"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Prilagodi odtenek"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Prilagodi svetlost"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Za osrednja področja sistema Android, ki so običajno prikazana v svetli temi, na primer nastavitve, je uporabljena temna tema."</string>
<string name="color_apply" msgid="9212602012641034283">"Uporabi"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Potrditev nastavitev"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Zaradi nekaterih barvnih nastavitev lahko postane ta naprava neuporabna. Kliknite »V redu«, če želite potrditi te barvne nastavitve. V nasprotnem primeru se bodo čez 10 sekund ponastavile na prvotno vrednost."</string>
@@ -488,21 +499,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Začetni zaslon"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Nedavni"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Nazaj"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Pokaži način »ne moti« v nadzoru glasnosti"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Omogoča popoln nadzor načina »ne moti« v pogovornem oknu za glasnost."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Nadzor glasnosti in način »ne moti«"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Odpiranje načina »ne moti« pri zmanjšanju glasnosti"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Prikaži s kontrolniki glasnosti"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ne moti"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Bližnjica z gumboma za glasnost"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Zapustitev načina »ne moti« pri povečanju glasnosti"</string>
<string name="battery" msgid="7498329822413202973">"Akumulator"</string>
<string name="clock" msgid="7416090374234785905">"Ura"</string>
<string name="headset" msgid="4534219457597457353">"Slušalke z mikrofonom"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Slušalke priključene"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Slušalke z mikrofonom priključene"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Omogoči ali onemogoči prikaz ikon v vrstici stanja."</string>
<string name="data_saver" msgid="5037565123367048522">"Varčevanje s podatki"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Varčevanje s podatki je vklopljeno"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Varčevanje s podatki je izklopljeno"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Vklopljeno"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Izklop"</string>
<string name="nav_bar" msgid="1993221402773877607">"Vrstica za krmarjenje"</string>
<string name="start" msgid="6873794757232879664">"Začetek"</string>
<string name="center" msgid="4327473927066010960">"Sredina"</string>
@@ -525,4 +535,21 @@
<string name="preview" msgid="9077832302472282938">"Predogled"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Povlecite, če želite dodati ploščice"</string>
<string name="qs_edit" msgid="2232596095725105230">"Uredi"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Ura"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Prikaži ure, minute in sekunde"</item>
+ <item msgid="1427801730816895300">"Prikaži ure in minute (privzeto)"</item>
+ <item msgid="3830170141562534721">"Ne prikaži te ikone"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Vedno prikaži odstotek"</item>
+ <item msgid="2139628951880142927">"Prikaži odstotek med polnjenjem (privzeto)"</item>
+ <item msgid="3327323682209964956">"Ne prikaži te ikone"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Drugo"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Razdelilnik zaslonov"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Premakni navzdol"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Premakni navzgor"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Premakni levo"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Premakni desno"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index 3f25e7d..8b3861e 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Pamja e ekranit u kap."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Prek për të parë pamjen e ekranit tënd."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Nuk mundi të kapte pamjen e ekranit."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Nuk pranon pamje ekrani për shkak të hapësirës së kufizuar ruajtëse, ose një gjë e tillë nuk lejohet nga aplikacioni apo organizata jote."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Pamja e ekranit nuk mund të ruhet për shkak të hapësirës ruajtëse të kufizuar."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Nxjerrja e pamjeve të ekranit nuk lejohet nga aplikacioni ose organizata jote."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Opsionet e transferimit të dosjeve të USB-së"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Lidh si një lexues \"media\" (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Montoje si kamerë (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Më shumë kohë."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Më pak kohë."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Elektriku është i çaktivizuar."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Blici është i padisponueshëm"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Elektriku u aktivizua."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Elektriku u çaktivizua."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Elektriku është i aktivizuar."</string>
@@ -304,6 +306,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> është i çaktivizuar në modalitetin e sigurt."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Historiku"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Pastro"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Ky aplikacion nuk e mbështet modalitetin me shumë dritare"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Aplikacioni nuk e mbështet modalitetin me shumë dritare"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Ndaje horizontalisht"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Ndaj vertikalisht"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Ndaj të personalizuarën"</string>
@@ -333,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Heshtje\ne plotë"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Vetëm\nme prioritet"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Vetëm\nalarmet"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Të gjitha"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Të gjitha\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Po ngarkohet (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> deri sa të mbushet)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Po ngarkon me shpejtësi (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> derisa të mbushet)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Po ngarkon me ngadalë (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> derisa të mbushet)"</string>
@@ -447,34 +449,43 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Trego sekondat e orës në shiritin e statusit. Mund të ndikojë te jeta e baterisë."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Risistemo Cilësimet e shpejta"</string>
<string name="show_brightness" msgid="6613930842805942519">"Shfaq ndriçimin te Cilësimet e shpejta"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Aktivizo përshpejtuesin e rrëshqitjes lart për ekranin e ndarë"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Aktivizo gjestin e rrëshqitjes lart për ekranin e ndarë"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Aktivizo gjestin për të hyrë tek ekrani i ndarë duke rrëshqitur lart nga butoni \"Përmbledhja\""</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimentale"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Të aktivizohet \"bluetooth-i\"?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Për të lidhur tastierën me tabletin, në fillim duhet të aktivizosh \"bluetooth-in\"."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Aktivizo"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Zbatoje për njoftimet nga <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Zbatoje për të gjitha njoftimet nga ky aplikacion"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Shfaqi njoftimet në heshtje"</string>
+ <string name="block" msgid="2734508760962682611">"Blloko të gjitha njoftimet"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Mos e vendos në heshtje"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Mos e vendos në heshtje ose mos e blloko"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Shfaq cilësimet e plota të rëndësisë"</string>
<string name="blocked_importance" msgid="5198578988978234161">"I bllokuar"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Rëndësi minimale"</string>
<string name="low_importance" msgid="4109929986107147930">"Rëndësi e ulët"</string>
<string name="default_importance" msgid="8192107689995742653">"Rëndësi normale"</string>
<string name="high_importance" msgid="1527066195614050263">"Rëndësi e lartë"</string>
<string name="max_importance" msgid="5089005872719563894">"Rëndësi urgjente"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Mos i shfaq asnjëherë këto njoftime"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Shfaqi në heshtje në fund të listës së njoftimeve"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Shfaqi këto njoftime në heshtje"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Shfaqi në krye të listës së njoftimeve dhe lësho tingull"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Shfaq një vështrim të shpejtë në ekran dhe lësho tingull"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Shfaqi në heshtje në fund të listës së njoftimeve"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Shfaqi këto njoftime në heshtje"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Lejoji këto njoftime të nxjerrin tinguj"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Shfaq një vështrim të shpejtë në ekran dhe lësho një tingull"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Shfaqi në krye të listës së njoftimeve, shfaq vështrim të shpejtë në ekran dhe lësho një tingull"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Cilësime të tjera"</string>
<string name="notification_done" msgid="5279426047273930175">"U krye"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Ngjyrat normale"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Ngjyrat e natës"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Ngjyrat e personalizuara"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automatike"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Ngjyra të panjohura"</string>
- <string name="color_transform" msgid="6985460408079086090">"Modifikimi i ngjyrës"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Pllakëza Shfaq cilësimet e shpejta"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Zbato transformimin e personalizuar"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Ngjyra dhe pamja"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Modaliteti i natës"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Kalibro ekranin"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Aktiv"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Joaktiv"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Aktivizoje automatikisht"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Kalo në \"Modalitetin e natës\" sipas përshtatshmërisë për vendin dhe kohën e ditës"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Kur \"Modaliteti i natës\" është aktiv"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Përdor temën e errët për Android OS"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Rregullo nuancën"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Rregullo ndriçimin"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Tema e errët zbatohet në zonat kryesore të Android OS që shfaqen zakonisht në një temë të çelur, siç janë \"Cilësimet\"."</string>
<string name="color_apply" msgid="9212602012641034283">"Zbato"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Konfirmo cilësimet"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Disa cilësime ngjyrash mund ta bëjnë këtë pajisje të papërdorshme. Kliko OK për të konfirmuar këto cilësime ngjyrash, përndryshe këto cilësime do të rivendosen pas 10 sekondash."</string>
@@ -486,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Kreu"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Të fundit"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Prapa"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Shfaq \"Mos shqetëso\" te volumi"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Lejo kontrollin e plotë të opsionit \"Mos shqetëso\" në dialogun e volumit."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Volumi dhe \"Mos shqetëso\""</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Vendos \"Mos shqetëso\" me volumin poshtë"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Shfaq me kontrollet e volumit"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Mos shqetëso"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Shkurtorja e butonave të volumit"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Dil nga \"Mos shqetëso\" me volumin lart"</string>
<string name="battery" msgid="7498329822413202973">"Bateria"</string>
<string name="clock" msgid="7416090374234785905">"Ora"</string>
<string name="headset" msgid="4534219457597457353">"Kufjet me mikrofon"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Kufjet u lidhën"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Kufjet me mikrofon u lidhën"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Aktivizo ose çaktivizo shfaqjen e ikonave në shiritin e statusit."</string>
<string name="data_saver" msgid="5037565123367048522">"Kursyesi i të dhënave"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Kursyesi i të dhënave është aktiv"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Kursyesi i të dhënave është joaktiv"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Aktiv"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Joaktiv"</string>
<string name="nav_bar" msgid="1993221402773877607">"Shiriti i navigimit"</string>
<string name="start" msgid="6873794757232879664">"Nis"</string>
<string name="center" msgid="4327473927066010960">"Qendror"</string>
@@ -523,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Pamja paraprake"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Zvarrit për të shtuar pllakëzat"</string>
<string name="qs_edit" msgid="2232596095725105230">"Redakto"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Ora"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Shfaq orët, minutat dhe sekondat"</item>
+ <item msgid="1427801730816895300">"Shfaq orët dhe minutat (e parazgjedhur)"</item>
+ <item msgid="3830170141562534721">"Mos e shfaq këtë ikonë"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Shfaq gjithmonë përqindjen"</item>
+ <item msgid="2139628951880142927">"Shfaq përqindjen gjatë ngarkimit (e parazgjedhur)"</item>
+ <item msgid="3327323682209964956">"Mos e shfaq këtë ikonë"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Të tjera"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Ndarësi i ekranit të ndarë"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Lëviz poshtë"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Lëviz lart"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Lëviz majtas"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Lëviz djathtas"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 8d54ca2..991e9e2 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -74,7 +74,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Снимак екрана је направљен."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Додирните да бисте видели снимак екрана."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Није могуће направити снимак екрана."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Није могуће снимити екран због недовољне меморије или то не дозвољава апликација или организација."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Чување снимка екрана није успело због ограниченог меморијског простора."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Апликација или организација не дозвољавају прављење снимака екрана."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Опције USB преноса датотека"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Прикључи као медија плејер (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Прикључи као камеру (PTP)"</string>
@@ -207,6 +208,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Више времена."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Мање времена."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Батеријска лампа је искључена."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Лампа није доступна."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Батеријска лампа је укључена."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Батеријска лампа је искључена."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Батеријска лампа је укључена."</string>
@@ -302,10 +304,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"качење екрана"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"претражи"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Покретање апликације <xliff:g id="APP">%s</xliff:g> није успело."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Апликација <xliff:g id="APP">%s</xliff:g> је онемогућена у безбедном режиму."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Историја"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Обриши"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Ова апликација не подржава режим са више прозора"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Апликација не подржава режим са више прозора"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Подели хоризонтално"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Подели вертикално"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Прилагођено дељење"</string>
@@ -335,8 +338,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Потпуна\nтишина"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Само\nприорит. прекиди"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Само\nаларми"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Све"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Сви\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Споро се пуни (напуниће се за <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
@@ -449,39 +450,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Секунде на сату се приказују на статусној траци. То може да утиче на трајање батерије."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Преуреди Брза подешавања"</string>
<string name="show_brightness" msgid="6613930842805942519">"Прикажи осветљеност у Брзим подешавањима"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Омогући убрзавач за превлачење нагоре за подељени екран"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Омогући покрет за превлачење нагоре за подељени екран"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Омогућава покрет за прелазак на подељени екран превлачењем нагоре од дугмета Преглед"</string>
<string name="experimental" msgid="6198182315536726162">"Експериментално"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Желите ли да укључите Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Да бисте повезали тастатуру са таблетом, прво морате да укључите Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Укључи"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Примени на обавештења о теми <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Примени на сва обавештења из ове апликације"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Приказуј обавештења без звука"</string>
+ <string name="block" msgid="2734508760962682611">"Блокирај сва обавештења"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Не искључуј звук"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Не искључују звук нити блокирај"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Прикажи комплетна подешавања важности"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Блокирана"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Веома мала важност"</string>
<string name="low_importance" msgid="4109929986107147930">"Мала важност"</string>
<string name="default_importance" msgid="8192107689995742653">"Уобичајена важност"</string>
<string name="high_importance" msgid="1527066195614050263">"Велика важност"</string>
<string name="max_importance" msgid="5089005872719563894">"Важност: хитно"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Ова обавештења се никада не приказују"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Приказују се у дну листе обавештења без звука"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Ова обавештења се приказују без звука"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Приказују се у врху листе обавештења и емитује се звук"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Накратко се приказују на екрану и емитује се звук"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Приказују се у дну листе обавештења без звука"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Ова обавештења се приказују без звука"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Дозволите да ова обавештења емитују звук"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Накратко се приказују на екрану и емитују звук"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Приказују се у врху листе обавештења, накратко се приказују на екрану и емитују звук"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Још подешавања"</string>
<string name="notification_done" msgid="5279426047273930175">"Готово"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Нормалне боје"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Ноћне боје"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Прилагођене боје"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Аутоматски"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Непознате боје"</string>
- <string name="color_transform" msgid="6985460408079086090">"Измена боја"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Прикажи плочицу Брза подешавања"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Омогући прилагођену трансформацију"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Боја и изглед"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Ноћни режим"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Калибришите екран"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Укључено"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Искључено"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Аутоматски укључи"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Пређите на ноћни режим у зависности од локације и доба дана"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Када је ноћни режим укључен"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Користи тамну тему за Android ОС"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Прилагоди сенку"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Прилагоди осветљеност"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Тамна тема се примењује на кључне делове Android ОС-а који се обично приказују у светлој теми, попут Подешавања."</string>
<string name="color_apply" msgid="9212602012641034283">"Примени"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Потврдите подешавања"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Нека подешавања боја могу да учине уређај неупотребљивим. Кликните на Потврди да бисте потврдили ова подешавања боја, пошто ће се у супротном ова подешавања ресетовати након 10 секунди."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Потрошња батерије"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Уштеда батерије није доступна током пуњења"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Уштеда батерије"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Смањује перформансе и позадинске податке"</string>
@@ -489,21 +498,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Почетни"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Недавни садржај"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Назад"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Прикажи подешавање Не узнемиравај у дијалогу за јачину звука"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Дозвољава потпуну контролу подешавања Не узнемиравај у дијалогу за јачину звука."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Јачина звука и Не узнемиравај"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Уђи у режим Не узнемиравај када је звук утишан"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Прикажи са контролама јачине звука"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Не узнемиравај"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Пречица за дугмад за јачину звука"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Изађи из режима Не узнемиравај када је звук појачан"</string>
<string name="battery" msgid="7498329822413202973">"Батерија"</string>
<string name="clock" msgid="7416090374234785905">"Сат"</string>
<string name="headset" msgid="4534219457597457353">"Наглавне слушалице"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Слушалице су повезане"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Наглавне слушалице су повезане"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Омогућите или онемогућите приказивање икона на статусној траци."</string>
<string name="data_saver" msgid="5037565123367048522">"Уштеда података"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Уштеда података је укључена"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Уштеда података је искључена"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Укључено"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Искључено"</string>
<string name="nav_bar" msgid="1993221402773877607">"Трака за навигацију"</string>
<string name="start" msgid="6873794757232879664">"Покрени"</string>
<string name="center" msgid="4327473927066010960">"Центар"</string>
@@ -526,4 +534,21 @@
<string name="preview" msgid="9077832302472282938">"Преглед"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Превуците да бисте додали плочице"</string>
<string name="qs_edit" msgid="2232596095725105230">"Измени"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Време"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Прикажи сате, минуте и секунде"</item>
+ <item msgid="1427801730816895300">"Прикажи сате и минуте (подразумевано)"</item>
+ <item msgid="3830170141562534721">"Не приказуј ову икону"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Увек приказуј проценат"</item>
+ <item msgid="2139628951880142927">"Прикажи проценат током пуњења (подразумевано)"</item>
+ <item msgid="3327323682209964956">"Не приказуј ову икону"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Друго"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Разделник подељеног екрана"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Помери надоле"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Помери нагоре"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Помери улево"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Помери удесно"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 2a91962..d35fad5 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Skärmdumpen har tagits."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Tryck här om du vill visa skärmdumpen."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Det gick inte att ta någon skärmdump."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Skärmdump misslyckades. Lagringsutrymmet räcker inte eller appen/organisationen tillåter det inte."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Det går inte att spara skärmdumpen eftersom lagringsutrymmet inte räcker."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Appen eller organisationen tillåter inte att du tar skärmdumpar."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Överföringsalternativ"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Montera som mediaspelare (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Montera som kamera (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Längre tid."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Kortare tid."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Ficklampa av."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Ficklampan är inte tillgänglig."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Ficklampa på."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Ficklampan har inaktiverats."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Ficklampan har aktiverats."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fästa skärmen"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"sök"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Det gick inte att starta appen <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> är inaktiverad i säkert läge."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Historik"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Rensa"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Den här appen har inte stöd för flera fönster"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Appen har inte stöd för flera fönster"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Dela horisontellt"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Dela vertikalt"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Dela anpassad"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Helt\ntyst"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Endast\nprioriterade"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Endast\nalarm"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Alla"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Alla\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Laddar (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> tills batteriet är fulladdat)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Laddas snabbt (batteriet fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Laddas sakta (batteriet fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Visa klocksekunder i statusfältet. Detta kan påverka batteritiden."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Ordna snabbinställningarna"</string>
<string name="show_brightness" msgid="6613930842805942519">"Visa ljusstyrka i snabbinställningarna"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Aktivera accelerator för delad skärm när du sveper uppåt"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Aktivera delad skärm när du sveper uppåt"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Aktivera en rörelse som delar skärmen när du sveper uppåt från knappen Översikt"</string>
<string name="experimental" msgid="6198182315536726162">"Experimentella"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Vill du aktivera Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Om du vill ansluta tangentbordet till surfplattan måste du först aktivera Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Aktivera"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Ändra för alla aviseringar för <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Ändra för alla aviseringar från den här appen"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Visa aviseringar utan ljud"</string>
+ <string name="block" msgid="2734508760962682611">"Blockera alla aviseringar"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Stäng inte av ljudet"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Stäng inte av ljudet och blockera inte"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Visa alla relevansinställningarna"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Blockerad"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Oviktig avisering"</string>
<string name="low_importance" msgid="4109929986107147930">"Oviktig avisering"</string>
<string name="default_importance" msgid="8192107689995742653">"Vanlig avisering"</string>
<string name="high_importance" msgid="1527066195614050263">"Viktig avisering"</string>
<string name="max_importance" msgid="5089005872719563894">"Brådskande avisering"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Visa aldrig de här aviseringarna"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Visa längst ned på listan, utan ljud"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Visa aviseringarna utan ljud"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Visa högst upp på listan, med ljud"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Visa på skärmen, med ljud"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Visa längst ned i listan, utan ljud"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Visa aviseringarna utan ljud"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Tillåt ljud för de här aviseringarna"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Visa med snabbtitt på skärmen och tillåt ljud"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Visa högst upp i aviseringslistan och med snabbtitt på skärmen samt tillåt ljud"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Fler inställningar"</string>
<string name="notification_done" msgid="5279426047273930175">"Klar"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Normala färger"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Nattfärger"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Anpassade färger"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Automatiskt"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Okända färger"</string>
- <string name="color_transform" msgid="6985460408079086090">"Färgändring"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Visa rutan Snabbinställningar"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Aktivera anpassad omvandling"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Färg och utseende"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Nattläge"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Kalibrera skärmen"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Aktiverat"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Inaktiverat"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Aktivera automatiskt"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Byt till Nattläge vid passande platser och tider på dygnet"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"När Nattläget är aktiverat"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Använd mörkt tema för Android OS"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Justera ton"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Justera ljusstyrka"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Det mörka temat används för kärnfunktioner i Android OS som brukar visas med ett ljust tema, t.ex. inställningarna."</string>
<string name="color_apply" msgid="9212602012641034283">"Verkställ"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Bekräfta inställningarna"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Vissa färginställningar kan göra den här enheten oanvändbar. Klicka på OK om du vill bekräfta färginställningarna, annars återställs inställningarna efter 10 sekunder."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Batteriförbrukning"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Batterisparläget är inte tillgängligt vid laddning"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Batterisparläge"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Minskar prestanda och bakgrundsdata"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Startsida"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Senaste"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Tillbaka"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Visa Stör ej i volymkontrollen"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Tillåt full kontroll över Stör ej i volymkontrollen"</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Volym och Stör ej"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Aktivera Stör ej när volymen sänks"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Visa med volymkontroller"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Stör ej"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Genväg till volymknappar"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Inaktivera Stör ej när volymen höjs"</string>
<string name="battery" msgid="7498329822413202973">"Batteri"</string>
<string name="clock" msgid="7416090374234785905">"Klocka"</string>
<string name="headset" msgid="4534219457597457353">"Headset"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Hörlurar anslutna"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset anslutet"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Visa eller dölj ikoner i statusfältet."</string>
<string name="data_saver" msgid="5037565123367048522">"Databesparing"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Databesparing är aktiverat"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Databesparing är inaktiverat"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"På"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Inaktiverat"</string>
<string name="nav_bar" msgid="1993221402773877607">"Navigeringsfält"</string>
<string name="start" msgid="6873794757232879664">"Början"</string>
<string name="center" msgid="4327473927066010960">"Centrera"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Förhandsgranskning"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Lägg till rutor genom att dra"</string>
<string name="qs_edit" msgid="2232596095725105230">"Redigera"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Tid"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Visa timmar, minuter och sekunder"</item>
+ <item msgid="1427801730816895300">"Visa timmar och minuter (standard)"</item>
+ <item msgid="3830170141562534721">"Visa inte den här ikonen"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Visa alltid procent"</item>
+ <item msgid="2139628951880142927">"Visa procent under laddning (standard)"</item>
+ <item msgid="3327323682209964956">"Visa inte den här ikonen"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Annat"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Avdelare för delad skärm"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Flytta nedåt"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Flytta uppåt"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Flytta åt vänster"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Flytta åt höger"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 55f0213..4978d94 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Picha ya skrini imenaswa."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Gusa ili kuona picha yako ya skrini."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Haikuweza kunasa picha ya skrini"</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Haiwezi kupiga picha ya skrini kwa sababu nafasi ya hifadhi haitoshi, au hairuhusiwi na programu yako au ya shirika."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Haina nafasi ya kutosha kuhifadhi picha ya skrini."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Shirika au programu yako haikuruhusu upige picha za skrini."</string>
<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 kichezeshi cha midia (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Angika kama kamera (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Muda zaidi."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Muda kidogo"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Tochi imezimwa."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Tochi haipatikani."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Tochi inawaka."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Tochi imezimwa."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Tochi imewashwa."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"kudumisha programu moja"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"tafuta"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Haikuweza kuanzisha <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> imezimwa katika hali salama."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Historia"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Futa"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Programu hii haitumiki katika hali ya madirisha mengi"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Programu haitumiki katika hali ya madirisha mengi"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Gawanya Mlalo"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Gawanya Wima"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Maalum Iliyogawanywa"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Kimya\nkabisa"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Kipaumbele\npekee"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Kengele\npekee"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Zote"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Zote\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Inachaji (Imebakisha <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ijae)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Inachaji kwa kasi (itajaa baada ya <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Inachaji pole pole (itajaa baada ya <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Onyesha sekunde za saa katika sehemu ya arifa. Inaweza kuathiri muda wa matumizi ya betri."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Panga Upya Mipangilio ya Haraka"</string>
<string name="show_brightness" msgid="6613930842805942519">"Onyesha unga\'avu katika Mipangilio ya Haraka"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Washa kiakibishaji cha skrini inayogawanywa kwa kutelezesha kidole juu"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Ruhusu kugawanya skrini kwa ishara ya kutelezesha kidole juu"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Washa kipengele cha ishara ili utumie skrini iliyogawanywa kwa kutelezesha kidole juu kutoka kitufe cha Muhtasari"</string>
<string name="experimental" msgid="6198182315536726162">"Ya majaribio"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Je, ungependa kuwasha Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Ili uunganishe Kibodi yako kwenye kompyuta yako kibao, lazima kwanza uwashe Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Washa"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Tumia katika arifa za <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Tumia katika arifa zote kutoka programu hii"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Onyesha arifa bila sauti"</string>
+ <string name="block" msgid="2734508760962682611">"Zuia arifa zote"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Usinyamazishe"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Usinyamazishe wala kuzuia"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Onyesha mipangilio kamili ya umuhimu"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Amezuiwa"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Umuhimu wa kiwango cha chini zaidi"</string>
<string name="low_importance" msgid="4109929986107147930">"Umuhimu kiwango cha chini"</string>
<string name="default_importance" msgid="8192107689995742653">"Umuhimu wa kiwango cha kawaida"</string>
<string name="high_importance" msgid="1527066195614050263">"Umuhimu wa kiwango cha juu"</string>
<string name="max_importance" msgid="5089005872719563894">"Umuhimu wa hali ya dharura"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Usionyeshe arifa hizi kamwe"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Onyesha katika sehemu ya chini ya orodha ya arifa bila sauti"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Onyesha arifa hizi bila sauti"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Onyesha katika sehemu ya juu ya orodha ya arifa na itoe sauti"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Weka onyesho la kuchungulia kwenye skrini na itoe sauti"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Onyesha katika sehemu ya chini ya orodha ya arifa bila sauti"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Onyesha arifa hizi bila sauti"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Ruhusu arifa hizi zitoe sauti"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Chungulia kwenye skrini na uruhusu sauti"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Onyesha katika sehemu ya juu ya orodha ya arifa, chungulia kwenye skrini na uruhusu sauti"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Mipangilio zaidi"</string>
<string name="notification_done" msgid="5279426047273930175">"Nimemaliza"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Rangi za kawaida"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Rangi za usiku"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Rangi maalum"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Otomatiki"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Rangi zisizojulikana"</string>
- <string name="color_transform" msgid="6985460408079086090">"Ubadilishaji wa rangi"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Onyesha kigae cha Mipangilio ya Haraka"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Washa ubadilishaji maalum"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Rangi na mwonekano"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Hali ya usiku"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Rekebisha onyesho"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Imewashwa"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Imezimwa"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Washa kiotomatiki"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Badilisha kuwa Hali ya Usiku kulingana na mahali na wakati"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Hali ya Usiku inapowashwa"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Tumia mandhari ya giza katika Mfumo wa Uendeshaji wa Android"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Rekebisha kivulivuli"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Rekebisha mwangaza"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Mandhari yenye giza yametumika katika maeneo muhimu ya Mfumo wa Uendeshaji wa Android ambayo kwa kawaida huonyeshwa katika mandhari yenye mwangaza, kama vile Mipangilio."</string>
<string name="color_apply" msgid="9212602012641034283">"Tumia"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Thibitisha mipangilio"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Baadhi ya mipangilio ya rangi inaweza kufanya kifaa hiki kisitumike. Bofya Sawa ili uthibitishe mipangilio hii ya rangi, vinginevyo, mipangilio hii itajiweka upya baada ya sekunde 10."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Matumizi ya betri"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Kiokoa Betri hakipatikani unapochaji betri"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Kiokoa Betri"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Hupunguza data ya chini chini na utendaji"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Mwanzo"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Zilizotumika majuzi"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Nyuma"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Onyesha hali ya usinisumbue katika sauti"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Ruhusu udhibiti kamili wa hali ya usinisumbue katika kidirisha cha sauti."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Sauti na Usinisumbue"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Weka hali ya usinisumbue sauti inapopunguzwa"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Onyesha katika vidhibiti vya sauti"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Usinisumbue"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Njia ya mkato ya vitufe vya sauti"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Ondoa hali ya usinisumbue sauti inapoongezwa"</string>
<string name="battery" msgid="7498329822413202973">"Betri"</string>
<string name="clock" msgid="7416090374234785905">"Saa"</string>
<string name="headset" msgid="4534219457597457353">"Vifaa vya sauti"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Imeunganisha spika za masikioni"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Imeunganisha vifaa vya sauti"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Washa au uzime aikoni ili zisionekane kwenye sehemu ya arifa"</string>
<string name="data_saver" msgid="5037565123367048522">"Kiokoa Data"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Kiokoa Data kimewashwa"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Kiokoa Data kimezimwa"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Imewashwa"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Imezimwa"</string>
<string name="nav_bar" msgid="1993221402773877607">"Sehemu ya viungo muhimu"</string>
<string name="start" msgid="6873794757232879664">"Anza"</string>
<string name="center" msgid="4327473927066010960">"Weka katikati"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Onyesho la kuchungulia"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Buruta ili uongeze vigae"</string>
<string name="qs_edit" msgid="2232596095725105230">"Badilisha"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Wakati"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Onyesha saa, dakika na sekunde"</item>
+ <item msgid="1427801730816895300">"Onyesha saa na dakika (chaguo-msingi)"</item>
+ <item msgid="3830170141562534721">"Usionyeshe aikoni hii"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Onyesha asilimia kila wakati"</item>
+ <item msgid="2139628951880142927">"Onyesha asilimia wakati inachaji (chaguo-msingi)"</item>
+ <item msgid="3327323682209964956">"Usionyeshe aikoni hii"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Nyingine"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Kitenganishi cha skrini inayogawanywa"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Sogeza chini"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Sogeza juu"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Sogeza kushoto"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Sogeza kulia"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/styles.xml b/packages/SystemUI/res/values-sw600dp/styles.xml
index 4d7d6b5..791d761 100644
--- a/packages/SystemUI/res/values-sw600dp/styles.xml
+++ b/packages/SystemUI/res/values-sw600dp/styles.xml
@@ -16,7 +16,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="BrightnessDialogContainer" parent="@style/BaseBrightnessDialogContainer">
- <item name="android:layout_width">480dp</item>
+ <item name="android:layout_width">@dimen/standard_notification_panel_width</item>
</style>
<style name="UserDetailView">
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index ecfc446..66a1496 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"ஸ்கிரீன் ஷாட் எடுக்கப்பட்டது."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"உங்கள் ஸ்க்ரீன் ஷாட்டைப் பார்க்க தொடவும்."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"ஸ்க்ரீன் ஷாட்டை எடுக்க முடியவில்லை."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"குறைந்த சேமிப்பகம் காரணமாக ஸ்கிரீன்ஷாட் எடுக்க முடியவில்லை, அல்லது பயன்பாடு அல்லது உங்கள் நிறுவனத்தால் அனுமதிக்கப்படவில்லை."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"போதுமான சேமிப்பிடம் இல்லாததால் ஸ்கிரீன்ஷாட்டைச் சேமிக்க முடியவில்லை."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"பயன்பாடு அல்லது உங்கள் நிறுவனம் ஸ்கிரீன்ஷாட்டுகளை எடுக்க அனுமதிக்கவில்லை."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB கோப்பு இடமாற்ற விருப்பங்கள்"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"(MTP) மீடியா பிளேயராக ஏற்று"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"(PTP) கேமராவாக ஏற்று"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"நேரத்தை அதிகரி."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"நேரத்தைக் குறை."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ஃபிளாஷ்லைட் முடக்கத்தில்."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ஃபிளாஷ்லைட் இல்லை."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ஃபிளாஷ்லைட் இயக்கத்தில்."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ஃபிளாஷ்லைட் முடக்கப்பட்டது."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ஃபிளாஷ்லைட் இயக்கப்பட்டது."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"திரையை பின் செய்தல்"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"தேடு"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>ஐத் தொடங்க முடியவில்லை."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"பாதுகாப்புப் பயன்முறையில் <xliff:g id="APP">%s</xliff:g> முடக்கப்பட்டது."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"வரலாறு"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"அழி"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"இந்தப் பயன்பாடு பல சாளர அம்சத்தை ஆதரிக்கவில்லை"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"பயன்பாடு பல சாளர அம்சத்தை ஆதரிக்காது"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"கிடைமட்டமாகப் பிரி"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"செங்குத்தாகப் பிரி"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"தனிவிருப்பத்தில் பிரி"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"அறிவிப்புகள்\nவேண்டாம்"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"முன்னுரிமைகள்\nமட்டும்"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"அலாரங்கள்\nமட்டும்"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"எல்லாம்"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"எல்லாம்\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"மெதுவாக சார்ஜாகிறது (முழு சார்ஜிற்கு: <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"நிலைப் பட்டியில் கடிகார வினாடிகளைக் காட்டும். பேட்டரியின் ஆயுளைக் குறைக்கலாம்."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"விரைவு அமைப்புகளை மறுவரிசைப்படுத்து"</string>
<string name="show_brightness" msgid="6613930842805942519">"விரைவு அமைப்புகளில் ஒளிர்வுப் பட்டியைக் காட்டு"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"மேலே ஸ்வைப் செய்வதன் மூலம் திரைப் பிரிப்பை இயக்கு"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"மேலே ஸ்வைப் செய்வதன் மூலம் திரையைப் பிரிக்கும் சைகையை இயக்கு"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"மேலோட்டப் பார்வை பொத்தானிலிருந்து மேலே ஸ்வைப் செய்வதன் மூலம், திரைப் பிரிப்பைச் செயலாக்குவதற்கான சைகையை இயக்கும்"</string>
<string name="experimental" msgid="6198182315536726162">"சோதனை முயற்சி"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"புளூடூத்தை இயக்கவா?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"உங்கள் டேப்லெட்டுடன் விசைப்பலகையை இணைக்க, முதலில் புளூடூத்தை இயக்க வேண்டும்."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"இயக்கு"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> அறிவிப்புகளுக்குப் பயன்படுத்து"</string>
- <string name="apply_to_app" msgid="363016783939815960">"இந்தப் பயன்பாட்டிலிருந்து வரும் எல்லா அறிவிப்புகளுக்கும் பயன்படுத்து"</string>
+ <string name="show_silently" msgid="6841966539811264192">"ஒலியின்றி அறிவிப்புகளைக் காட்டு"</string>
+ <string name="block" msgid="2734508760962682611">"எல்லா அறிவிப்புகளையும் தடு"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"ஒலியை அனுமதி"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"ஒலி அல்லது அறிவிப்பைத் தடுக்காதே"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"முக்கியத்துவ அமைப்புகள் முழுவதையும் காட்டு"</string>
<string name="blocked_importance" msgid="5198578988978234161">"தடுக்கப்பட்டது"</string>
+ <string name="min_importance" msgid="1901894910809414782">"குறைந்தபட்ச முக்கியத்துவம்"</string>
<string name="low_importance" msgid="4109929986107147930">"முக்கியத்துவம் (குறைவு)"</string>
<string name="default_importance" msgid="8192107689995742653">"முக்கியத்துவம் (இயல்பு)"</string>
<string name="high_importance" msgid="1527066195614050263">"முக்கியத்துவம் (அதிகம்)"</string>
<string name="max_importance" msgid="5089005872719563894">"முக்கியத்துவம் (அவசரம்)"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"இந்த அறிவிப்புகளை ஒருபோதும் காட்டாதே"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"ஒலியின்றி அறிவிப்புப் பட்டியலின் கீழே காட்டு"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"ஒலியின்றி இந்த அறிவிப்புகளைக் காட்டு"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"அறிவிப்புகள் பட்டியலின் மேல் பகுதியில் ஒலியுடன் காட்டு"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"ஒலியுடன் திரையில் காட்டு"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"ஒலியின்றி அறிவிப்புப் பட்டியலின் கீழே காட்டு"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"ஒலியின்றி இந்த அறிவிப்புகளைக் காட்டு"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"இந்த அறிவிப்புகளுக்கு ஒலியை அனுமதி"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"சில வினாடிகளுக்கு ஒலியுடன் திரையில் காட்டு"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"அறிவிப்புகள் பட்டியலின் மேற்பகுதியில், சில வினாடிகளுக்கு ஒலியுடன் திரையில் காட்டு"</string>
<string name="notification_more_settings" msgid="816306283396553571">"மேலும் அமைப்புகள்"</string>
<string name="notification_done" msgid="5279426047273930175">"முடிந்தது"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"இயல்பான வண்ணங்கள்"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"இரவுநேர வண்ணங்கள்"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"தனிப்பயன் வண்ணங்கள்"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"தானியங்கு"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"அறியப்படாத வண்ணங்கள்"</string>
- <string name="color_transform" msgid="6985460408079086090">"வண்ண மாற்றம்"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"விரைவு அமைப்புகள் டைலைக் காட்டு"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"தனிப்பயன் வண்ண மாற்றத்தை இயக்கு"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"வண்ணமும் தோற்றமும்"</string>
+ <string name="night_mode" msgid="3540405868248625488">"இரவுப் பயன்முறை"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"திரையை அளவுத்திருத்தம் செய்"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"இயக்கத்தில்"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"முடக்கத்தில்"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"தானாகவே இயக்கு"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"இருப்பிடம் மற்றும் நேரத்தின்படி இரவுப் பயன்முறைக்கு மாற்று"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"இரவுப் பயன்முறை இயக்கப்பட்டிருக்கும் போது"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Android OSக்காக அடர் தீமினைப் பயன்படுத்து"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"டிண்ட்டைச் சரிசெய்"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"ஒளிர்வைச் சரிசெய்"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"வழக்கமாக வெளிர் தீமில் காட்டப்படுகிற Android OS இன் முக்கிய பகுதிகளில் (எ.கா. அமைப்புகள்) அடர் தீம் பயன்படுத்தப்படுகிறது."</string>
<string name="color_apply" msgid="9212602012641034283">"பயன்படுத்து"</string>
<string name="color_revert_title" msgid="4746666545480534663">"அமைப்புகளை உறுதிப்படுத்து"</string>
<string name="color_revert_message" msgid="9116001069397996691">"சில வண்ண அமைப்புகள் இந்தச் சாதனத்தைப் பயன்படுத்த முடியாதபடி செய்யலாம். இந்த வண்ண அமைப்புகளை உறுதிப்படுத்த, சரி என்பதைக் கிளிக் செய்யவும், இல்லையெனில் இந்த அமைப்புகள் 10 வினாடிகளுக்குப் பின் மீட்டமைக்கப்படும்."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"பேட்டரி உபயோகம்"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"சார்ஜ் செய்யும் போது பேட்டரி சேமிப்பானைப் பயன்படுத்த முடியாது"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"பேட்டரி சேமிப்பான்"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"செயல்திறனையும் பின்புலத்தில் தரவு செயலாக்கப்படுவதையும் குறைக்கும்"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"முகப்பு"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"சமீபத்தியவை"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"முந்தையது"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"ஒலி உரையாடலில் தொந்தரவு செய்ய வேண்டாம் என்பதைக் காட்டு"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"ஒலி உரையாடலில் தொந்தரவு செய்ய வேண்டாம் என்பதன் முழுக் கட்டுப்பாட்டையும் அனுமதி."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"ஒலி மற்றும் தொந்தரவு செய்ய வேண்டாம்"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"ஒலியைக் குறைக்கும்போது தொந்தரவு செய்ய வேண்டாம் என்பதை இயக்கு"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"ஒலிக் கட்டுப்பாடுகளுடன் காட்டு"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"தொந்தரவு செய்ய வேண்டாம்"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"ஒலியளவுப் பொத்தான்களுக்கான குறுக்குவழி"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"ஒலியைக் கூட்டும் போது தொந்தரவு செய்ய வேண்டாம் என்பதை முடக்கு"</string>
<string name="battery" msgid="7498329822413202973">"பேட்டரி"</string>
<string name="clock" msgid="7416090374234785905">"கடிகாரம்"</string>
<string name="headset" msgid="4534219457597457353">"ஹெட்செட்"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ஹெட்ஃபோன்கள் இணைக்கப்பட்டன"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ஹெட்செட் இணைக்கப்பட்டது"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"நிலைப் பட்டியில் ஐகான்களைக் காட்டுவதை இயக்கும் அல்லது முடக்கும்."</string>
<string name="data_saver" msgid="5037565123367048522">"தரவுச்சேமிப்பான்"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"தரவு சேமிப்பான் இயக்கப்பட்டது"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"தரவு சேமிப்பான் முடக்கப்பட்டது"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"இயக்கு"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"முடக்கு"</string>
<string name="nav_bar" msgid="1993221402773877607">"வழிசெலுத்தல் பட்டி"</string>
<string name="start" msgid="6873794757232879664">"தொடங்கு"</string>
<string name="center" msgid="4327473927066010960">"மையம்"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"மாதிரிக்காட்சி"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"கட்டங்களைச் சேர்க்க, இழுக்கவும்"</string>
<string name="qs_edit" msgid="2232596095725105230">"மாற்று"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"நேரம்"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"மணிநேரம், நிமிடங்கள், வினாடிகளைக் காட்டு"</item>
+ <item msgid="1427801730816895300">"மணிநேரம், நிமிடங்களைக் காட்டு (இயல்பு)"</item>
+ <item msgid="3830170141562534721">"இந்த ஐகானைக் காட்டாதே"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"எப்போதும் சதவீதத்தைக் காட்டு"</item>
+ <item msgid="2139628951880142927">"சார்ஜ் செய்யும் போது சதவீதத்தைக் காட்டு (இயல்பு)"</item>
+ <item msgid="3327323682209964956">"இந்த ஐகானைக் காட்டாதே"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"மற்றவை"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"திரையைப் பிரிக்கும் பிரிப்பான்"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"கீழே நகர்த்து"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"மேலே நகர்த்து"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"இடப்புறம் நகர்த்து"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"வலப்புறம் நகர்த்து"</string>
</resources>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index 4f702b6..d02b353 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"స్క్రీన్షాట్ క్యాప్చర్ చేయబడింది."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"మీ స్క్రీన్షాట్ను వీక్షించడానికి తాకండి."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"స్క్రీన్షాట్ను క్యాప్చర్ చేయడం సాధ్యపడలేదు."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"పరిమిత నిల్వ స్థలం కారణంగా స్క్రీన్షాట్ను తీయడం సాధ్యపడదు లేదా దీన్ని మీ అనువర్తనం లేదా మీ సంస్థ అనుమతించలేదు."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"పరిమిత నిల్వ స్థలం కారణంగా స్క్రీన్షాట్ను సేవ్ చేయడం సాధ్యపడదు."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"స్క్రీన్షాట్లు తీయడానికి అనువర్తనం లేదా మీ సంస్థ అనుమతించలేదు."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB ఫైల్ బదిలీ ఎంపికలు"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"మీడియా ప్లేయర్గా (MTP) మౌంట్ చేయి"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"కెమెరాగా (PTP) మౌంట్ చేయి"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"ఎక్కువ సమయం."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"తక్కువ సమయం."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ఫ్లాష్లైట్ ఆఫ్లో ఉంది."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ఫ్లాష్లైట్ అందుబాటులో లేదు."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ఫ్లాష్లైట్ ఆన్లో ఉంది."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ఫ్లాష్లైట్ ఆఫ్ చేయబడింది."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ఫ్లాష్లైట్ ఆన్ చేయబడింది."</string>
@@ -304,6 +306,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> సురక్షిత-మోడ్లో నిలిపివేయబడింది."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"చరిత్ర"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"తీసివేయి"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"ఈ అనువర్తనం బహుళ విండోలకు మద్దతు ఇవ్వదు"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"అనువర్తనం బహుళ విండోలకు మద్దతు ఇవ్వదు"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"సమతలంగా విభజించు"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"లంబంగా విభజించు"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"అనుకూలంగా విభజించు"</string>
@@ -333,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"మొత్తం\nనిశ్శబ్దం"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"ప్రాధాన్యమైనవి\nమాత్రమే"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"అలారాలు\nమాత్రమే"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"అన్నిటికీ"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"అన్నీ\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"నెమ్మదిగా ఛార్జ్ అవుతోంది (నిండటానికి <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
@@ -447,34 +449,43 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"స్థితి పట్టీలో గడియారం సెకన్లు చూపుతుంది. బ్యాటరీ శక్తి ప్రభావితం చేయవచ్చు."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"శీఘ్ర సెట్టింగ్ల ఏర్పాటు క్రమం మార్చు"</string>
<string name="show_brightness" msgid="6613930842805942519">"శీఘ్ర సెట్టింగ్ల్లో ప్రకాశం చూపు"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"పైకి స్వైప్ చేయడం ద్వారా స్క్రీన్ విభజన యాక్సిలరేటర్ను ప్రారంభించు"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"పైకి స్వైప్ చేయడం ద్వారా స్క్రీన్ విభజన సంజ్ఞను ప్రారంభించు"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"స్థూలదృష్టి బటన్ నుండి పైకి స్వైప్ చేయడం ద్వారా స్క్రీన్ విభజనలోకి ప్రవేశించడానికి సంజ్ఞను ప్రారంభిస్తుంది"</string>
<string name="experimental" msgid="6198182315536726162">"ప్రయోగాత్మకం"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"బ్లూటూత్ ఆన్ చేయాలా?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"మీ కీబోర్డ్ను మీ టాబ్లెట్తో కనెక్ట్ చేయడానికి, మీరు ముందుగా బ్లూటూత్ ఆన్ చేయాలి."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"ఆన్ చేయి"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> నోటిఫికేషన్లకు వర్తింపజేయి"</string>
- <string name="apply_to_app" msgid="363016783939815960">"ఈ అనువర్తనం నుండి అందించబడే అన్ని నోటిఫికేషన్లకు వర్తింపజేయి"</string>
+ <string name="show_silently" msgid="6841966539811264192">"నోటిఫికేషన్లను శబ్దం లేకుండా చూపు"</string>
+ <string name="block" msgid="2734508760962682611">"అన్ని నోటిఫికేషన్లను బ్లాక్ చేయి"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"నిశ్శబ్దం చేయవద్దు"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"నిశ్శబ్దం చేయవద్దు లేదా బ్లాక్ చేయవద్దు"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"పూర్తి ప్రాముఖ్యత సెట్టింగ్లను చూపండి"</string>
<string name="blocked_importance" msgid="5198578988978234161">"బ్లాక్ చేయబడింది"</string>
+ <string name="min_importance" msgid="1901894910809414782">"కని. ప్రాముఖ్యత"</string>
<string name="low_importance" msgid="4109929986107147930">"తక్కువ ప్రాముఖ్యత"</string>
<string name="default_importance" msgid="8192107689995742653">"సాధారణ ప్రాముఖ్యత"</string>
<string name="high_importance" msgid="1527066195614050263">"అధిక ప్రాముఖ్యత"</string>
<string name="max_importance" msgid="5089005872719563894">"అత్యవసర ప్రాముఖ్యత"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"ఈ నోటిఫికేషన్లను ఎప్పుడూ చూపదు"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"నోటిఫికేషన్ల జాబితా దిగువ భాగంలో శబ్దం లేకుండా చూపుతుంది"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"ఈ నోటిఫికేషన్లను శబ్దం లేకుండా చూపుతుంది"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"నోటిఫికేషన్ల జాబితా ఎగువ భాగంలో శబ్దంతో చూపుతుంది"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"స్క్రీన్పై శీఘ్రంగా శబ్దంతో చూపుతుంది"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"నోటిఫికేషన్ల జాబితా దిగువ భాగంలో శబ్దం లేకుండా చూపుతుంది"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"ఈ నోటిఫికేషన్లను శబ్దం లేకుండా చూపుతుంది"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"ఈ నోటిఫికేషన్లను శబ్దంతో చూపేలా అనుమతిస్తుంది"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"స్క్రీన్పై శీఘ్రంగా శబ్దంతో చూపుతుంది"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"నోటిఫికేషన్ల జాబితా అగ్ర భాగాన, స్క్రీన్పై శీఘ్రంగా శబ్దంతో చూపుతుంది"</string>
<string name="notification_more_settings" msgid="816306283396553571">"మరిన్ని సెట్టింగ్లు"</string>
<string name="notification_done" msgid="5279426047273930175">"పూర్తయింది"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"సాధారణ రంగులు"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"రాత్రి రంగులు"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"అనుకూల రంగులు"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"స్వయంచాలకం"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"తెలియని రంగులు"</string>
- <string name="color_transform" msgid="6985460408079086090">"రంగు సవరణ"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"శీఘ్ర సెట్టింగ్ల టైల్ను చూపండి"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"అనుకూల పరివర్తనను ప్రారంభించండి"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"రంగు మరియు కనిపించే తీరు"</string>
+ <string name="night_mode" msgid="3540405868248625488">"రాత్రి మోడ్"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"డిస్ప్లేని క్రమాంకనం చేయండి"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"ఆన్లో ఉంది"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"ఆఫ్లో ఉంది"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"స్వయంచాలకంగా ఆన్ చేయి"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"స్థానం మరియు రోజులో సమయానికి తగినట్లుగా రాత్రి మోడ్కి మారుస్తుంది"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"రాత్రి మోడ్ ఆన్లో ఉన్నప్పుడు"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Android OS కోసం ముదురు రంగు థీమ్ ఉపయోగించండి"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"లేత రంగును సర్దుబాటు చేయండి"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"ప్రకాశాన్ని సర్దుబాటు చేయండి"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"సాధారణంగా లేత రంగు థీమ్లో ప్రదర్శించబడే సెట్టింగ్ల వంటి Android OS ప్రధాన అంశాలకు ముదురు రంగు థీమ్ వర్తింపజేయబడుతుంది."</string>
<string name="color_apply" msgid="9212602012641034283">"వర్తింపజేయి"</string>
<string name="color_revert_title" msgid="4746666545480534663">"సెట్టింగ్లను నిర్ధారించండి"</string>
<string name="color_revert_message" msgid="9116001069397996691">"కొన్ని రంగు సెట్టింగ్ల వలన ఈ పరికరం ఉపయోగించలేని విధంగా అయిపోవచ్చు. ఈ రంగు సెట్టింగ్లను నిర్ధారించడానికి సరే క్లిక్ చేయండి లేదంటే ఈ సెట్టింగ్లు 10 సెకన్ల తర్వాత రీసెట్ చేయబడతాయి."</string>
@@ -486,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"హోమ్"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"ఇటీవలివి"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"వెనుకకు"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"వాల్యూమ్లో అంతరాయం కలిగించవద్దు ప్యానెల్ను చూపు"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"వాల్యూమ్ డైలాగ్లో అంతరాయం కలిగించవద్దు ప్యానెల్ పూర్తి నియంత్రణను అనుమతిస్తుంది."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"వాల్యూమ్ మరియు అంతరాయం కలిగించవద్దు"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"వాల్యూమ్ తగ్గిస్తే అంతరాయం కలిగించవద్దులోకి ప్రవేశిస్తుంది"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"వాల్యూమ్ నియంత్రణలతో చూపు"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"అంతరాయం కలిగించవద్దు"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"వాల్యూమ్ బటన్ల సత్వరమార్గం"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"వాల్యూమ్ పెంచితే అంతరాయం కలిగించవద్దు నుండి నిష్క్రమిస్తుంది"</string>
<string name="battery" msgid="7498329822413202973">"బ్యాటరీ"</string>
<string name="clock" msgid="7416090374234785905">"గడియారం"</string>
<string name="headset" msgid="4534219457597457353">"హెడ్సెట్"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"హెడ్ఫోన్లు కనెక్ట్ చేయబడ్డాయి"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"హెడ్సెట్ కనెక్ట్ చేయబడింది"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"స్థితి పట్టీలో చిహ్నాలు ప్రదర్శించడాన్ని ప్రారంభించండి లేదా నిలిపివేయండి."</string>
<string name="data_saver" msgid="5037565123367048522">"డేటా సేవర్"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"డేటా సేవర్ ఆన్లో ఉంది"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"డేటా సేవర్ ఆఫ్లో ఉంది"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"ఆన్"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"ఆఫ్ చేయి"</string>
<string name="nav_bar" msgid="1993221402773877607">"నావిగేషన్ బార్"</string>
<string name="start" msgid="6873794757232879664">"ప్రారంభం"</string>
<string name="center" msgid="4327473927066010960">"మధ్య"</string>
@@ -523,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"పరిదృశ్యం"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"టైల్లను జోడించడానికి లాగండి"</string>
<string name="qs_edit" msgid="2232596095725105230">"సవరించు"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"సమయం"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"గంటలు, నిమిషాలు మరియు సెకన్లను చూపు"</item>
+ <item msgid="1427801730816895300">"గంటలు మరియు నిమిషాలను చూపు (డిఫాల్ట్)"</item>
+ <item msgid="3830170141562534721">"ఈ చిహ్నాన్ని చూపవద్దు"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"ఎల్లప్పుడూ శాతాన్ని చూపు"</item>
+ <item msgid="2139628951880142927">"ఛార్జ్ అవుతున్నప్పుడు శాతాన్ని చూపు (డిఫాల్ట్)"</item>
+ <item msgid="3327323682209964956">"ఈ చిహ్నాన్ని చూపవద్దు"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"ఇతరం"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"విభజన స్క్రీన్ విభాగిని"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"క్రిందికి తరలించు"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"పైకి తరలించు"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"ఎడమవైపుకు తరలించు"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"కుడివైపుకు తరలించు"</string>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index bc7e26f..9b1ea74 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"จับภาพหน้าจอแล้ว"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"แตะเพื่อดูภาพหน้าจอของคุณ"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"ไม่สามารถจับภาพหน้าจอ"</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"ไม่สามารถจับภาพหน้าจอได้ เนื่องจากพื้นที่ว่างมีจำกัด หรือไม่ได้รับอนุญาตจากแอปหรือองค์กรของคุณ"</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ไม่สามารถบันทึกภาพหน้าจอเนื่องจากพื้นที่เก็บข้อมูลมีจำกัด"</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"แอปหรือองค์กรของคุณไม่อนุญาตให้จับภาพหน้าจอ"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"ตัวเลือกการถ่ายโอนไฟล์ USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"ต่อเชื่อมเป็นโปรแกรมเล่นสื่อ (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"ต่อเชื่อมเป็นกล้องถ่ายรูป (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"เวลามากขึ้น"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"เวลาน้อยลง"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ไฟฉายปิดอยู่"</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ไฟฉายไม่พร้อมใช้งาน"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ไฟฉายเปิดอยู่"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ปิดไฟฉายแล้ว"</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"เปิดไฟฉายแล้ว"</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"การตรึงหน้าจอ"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ค้นหา"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"ไม่สามารถเริ่มใช้ <xliff:g id="APP">%s</xliff:g>"</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ปิดใช้ในโหมดปลอดภัย"</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"ประวัติ"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"ล้าง"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"แอปนี้ไม่สนับสนุนหลายหน้าต่าง"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"แอปไม่สนับสนุนหลายหน้าต่าง"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"แยกในแนวนอน"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"แยกในแนวตั้ง"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"แยกแบบกำหนดเอง"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"ปิดเสียง\nทั้งหมด"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"เฉพาะเรื่อง\nสำคัญ"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"เฉพาะปลุก\nเท่านั้น"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"ทั้งหมด"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"ทั้งหมด\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"กำลังชาร์จอย่างช้าๆ (อีก <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> จะเต็ม)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"แสดงวินาทีของนาฬิกาในแถบสถานะ อาจส่งผลต่ออายุแบตเตอรี"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"จัดเรียงการตั้งค่าด่วนใหม่"</string>
<string name="show_brightness" msgid="6613930842805942519">"แสดงความสว่างในการตั้งค่าด่วน"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"เปิดใช้ตัวเร่งการเลื่อนขึ้นเพื่อแยกหน้าจอ"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"เปิดใช้ท่าทางสัมผัสการเลื่อนขึ้นเพื่อแยกหน้าจอ"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"เปิดใช้ท่าทางสัมผัสเพื่อเข้าสู่โหมดแยกหน้าจอโดยเลื่อนขึ้นจากปุ่มภาพรวม"</string>
<string name="experimental" msgid="6198182315536726162">"ทดสอบ"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"เปิดบลูทูธไหม"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"หากต้องการเชื่อมต่อแป้นพิมพ์กับแท็บเล็ต คุณต้องเปิดบลูทูธก่อน"</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"เปิด"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"นำไปใช้กับการแจ้งเตือน <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"นำไปใช้กับการแจ้งเตือนทั้งหมดจากแอปนี้"</string>
+ <string name="show_silently" msgid="6841966539811264192">"แสดงการแจ้งเตือนโดยไม่ส่งเสียง"</string>
+ <string name="block" msgid="2734508760962682611">"บล็อกการแจ้งเตือนทั้งหมด"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"ไม่ปิดเสียง"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"ไม่ปิดเสียงหรือบล็อก"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"แสดงการตั้งค่าความสำคัญแบบเต็ม"</string>
<string name="blocked_importance" msgid="5198578988978234161">"บล็อกแล้ว"</string>
+ <string name="min_importance" msgid="1901894910809414782">"ความสำคัญน้อย"</string>
<string name="low_importance" msgid="4109929986107147930">"ความสำคัญต่ำ"</string>
<string name="default_importance" msgid="8192107689995742653">"ความสำคัญปกติ"</string>
<string name="high_importance" msgid="1527066195614050263">"ความสำคัญสูง"</string>
<string name="max_importance" msgid="5089005872719563894">"ความสำคัญเร่งด่วน"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"ไม่ต้องแสดงการแจ้งเตือนเหล่านี้"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"แสดงที่ด้านล่างของรายการแจ้งเตือนโดยไม่ส่งเสียง"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"แสดงการแจ้งเตือนเหล่านี้โดยไม่ส่งเสียง"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"แสดงที่ด้านบนของรายการแจ้งเตือนและส่งเสียง"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"แสดงบนหน้าจอในช่วงเวลาสั้นๆ และส่งเสียง"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"แสดงที่ด้านล่างของรายการแจ้งเตือนโดยไม่ส่งเสียง"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"แสดงการแจ้งเตือนเหล่านี้โดยไม่ส่งเสียง"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"ให้การแจ้งเตือนเหล่านี้ส่งเสียงได้"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"แสดงบนหน้าจอและให้ส่งเสียงได้"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"แสดงที่ด้านบนของรายการการแจ้งเตือน แสดงบนหน้าจอและให้ส่งเสียงได้"</string>
<string name="notification_more_settings" msgid="816306283396553571">"การตั้งค่าเพิ่มเติม"</string>
<string name="notification_done" msgid="5279426047273930175">"เสร็จสิ้น"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"สีปกติ"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"สียามค่ำคืน"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"สีที่กำหนดเอง"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"อัตโนมัติ"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"สีที่ไม่รู้จัก"</string>
- <string name="color_transform" msgid="6985460408079086090">"การปรับเปลี่ยนสี"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"แสดงไทล์การตั้งค่าด่วน"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"เปิดใช้การเปลี่ยนที่กำหนดเอง"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"สีและลักษณะที่ปรากฏ"</string>
+ <string name="night_mode" msgid="3540405868248625488">"โหมดกลางคืน"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"ปรับเทียบการแสดงผล"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"เปิด"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"ปิด"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"เปิดอัตโนมัติ"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"เปลี่ยนเป็นโหมดกลางคืนตามความเหมาะสมกับสถานที่และเวลาของวัน"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"เมื่อเปิดโหมดกลางคืน"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"ใช้ธีมสีเข้มสำหรับ Android OS"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"ปรับการแต้มสี"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"ปรับความสว่าง"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"ใช้ธีมสีเข้มในบริเวณสำคัญของระบบปฏิบัติการ Android ซึ่งปกติแล้วจะแสดงด้วยธีมสีอ่อน เช่น การตั้งค่า"</string>
<string name="color_apply" msgid="9212602012641034283">"ใช้"</string>
<string name="color_revert_title" msgid="4746666545480534663">"ยืนยันการตั้งค่า"</string>
<string name="color_revert_message" msgid="9116001069397996691">"การตั้งค่าสีบางอย่างอาจทำให้อุปกรณ์นี้ใช้งานไม่ได้ คลิกตกลงเพื่อยืนยันการตั้งค่าสีเหล่านี้ มิฉะนั้นระบบจะรีเซ็ตการตั้งค่าหลังจาก 10 วินาที"</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"การใช้งานแบตเตอรี่"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"ไม่สามารถใช้โหมดประหยัดแบตเตอรี่ระหว่างการชาร์จ"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"โหมดประหยัดแบตเตอรี่"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"ลดประสิทธิภาพการทำงานและข้อมูลแบ็กกราวด์"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"หน้าแรก"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"ล่าสุด"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"กลับ"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"แสดงโหมดห้ามรบกวนในระดับเสียง"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"อนุญาตให้ควบคุมโหมดห้ามรบกวนได้อย่างสมบูรณ์ในกล่องโต้ตอบระดับเสียง"</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"ระดับเสียงและโหมดห้ามรบกวน"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"เข้าสู่โหมดห้ามรบกวนเมื่อลดระดับเสียง"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"แสดงพร้อมการควบคุมระดับเสียง"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"ห้ามรบกวน"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"ทางลัดปุ่มปรับระดับเสียง"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"ออกจากโหมดห้ามรบกวนเมื่อเพิ่มระดับเสียง"</string>
<string name="battery" msgid="7498329822413202973">"แบตเตอรี่"</string>
<string name="clock" msgid="7416090374234785905">"นาฬิกา"</string>
<string name="headset" msgid="4534219457597457353">"ชุดหูฟัง"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"เชื่อมต่อหูฟังแล้ว"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"เชื่อมต่อชุดหูฟังแล้ว"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"เปิดหรือปิดไอคอนจากการแสดงในแถบสถานะ"</string>
<string name="data_saver" msgid="5037565123367048522">"โปรแกรมประหยัดอินเทอร์เน็ต"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"โปรแกรมประหยัดอินเทอร์เน็ตเปิดอยู่"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"โปรแกรมประหยัดอินเทอร์เน็ตปิดอยู่"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"เปิด"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"ปิด"</string>
<string name="nav_bar" msgid="1993221402773877607">"แถบนำทาง"</string>
<string name="start" msgid="6873794757232879664">"บนสุด"</string>
<string name="center" msgid="4327473927066010960">"กึ่งกลาง"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"ดูตัวอย่าง"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"ลากเพื่อเพิ่มชิ้นส่วน"</string>
<string name="qs_edit" msgid="2232596095725105230">"แก้ไข"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"เวลา"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"แสดงชั่วโมง นาที และวินาที"</item>
+ <item msgid="1427801730816895300">"แสดงชั่วโมงและนาที (ค่าเริ่มต้น)"</item>
+ <item msgid="3830170141562534721">"อย่าแสดงไอคอนนี้"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"แสดงเปอร์เซ็นต์เสมอ"</item>
+ <item msgid="2139628951880142927">"แสดงเปอร์เซ็นต์เมื่อชาร์จ (ค่าเริ่มต้น)"</item>
+ <item msgid="3327323682209964956">"อย่าแสดงไอคอนนี้"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"อื่นๆ"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"เส้นแบ่งหน้าจอ"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"เลื่อนลง"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"เลื่อนขึ้น"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"เลื่อนไปทางซ้าย"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"เลื่อนไปทางขวา"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index ab800d4..d131c84 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Nakuha ang screenshot."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Pindutin upang tingnan ang iyong screenshot."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Hindi makuha ang screenshot."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Di makapag-screenshot dahil sa limitadong storage space o di ito pinapayagan ng app o organisasyon."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Hindi ma-save ang screenshot dahil sa limitadong espasyo ng storage."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Hindi pinapayagan ng app o ng iyong organisasyon ang pagkuha ng mga screenshot."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Opsyon paglipat ng USB file"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"I-mount bilang isang media player (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"I-mount bilang camera (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Higit pang oras."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Mas kaunting oras."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Naka-off ang flashlight."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Hindi available ang flashlight."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Naka-on ang flashlight."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Na-off ang flashlight."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Na-on ang flashlight."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pagpi-pin sa screen"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"maghanap"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Hindi masimulan <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Naka-disable ang <xliff:g id="APP">%s</xliff:g> sa safe-mode."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"History"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"I-clear"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Hindi sinusuportahan ng app na ito ang multi-window"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Hindi sinusuportahan ng app na ito ang multi-window"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Custom"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Ganap na\nkatahimikan"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Priyoridad\nlang"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Mga alarm\nlang"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Lahat"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Lahat\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Nagtsa-charge (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hanggang mapuno)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Mabilis mag-charge (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hanggang sa mapuno)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Mabagal mag-charge (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hanggang sa mapuno)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Ipakita ang mga segundo ng orasan sa status bar. Maaaring makaapekto sa tagal ng baterya."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Ayusing Muli ang Mga Mabilisang Setting"</string>
<string name="show_brightness" msgid="6613930842805942519">"Ipakita ang liwanag sa Mga Mabilisang Setting"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"I-enable ang split-screen na swipe-up accelerator"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"I-enable ang pag-swipe pataas na galaw para sa split-screen"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"I-enable ang gesture upang makapasok sa split-screen sa pamamagitan ng pagsa-swipe pataas mula sa button ng Pangkalahatang-ideya"</string>
<string name="experimental" msgid="6198182315536726162">"Pang-eksperimento"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"I-on ang Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Upang ikonekta ang iyong keyboard sa iyong tablet, kailangan mo munang i-on ang Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"I-on"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Naaangkop sa mga notification tungkol sa <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Naaangkop sa lahat ng notification mula sa app na ito"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Tahimik na ipakita ang mga notification"</string>
+ <string name="block" msgid="2734508760962682611">"I-block ang lahat ng notification"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Huwag i-silent"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Huwag i-silent o i-block"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Ipakita ang kumpletong mga setting ng kahalagahan"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Na-block"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Hindi masyadong mahalaga"</string>
<string name="low_importance" msgid="4109929986107147930">"Hindi masyadong mahalaga"</string>
<string name="default_importance" msgid="8192107689995742653">"Mahalaga"</string>
<string name="high_importance" msgid="1527066195614050263">"Napakahalaga"</string>
<string name="max_importance" msgid="5089005872719563894">"Mahalagang-mahalaga"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Huwag kailanman ipakita ang mga notification na ito"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Tahimik na ipakita sa ibaba ng listahan ng notification"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Tahimik na ipakita ang mga notification na ito"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Ipakita sa itaas ng listahan ng mga notification at mag-play ng tunog"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Ipasilip sa screen at mag-play ng tunog"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Tahimik na ipakita sa ibaba ng listahan ng notification"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Tahimik na ipakita ang mga notification na ito"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Payagan ang mga notification na ito na tumunog"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Palitawin sa screen at payagang tumunog"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Ipakita sa itaas ng listahan ng mga notification, palitawin sa screen at payagang tumunog"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Higit pang mga setting"</string>
<string name="notification_done" msgid="5279426047273930175">"Tapos Na"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Mga karaniwang kulay"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Madidilim na kulay"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Mga custom na kulay"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Auto"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Mga hindi kilalang kulay"</string>
- <string name="color_transform" msgid="6985460408079086090">"Pagbago sa kulay"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Ipakita ang tile ng Mga Mabilisang Setting"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"I-enable ang custom na pagpalit"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Kulay at hitsura"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Night mode"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"I-calibrate ang display"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Naka-on"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Naka-off"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Awtomatikong i-on"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Lumipat sa Night Mode kapag naaangkop sa lokasyon at oras"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Kapag naka-on ang Night Mode"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Gumamit ng madilim na tema para sa Android OS"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Isaayos ang tint"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Isaayos ang liwanag"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Ilalapat ang madilim na tema sa mga mahalagang bahagi ng Android OS na karaniwang ipinapakita nang may maliwanag na tema, gaya ng Mga Setting."</string>
<string name="color_apply" msgid="9212602012641034283">"Ilapat"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Kumpirmahin ang mga setting"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Maaaring hindi magamit ang device na ito dahil sa ilang setting ng kulay. I-click ang OK upang kumpirmahin ang mga setting ng kulay na ito, kung hindi ay mare-reset ang mga setting na ito pagkatapos ng 10 segundo."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Paggamit ng baterya"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Hindi available ang Pangtipid sa Baterya kapag nagcha-charge"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Pangtipid sa Baterya"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Binabawasan ang pagganap at data sa background"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Home"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Mga Kamakailang Ginamit"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Bumalik"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Ipakita ang huwag istorbohin sa volume"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Payagang ganap na makontrol ang huwag istorbohin sa dialog ng volume."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Volume at Huwag istorbohin"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Gamitin ang huwag istorbohin nang mahina ang volume"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Ipakita nang may mga kontrol ng volume"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Huwag istorbohin"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Shortcut ng mga button ng volume"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Umalis sa huwag istorbohin nang malakas ang volume"</string>
<string name="battery" msgid="7498329822413202973">"Baterya"</string>
<string name="clock" msgid="7416090374234785905">"Orasan"</string>
<string name="headset" msgid="4534219457597457353">"Headset"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Nakakonekta ang mga headphone"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Nakakonekta ang headset"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"I-enable o i-disable ang pagpapakita sa mga icon sa status bar."</string>
<string name="data_saver" msgid="5037565123367048522">"Data Saver"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Naka-on ang Data Saver"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Naka-off ang Data Saver"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"I-on"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"I-off"</string>
<string name="nav_bar" msgid="1993221402773877607">"Navigation bar"</string>
<string name="start" msgid="6873794757232879664">"Simula"</string>
<string name="center" msgid="4327473927066010960">"Gitna"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"I-preview"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Mag-drag upang magdagdag ng mga tile"</string>
<string name="qs_edit" msgid="2232596095725105230">"I-edit"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Oras"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Ipakita ang oras, minuto at segundo"</item>
+ <item msgid="1427801730816895300">"Ipakita ang oras at minuto (default)"</item>
+ <item msgid="3830170141562534721">"Huwag ipakita ang icon na ito"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Palaging ipakita ang porsyento"</item>
+ <item msgid="2139628951880142927">"Ipakita ang porsyento kapag nagcha-charge (default)"</item>
+ <item msgid="3327323682209964956">"Huwag ipakita ang icon na ito"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Iba pa"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Divider ng split-screen"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Ilipat pababa"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Ilipat pataas"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Ilipat pakaliwa"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Ilipat pakanan"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 1acffad..fd9e14c 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Ekran görüntüsü alındı."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Ekran görüntünüzü izlemek için dokunun."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Ekran görüntüsü alınamadı."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Depolama alanı sınırlı olduğundan veya uygulamanız ya da kuruluşunuz tarafından izin verilmediğinden ekran görüntüsü alınamıyor."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Depolama alanı sınırlı olduğundan ekran görüntüsü kaydedilemiyor."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Uygulama veya kuruluşunuz, ekran görüntüsü alınmasına izin vermiyor."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB dosya aktarım seçenekleri"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Medya oynatıcı olarak ekle (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Kamera olarak ekle (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Daha uzun süre."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Daha kısa süre."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"El feneri kapalı."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"El feneri kullanılamıyor."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"El feneri açık."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"El feneri kapatıldı."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"El feneri açıldı."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekran sabitleme"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ara"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> başlatılamadı."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g>, güvenli modda devre dışıdır."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Geçmiş"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Sil"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Bu uygulama, çoklu pencere kullanımını desteklemiyor"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Uygulama, çoklu pencere kullanımını desteklemiyor"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Yatay Ayırma"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Dikey Ayırma"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Özel Ayırma"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Tamamen\nsessiz"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Yalnızca\nöncelik"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Yalnızca\nalarmlar"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Tümü"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Tümü\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Şarj oluyor (tamamen dolmasına <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> kaldı)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Hızlı şarj oluyor (tam dolmasına <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> kaldı)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Yavaş şarj oluyor (tam dolmasına <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> kaldı)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Durum çubuğunda saatin saniyelerini gösterir. Pil ömrünü etkileyebilir."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Hızlı Ayarlar\'ı Yeniden Düzenle"</string>
<string name="show_brightness" msgid="6613930842805942519">"Hızlı Ayarlar\'da parlaklığı göster"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Ekranı bölmek için yukarı hızlıca kaydırmayı etkinleştir"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Hızlıca yukarı kaydırma hareketiyle ekran bölm. etkinleştir"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Genel bakış düğmesinden yukarı hızlıca kaydırarak bölünmüş ekrana geçme hareketini etkinleştir"</string>
<string name="experimental" msgid="6198182315536726162">"Deneysel"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth açılsın mı?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Klavyenizi tabletinize bağlamak için önce Bluetooth\'u açmanız gerekir."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Aç"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> bildirimlerine uygula"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Bu uygulamadan gelen tüm bildirimlere uygulansın mı?"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Bildirimleri sessizce göster"</string>
+ <string name="block" msgid="2734508760962682611">"Tüm bildirimleri engelle"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Sessiz moda alma"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Sessiz moda alma veya engelleme"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Tüm önem ayarlarını göster"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Engellendi"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Önemi en düşük"</string>
<string name="low_importance" msgid="4109929986107147930">"Önem düzeyi düşük"</string>
<string name="default_importance" msgid="8192107689995742653">"Önem düzeyi normal"</string>
<string name="high_importance" msgid="1527066195614050263">"Önem düzeyi yüksek"</string>
<string name="max_importance" msgid="5089005872719563894">"Önem düzeyi acil"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Bu bildirimleri hiçbir zaman gösterme"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Bildirim listesinin en altında sessizce göster"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Bu bildirimleri sessizce göster"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Bildirim listesinin en üstünde göster ve ses çıkar"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Ekrana getir ve ses çıkar"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Bildirim listesinin en altında sessizce göster"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Bu bildirimleri sessizce göster"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Bu bildirimlerin ses çıkarmasına izin ver"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Ekrana getir ve sesli bildirime izin ver"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Bildirim listesinin üstünde göster, ekrana getir ve sesli bildirime izin ver"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Diğer ayarlar"</string>
<string name="notification_done" msgid="5279426047273930175">"Bitti"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Normal renkler"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Gece renkleri"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Özel renkler"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Otomatik"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Bilinmeyen renkler"</string>
- <string name="color_transform" msgid="6985460408079086090">"Renk değişikliği"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Hızlı Ayarlar kutusunu göster"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Özel dönüşümü etkinleştir"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Renk ve görünüm"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Gece modu"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Ekranı kalibre et"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Açık"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Kapalı"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Otomatik olarak aç"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Konuma ve günün saatine uygun şekilde Gece Modu\'na geç"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Gece Modu açık olduğunda"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Android OS için koyu renk tema kullan"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Tonu ayarla"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Parlaklığı ayarla"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Koyu renk tema, Android OS\'nin normalde Ayarlar gibi açık renk bir temayla görüntülenen temel alanlarına uygulanır."</string>
<string name="color_apply" msgid="9212602012641034283">"Uygula"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Ayarları onaylayın"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Bazı renkler bu cihazı kullanılmaz yapabilir. Bu renkleri onaylamak için Tamam\'ı tıklayın. Tıklamazsanız bu ayarlar 10 saniye sonra sıfırlanacaktır."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Pil kullanımı"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Şarj sırasında Pil Tasarrufu özelliği kullanılamaz"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Pil Tasarrufu"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Performansı ve arka plan verilerini azaltır"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Ana ekran"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Son çağrılar"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Geri"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Ses iletişim kutusunda rahatsız etmeyin modunu göster"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Ses iletişim kutusunda rahatsız etmeyin modunu tam olarak denetlemeye izin ver."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Ses ve Rahatsız etmeyin"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Ses kısıldığında rahatsız etmeyin moduna geç"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Ses seviyesi kontrolleriyle göster"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Rahatsız etmeyin"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Ses düğmeleri kısayolu"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Ses açıldığında rahatsız etmeyin modundan çık"</string>
<string name="battery" msgid="7498329822413202973">"Pil"</string>
<string name="clock" msgid="7416090374234785905">"Saat"</string>
<string name="headset" msgid="4534219457597457353">"Mikrofonlu kulaklık"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Mikrofonlu kulaklık bağlı"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Mikrofonlu kulaklık bağlı"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Simgelerin durum çubuğunda görüntülenmesini etkinleştir veya devre dışı bırak"</string>
<string name="data_saver" msgid="5037565123367048522">"Veri Tasarrufu"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Veri Tasarrufu açık"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Veri Tasarrufu kapalı"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Açık"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Kapalı"</string>
<string name="nav_bar" msgid="1993221402773877607">"Gezinme çubuğu"</string>
<string name="start" msgid="6873794757232879664">"Başlangıç"</string>
<string name="center" msgid="4327473927066010960">"Merkez"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Önizle"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Blok eklemek için sürükleyin"</string>
<string name="qs_edit" msgid="2232596095725105230">"Düzenle"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Saat"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Saati, dakikayı ve saniyeyi göster"</item>
+ <item msgid="1427801730816895300">"Saati ve dakikayı göster (varsayılan)"</item>
+ <item msgid="3830170141562534721">"Bu simgeyi gösterme"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Her zaman yüzdeyi göster"</item>
+ <item msgid="2139628951880142927">"Şarj olurken yüzdeyi göster (varsayılan)"</item>
+ <item msgid="3327323682209964956">"Bu simgeyi gösterme"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Diğer"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Bölünmüş ekran ayırıcı"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Aşağı taşı"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Yukarı taşı"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Sola taşı"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Sağa taşı"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 0a00467..e5bf06d 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -75,7 +75,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Знімок екрана зроблено."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Торкніться, щоб переглянути знімок екрана."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Не вдалося зробити знімок екрана."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Не вдається зробити знімок екрана через обмежений обсяг пам’яті або заборону додатка чи організації."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Не вдалося зберегти знімок екрана через обмежений обсяг пам’яті."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Додаток або ваша організація не дозволяють робити знімки екрана."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Парам.передав.файлів через USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Підключити як медіапрогравач (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Підключити як камеру (PTP)"</string>
@@ -208,6 +209,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Більше часу."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Менше часу."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Ліхтарик вимк."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Ліхтарик недоступний."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Ліхтарик увімк."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Ліхтарик вимкнено."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Ліхтарик увімкнено."</string>
@@ -303,10 +305,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"закріпити екран"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"пошук"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Не вдалося запустити <xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Додаток <xliff:g id="APP">%s</xliff:g> вимкнено в безпечному режимі."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Історія"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Очистити"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Цей додаток не підтримує багатоекранний режим"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Додаток не підтримує багатоекранний режим"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Розділити горизонтально"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Розділити вертикально"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Розділити (власний варіант)"</string>
@@ -336,8 +339,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Без\nсигналів"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Лише\nприорітетні"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Лише\nсигнали"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Усі"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Усі\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Повільне заряджання (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> до повного заряду)"</string>
@@ -450,39 +451,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Показувати секунди на годиннику в рядку стану. Акумулятор може розряджатися швидше."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Упорядкувати швидкі налаштування"</string>
<string name="show_brightness" msgid="6613930842805942519">"Показувати панель яскравості у швидких налаштуваннях"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Увімкнути акселератор розділення екрана рухом пальця вгору"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Увімкнути розділення екрана рухом пальця вгору"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Увімкнути жест розділення екрана рухом пальця вгору від кнопки \"Огляд\""</string>
<string name="experimental" msgid="6198182315536726162">"Експериментальні налаштування"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Увімкнути Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Щоб під’єднати клавіатуру до планшета, спершу потрібно ввімкнути Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Увімкнути"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Застосувати до сповіщень на тему \"<xliff:g id="TOPIC_NAME">%1$s</xliff:g>\""</string>
- <string name="apply_to_app" msgid="363016783939815960">"Застосувати до всіх сповіщень із цього додатка"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Показувати сповіщення без звукового сигналу"</string>
+ <string name="block" msgid="2734508760962682611">"Блокувати всі сповіщення"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Не вимикати звуковий сигнал"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Не вимикати звуковий сигнал і не блокувати"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Показати налаштування пріоритетності"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Заблоковано"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Низький пріоритет"</string>
<string name="low_importance" msgid="4109929986107147930">"Низький пріоритет"</string>
<string name="default_importance" msgid="8192107689995742653">"Стандартний пріоритет"</string>
<string name="high_importance" msgid="1527066195614050263">"Високий пріоритет"</string>
<string name="max_importance" msgid="5089005872719563894">"Терміново"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Ніколи не показувати ці сповіщення"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Показувати сповіщення внизу списку без звукового сигналу"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Показувати ці сповіщення без звукового сигналу"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Показувати сповіщення вгорі списку зі звуковим сигналом"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Показувати сповіщення на екрані зі звуковим сигналом"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Показувати сповіщення внизу списку без звукового сигналу"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Показувати ці сповіщення без звукового сигналу"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Увімкнути звуковий сигнал для цих сповіщень"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Показувати сповіщення на екрані зі звуковим сигналом"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Показувати сповіщення вгорі списку, на екрані та зі звуковим сигналом"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Більше налаштувань"</string>
<string name="notification_done" msgid="5279426047273930175">"Готово"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Стандартні кольори"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Нічні кольори"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Користувацькі кольори"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Авто"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Невідомі кольори"</string>
- <string name="color_transform" msgid="6985460408079086090">"Змінення кольорів"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Показати опцію швидких налаштувань"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Увімкнути користувацьке перетворення"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Колір і вигляд"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Нічний режим"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Калібрувати дисплей"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Увімкнено"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Вимкнено"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Вмикати автоматично"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Переходити на нічний режим відповідно до місцезнаходження та часу доби"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Коли нічний режим увімкнено"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Використати нічну тему для ОС Android"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Налаштувати відтінок"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Регулювати яскравість"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Темна тема застосовується в основних областях ОС Android, які зазвичай відображаються у світлій темі, як-от у налаштуваннях."</string>
<string name="color_apply" msgid="9212602012641034283">"Застосувати"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Підтвердити налаштування"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Деякі налаштування кольорів можуть зробити цей пристрій непридатним для використання. Натисніть OK, щоб підтвердити налаштування, інакше їх буде скинуто через 10 секунд."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Використання заряду"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Режим економії заряду акумулятора недоступний під час заряджання"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Режим економії заряду акумулятора"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Знижується продуктивність і обмежується обмін даними у фоновому режимі"</string>
@@ -490,21 +499,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Головний екран"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Останні"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Назад"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Показувати режим \"Не турбувати\" у вікні регулятора гучності"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Дозволити керувати режимом \"Не турбувати\" у вікні регулятора гучності."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Регулятор гучності та режим \"Не турбувати\""</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Вмикати режим \"Не турбувати\" під час зменшення гучності"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Показувати регулятори гучності"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Не турбувати"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Кнопки гучності на корпусі"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Вимикати режим \"Не турбувати\" під час збільшення гучності"</string>
<string name="battery" msgid="7498329822413202973">"Акумулятор"</string>
<string name="clock" msgid="7416090374234785905">"Годинник"</string>
<string name="headset" msgid="4534219457597457353">"Гарнітура"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Навушники під’єднано"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Гарнітуру під’єднано"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Показати або сховати значки в рядку стану."</string>
<string name="data_saver" msgid="5037565123367048522">"Заощадження трафіку"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Заощадження трафіку ввімкнено"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Заощадження трафіку вимкнено"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Увімкнено"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Вимкнути"</string>
<string name="nav_bar" msgid="1993221402773877607">"Панель навігації"</string>
<string name="start" msgid="6873794757232879664">"На початку"</string>
<string name="center" msgid="4327473927066010960">"У центрі"</string>
@@ -527,4 +535,21 @@
<string name="preview" msgid="9077832302472282938">"Переглянути"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Перетягуйте фрагменти, щоб додавати їх"</string>
<string name="qs_edit" msgid="2232596095725105230">"Редагувати"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Час"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Показувати години, хвилини та секунди"</item>
+ <item msgid="1427801730816895300">"Показувати години та хвилини (за умовчанням)"</item>
+ <item msgid="3830170141562534721">"Не показувати цей значок"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Завжди показувати відсотки"</item>
+ <item msgid="2139628951880142927">"Показувати відсотки під час заряджання (за умовчанням)"</item>
+ <item msgid="3327323682209964956">"Не показувати цей значок"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Інше"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Розділювач екрана"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Перемістити вниз"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Перемістити вгору"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Перемістити ліворуч"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Перемістити праворуч"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index 0e1d78f..7a10732 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"اسکرین شاٹ کیپچر کیا گیا۔"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"اپنے اسکرین شاٹ دیکھنے کیلئے چھوئیں۔"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"اسکرین شاٹ کیپچر نہیں کر سکے۔"</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"اسٹوریج کی محدود جگہ کی وجہ سے اسکرین شاٹ نہیں لے سکتے، یا ایپ یا آپکی تنظیم کے ذریعے یہ مجاز نہیں ہے۔"</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"محدود اسٹوریج جگہ کی وجہ سے اسکرین شاٹس نہیں لئے جا سکتے۔"</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ایپ یا آپ کی تنظیم کی جانب سے اسکرین شاٹس لینے کی اجازت نہیں ہے۔"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB فائل منتقل کرنیکے اختیارات"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"ایک میڈیا پلیئر (MTP) کے بطور ماؤنٹ کریں"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"ایک کیمرہ (PTP) کے بطور ماؤنٹ کریں"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"مزید وقت۔"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"کم وقت۔"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"فلیش لائٹ آف ہے۔"</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"فلیش لائٹ دستیاب نہیں ہے"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"فلیش لائٹ آن ہے۔"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"فلیش لائٹ کو آف کر دیا گیا۔"</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"فلیش لائٹ کو آن کر دیا گیا۔"</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"اسکرین کو پن کرنا"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"تلاش کریں"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> کو شروع نہیں کیا جا سکا۔"</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"محفوظ موڈ میں <xliff:g id="APP">%s</xliff:g> غیر فعال ہوتی ہے۔"</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"سرگزشت"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"صاف کریں"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"یہ ایپ ملٹی ونڈو کی معاونت نہیں کرتی"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"ایپ ملٹی ونڈز کی معاونت نہیں کرتی"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"بلحاظ افقی الگ کریں"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"بلحاظ عمودی الگ کریں"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"بلحاظ حسب ضرورت الگ کریں"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"مکمل\nخاموشی"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"صرف\nترجیحی"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"صرف\nالارمز"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"سبھی"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"تمام\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"آہستہ چارج ہو رہا ہے (مکمل ہونے میں <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"گھڑی کے سیکنڈز اسٹیٹس بار میں دکھائیں۔ اس کا بیٹری کی زندگی پر اثر پڑ سکتا ہے۔"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"فوری ترتیبات کو دوبارہ ترتیب دیں"</string>
<string name="show_brightness" msgid="6613930842805942519">"فوری ترتیبات میں چمکیلا پن دکھائیں"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"سپلٹ اسکرین کیلئے سوائپ اپ ایکسلریٹر فعال کریں"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"سپلٹ اسکرین کیلئے سوائپ اپ اشارہ فعال کریں"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"مجموعی جائزہ بٹن سے سوائپ اپ کرکے سپلٹ اسکرین میں داخل ہونے کیلئے اشارہ فعال کریں"</string>
<string name="experimental" msgid="6198182315536726162">"تجرباتی"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"بلوٹوتھ آن کریں؟"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"اپنے کی بورڈ کو اپنے ٹیبلٹ کے ساتھ منسلک کرنے کیلئے پہلے آپ کو اپنا بلو ٹوتھ آن کرنا ہو گا۔"</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"آن کریں"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"<xliff:g id="TOPIC_NAME">%1$s</xliff:g> اطلاعات پر لاگو کریں"</string>
- <string name="apply_to_app" msgid="363016783939815960">"اس ایپ سے تمام اطلاعات پر لاگو کریں"</string>
+ <string name="show_silently" msgid="6841966539811264192">"اطلاعات خاموشی سے دکھائیں"</string>
+ <string name="block" msgid="2734508760962682611">"تمام اطلاعات کو مسدود کریں"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"خاموش نہ کریں"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"خاموش یا مسدود نہ کریں"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"اہمیت کی پوری ترتیبات دکھائیں"</string>
<string name="blocked_importance" msgid="5198578988978234161">"مسدود کردہ"</string>
+ <string name="min_importance" msgid="1901894910809414782">"کم سے کم اہمیت"</string>
<string name="low_importance" msgid="4109929986107147930">"کم اہمیت"</string>
<string name="default_importance" msgid="8192107689995742653">"عمومی اہمیت"</string>
<string name="high_importance" msgid="1527066195614050263">"زیادہ اہمیت"</string>
<string name="max_importance" msgid="5089005872719563894">"فوری اہمیت"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"یہ اطلاعات کبھی مت دکھائیں"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"اطلاعات کی فہرست کے سب سے نیچے خاموشی سے دکھائیں"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"خاموشی سے یہ اطلاعات دکھائیں"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"اطلاعات کی فہرست پر سب سے اوپر دکھائیں اور آواز چلائیں"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"اسکرین پر دکھائیں اور آواز چلائیں"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"اطلاعات کی فہرست کے سب سے نیچے خاموشی سے دکھائیں"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"خاموشی سے یہ اطلاعات دکھائیں"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"ان اطلاعات کو آواز نکالنے کی اجازت دیں"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"اسکرین پر دکھائیں اور آواز کی اجازت دیں"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"اطلاعات کی فہرست پر سب سے اوپر دکھائیں، اسکرین پر دکھائیں اور آواز کی اجازت دیں"</string>
<string name="notification_more_settings" msgid="816306283396553571">"مزید ترتیبات"</string>
<string name="notification_done" msgid="5279426047273930175">"ہوگیا"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"عام رنگ"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"رات کے رنگ"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"حسب ضرورت رنگ"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"خودکار"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"نامعلوم رنگ"</string>
- <string name="color_transform" msgid="6985460408079086090">"رنگوں کی تبدیلی"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"فوری ترتیبات والی ٹائل دکھائیں"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"حسب ضرورت ٹرانسفارم فعال کریں"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"رنگ اور ظہور"</string>
+ <string name="night_mode" msgid="3540405868248625488">"رات موڈ"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"نشان زد ڈسپلے"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"آن"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"آف"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"خودکار طور پر آن کریں"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"مقام اور دن کے وقت کی مناسبت سے نائٹ موڈ میں سوئچ کریں"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"جب نائٹ موڈ آن ہو"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Android OS کیلئے ڈارک تھیم استعمال کریں"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"ٹنٹ ایڈجسٹ کریں"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"چمک کو ایڈجسٹ کریں"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"ڈارک تھیم Android OS کی بنیادی جگہوں پر لاگو کی جاتی ہے جو عام طور لائٹ تھیم میں ڈسپلے ہوتے ہیں، جیسے ترتیبات۔"</string>
<string name="color_apply" msgid="9212602012641034283">"لاگو کریں"</string>
<string name="color_revert_title" msgid="4746666545480534663">"ترتیبات کی توثیق کریں"</string>
<string name="color_revert_message" msgid="9116001069397996691">"رنگوں کی کچھ ترتیبات اس آلے کو ناقابل استعمال بنا سکتی ہیں۔ رنگوں کی ان ترتیبات کی توثیق کرنے کیلئے ٹھیک ہے پر کلک کریں، بصورت دیگر 10 سیکنڈ بعد یہ ترتیبات ری سیٹ ہو جائیں گی۔"</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"بیٹری کا استعمال"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"چارجنگ کے دوران بیٹری سیور دستیاب نہیں ہے"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"بیٹری سیور"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"کارکردگی اور پس منظر کا ڈیٹا کم کر دیتا ہے"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"ہوم"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"حالیہ"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"پیچھے"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"والیوم میں ڈسٹرب نہ کریں دکھائیں"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"والیوم ڈائیلاگ میں ڈسٹرب نہ کریں کے مکمل کنٹرول کی اجازت دیں۔"</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"والیوم اور ڈسٹرب نہ کریں"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"کم والیوم پر \'ڈسٹرب نہ کریں\' میں داخل ہوں"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"والیوم کنٹرولز کے ساتھ دکھائیں"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"ڈسٹرب نہ کریں"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"والیوم بٹنز کے شارٹ کٹ"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"زیادہ والیوم پر \'ڈسٹرب نہ کریں\' سے خارج ہوں"</string>
<string name="battery" msgid="7498329822413202973">"بیٹری"</string>
<string name="clock" msgid="7416090374234785905">"گھڑی"</string>
<string name="headset" msgid="4534219457597457353">"ہیڈ سیٹ"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ہیڈ فونز منسلک ہیں"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ہیڈ سیٹ منسلک ہے"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"اسٹیٹس بار میں دکھائے جانے کیلئے آئیکنز فعال یا غیر فعال کریں۔"</string>
<string name="data_saver" msgid="5037565123367048522">"ڈیٹا سیور"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"ڈیٹا سیور آن ہے"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"ڈیٹا سیور آف ہے"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"آن"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"آف"</string>
<string name="nav_bar" msgid="1993221402773877607">"نیویگیشن بار"</string>
<string name="start" msgid="6873794757232879664">"شروع کریں"</string>
<string name="center" msgid="4327473927066010960">"مرکز"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"پیش منظر"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"ٹائٹلز شامل کرنے کیلئے گھسیٹیں"</string>
<string name="qs_edit" msgid="2232596095725105230">"ترمیم کریں"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"وقت"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"گھنٹے، منٹ اور سیکنڈ دکھائیں"</item>
+ <item msgid="1427801730816895300">"گھنٹے اور منٹ دکھائیں (ڈیفالٹ)"</item>
+ <item msgid="3830170141562534721">"یہ آئیکن نہ دکھائیں"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"ہمیشہ شرح فیصد دکھائیں"</item>
+ <item msgid="2139628951880142927">"چارج ہوتے وقت فیصد دکھائیں (ڈیفالٹ)"</item>
+ <item msgid="3327323682209964956">"یہ آئیکن نہ دکھائیں"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"دیگر"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"سپلٹ اسکرین تقسیم کار"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"نیچے منتقل کریں"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"اوپر منتقل کریں"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"بائیں منتقل کریں"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"دائیں منتقل کریں"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index 68393ff..79729dc 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Skrinshot saqlandi."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Ko‘rish uchun bu yerga bosing."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Skrinshot saqlanmadi."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Ekrandan suratga olib bo‘lmadi: xotirada joy kam yoki ilova/tashkilot bunga ruxsat bermagan."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Xotirada joy kamligi uchun skrinshotni saqlab bo‘lmadi."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Ilova yoki tashkilotingiz skrinshot olishni taqiqlagan."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB fayl ko‘chirish moslamalari"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Media pleyer sifatida ulash (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Kamera sifatida ulash (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Ko‘proq vaqt."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Kamroq vaqt."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Fonar o‘chirilgan."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Bu yerda fonar yo‘q."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Fonar yoqilgan."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Fonar o‘chirildi."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Fonar yoqildi."</string>
@@ -217,7 +219,7 @@
<string name="accessibility_quick_settings_work_mode_off" msgid="7045417396436552890">"Ish rejimi o‘chiq."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Ish rejimi yoniq."</string>
<string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Ish rejimi o‘chirib qo‘yildi."</string>
- <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Ish rejimi yoqildi."</string>
+ <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Ishchi rejim yoqildi."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Ekran yorqinligi"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G internet to‘xtatib qo‘yildi"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G internet to‘xtatib qo‘yildi"</string>
@@ -269,7 +271,7 @@
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Ulanmagan"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Tarmoq mavjud emas"</string>
- <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi o‘chirilgan"</string>
+ <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi o‘chiq"</string>
<string name="quick_settings_wifi_detail_empty_text" msgid="269990350383909226">"Hech qanday Wi-Fi tarmog‘i mavjud emas"</string>
<string name="quick_settings_cast_title" msgid="7709016546426454729">"Wi-Fi monitor"</string>
<string name="quick_settings_casting" msgid="6601710681033353316">"Translatsiya qilinmoqda"</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"o‘zgarmas ekran"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"qidirish"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"“<xliff:g id="APP">%s</xliff:g>” ilovasini ishga tushirib bo‘lmadi."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"Xavfsiz rejimda <xliff:g id="APP">%s</xliff:g> ilovasi o‘chirib qo‘yildi."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Jurnal"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Tozalash"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Bu ilova ko‘p oynali rejimni qo‘llab-quvvatlamaydi"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Bu ilova ko‘p oynali rejimni qo‘llab-quvvatlamaydi"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Gorizontal yo‘nalishda bo‘lish"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikal yo‘nalishda bo‘lish"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Boshqa usulda bo‘lish"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Tinchlik\nsaqlansin"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Faqat\nmuhimlar"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Faqat\nsignallar"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Barchasi"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Barcha\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Quvvat olmoqda (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>da to‘ladi)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Tez quvvat olmoqda (to‘lishiga <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> qoldi)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Sekin quvvat olmoqda (to‘lishiga <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> qoldi)"</string>
@@ -367,8 +368,8 @@
<string name="user_remove_user_message" msgid="1453218013959498039">"Ushbu foydalanuvchining barcha ilovalari va ma’lumotlari o‘chirib tashlanadi."</string>
<string name="user_remove_user_remove" msgid="7479275741742178297">"Olib tashlash"</string>
<string name="battery_saver_notification_title" msgid="237918726750955859">"Quvvat tejash rejimi yoqildi"</string>
- <string name="battery_saver_notification_text" msgid="820318788126672692">"Unumdorlikni pasaytiradi va fonda int-dan foyd-ni cheklaydi"</string>
- <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Quvvat tejash funksiyasini o‘chiring"</string>
+ <string name="battery_saver_notification_text" msgid="820318788126672692">"Unumdorlik pasayadi va fonda internetdan foydalanish cheklanadi"</string>
+ <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Quvvat tejash rejimidan chiqish"</string>
<string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ilovasi qurilma ekranidagi har qanday tasvirni ko‘rishni boshlaydi."</string>
<string name="media_projection_remember_text" msgid="3103510882172746752">"Boshqa ko‘rsatilmasin"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"Barchasini tozalash"</string>
@@ -448,61 +449,68 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Holat panelida soat soniyalari ko‘rsatilsin. Bu batareya resursiga ta’sir qilishi mumkin."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Tezkor sozlamalarni qayta tartiblash"</string>
<string name="show_brightness" msgid="6613930842805942519">"Tezkor sozlamalarda yorqinlikni ko‘rsatish"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Tepaga surib, ekranni bo‘lish uchun tezlatkichni yoqish"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Tepaga surish orqali ekranni ikkiga bo‘lish"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Umumiy ma’lumot tugmasini tepaga surish orqali ekranni bo‘lish ishorasini yoqish"</string>
<string name="experimental" msgid="6198182315536726162">"Tajribaviy"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth yoqilsinmi?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Klaviaturani planshetingizga ulash uchun Bluetooth xizmatini yoqishingiz kerak."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Yoqish"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"“<xliff:g id="TOPIC_NAME">%1$s</xliff:g>” bildirishnomalariga qo‘llash"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Ushbu ilovaning barcha bildirishnomalariga qo‘llash"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Bildirishnomalar ovozsiz ko‘rsatilsin"</string>
+ <string name="block" msgid="2734508760962682611">"Barcha bildirishnomalar bloklansin"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Ovozi o‘chirilmasin"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Ovozi o‘chirilmasin yoki bloklanmasin"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Barcha muhimlik sozlamalarini ko‘rsatish"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloklangan"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Kamroq muhim"</string>
<string name="low_importance" msgid="4109929986107147930">"Kamroq muhim"</string>
<string name="default_importance" msgid="8192107689995742653">"O‘rtacha muhim"</string>
<string name="high_importance" msgid="1527066195614050263">"Juda muhim"</string>
<string name="max_importance" msgid="5089005872719563894">"Favqulodda muhim"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Bu bildirishnomalar boshqa ko‘rsatilmasin"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Bildirishnomalar ro‘yxatining oxirida ovozsiz ko‘rsatilsin"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Bu bildirishnomalar ovozsiz ko‘rsatilsin"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Bildirishnomalar ro‘yxatining boshida ovoz bilan ko‘rsatilsin"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Barcha oynalar ustida signal ovozi bilan ko‘rsatilsin"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Bildirishnomalar ro‘yxatining oxirida ovozsiz ko‘rsatilsin"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Bu bildirishnomalar ovozsiz ko‘rsatilsin"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Bu bildirishnomalar ovoz bilan ko‘rsatilsin"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Barcha oynalar ustida ovoz bilan ko‘rsatilsin"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Bildirishnomalar ro‘yxatining boshida va barcha oynalar ustida ovoz bilan ko‘rsatilsin"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Boshqa sozlamalar"</string>
<string name="notification_done" msgid="5279426047273930175">"Tayyor"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Odatiy ranglar"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Qoramtir ranglar"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Foydalanuvchi rangi"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Avtomatik"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Noma’lum ranglar"</string>
- <string name="color_transform" msgid="6985460408079086090">"Rang sozlamalari"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Tezkor sozlamalar panelini ko‘rsatish"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Foydalanuvchi sozlamalarini yoqish"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Rang va ko‘rinishi"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Tungi rejim"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Ekranni kalibrlash"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Yoniq"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"O‘chiq"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Avtomatik yoqish"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Joylashuv va vaqtga mos ravishda tungi rejimga o‘tish"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Agar tungi rejim yoniq bo‘lsa"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Android uchun to‘q rangli mavzudan foydalanish"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Rang tusini o‘zgartirish"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Yorqinlikni o‘zgartirish"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"To‘q rangli mavzu Android tizimining odatda och rangda ko‘rsatiladigan o‘zak sahifalariga (masalan, Sozlamalar) nisbatan qo‘llaniladi."</string>
<string name="color_apply" msgid="9212602012641034283">"Qo‘llash"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Sozlamalarni tasdiqlang"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Ba’zi rang sozlamalari qurilmadan foydalanishni qiyinlashtirish mumkin. Tanlgan parametrlarni tasdiqlash uchun “OK” tugmasini bosing. Aks holda, ular 10 soniyadan so‘ng qayta tiklanadi."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Batareya sarfi"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Quvvat tejash rejimidan quvvatlash vaqtida foydalanib bo‘lmaydi"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Quvvat tejash rejimi"</string>
- <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Unumdorlikni pasaytiradi va fonda internetdan foydalanishni cheklaydi"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Unumdorlik pasayadi va fonda internetdan foydalanish cheklanadi"</string>
<string name="keyboard_shortcut_group_system" msgid="6472647649616541064">"Tizim"</string>
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Bosh ekran"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"So‘nggi ishlatilganlar"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Orqaga"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Ovoz boshqarish oynasida “Bezovta qilinmasin” panelini ko‘rsatish"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Ovoz balandligini boshqarish oynasida “Bezovta qilinmasin” rejimini to‘liq boshqarishga ruxsat beradi."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Ovoz balandligini boshqarish va “Bezovta qilinmasin” rejimi"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Ovozni pasaytirganda “Bezovta qilinmasin” rejimini yoqish"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Ovoz balandligini boshqarish tugmalari bilan ko‘rsatish"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Bezovta qilinmasin"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Ovoz balandligini boshqarish tugmalari"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Ovozni ko‘targanda “Bezovta qilinmasin” rejimini o‘chirish"</string>
<string name="battery" msgid="7498329822413202973">"Batareya"</string>
<string name="clock" msgid="7416090374234785905">"Soat"</string>
<string name="headset" msgid="4534219457597457353">"Audio moslama"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Quloqchinlar ulandi"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Audio moslama ulandi"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Holat qatorida begilarning ko‘rsatilishini yoqish yoki o‘chirish."</string>
<string name="data_saver" msgid="5037565123367048522">"Trafik tejash"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Trafik tejash yoniq"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Trafik tejash o‘chiq"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Yoniq"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"O‘chiq"</string>
<string name="nav_bar" msgid="1993221402773877607">"Navigatsiya paneli"</string>
<string name="start" msgid="6873794757232879664">"Boshlash"</string>
<string name="center" msgid="4327473927066010960">"Markazda"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Oldindan ko‘rish"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Fragmentlar qo‘shish uchun torting"</string>
<string name="qs_edit" msgid="2232596095725105230">"Tahrirlash"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Vaqt"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Soat, daqiqa va soniyalar ko‘rsatilsin"</item>
+ <item msgid="1427801730816895300">"Soat va daqiqalar ko‘rsatilsin (birlamchi)"</item>
+ <item msgid="3830170141562534721">"Bu belgi boshqa ko‘rsatilmasin"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Har doim foizda ko‘rsatilsin"</item>
+ <item msgid="2139628951880142927">"Quvvat olayotganda foizda ko‘rsatilsin (birlamchi)"</item>
+ <item msgid="3327323682209964956">"Bu belgi boshqa ko‘rsatilmasin"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Boshqa"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Ekranni ikkiga bo‘lish chizig‘i"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Pastga siljitish"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Tepaga siljitish"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Chapga siljitish"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"O‘ngga siljitish"</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index d4c7317..e8babe5 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Đã chụp ảnh màn hình."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Chạm để xem ảnh chụp màn hình của bạn."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Không thể chụp ảnh màn hình."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Ko thể chụp ảnh màn hình do dung lượng bộ nhớ hạn chế hoặc ứng dụng hay tổ chức của bạn ko cho phép."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Không thể lưu ảnh chụp màn hình do giới hạn dung lượng bộ nhớ."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Ứng dụng hoặc tổ chức của bạn không cho phép chụp ảnh màn hình."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Tùy chọn truyền tệp USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Gắn như một trình phát đa phương tiện (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Gắn như một máy ảnh (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Nhiều thời gian hơn."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Ít thời gian hơn."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Đèn pin tắt."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Đèn flash không khả dụng."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Đèn pin bật."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Đã tắt đèn pin."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Đã bật đèn pin."</string>
@@ -305,6 +307,8 @@
<skip />
<string name="recents_history_button_label" msgid="5153358867807604821">"Lịch sử"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Xóa"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Ứng dụng này không hỗ trợ chế độ nhiều cửa sổ"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Ứng dụng không hỗ trợ chế độ nhiều cửa sổ"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Phân tách ngang"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Phân tách dọc"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Tùy chỉnh phân tách"</string>
@@ -334,8 +338,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Hoàn toàn\ntắt tiếng"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Chỉ\nưu tiên"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Chỉ\nbáo thức"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Tất cả"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Tất cả\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Đang sạc (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> cho đến khi đầy)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Sạc nhanh (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> cho tới khi đầy)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Sạc chậm (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> cho tới khi đầy)"</string>
@@ -448,39 +450,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Hiển thị giây đồng hồ trong thanh trạng thái. Có thể ảnh hưởng đến thời lượng pin."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Sắp xếp lại Cài đặt nhanh"</string>
<string name="show_brightness" msgid="6613930842805942519">"Hiển thị độ sáng trong Cài đặt nhanh"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Bật trình tăng tốc vuốt lên ở chế độ chia đôi màn hình"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Bật cử chỉ vuốt lên ở chế độ chia đôi màn hình"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Cho phép cử chỉ truy cập chế độ chia đôi màn hình bằng cách vuốt lên từ nút Tổng quan"</string>
<string name="experimental" msgid="6198182315536726162">"Thử nghiệm"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bật Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Để kết nối bàn phím với máy tính bảng, trước tiên, bạn phải bật Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Bật"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Áp dụng cho thông báo <xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Áp dụng cho tất cả thông báo từ ứng dụng này"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Hiển thị im lặng các thông báo"</string>
+ <string name="block" msgid="2734508760962682611">"Chặn tất cả thông báo"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Không im lặng"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Không im lặng hoặc chặn"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Hiển thị cài đặt tầm quan trọng đầy đủ"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bị chặn"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Tầm quan trọng thấp nhất"</string>
<string name="low_importance" msgid="4109929986107147930">"Tầm quan trọng thấp"</string>
<string name="default_importance" msgid="8192107689995742653">"Tầm quan trọng bình thường"</string>
<string name="high_importance" msgid="1527066195614050263">"Tầm quan trọng cao"</string>
<string name="max_importance" msgid="5089005872719563894">"Tầm quan trọng khẩn cấp"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Không bao giờ hiển thị các thông báo này"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Hiển thị im lặng ở cuối danh sách thông báo"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Hiển thị im lặng các thông báo này"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Hiển thị ở đầu danh sách thông báo và phát ra âm thanh"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Hiển thị trên màn hình và phát ra âm thanh"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Hiển thị im lặng ở cuối danh sách thông báo"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Hiển thị im lặng các thông báo này"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Cho phép các thông báo này phát ra âm thanh"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Hiển thị trên màn hình và phát ra âm thanh"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Hiển thị ở đầu danh sách thông báo, hiển thị trên màn hình và phát ra âm thanh"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Cài đặt khác"</string>
<string name="notification_done" msgid="5279426047273930175">"Xong"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Màu thông thường"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Màu tối"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Màu tùy chỉnh"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Tự động"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Màu không xác định"</string>
- <string name="color_transform" msgid="6985460408079086090">"Sửa đổi màu"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Hiển thị ô Cài đặt nhanh"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Bật chuyển đổi tùy chỉnh"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Màu sắc và giao diện"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Chế độ ban đêm"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Hiệu chỉnh hiển thị"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Bật"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Tắt"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Tự động bật"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Chuyển sang Chế bộ ban đêm khi thích hợp cho vị trí và thời gian trong ngày"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Khi Chế độ ban đêm đang bật"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Sử dụng chủ đề sẫm màu cho Android OS"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Điều chỉnh phủ màu"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Điều chỉnh độ sáng"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Chủ đề sẫm màu được áp dụng cho các vùng chính của Android OS được hiển thị bình thường trong chủ đề sáng màu, chẳng hạn như Cài đặt."</string>
<string name="color_apply" msgid="9212602012641034283">"Áp dụng"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Xác nhận cài đặt"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Một số cài đặt màu có thể khiến thiết bị này không sử dụng được. Hãy nhấp vào OK để xác nhận các cài đặt màu này, nếu không những cài đặt này sẽ được đặt lại sau 10 giây."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Mức sử dụng pin"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Trình tiết kiệm pin không khả dụng trong khi sạc"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Trình tiết kiệm pin"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Giảm hiệu suất và dữ liệu nền"</string>
@@ -488,21 +498,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Màn hình chính"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Gần đây"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Quay lại"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Hiển thị không làm phiền theo âm lượng"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Cho phép kiểm soát toàn bộ tính năng không làm phiền trong hộp thoại âm lượng."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Âm lượng và Không làm phiền"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Truy cập không làm phiền khi giảm âm lượng"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Hiển thị với các điều khiển âm lượng"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Không làm phiền"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Phím tắt các nút âm lượng"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Thoát không làm phiền khi tăng âm lượng"</string>
<string name="battery" msgid="7498329822413202973">"Pin"</string>
<string name="clock" msgid="7416090374234785905">"Đồng hồ"</string>
<string name="headset" msgid="4534219457597457353">"Tai nghe"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Đã kết nối tai nghe"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Đã kết nối tai nghe"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Bật hoặc tắt biểu tượng hiển thị trong thanh trạng thái."</string>
<string name="data_saver" msgid="5037565123367048522">"Trình tiết kiệm dữ liệu"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Trình tiết kiệm dữ liệu đang bật"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Trình tiết kiệm dữ liệu đang tắt"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Bật"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Tắt"</string>
<string name="nav_bar" msgid="1993221402773877607">"Thanh điều hướng"</string>
<string name="start" msgid="6873794757232879664">"Đầu"</string>
<string name="center" msgid="4327473927066010960">"Căn giữa"</string>
@@ -525,4 +534,21 @@
<string name="preview" msgid="9077832302472282938">"Xem trước"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Kéo để thêm ô"</string>
<string name="qs_edit" msgid="2232596095725105230">"Chỉnh sửa"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Thời gian"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Hiển thị giờ, phút và giây"</item>
+ <item msgid="1427801730816895300">"Hiển thị giờ và phút (mặc định)"</item>
+ <item msgid="3830170141562534721">"Không hiển thị biểu tượng này"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Luôn hiển thị phần trăm"</item>
+ <item msgid="2139628951880142927">"Hiển thị phần trăm khi sạc (mặc định)"</item>
+ <item msgid="3327323682209964956">"Không hiển thị biểu tượng này"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Khác"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Bộ chia chia đôi màn hình"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Chuyển xuống"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Chuyển lên"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Di chuyển sang trái"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Di chuyển sang phải"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 8a3723a..f828306 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"已抓取屏幕截图。"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"触摸可查看您的屏幕截图。"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"无法抓取屏幕截图。"</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"无法进行屏幕截图,原因可能是存储空间不足,或者该应用或您所属的单位不允许执行此操作。"</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"由于存储空间有限,无法保存屏幕截图。"</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"此应用或贵单位不允许进行屏幕截图。"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB文件传输选项"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"作为媒体播放器(MTP)装载"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"作为相机(PTP)装载"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"延长时间。"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"缩短时间。"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"手电筒关闭。"</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"无法使用手电筒。"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"手电筒打开。"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"手电筒已关闭。"</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"手电筒已打开。"</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"固定屏幕"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"搜索"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"无法启动<xliff:g id="APP">%s</xliff:g>。"</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g>已在安全模式下停用。"</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"历史记录"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"清除"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"此应用不支持多窗口模式"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"应用不支持多窗口模式"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"水平分割"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"垂直分割"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"自定义分割"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"完全\n静音"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"仅限\n优先打扰"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"仅限\n闹钟"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"全部"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"全部\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"正在慢速充电(还需<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>充满)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"在状态栏中显示时钟的秒数。这可能会影响电池的续航时间。"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"重新排列快捷设置"</string>
<string name="show_brightness" msgid="6613930842805942519">"在快捷设置中显示亮度栏"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"启用分屏向上滑动加速器"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"启用分屏上滑手势"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"启用通过从“概览”按钮向上滑动的手势进入分屏模式"</string>
<string name="experimental" msgid="6198182315536726162">"实验性"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"要开启蓝牙吗?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"要将您的键盘连接到平板电脑,您必须先开启蓝牙。"</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"开启"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"应用于<xliff:g id="TOPIC_NAME">%1$s</xliff:g>通知"</string>
- <string name="apply_to_app" msgid="363016783939815960">"应用于来自此应用的所有通知"</string>
+ <string name="show_silently" msgid="6841966539811264192">"显示通知,但不发出提示音"</string>
+ <string name="block" msgid="2734508760962682611">"屏蔽所有通知"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"不静音"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"不静音或不屏蔽"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"显示完整的重要性设置"</string>
<string name="blocked_importance" msgid="5198578988978234161">"屏蔽"</string>
+ <string name="min_importance" msgid="1901894910809414782">"最低重要性"</string>
<string name="low_importance" msgid="4109929986107147930">"重要性:低"</string>
<string name="default_importance" msgid="8192107689995742653">"重要性:一般"</string>
<string name="high_importance" msgid="1527066195614050263">"重要性:高"</string>
<string name="max_importance" msgid="5089005872719563894">"重要性:紧急"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"一律不显示这些通知"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"在通知列表底部显示,但不发出提示音"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"显示这些通知,但不发出提示音"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"在通知列表顶部显示,并发出提示音"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"在屏幕上持续显示,并发出提示音"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"在通知列表底部显示,但不发出提示音"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"显示这些通知,但不发出提示音"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"允许这些通知发出提示音"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"在屏幕上短暂显示,并发出提示音"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"在通知列表顶部显示,同时在屏幕上短暂显示,并发出提示音"</string>
<string name="notification_more_settings" msgid="816306283396553571">"更多设置"</string>
<string name="notification_done" msgid="5279426047273930175">"完成"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"常规颜色"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"夜间颜色"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"自定义颜色"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"自动"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"未知颜色"</string>
- <string name="color_transform" msgid="6985460408079086090">"颜色修改"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"显示“快捷设置”图块"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"启用自定义转换"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"颜色和外观"</string>
+ <string name="night_mode" msgid="3540405868248625488">"夜间模式"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"校准显示画面"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"开启"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"关闭"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"自动开启"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"根据地点和时间适时切换到夜间模式"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"夜间模式开启时"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"对 Android 操作系统使用深色主题背景"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"调整色调"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"调整亮度"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"系统会将深色主题背景应用于 Android 操作系统的核心区域(通常以浅色主题背景显示),例如“设置”部分。"</string>
<string name="color_apply" msgid="9212602012641034283">"应用"</string>
<string name="color_revert_title" msgid="4746666545480534663">"确认设置"</string>
<string name="color_revert_message" msgid="9116001069397996691">"部分颜色设置可能会导致此设备无法使用。请点击“确定”确认这些颜色设置,否则,系统将在 10 秒后重置这些设置。"</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"电池使用情况"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"充电过程中无法使用节电助手"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"节电助手"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"降低性能并限制后台流量"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"主屏幕"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"最近"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"返回"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"在音量对话框中显示“请勿打扰”模式"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"允许在音量对话框中完全控制“请勿打扰”模式。"</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"音量和“请勿打扰”设置"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"按音量调低键时进入“请勿打扰”模式"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"与音量控件一起显示"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"请勿打扰"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"音量按钮快捷键"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"按音量调高键时退出“请勿打扰”模式"</string>
<string name="battery" msgid="7498329822413202973">"电池"</string>
<string name="clock" msgid="7416090374234785905">"时钟"</string>
<string name="headset" msgid="4534219457597457353">"耳机"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"已连接到耳机"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"已连接到耳机"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"指定在状态栏中显示或隐藏图标。"</string>
<string name="data_saver" msgid="5037565123367048522">"流量节省程序"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"流量节省程序已开启"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"流量节省程序已关闭"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"开启"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"关闭"</string>
<string name="nav_bar" msgid="1993221402773877607">"导航栏"</string>
<string name="start" msgid="6873794757232879664">"顶部"</string>
<string name="center" msgid="4327473927066010960">"中心位置"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"预览"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"拖动即可添加图块"</string>
<string name="qs_edit" msgid="2232596095725105230">"修改"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"时间"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"显示小时、分钟和秒"</item>
+ <item msgid="1427801730816895300">"显示小时和分钟(默认)"</item>
+ <item msgid="3830170141562534721">"不显示此图标"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"一律显示百分比"</item>
+ <item msgid="2139628951880142927">"充电时显示百分比(默认)"</item>
+ <item msgid="3327323682209964956">"不显示此图标"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"其他"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"分屏分隔线"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"下移"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"上移"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"左移"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"右移"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 675d0f3..bd379b7 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"已擷取螢幕畫面。"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"輕觸即可查看螢幕擷取畫面。"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"無法擷取螢幕畫面。"</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"由於儲存空間有限,或被應用程式或貴機構禁止,因此無法擷取螢幕擷圖。"</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"由於儲存空間有限,因此無法儲存螢幕擷取畫面。"</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"此應用程式或您的機構禁止擷取螢幕畫面。"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB 檔案傳輸選項"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"掛接為媒體播放器 (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"掛接為相機 (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"增加時間。"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"減少時間。"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"閃光燈已關閉。"</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"無法使用手電筒。"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"閃光燈已開啟。"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"閃光燈已關閉。"</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"閃光燈已開啟。"</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"螢幕固定"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"搜尋"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"無法啟動「<xliff:g id="APP">%s</xliff:g>」。"</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"「<xliff:g id="APP">%s</xliff:g>」已在安全模式中停用。"</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"記錄"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"清除"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"此應用程式不支援多視窗模式"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"應用程式不支援多視窗模式"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"水平分割"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"垂直分割"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"自訂分割"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"完全\n靜音"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"僅限\n優先"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"僅限\n鬧鐘"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"全部"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"全部\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"正在緩慢充電 (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>後完成充電)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"在狀態列中顯示時鐘秒數,但可能會影響電池壽命。"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"重新排列快速設定"</string>
<string name="show_brightness" msgid="6613930842805942519">"在快速設定顯示亮度"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"啟用分割畫面向上滑動加速工具"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"啟用分割畫面向上快速滑動手勢"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"從 [概覽] 按鈕向上快速滑動,即可使用手勢功能進入分割畫面模式"</string>
<string name="experimental" msgid="6198182315536726162">"實驗版"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"要開啟藍牙嗎?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"如要將鍵盤連接至平板電腦,請先開啟藍牙。"</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"開啟"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"套用到「<xliff:g id="TOPIC_NAME">%1$s</xliff:g>」通知"</string>
- <string name="apply_to_app" msgid="363016783939815960">"套用到此應用程式的所有通知"</string>
+ <string name="show_silently" msgid="6841966539811264192">"顯示通知,但不發出音效"</string>
+ <string name="block" msgid="2734508760962682611">"封鎖所有通知"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"不設為靜音"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"不設為靜音或封鎖"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"顯示所有重要性設定"</string>
<string name="blocked_importance" msgid="5198578988978234161">"已封鎖"</string>
+ <string name="min_importance" msgid="1901894910809414782">"最低重要性"</string>
<string name="low_importance" msgid="4109929986107147930">"低重要性"</string>
<string name="default_importance" msgid="8192107689995742653">"一般重要性"</string>
<string name="high_importance" msgid="1527066195614050263">"高重要性"</string>
<string name="max_importance" msgid="5089005872719563894">"緊急重要性"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"永不顯示這些通知"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"顯示在通知清單底部但不發出音效"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"顯示這些通知但不發出音效"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"顯示在通知清單頂部並發出音效"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"不時於螢幕出現並發出音效"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"在通知清單底部顯示但不發出音效"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"顯示這些通知但不發出音效"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"允許這些通知發出音效"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"不時於螢幕出現並發出音效"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"在通知清單頂部顯示,並不時於螢幕出現及發出音效"</string>
<string name="notification_more_settings" msgid="816306283396553571">"更多設定"</string>
<string name="notification_done" msgid="5279426047273930175">"完成"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"一般色系"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"深沉色系"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"自訂顏色"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"自動"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"不明色系"</string>
- <string name="color_transform" msgid="6985460408079086090">"顏色修改"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"顯示「快速設定」圖塊"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"啟用自訂變色功能"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"顏色和外觀"</string>
+ <string name="night_mode" msgid="3540405868248625488">"夜間模式"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"校準螢幕"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"已開啟"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"已關閉"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"自動開啟"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"在適當的位置和時間切換至「夜間模式」"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"「夜間模式」開啟時"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"在 Android OS 中使用深色主題背景"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"調整色調"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"調整亮度"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"系統會將深色主題背景套用至 Android OS 核心區域 (一般以淺色主題背景顯示),例如「設定」。"</string>
<string name="color_apply" msgid="9212602012641034283">"套用"</string>
<string name="color_revert_title" msgid="4746666545480534663">"確認設定"</string>
<string name="color_revert_message" msgid="9116001069397996691">"部分顏色設定會令此裝置無法使用。請按一下 [確定] 加以確認,否則這些顏色設定將於 10 秒後重設。"</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"電池用量"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"充電時無法使用「省電模式」"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"省電模式"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"降低效能並限制背景數據傳輸"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"主畫面"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"最近的活動"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"返回"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"在音量對話框中顯示「請勿騷擾」設定"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"允許在音量對話框中全面控制「請勿騷擾」功能。"</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"音量和「請勿騷擾」設定"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"調低音量時啟用「請勿騷擾」模式"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"與音量控制一起顯示"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"請勿騷擾"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"音量按鈕快速鍵"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"調高音量時停用「請勿騷擾」模式"</string>
<string name="battery" msgid="7498329822413202973">"電池"</string>
<string name="clock" msgid="7416090374234785905">"時鐘"</string>
<string name="headset" msgid="4534219457597457353">"耳機"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"已連接至耳機"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"已連接至耳機"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"顯示或隱藏狀態列上的圖示。"</string>
<string name="data_saver" msgid="5037565123367048522">"數據節省程式"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"數據節省程式已開啟"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"數據節省程式已關閉"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"開啟"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"關閉"</string>
<string name="nav_bar" msgid="1993221402773877607">"導覽列"</string>
<string name="start" msgid="6873794757232879664">"畫面頂部"</string>
<string name="center" msgid="4327473927066010960">"畫面中央"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"預覽"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"拖曳即可新增圖塊"</string>
<string name="qs_edit" msgid="2232596095725105230">"編輯"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"時間"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"顯示小時、分鐘和秒"</item>
+ <item msgid="1427801730816895300">"顯示小時和分鐘 (預設)"</item>
+ <item msgid="3830170141562534721">"不顯示這個圖示"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"永遠顯示百分比"</item>
+ <item msgid="2139628951880142927">"充電時顯示百分比 (預設)"</item>
+ <item msgid="3327323682209964956">"不顯示這個圖示"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"其他"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"分割畫面分隔線"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"向下移"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"向上移"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"向左移"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"向右移"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 08cbb17..d580b28 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"已拍攝螢幕擷取畫面。"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"輕觸即可查看螢幕擷取畫面。"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"無法拍攝螢幕擷取畫面。"</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"由於儲存空間有限,或是遭到應用程式或貴機構禁止,因此無法擷取螢幕畫面。"</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"由於儲存空間有限,因此無法儲存螢幕擷取畫面。"</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"這個應用程式或貴機構禁止擷取螢幕畫面。"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB 檔案傳輸選項"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"掛接為媒體播放器 (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"掛接為相機 (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"增加時間。"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"減少時間。"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"閃光燈已關閉。"</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"無法使用手電筒。"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"閃光燈已開啟。"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"閃光燈已關閉。"</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"閃光燈已開啟。"</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"螢幕固定"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"搜尋"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"無法啟動「<xliff:g id="APP">%s</xliff:g>」。"</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"「<xliff:g id="APP">%s</xliff:g>」在安全模式中為停用狀態。"</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"紀錄"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"清除"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"這個應用程式不支援多視窗模式"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"應用程式不支援多視窗模式"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"水平分割"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"垂直分割"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"自訂分割"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"完全\n靜音"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"僅允許\n優先通知"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"僅允許\n鬧鐘"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"全部"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"全部\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>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"慢速充電中 (充飽需要 <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"在狀態列中顯示時鐘秒數。這可能會影響電池續航力。"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"重新排列快速設定"</string>
<string name="show_brightness" msgid="6613930842805942519">"在快速設定中顯示亮度"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"啟用分割畫面向上滑動加速工具"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"啟用分割畫面向上滑動手勢"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"啟用透過從 [總覽] 按鈕向上滑動的手勢進入分割畫面"</string>
<string name="experimental" msgid="6198182315536726162">"實驗性"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"要開啟藍牙功能嗎?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"如要將鍵盤連線到平板電腦,您必須先開啟藍牙。"</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"開啟"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"套用到「<xliff:g id="TOPIC_NAME">%1$s</xliff:g>」通知"</string>
- <string name="apply_to_app" msgid="363016783939815960">"套用到這個應用程式的所有通知"</string>
+ <string name="show_silently" msgid="6841966539811264192">"顯示通知,但不發出任何音效"</string>
+ <string name="block" msgid="2734508760962682611">"封鎖所有通知"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"不設定靜音"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"不設定靜音或封鎖"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"顯示完整的重要性設定"</string>
<string name="blocked_importance" msgid="5198578988978234161">"封鎖"</string>
+ <string name="min_importance" msgid="1901894910809414782">"最低重要性"</string>
<string name="low_importance" msgid="4109929986107147930">"低重要性"</string>
<string name="default_importance" msgid="8192107689995742653">"一般重要性"</string>
<string name="high_importance" msgid="1527066195614050263">"高重要性"</string>
<string name="max_importance" msgid="5089005872719563894">"緊急重要性"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"一律不顯示這些通知"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"顯示在通知清單底部且不發出任何音效"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"顯示這些通知且不發出任何音效"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"顯示在通知清單頂端並發出音效"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"短暫顯示在螢幕上並發出音效"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"顯示在通知清單底端,但不發出任何音效"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"顯示這些通知,但不發出任何音效"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"允許這些通知發出音效"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"短暫顯示在畫面上並發出音效"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"顯示在通知清單頂端,同時短暫顯示在畫面上並發出音效"</string>
<string name="notification_more_settings" msgid="816306283396553571">"更多設定"</string>
<string name="notification_done" msgid="5279426047273930175">"完成"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"一般顏色"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"夜間顏色"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"自訂顏色"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"自動"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"不明顏色"</string>
- <string name="color_transform" msgid="6985460408079086090">"顏色修改"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"顯示快速設定圖塊"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"啟用自訂顏色變換"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"顏色和外觀"</string>
+ <string name="night_mode" msgid="3540405868248625488">"夜間模式"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"校正顯示畫面"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"開啟"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"關閉"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"自動開啟"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"根據地點和時段適時切換到「夜間模式」"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"「夜間模式」開啟時"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"針對 Android 作業系統使用深色主題"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"調整色調"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"調整亮度"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"深色主題會套用到 Android 作業系統的核心區塊 (一般是以淺色主題顯示),例如「設定」區塊。"</string>
<string name="color_apply" msgid="9212602012641034283">"套用"</string>
<string name="color_revert_title" msgid="4746666545480534663">"確認設定"</string>
<string name="color_revert_message" msgid="9116001069397996691">"部分顏色設定可能會造成這部裝置無法使用。請按一下 [確定] 來確認您要使用這類顏色設定,否則系統將在 10 秒後重設這些設定。"</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"電池用量"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"充電時無法使用節約耗電量模式"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"節約耗電量"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"降低效能並限制背景資料傳輸"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"主畫面"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"近期活動"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"返回"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"在音量對話方塊中顯示「零打擾」設定"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"在音量對話方塊中顯示完整的「零打擾」設定。"</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"音量和「零打擾」設定"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"按下調低音量鍵時啟用「零打擾」模式"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"與音量控制項一起顯示"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"零打擾"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"音量按鈕快速鍵"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"按下調高音量鍵時停用「零打擾」模式"</string>
<string name="battery" msgid="7498329822413202973">"電池"</string>
<string name="clock" msgid="7416090374234785905">"時鐘"</string>
<string name="headset" msgid="4534219457597457353">"耳機"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"已與耳機連線"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"已與耳機連線"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"指定在狀態列中顯示或隱藏圖示。"</string>
<string name="data_saver" msgid="5037565123367048522">"Data Saver"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Data Saver 已開啟"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Data Saver 已關閉"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"開啟"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"關閉"</string>
<string name="nav_bar" msgid="1993221402773877607">"導覽列"</string>
<string name="start" msgid="6873794757232879664">"畫面頂端"</string>
<string name="center" msgid="4327473927066010960">"畫面中央"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"預覽"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"拖曳即可新增圖塊"</string>
<string name="qs_edit" msgid="2232596095725105230">"編輯"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"時間"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"顯示小時、分鐘和秒"</item>
+ <item msgid="1427801730816895300">"顯示小時和分鐘 (預設)"</item>
+ <item msgid="3830170141562534721">"不顯示這個圖示"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"一律顯示百分比"</item>
+ <item msgid="2139628951880142927">"充電時顯示百分比 (預設)"</item>
+ <item msgid="3327323682209964956">"不顯示這個圖示"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"其他"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"分割畫面分隔線"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"向下移"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"向上移"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"向左移"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"向右移"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index df58a62..9382b26 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -73,7 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Umfanekiso weskrini uqoshiwe"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Thinta ukubona imifanekiso yakho yeskrini"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Yehlulekile ukulondoloza umfanekiso weskrini."</string>
- <string name="screenshot_failed_text" msgid="1260203058661337274">"Ayikwazi ukuthatha izithombe zesikrini ngenxa yesikhala sesitoreji esikhawulelwe ngohlelo lokusebenza noma inhlangano yakho."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Ayikwazi ukulondoloza isithombe-skrini ngenxa yesikhala sesitoreji esikhawulelwe."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Ukuthatha izithombe-skrini akuvunyelwe uhlelo lokusebenza noma inhlangano yakho."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Okukhethwa kokudluliswa kwefayela ye-USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Lengisa njengesidlali semediya (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Lengisa ikhamera (PTP)"</string>
@@ -206,6 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Isikhathi esiningi."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Isikhathi esincane."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"I-Flashlight ivaliwe."</string>
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"I-Flashlight ayitholakali."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"I-Flashlight ivuliwe."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"I-Flashlight ivaliwe."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"I-Flashlight ivuliwe."</string>
@@ -301,10 +303,11 @@
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ukuphina isikrini"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"sesha"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Ayikwazanga ukuqala i-<xliff:g id="APP">%s</xliff:g>."</string>
- <!-- no translation found for recents_launch_disabled_message (1624523193008871793) -->
- <skip />
+ <string name="recents_launch_disabled_message" msgid="1624523193008871793">"I-<xliff:g id="APP">%s</xliff:g> ikhutshaziwe kumodi yokuphepha."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Umlando"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Sula"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Lolu hlelo lokusebenza alusekeli amawindi amaningi"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Uhlelo lokusebenza alusekeli amawindi amaningi"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Hlukanisa okuvundlile"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Hlukanisa okumile"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Hlukanisa kwezifiso"</string>
@@ -334,8 +337,6 @@
<string name="interruption_level_none_twoline" msgid="3957581548190765889">"Ukuthula\niokuphelele"</string>
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Okubalulekile\nkuphela"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Ama-alamu\nkuphela"</string>
- <string name="interruption_level_all" msgid="1330581184930945764">"Konke"</string>
- <string name="interruption_level_all_twoline" msgid="3719402899156124780">"Konke\n"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Iyashaja (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ize igcwale)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Iyashaja ngokushesha (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ize igcwale)"</string>
<string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Iyashaja kancane (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ize igcwale)"</string>
@@ -448,39 +449,47 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Bonisa amasekhondi wewashi kubha yesimo. Ingathinta impilo yebhethri."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Hlela kabusha izilungiselelo ezisheshayo"</string>
<string name="show_brightness" msgid="6613930842805942519">"Bonisa ukukhanya kuzilungiselelo ezisheshayo"</string>
- <string name="overview_nav_bar_gesture" msgid="1852503363271291341">"Nika amandla isisheshisi sokuhlukanisa isikrini sokuswayiphela phezulu"</string>
+ <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Nika amandla ukuthinta kokuswayiphela phezulu ukuhlukanisa isikrini"</string>
<string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Nika amandla ukuthinta ukuze ungene ekuhlukaniseni isikrini ngokuswayiphela phezulu kusukela kunkinobho yokubuka konke"</string>
<string name="experimental" msgid="6198182315536726162">"Okokulinga"</string>
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Vula i-Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Ukuze uxhume ikhibhodi yakho nethebhulethi yakho, kufanele uqale ngokuvula i-Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Vula"</string>
- <string name="apply_to_topic" msgid="3641403489318659666">"Sebenzisa kuzaziso ze-<xliff:g id="TOPIC_NAME">%1$s</xliff:g>"</string>
- <string name="apply_to_app" msgid="363016783939815960">"Sebenzisa kuzo zonke izaziso ezivela kulolu hlelo lokusebenza"</string>
+ <string name="show_silently" msgid="6841966539811264192">"Bonisa izaziso ngokuthulile"</string>
+ <string name="block" msgid="2734508760962682611">"Vimbela zonke izaziso"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Ungathulisi"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Ungathulisi noma uvimbele"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Bonisa izilungiselelo ezibalulekile ezigcwele"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Kuvinjelwe"</string>
+ <string name="min_importance" msgid="1901894910809414782">"Okubaluleke kancane"</string>
<string name="low_importance" msgid="4109929986107147930">"Ukubaluleka okuphansi"</string>
<string name="default_importance" msgid="8192107689995742653">"Ukubaluleka okujwayelekile"</string>
<string name="high_importance" msgid="1527066195614050263">"Ukubaluleka okuphezulu"</string>
<string name="max_importance" msgid="5089005872719563894">"Ukubaluleka okusheshayo"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Ungalokothi ubonise lezi zaziso"</string>
- <string name="notification_importance_low" msgid="4383563267370859725">"Bonisa ngokuthulile ngaphansi kohlu lwesaziso"</string>
- <string name="notification_importance_default" msgid="4926529615920610817">"Bonisa ngokuthulile lezi zaziso"</string>
- <string name="notification_importance_high" msgid="3222680136612408223">"Bonisa ngaphezulu kohlu lwezaziso uphinde wenze umsindo"</string>
- <string name="notification_importance_max" msgid="5236987171904756134">"Bheka kusikrini uphinde wenze umsindo"</string>
+ <string name="notification_importance_min" msgid="1938190340516905748">"Bonisa ngokuthulile ngaphansi kohlu lwesaziso"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Bonisa ngokuthulile lezi zaziso"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Vumela lezi zaziso ukwenza umsindo"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Beka kusikrini futhi uvumele umsindo"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Bonisa phezulu kohlu lwezaziso, beka phezu kwesikrini futhi uvumele umsindo"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Izilungiselelo eziningi"</string>
<string name="notification_done" msgid="5279426047273930175">"Kwenziwe"</string>
- <string name="color_matrix_none" msgid="2121957926040543148">"Imibala ejwayelekile"</string>
- <string name="color_matrix_night" msgid="5943817622105307072">"Imibala yasebusuku"</string>
- <string name="color_matrix_custom" msgid="3655576492322298713">"Imibala yangokwezifiso"</string>
- <string name="color_matrix_auto" msgid="4896624757412029265">"Okuzenzakalelayo"</string>
- <string name="color_matrix_unknown" msgid="2709202104256265107">"Imibala engaziwa"</string>
- <string name="color_transform" msgid="6985460408079086090">"Ukulungiswa kombala"</string>
- <string name="color_matrix_show_qs" msgid="1763244354399276679">"Bonisa ithayili lezilungiselelo ezisheshayo"</string>
- <string name="color_enable_custom" msgid="6729001308217347501">"Nika amandla ukuguqulwa kwangokwezifiso"</string>
+ <string name="color_and_appearance" msgid="1254323855964993144">"Umbala nokubonakala"</string>
+ <string name="night_mode" msgid="3540405868248625488">"Imodi yasebusuku"</string>
+ <string name="calibrate_display" msgid="5974642573432039217">"Sika isibonisi"</string>
+ <string name="night_mode_on" msgid="5597545513026541108">"Vuliwe"</string>
+ <string name="night_mode_off" msgid="8035605276956057508">"Valiwe"</string>
+ <string name="turn_on_automatically" msgid="4167565356762016083">"Vula ngokuzenzakalela"</string>
+ <string name="turn_on_auto_summary" msgid="2190994512406701520">"Shintshela kwimodi yasebusuku njengokuqondile ngendawo nesikhathi sosuku"</string>
+ <string name="when_night_mode_on" msgid="2969436026899172821">"Uma imodi yasebusuku ivulekile"</string>
+ <string name="use_dark_theme" msgid="2900938704964299312">"Sebenzisa ingqikithi emnyama ku-Android OS"</string>
+ <string name="adjust_tint" msgid="3398569573231409878">"Lungisa i-tint"</string>
+ <string name="adjust_brightness" msgid="980039329808178246">"Lungisa ukukhanya"</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Itimu emnyama isetshenziswa ezindaweni eziqinile ze-Android OS ezivamise ukuoniswa ngetimu ekhanyayo, efana nezilungiselelo."</string>
<string name="color_apply" msgid="9212602012641034283">"Sebenzisa"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Qinisekisa izilungiselelo"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Ezinye izilungiselelo zombala zingenza le divayisi ingasebenziseki. Chofoza ku-KULUNGILE ukuze uqinisekise lezi zilungiselelo zombala, uma kungenjalo lezi zilungiselelo zizosethwa kabusha ngemuva kwamasekhondi angu-10."</string>
- <!-- no translation found for battery_panel_title (7944156115535366613) -->
- <skip />
+ <string name="battery_panel_title" msgid="7944156115535366613">"Ukusetshenziswa kwebhethri"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Isilondolozi sebhethri asitholakali ngesikhathi sokushaja"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Isilondolozi sebhethri"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"Sehlisa ukusebenza nedatha yasemuva"</string>
@@ -488,21 +497,20 @@
<string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Ekhaya"</string>
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Okwakamuva"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Emuva"</string>
- <string name="tuner_full_zen_title" msgid="5905081395132280054">"Bonisa ukungaphazamisi kuvolumu"</string>
- <string name="tuner_full_zen_summary" msgid="6883568374520596402">"Vumela ulawulo olugcwele lokungaphazamisi kungxoxo yevolumu."</string>
- <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"Ivolumu nokungaphazamisi"</string>
- <string name="volume_down_silent" msgid="66962568467719591">"Faka ukungaphazamisi ekwehliseni ivolumu"</string>
+ <string name="tuner_full_zen_title" msgid="4540823317772234308">"Bonisa ngezilawuli zevolomu"</string>
+ <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ungaphazamisi"</string>
+ <string name="volume_dnd_silent" msgid="4363882330723050727">"Izinqamuleli zezinkinobho zevolomu"</string>
<string name="volume_up_silent" msgid="7141255269783588286">"Phuma kokuthi ungaphazamisi ekukhuphuleni ivolumu"</string>
<string name="battery" msgid="7498329822413202973">"Ibhethri"</string>
<string name="clock" msgid="7416090374234785905">"Iwashi"</string>
<string name="headset" msgid="4534219457597457353">"Ama-earphone"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Amahedfoni axhunyiwe"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Ama-earphone axhunyiwe"</string>
- <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Nika amandla noma khubaza izithonjana kusukela ekubonisweni kubha yesimo."</string>
<string name="data_saver" msgid="5037565123367048522">"Iseva yedatha"</string>
<string name="accessibility_data_saver_on" msgid="8454111686783887148">"Iseva yedatha ivuliwe"</string>
<string name="accessibility_data_saver_off" msgid="8841582529453005337">"Iseva yedatha ivaliwe"</string>
<string name="switch_bar_on" msgid="1142437840752794229">"Vuliwe"</string>
+ <string name="switch_bar_off" msgid="8803270596930432874">"Valiwe"</string>
<string name="nav_bar" msgid="1993221402773877607">"Ibha yokuzula"</string>
<string name="start" msgid="6873794757232879664">"Qala"</string>
<string name="center" msgid="4327473927066010960">"Maphakathi"</string>
@@ -525,4 +533,21 @@
<string name="preview" msgid="9077832302472282938">"Hlola kuqala"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Hudula ukuze ungeze amathayili"</string>
<string name="qs_edit" msgid="2232596095725105230">"Hlela"</string>
+ <string name="tuner_time" msgid="6572217313285536011">"Isikhathi"</string>
+ <string-array name="clock_options">
+ <item msgid="5965318737560463480">"Bonisa amahora, amaminithi, namasekhondi"</item>
+ <item msgid="1427801730816895300">"Bonisa amahora namaminithi (okuzenzakalelayo)"</item>
+ <item msgid="3830170141562534721">"Ungabonisi lesi sithonjana"</item>
+ </string-array>
+ <string-array name="battery_options">
+ <item msgid="3160236755818672034">"Njlalo bonisa iphesentheji"</item>
+ <item msgid="2139628951880142927">"Bonisa iphesentheji uma ishaja (okuzenzakalelayo)"</item>
+ <item msgid="3327323682209964956">"Ungabonisi lesi sithonjana"</item>
+ </string-array>
+ <string name="other" msgid="4060683095962566764">"Okunye"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Isihlukanisi sokuhlukanisa isikrini"</string>
+ <string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Iya phansi"</string>
+ <string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Iya phezulu"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Iya kwesokunxele"</string>
+ <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Iya kwesokudla"</string>
</resources>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 19bc755..e040ab2 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -91,6 +91,11 @@
<declare-styleable name="TunerSwitch">
<attr name="defValue" format="boolean" />
+ <attr name="metricsAction" format="integer" />
+ </declare-styleable>
+
+ <declare-styleable name="DensityContainer">
+ <attr name="android:layout" />
</declare-styleable>
</resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 4cd920a..30acc72 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -31,7 +31,7 @@
<color name="batterymeter_bolt_color">#FFFFFFFF</color>
<color name="qs_batterymeter_frame_color">#FF404040</color>
<color name="system_primary_color">#ff263238</color><!-- blue grey 900 -->
- <color name="system_secondary_color">#ff384248</color>
+ <color name="system_secondary_color">#ff37474F</color><!-- blue grey 800 -->
<color name="system_accent_color">#ff80CBC4</color><!-- deep teal 200 -->
<color name="system_warning_color">#fff4511e</color><!-- deep orange 600 -->
<color name="qs_text">#FFFFFFFF</color>
@@ -102,6 +102,9 @@
<!-- The color of the circle around the primary user in the user switcher -->
<color name="current_user_border_color">@color/system_accent_color</color>
+ <!-- The color of the gear shown behind a notification -->
+ <color name="notification_gear_color">#ff757575</color>
+
<!-- The "inside" of a notification, reached via longpress -->
<color name="notification_guts_bg_color">#eeeeee</color>
<color name="notification_guts_slider_color">@*android:color/material_deep_teal_500</color>
diff --git a/packages/SystemUI/res/values/colors_tv.xml b/packages/SystemUI/res/values/colors_tv.xml
index 6f4c983..af99aae 100644
--- a/packages/SystemUI/res/values/colors_tv.xml
+++ b/packages/SystemUI/res/values/colors_tv.xml
@@ -18,7 +18,5 @@
-->
<resources>
<color name="recents_tv_card_background_color">#FF37474F</color>
- <color name="recents_tv_card_title_text_color">#FFEEEEEE</color>
- <color name="recents_tv_card_content_text_color">#99EEEEEE</color>
- <color name="recents_tv_card_source_text_color">#99EEEEEE</color>
+ <color name="recents_tv_card_title_text_color">#CCEEEEEE</color>
</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index b8044ba..12c3a5d 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -58,7 +58,7 @@
<item name="status_bar_icon_scale_factor" format="float" type="dimen">1.0</item>
<!-- Height of a small notification in the status bar-->
- <dimen name="notification_min_height">84dp</dimen>
+ <dimen name="notification_min_height">86dp</dimen>
<!-- Height of a small notification in the status bar which was used before android N -->
<dimen name="notification_min_height_legacy">64dp</dimen>
@@ -78,6 +78,18 @@
<!-- Minimum layouted height of a notification in the statusbar-->
<dimen name="min_notification_layout_height">48dp</dimen>
+ <!-- Width of the space containing the gear icon behind a notification -->
+ <dimen name="notification_gear_width">64dp</dimen>
+
+ <!-- Height of the space containing the gear icon behind a notification -->
+ <dimen name="notification_gear_height">74dp</dimen>
+
+ <!-- The space above the gear icon displayed behind a notification -->
+ <dimen name="notification_gear_top_padding">30dp</dimen>
+
+ <!-- The space on either side and below the gear icon displayed behind a notification -->
+ <dimen name="notification_gear_padding">20dp</dimen>
+
<!-- size at which Notification icons will be drawn in the status bar -->
<dimen name="status_bar_icon_drawing_size">17dip</dimen>
@@ -162,11 +174,11 @@
<dimen name="qs_tile_margin">16dp</dimen>
<dimen name="qs_quick_tile_size">48dp</dimen>
<dimen name="qs_quick_tile_padding">12dp</dimen>
- <dimen name="qs_date_anim_translation">36dp</dimen>
- <dimen name="qs_date_alarm_anim_translation">26dp</dimen>
+ <dimen name="qs_date_anim_translation">32dp</dimen>
+ <dimen name="qs_date_alarm_anim_translation">22dp</dimen>
<dimen name="qs_date_collapsed_text_size">14sp</dimen>
<dimen name="qs_date_text_size">16sp</dimen>
- <dimen name="qs_header_gear_translation">120dp</dimen>
+ <dimen name="qs_header_gear_translation">150dp</dimen>
<dimen name="qs_page_indicator_size">12dp</dimen>
<dimen name="qs_tile_icon_size">24dp</dimen>
<dimen name="qs_tile_text_size">12sp</dimen>
@@ -191,6 +203,7 @@
<dimen name="qs_data_usage_text_size">14sp</dimen>
<dimen name="qs_data_usage_usage_text_size">36sp</dimen>
<dimen name="qs_expand_margin">0dp</dimen>
+ <dimen name="qs_battery_padding">2dp</dimen>
<dimen name="segmented_button_spacing">0dp</dimen>
<dimen name="borderless_button_radius">2dp</dimen>
@@ -222,7 +235,7 @@
<dimen name="glowpadview_inner_radius">15dip</dimen>
<!-- The size of the icon in the recents task view header. -->
- <dimen name="recents_task_view_header_icon_width">64dp</dimen>
+ <dimen name="recents_task_view_header_icon_width">56dp</dimen>
<dimen name="recents_task_view_header_icon_height">@dimen/recents_task_bar_height</dimen>
<!-- The size of a button in the recents task view header. -->
@@ -250,7 +263,7 @@
<dimen name="recents_task_view_affiliate_group_enter_offset">32dp</dimen>
<!-- The height of a task view bar. -->
- <dimen name="recents_task_bar_height">56dp</dimen>
+ <dimen name="recents_task_bar_height">50dp</dimen>
<!-- The height of the search bar space. -->
<dimen name="recents_search_bar_space_height">64dp</dimen>
@@ -279,6 +292,9 @@
<!-- The amount to allow the stack to overscroll. -->
<dimen name="recents_stack_overscroll">24dp</dimen>
+ <!-- The size of the initial peek area at the top of the stack (below the status bar). -->
+ <dimen name="recents_initial_top_peek_size">8dp</dimen>
+
<!-- The size of the peek area at the top of the stack (below the status bar). -->
<dimen name="recents_layout_focused_top_peek_size">@dimen/recents_history_button_height</dimen>
@@ -313,9 +329,6 @@
<!-- The minimum amount of top overscroll to go to the quick settings. -->
<dimen name="min_top_overscroll_to_qs">36dp</dimen>
- <!-- The padding to the second card when the notifications collapse. -->
- <dimen name="notification_collapse_second_card_padding">8dp</dimen>
-
<!-- The height of the speed bump view. -->
<dimen name="speed_bump_height">16dp</dimen>
@@ -339,8 +352,8 @@
<!-- The margin between the clock and the notifications on Keyguard. See
keyguard_clock_height_fraction_* for the difference between min and max.-->
- <dimen name="keyguard_clock_notifications_margin_min">24dp</dimen>
- <dimen name="keyguard_clock_notifications_margin_max">36dp</dimen>
+ <dimen name="keyguard_clock_notifications_margin_min">30dp</dimen>
+ <dimen name="keyguard_clock_notifications_margin_max">42dp</dimen>
<dimen name="heads_up_scrim_height">250dp</dimen>
<!-- The minimum amount the user needs to swipe to go to the camera / phone. -->
@@ -516,6 +529,13 @@
<dimen name="battery_margin_bottom">0dp</dimen>
+ <!-- Padding at the end of the view that displays the mobile signal icons. If the view is
+ empty, then this padding will not be added to that view. -->
+ <dimen name="mobile_signal_group_end_padding">0dp</dimen>
+
+ <!-- Padding between the mobile data type and the strength indicator. -->
+ <dimen name="mobile_data_icon_start_padding">0dp</dimen>
+
<!-- Extra padding between the mobile data type icon and the strength indicator when the data
type icon is wide. -->
<dimen name="wide_type_icon_start_padding">2dp</dimen>
diff --git a/packages/SystemUI/res/values/dimens_tv.xml b/packages/SystemUI/res/values/dimens_tv.xml
index 77605bd..b589110 100644
--- a/packages/SystemUI/res/values/dimens_tv.xml
+++ b/packages/SystemUI/res/values/dimens_tv.xml
@@ -18,17 +18,29 @@
-->
<resources>
<!-- Dimens for recents card in the recents view on tv -->
- <dimen name="recents_tv_card_width">150dip</dimen>
- <dimen name="recents_tv_card_height">85dip</dimen>
- <dimen name="recents_tv_card_extra_badge_size">16dip</dimen>
+ <dimen name="recents_tv_card_width">268dip</dimen>
+ <dimen name="recents_tv_card_height">151dip</dimen>
+ <dimen name="recents_tv_card_extra_badge_size">20dip</dimen>
+ <dimen name="recents_tv_banner_width">114dip</dimen>
+ <dimen name="recents_tv_banner_height">64dip</dimen>
+ <dimen name="recents_tv_banner_margin_top">16dip</dimen>
+ <dimen name="recents_tv_icon_padding_bottom">8dip</dimen>
+ <dimen name="recents_tv_icon_padding_end">12dip</dimen>
+ <dimen name="recents_tv_text_padding_bottom">12dip</dimen>
<!-- Padding for grid view in recents view on tv -->
<dimen name="recents_tv_grid_row_padding">56dip</dimen>
<dimen name="recents_tv_gird_row_top_padding">57dip</dimen>
- <dimen name="recents_tv_grid_max_row_height">200dip</dimen>
- <dimen name="recents_tv_gird_card_spacing">8dip</dimen>
+ <dimen name="recents_tv_grid_max_row_height">268dip</dimen>
+ <dimen name="recents_tv_gird_card_spacing">20dip</dimen>
<!-- Values for focus animation -->
<dimen name="recents_tv_unselected_item_z">6dp</dimen>
<dimen name="recents_tv_selected_item_z_delta">10dp</dimen>
-</resources>
\ No newline at end of file
+
+ <!-- Extra space around the PIP and its outline in PIP onboarding activity -->
+ <dimen name="tv_pip_bounds_space">3dp</dimen>
+
+ <!-- Values for text on recents cards on tv -->
+ <dimen name="recents_tv_title_text_size">12sp</dimen>
+</resources>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 87aedab..b9eee2e 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -44,6 +44,10 @@
<item type="id" name="notification_screenshot"/>
<item type="id" name="notification_hidden"/>
<item type="id" name="notification_volumeui"/>
+ <item type="id" name="transformation_start_x_tag"/>
+ <item type="id" name="transformation_start_y_tag"/>
+ <item type="id" name="transformation_start_scale_x_tag"/>
+ <item type="id" name="transformation_start_scale_y_tag"/>
<!-- Whether the icon is from a notification for which targetSdk < L -->
<item type="id" name="icon_is_pre_L"/>
@@ -56,5 +60,11 @@
<item type="id" name="image_icon_tag" />
<item type="id" name="contains_transformed_view" />
<item type="id" name="is_clicked_heads_up_tag" />
+
+ <!-- Accessibility actions for the docked stack divider -->
+ <item type="id" name="action_move_left" />
+ <item type="id" name="action_move_right" />
+ <item type="id" name="action_move_up" />
+ <item type="id" name="action_move_down" />
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 6135dc6..1f239c3 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -186,7 +186,9 @@
<!-- Notification title displayed when we fail to take a screenshot. [CHAR LIMIT=50] -->
<string name="screenshot_failed_title">Couldn\'t capture screenshot.</string>
<!-- Notification text displayed when we fail to take a screenshot. [CHAR LIMIT=100] -->
- <string name="screenshot_failed_text">Can\'t take screenshot due to limited storage space, or it isn\'t allowed by the app or your organization.</string>
+ <string name="screenshot_failed_to_save_text">Can\'t save screenshot due to limited storage space.</string>
+ <!-- Notification text displayed when we fail to take a screenshot. [CHAR LIMIT=100] -->
+ <string name="screenshot_failed_to_capture_text">Taking screenshots is not allowed by the app or your organization.</string>
<!-- Title for the USB function chooser in UsbPreferenceActivity. [CHAR LIMIT=30] -->
<string name="usb_preference_title">USB file transfer options</string>
@@ -495,6 +497,8 @@
<string name="accessibility_quick_settings_less_time">Less time.</string>
<!-- Content description of the flashlight tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_flashlight_off">Flashlight off.</string>
+ <!-- Content description of the flashlight tile in quick settings when unavailable (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_flashlight_unavailable">Flashlight unavailable.</string>
<!-- Content description of the flashlight tile in quick settings when on (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_flashlight_on">Flashlight on.</string>
<!-- Announcement made when the flashlight state changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
@@ -720,6 +724,10 @@
<string name="recents_history_button_label">History</string>
<!-- Recents: History clear all string. [CHAR LIMIT=NONE] -->
<string name="recents_history_clear_all_button_label">Clear</string>
+ <!-- Recents: Non-dockable task drag message. [CHAR LIMIT=NONE] -->
+ <string name="recents_drag_non_dockable_task_message">This app does not support multi-window</string>
+ <!-- Recents: Non-dockable task launch sub header. [CHAR LIMIT=NONE] -->
+ <string name="recents_launch_non_dockable_task_label">App does not support multi-window</string>
<!-- Recents: MultiStack add stack split horizontal radio button. [CHAR LIMIT=NONE] -->
<string name="recents_multistack_add_stack_dialog_split_horizontal">Split Horizontal</string>
@@ -1199,12 +1207,22 @@
<!-- Bluetooth enablement ok text [CHAR LIMIT=40] -->
<string name="enable_bluetooth_confirmation_ok">Turn on</string>
- <!-- Apply notification importance setting to a topic [CHAR LIMIT=NONE] -->
- <string name="apply_to_topic">Apply to <xliff:g id="topic_name" example="Friend Request">%1$s</xliff:g> notifications</string>
- <!-- Apply notification importance setting to an app [CHAR LIMIT=NONE] -->
- <string name="apply_to_app">Apply to all notifications from this app</string>
+ <!-- [CHAR LIMIT=100] Notification importance option -->
+ <string name="show_silently">Show notifications silently</string>
+ <!-- [CHAR LIMIT=100] Notification importance option -->
+ <string name="block">Block all notifications</string>
+ <!-- [CHAR LIMIT=100] Notification importance option -->
+ <string name="do_not_silence">Don\'t silence</string>
+ <!-- [CHAR LIMIT=100] Notification importance option -->
+ <string name="do_not_silence_block">Don\'t silence or block</string>
+
+ <!-- [CHAR LIMIT=NONE] Importance Tuner setting title -->
+ <string name="tuner_full_importance_settings">Show full importance settings</string>
+
<!-- Notification importance title, blocked status-->
<string name="blocked_importance">Blocked</string>
+ <!-- Notification importance title, min status-->
+ <string name="min_importance">Min importance</string>
<!-- Notification importance title, low status-->
<string name="low_importance">Low importance</string>
<!-- Notification importance title, normal status-->
@@ -1217,46 +1235,63 @@
<!-- [CHAR LIMIT=100] Notification Importance slider: blocked importance level description -->
<string name="notification_importance_blocked">Never show these notifications</string>
+ <!-- [CHAR LIMIT=100] Notification Importance slider: min importance level description -->
+ <string name="notification_importance_min">Silently show at the bottom of the notification list</string>
+
<!-- [CHAR LIMIT=100] Notification Importance slider: low importance level description -->
- <string name="notification_importance_low">Silently show at the bottom of the notification list</string>
+ <string name="notification_importance_low">Silently show these notifications</string>
<!-- [CHAR LIMIT=100] Notification Importance slider: normal importance level description -->
- <string name="notification_importance_default">Silently show these notifications</string>
+ <string name="notification_importance_default">Allow these notification to make sounds</string>
<!-- [CHAR LIMIT=100] Notification Importance slider: high importance level description -->
- <string name="notification_importance_high">Show at the top of the notifications list and make sound</string>
+ <string name="notification_importance_high">Peek onto the screen and allow sound and allow sound</string>
<!-- [CHAR LIMIT=100] Notification Importance slider: max importance level description -->
- <string name="notification_importance_max">Peek onto the screen and make sound</string>
+ <string name="notification_importance_max">Show at the top of the notifications list, peek onto the screen and allow sound</string>
<!-- Notification: Control panel: Label for button that launches notification settings. [CHAR LIMIT=NONE] -->
<string name="notification_more_settings">More settings</string>
<!-- Notification: Control panel: Label for button that dismisses control panel. [CHAR LIMIT=NONE] -->
<string name="notification_done">Done</string>
- <!-- Label for no color transform [CHAR LIMIT=30] -->
- <string name="color_matrix_none">Normal colors</string>
+ <!-- SysUI Tuner: Color and appearance screen title [CHAR LIMIT=50] -->
+ <string name="color_and_appearance">Color and appearance</string>
- <!-- Label for night color transform [CHAR LIMIT=30] -->
- <string name="color_matrix_night">Night colors</string>
+ <!-- SysUI Tuner: Name of the night mode feature [CHAR LIMIT=30] -->
+ <string name="night_mode">Night mode</string>
- <!-- Label for custom color transform [CHAR LIMIT=30] -->
- <string name="color_matrix_custom">Custom colors</string>
+ <!-- SysUI Tuner: Name of calibrate display dialog [CHAR LIMIT=30] -->
+ <string name="calibrate_display">Calibrate display</string>
- <!-- Label for auto color transforms [CHAR LIMIT=30] -->
- <string name="color_matrix_auto">Auto</string>
+ <!-- SysUI Tuner: Summary of night mode when its on [CHAR LIMIT=NONE] -->
+ <string name="night_mode_on">On</string>
- <!-- Label for unknown color transform [CHAR LIMIT=30] -->
- <string name="color_matrix_unknown">Unknown colors</string>
+ <!-- SysUI Tuner: Summary of night mode when its off [CHAR LIMIT=NONE] -->
+ <string name="night_mode_off">Off</string>
- <!-- Title for color transform [CHAR LIMIT=30] -->
- <string name="color_transform">Color modification</string>
+ <!-- SysUI Tuner: Label for switch to turn on night mode automatically [CHAR LIMIT=50] -->
+ <string name="turn_on_automatically">Turn on automatically</string>
- <!-- Title for setting to show Quick Settings tile [CHAR LIMIT=60] -->
- <string name="color_matrix_show_qs">Show Quick Settings tile</string>
+ <!-- SysUI Tuner: Summary for switch to turn on night mode automatically [CHAR LIMIT=NONE] -->
+ <string name="turn_on_auto_summary">Switch into Night Mode as appropriate for location and time of day</string>
- <!-- Title for switch to enable custom color transform [CHAR LIMIT=60] -->
- <string name="color_enable_custom">Enable custom transform</string>
+ <!-- SysUI Tuner: Label for section controlling what night mode does [CHAR LIMIT=60] -->
+ <string name="when_night_mode_on">When Night Mode is on</string>
+
+ <!-- SysUI Tuner: Switch controlling whether dark theme is turned on with night mode [CHAR LIMIT=45] -->
+ <string name="use_dark_theme">Use dark theme for Android OS</string>
+
+ <!-- SysUI Tuner: Switch controlling whether tint is changed with night mode [CHAR LIMIT=45] -->
+ <string name="adjust_tint">Adjust tint</string>
+
+ <!-- SysUI Tuner: Switch controlling whether brightness is changed with night mode [CHAR LIMIT=45] -->
+ <string name="adjust_brightness">Adjust brightness</string>
+
+ <!-- SysUI Tuner: Disclaimer about using dark theme with night mode [CHAR LIMIT=NONE] -->
+ <string name="night_mode_disclaimer">The dark theme is applied to
+ core areas of Android OS that are normally displayed in a light theme,
+ such as Settings.</string>
<!-- Button to apply settings [CHAR LIMIT=30] -->
<string name="color_apply">Apply</string>
@@ -1295,15 +1330,14 @@
<string name="keyboard_shortcut_group_system_back">Back</string>
<!-- SysUI Tuner: Option to show full do not disturb panel in volume [CHAR LIMIT=60] -->
- <string name="tuner_full_zen_title">Show do not disturb in volume</string>
- <!-- SysUI Tuner: Summary of option to show full do not disturb panel in volume [CHAR LIMIT=NONE] -->
- <string name="tuner_full_zen_summary">Allow full control of do not disturb in the volume dialog.</string>
+ <string name="tuner_full_zen_title">Show with volume controls</string>
- <!-- SysUI Tuner: Label for screen about volume and do not disturb settings [CHAR LIMIT=60] -->
- <string name="volume_and_do_not_disturb">Volume and Do not disturb</string>
+ <!-- SysUI Tuner: Label for screen about do not disturb settings [CHAR LIMIT=60] -->
+ <string name="volume_and_do_not_disturb">Do not disturb</string>
- <!-- SysUI Tuner: Switch to control volume down behavior [CHAR LIMIT=60] -->
- <string name="volume_down_silent">Enter do not disturb on volume down</string>
+ <!-- SysUI Tuner: Switch to control whether volume buttons enter/exit do
+ not disturb [CHAR LIMIT=60] -->
+ <string name="volume_dnd_silent">Volume buttons shortcut</string>
<!-- SysUI Tuner: Switch to control volume up behavior [CHAR LIMIT=60] -->
<string name="volume_up_silent">Exit do not disturb on volume up</string>
@@ -1323,9 +1357,6 @@
<!-- Accessibility description of headset icon [CHAR LIMIT=NONE] -->
<string name="accessibility_status_bar_headset">Headset connected</string>
- <!-- Explanation of the status bar section of the tuner [CHAR LIMIT=NONE] -->
- <string name="tuner_status_bar_explanation">Enable or disable icons from being shown in the status bar.</string>
-
<!-- Label for quick settings tile for data saver [CHAR LIMIT=30] -->
<string name="data_saver">Data Saver</string>
@@ -1338,6 +1369,9 @@
<!-- Label for feature switch [CHAR LIMIT=30] -->
<string name="switch_bar_on">On</string>
+ <!-- Label for feature switch [CHAR LIMIT=30] -->
+ <string name="switch_bar_off">Off</string>
+
<!-- SysUI Tuner: Button that leads to the navigation bar customization screen [CHAR LIMIT=60] -->
<string name="nav_bar">Navigation bar</string>
@@ -1398,4 +1432,39 @@
<!-- Button to edit the tile ordering of quick settings [CHAR LIMIT=60] -->
<string name="qs_edit">Edit</string>
+ <!-- SysUI Tuner: Options for how clock is displayed [CHAR LIMIT=NONE] -->
+ <string name="tuner_time">Time</string>
+
+ <!-- SysUI Tuner: Options for how clock is displayed [CHAR LIMIT=NONE] -->
+ <string-array name="clock_options">
+ <item>Show hours, minutes, and seconds</item>
+ <item>Show hours and minutes (default)</item>
+ <item>Don\'t show this icon</item>
+ </string-array>
+
+ <!-- SysUI Tuner: Options for how battery is displayed [CHAR LIMIT=NONE] -->
+ <string-array name="battery_options">
+ <item>Always show percentage</item>
+ <item>Show percentage when charging (default)</item>
+ <item>Don\'t show this icon</item>
+ </string-array>
+
+ <!-- SysUI Tuner: Other section -->
+ <string name="other">Other</string>
+
+ <!-- Accessibility label for the divider that separates the windows in split-screen mode [CHAR LIMIT=NONE] -->
+ <string name="accessibility_divider">Split-screen divider</string>
+
+ <!-- Accessibility action for moving down the docked stack divider [CHAR LIMIT=NONE] -->
+ <string name="accessibility_action_divider_move_down">Move down</string>
+
+ <!-- Accessibility action for moving down the docked stack divider [CHAR LIMIT=NONE] -->
+ <string name="accessibility_action_divider_move_up">Move up</string>
+
+ <!-- Accessibility action for moving down the docked stack divider [CHAR LIMIT=NONE] -->
+ <string name="accessibility_action_divider_move_left">Move left</string>
+
+ <!-- Accessibility action for moving down the docked stack divider [CHAR LIMIT=NONE] -->
+ <string name="accessibility_action_divider_move_right">Move right</string>
+
</resources>
diff --git a/packages/SystemUI/res/values/strings_tv.xml b/packages/SystemUI/res/values/strings_tv.xml
index 7c4768d..c7fb0ec 100644
--- a/packages/SystemUI/res/values/strings_tv.xml
+++ b/packages/SystemUI/res/values/strings_tv.xml
@@ -20,7 +20,7 @@
<!-- Picture-in-Picture menu -->
<eat-comment />
<!-- Button to close PIP on PIP UI -->
- <string name="pip_exit" translatable="false">Close PIP</string>
+ <string name="pip_close" translatable="false">Close PIP</string>
<!-- Button to move PIP screen to the fullscreen on PIP UI -->
<string name="pip_fullscreen" translatable="false">Full screen</string>
<!-- Button to play the current media on PIP UI -->
@@ -30,14 +30,14 @@
<!-- Button to close PIP overlay menu on PIP UI -->
<string name="pip_cancel" translatable="false">Cancel</string>
<!-- Overlay text on PIP -->
- <string name="pip_hold_home" translatable="false">Hold HOME to control PIP</string>
-
+ <string name="pip_hold_home" translatable="false">Hold <b>HOME</b> to control PIP</string>
<!-- Picture-in-Picture onboarding screen -->
<eat-comment />
- <!-- Title for onboarding screen. -->
- <string name="pip_onboarding_title" translatable="false">Picture-in-picture</string>
<!-- Description for onboarding screen. -->
<string name="pip_onboarding_description" translatable="false">Press and hold the HOME\nbutton to close or control it</string>
<!-- Button to close onboarding screen. -->
<string name="pip_onboarding_button" translatable="false">Got it</string>
+ <!-- Font for Recents -->
+ <!-- DO NOT TRANSLATE -->
+ <string name="font_roboto_regular" translatable="false">sans-serif</string>
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index a51b931..89890d6 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -214,7 +214,7 @@
<style name="QSBorderlessButton">
<item name="android:padding">12dp</item>
- <item name="android:background">@drawable/btn_borderless_rect</item>
+ <item name="android:background">@drawable/qs_btn_borderless_rect</item>
<item name="android:gravity">center</item>
</style>
@@ -323,6 +323,10 @@
<item name="android:textSize">16sp</item>
</style>
+ <style name="TextAppearance.NotificationGuts.Radio">
+ <item name="android:alpha">.87</item>
+ </style>
+
<style name="TextAppearance.NotificationGuts.Button">
<item name="android:textSize">14sp</item>
<item name="android:textAllCaps">true</item>
diff --git a/packages/SystemUI/res/values/styles_tv.xml b/packages/SystemUI/res/values/styles_tv.xml
index 3f0caab..263e1a4 100644
--- a/packages/SystemUI/res/values/styles_tv.xml
+++ b/packages/SystemUI/res/values/styles_tv.xml
@@ -22,4 +22,11 @@
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:backgroundDimEnabled">false</item>
</style>
+
+ <style name="RecentsTvTheme.Wallpaper" parent="@android:style/Theme.Material.NoActionBar.Overscan">
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:backgroundDimEnabled">false</item>
+ <item name="android:colorBackgroundCacheHint">@null</item>
+ <item name="android:windowIsTranslucent">true</item>
+ </style>
</resources>
diff --git a/packages/SystemUI/res/xml/color_and_appearance.xml b/packages/SystemUI/res/xml/color_and_appearance.xml
new file mode 100644
index 0000000..21f890e
--- /dev/null
+++ b/packages/SystemUI/res/xml/color_and_appearance.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:sysui="http://schemas.android.com/apk/res-auto"
+ android:title="@string/color_and_appearance">
+
+ <Preference
+ android:key="night_mode"
+ android:title="@string/night_mode"
+ android:fragment="com.android.systemui.tuner.NightModeFragment" />
+
+ <com.android.systemui.tuner.CalibratePreference
+ android:key="calibrate"
+ android:title="@string/calibrate_display" />
+
+</PreferenceScreen>
diff --git a/packages/SystemUI/res/xml/night_mode.xml b/packages/SystemUI/res/xml/night_mode.xml
new file mode 100644
index 0000000..d5f5333
--- /dev/null
+++ b/packages/SystemUI/res/xml/night_mode.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:sysui="http://schemas.android.com/apk/res-auto"
+ android:title="@string/night_mode">
+
+ <SwitchPreference
+ android:key="auto"
+ android:title="@string/turn_on_automatically"
+ android:summary="@string/turn_on_auto_summary" />
+
+ <PreferenceCategory
+ android:title="@string/when_night_mode_on">
+
+ <SwitchPreference
+ android:key="dark_theme"
+ android:title="@string/use_dark_theme" />
+
+ <SwitchPreference
+ android:key="adjust_tint"
+ android:title="@string/adjust_tint" />
+
+ <SwitchPreference
+ android:key="adjust_brightness"
+ android:title="@string/adjust_brightness" />
+
+ </PreferenceCategory>
+
+ <Preference
+ android:selectable="false"
+ android:summary="@string/night_mode_disclaimer" />
+
+</PreferenceScreen>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 39281bc..ddc03a3 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -18,19 +18,10 @@
xmlns:sysui="http://schemas.android.com/apk/res-auto"
android:title="@string/system_ui_tuner">
- <com.android.systemui.tuner.TunerSwitch
- android:key="qs_show_brightness"
- android:title="@string/show_brightness"
- sysui:defValue="true" />
-
<PreferenceScreen
android:key="status_bar"
android:title="@string/status_bar" >
- <Preference
- android:selectable="false"
- android:summary="@string/tuner_status_bar_explanation" />
-
<com.android.systemui.tuner.StatusBarSwitch
android:key="rotate"
android:title="@string/status_bar_settings_auto_rotation" />
@@ -91,9 +82,10 @@
<!-- other weird signal stuff -->
- <com.android.systemui.tuner.StatusBarSwitch
- android:key="battery"
- android:title="@string/battery" />
+ <com.android.systemui.tuner.BatteryPreference
+ android:title="@string/battery"
+ android:summary="%s"
+ android:entries="@array/battery_options" />
<com.android.systemui.tuner.StatusBarSwitch
android:key="alarm_clock"
@@ -101,16 +93,49 @@
<!-- secure -->
- <com.android.systemui.tuner.StatusBarSwitch
- android:key="clock"
- android:title="@string/clock" />
+ <com.android.systemui.tuner.ClockPreference
+ android:title="@string/tuner_time"
+ android:summary="%s"
+ android:entries="@array/clock_options" />
</PreferenceScreen>
+ <Preference
+ android:key="color_transform"
+ android:title="@string/color_and_appearance"
+ android:fragment="com.android.systemui.tuner.ColorAndAppearanceFragment" />
<PreferenceScreen
- android:key="overview"
- android:title="@string/overview" >
+ android:key="volume_and_do_not_disturb"
+ android:title="@string/volume_and_do_not_disturb">
+
+ <!-- Action for this is
+ MetricsConstants.ACTION_TUNER_DO_NOT_DISTURB_VOLUME_PANEL -->
+ <com.android.systemui.tuner.TunerSwitch
+ android:key="sysui_show_full_zen"
+ android:title="@string/tuner_full_zen_title"
+ sysui:metricsAction="314" />
+
+ <!-- Action for this is
+ MetricsConstants.ACTION_TUNER_DO_NOT_DISTURB_VOLUME_SHORTCUT -->
+ <com.android.systemui.tuner.TunerSwitch
+ android:key="sysui_volume_down_silent,sysui_volume_up_silent"
+ android:title="@string/volume_dnd_silent"
+ sysui:defValue="true"
+ sysui:metricsAction="315" />
+
+ </PreferenceScreen>
+
+ <!--
+ <Preference
+ android:key="nav_bar"
+ android:title="@string/nav_bar"
+ android:fragment="com.android.systemui.tuner.NavBarTuner" />
+ -->
+
+ <PreferenceScreen
+ android:key="other"
+ android:title="@string/other" >
<com.android.systemui.tuner.TunerSwitch
android:key="overview_disable_fast_toggle_via_button"
@@ -122,55 +147,13 @@
android:title="@string/overview_nav_bar_gesture"
android:summary="@string/overview_nav_bar_gesture_desc" />
- </PreferenceScreen>
-
- <SwitchPreference
- android:key="battery_pct"
- android:title="@string/show_battery_percentage"
- android:summary="@string/show_battery_percentage_summary"
- android:persistent="false" />
-
- <com.android.systemui.tuner.TunerSwitch
- android:key="clock_seconds"
- android:title="@string/clock_seconds"
- android:summary="@string/clock_seconds_desc" />
-
- <Preference
- android:key="demo_mode"
- android:title="@string/demo_mode"
- android:fragment="com.android.systemui.tuner.DemoModeFragment" />
-
- <Preference
- android:key="color_transform"
- android:title="@string/color_transform"
- android:fragment="com.android.systemui.tuner.ColorMatrixFragment" />
-
- <PreferenceScreen
- android:key="volume_and_do_not_disturb"
- android:title="@string/volume_and_do_not_disturb">
-
+ <!-- importance -->
<com.android.systemui.tuner.TunerSwitch
- android:key="sysui_show_full_zen"
- android:title="@string/tuner_full_zen_title"
- android:summary="@string/tuner_full_zen_summary" />
-
- <com.android.systemui.tuner.TunerSwitch
- android:key="sysui_volume_down_silent"
- android:title="@string/volume_down_silent"
- sysui:defValue="true" />
-
- <com.android.systemui.tuner.TunerSwitch
- android:key="sysui_volume_up_silent"
- android:title="@string/volume_up_silent"
- sysui:defValue="true" />
+ android:key="show_importance_slider"
+ android:title="@string/tuner_full_importance_settings" />
</PreferenceScreen>
- <Preference
- android:key="nav_bar"
- android:title="@string/nav_bar"
- android:fragment="com.android.systemui.tuner.NavBarTuner" />
-
<!-- Warning, this goes last. -->
<Preference
android:summary="@string/tuner_persistent_warning"
diff --git a/packages/SystemUI/src/com/android/systemui/DensityContainer.java b/packages/SystemUI/src/com/android/systemui/DensityContainer.java
new file mode 100644
index 0000000..2e3cb49
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/DensityContainer.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DensityContainer extends FrameLayout {
+
+ private final List<InflateListener> mInflateListeners = new ArrayList<>();
+ private final int mLayout;
+ private int mDensity;
+
+ public DensityContainer(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+
+ mDensity = context.getResources().getConfiguration().densityDpi;
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DensityContainer);
+ if (!a.hasValue(R.styleable.DensityContainer_android_layout)) {
+ throw new IllegalArgumentException("DensityContainer must contain a layout");
+ }
+ mLayout = a.getResourceId(R.styleable.DensityContainer_android_layout, 0);
+ inflateLayout();
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ int density = newConfig.densityDpi;
+ if (density != mDensity) {
+ mDensity = density;
+ inflateLayout();
+ }
+ }
+
+ private void inflateLayout() {
+ removeAllViews();
+ LayoutInflater.from(getContext()).inflate(mLayout, this);
+ final int N = mInflateListeners.size();
+ for (int i = 0; i < N; i++) {
+ mInflateListeners.get(i).onInflated(getChildAt(0));
+ }
+ }
+
+ public void addInflateListener(InflateListener listener) {
+ mInflateListeners.add(listener);
+ listener.onInflated(getChildAt(0));
+ }
+
+ public interface InflateListener {
+ /**
+ * Called whenever a new view is inflated.
+ */
+ void onInflated(View v);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java
index 1471622..9f2745b 100644
--- a/packages/SystemUI/src/com/android/systemui/Prefs.java
+++ b/packages/SystemUI/src/com/android/systemui/Prefs.java
@@ -48,6 +48,7 @@
Key.QS_DATA_SAVER_ADDED,
Key.QS_INVERT_COLORS_ADDED,
Key.QS_WORK_ADDED,
+ Key.QS_NIGHT_ADDED,
})
public @interface Key {
String OVERVIEW_SEARCH_APP_WIDGET_ID = "searchAppWidgetId";
@@ -68,6 +69,7 @@
String QS_DATA_SAVER_ADDED = "QsDataSaverAdded";
String QS_INVERT_COLORS_ADDED = "QsInvertColorsAdded";
String QS_WORK_ADDED = "QsWorkAdded";
+ String QS_NIGHT_ADDED = "QsNightAdded";
}
public static boolean getBoolean(Context context, @Key String key, boolean defaultValue) {
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 33b43fe..f6dcc11 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -69,9 +69,9 @@
private float mPerpendicularInitialTouchPos;
private boolean mDragging;
private View mCurrView;
- private View mCurrAnimView;
private boolean mCanCurrViewBeDimissed;
private float mDensityScale;
+ private float mTranslation = 0;
private boolean mLongPressSent;
private LongPressListener mLongPressListener;
@@ -121,7 +121,7 @@
return mSwipeDirection == X ? ev.getY() : ev.getX();
}
- private float getTranslation(View v) {
+ protected float getTranslation(View v) {
return mSwipeDirection == X ? v.getTranslationX() : v.getTranslationY();
}
@@ -130,7 +130,7 @@
vt.getYVelocity();
}
- private ObjectAnimator createTranslationAnimation(View v, float newPos) {
+ protected ObjectAnimator createTranslationAnimation(View v, float newPos) {
ObjectAnimator anim = ObjectAnimator.ofFloat(v,
mSwipeDirection == X ? View.TRANSLATION_X : View.TRANSLATION_Y, newPos);
return anim;
@@ -141,7 +141,19 @@
vt.getXVelocity();
}
- private void setTranslation(View v, float translate) {
+ protected Animator getViewTranslationAnimator(View v, float target,
+ AnimatorUpdateListener listener) {
+ ObjectAnimator anim = createTranslationAnimation(v, target);
+ if (listener != null) {
+ anim.addUpdateListener(listener);
+ }
+ return anim;
+ }
+
+ protected void setTranslation(View v, float translate) {
+ if (v == null) {
+ return;
+ }
if (mSwipeDirection == X) {
v.setTranslationX(translate);
} else {
@@ -237,15 +249,16 @@
mTouchAboveFalsingThreshold = false;
mDragging = false;
mLongPressSent = false;
- mCurrView = mCallback.getChildAtPosition(ev);
mVelocityTracker.clear();
+ mCurrView = mCallback.getChildAtPosition(ev);
+
if (mCurrView != null) {
- mCurrAnimView = mCallback.getChildContentView(mCurrView);
+ onDownUpdate(mCurrView);
mCanCurrViewBeDimissed = mCallback.canChildBeDismissed(mCurrView);
mVelocityTracker.addMovement(ev);
mInitialTouchPos = getPos(ev);
mPerpendicularInitialTouchPos = getPerpendicularPos(ev);
-
+ mTranslation = getTranslation(mCurrView);
if (mLongPressListener != null) {
if (mWatchLongPress == null) {
mWatchLongPress = new Runnable() {
@@ -268,7 +281,6 @@
}
mHandler.postDelayed(mWatchLongPress, mLongPressTimeout);
}
-
}
break;
@@ -283,8 +295,8 @@
&& Math.abs(delta) > Math.abs(deltaPerpendicular)) {
mCallback.onBeginDrag(mCurrView);
mDragging = true;
- mInitialTouchPos = getPos(ev) - getTranslation(mCurrAnimView);
-
+ mInitialTouchPos = getPos(ev);
+ mTranslation = getTranslation(mCurrView);
removeLongPressCallback();
}
}
@@ -295,7 +307,6 @@
final boolean captured = (mDragging || mLongPressSent);
mDragging = false;
mCurrView = null;
- mCurrAnimView = null;
mLongPressSent = false;
removeLongPressCallback();
if (captured) return true;
@@ -320,12 +331,11 @@
* @param useAccelerateInterpolator Should an accelerating Interpolator be used
* @param fixedDuration If not 0, this exact duration will be taken
*/
- public void dismissChild(final View view, float velocity, final Runnable endAction,
+ public void dismissChild(final View animView, float velocity, final Runnable endAction,
long delay, boolean useAccelerateInterpolator, long fixedDuration) {
- final View animView = mCallback.getChildContentView(view);
- final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view);
+ final boolean canBeDismissed = mCallback.canChildBeDismissed(animView);
float newPos;
- boolean isLayoutRtl = view.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
+ boolean isLayoutRtl = animView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
if (velocity < 0
|| (velocity == 0 && getTranslation(animView) < 0)
@@ -355,7 +365,16 @@
if (!mDisableHwLayers) {
animView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}
- ObjectAnimator anim = createTranslationAnimation(animView, newPos);
+ AnimatorUpdateListener updateListener = new AnimatorUpdateListener() {
+ public void onAnimationUpdate(ValueAnimator animation) {
+ onTranslationUpdate(animView, (float) animation.getAnimatedValue(), canBeDismissed);
+ }
+ };
+
+ Animator anim = getViewTranslationAnimator(animView, newPos, updateListener);
+ if (anim == null) {
+ return;
+ }
if (useAccelerateInterpolator) {
anim.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
} else {
@@ -367,8 +386,8 @@
}
anim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
- updateSwipeProgressFromOffset(animView, canAnimViewBeDismissed);
- mCallback.onChildDismissed(view);
+ updateSwipeProgressFromOffset(animView, canBeDismissed);
+ mCallback.onChildDismissed(animView);
if (endAction != null) {
endAction.run();
}
@@ -377,11 +396,6 @@
}
}
});
- anim.addUpdateListener(new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- updateSwipeProgressFromOffset(animView, canAnimViewBeDismissed);
- }
- });
prepareDismissAnimation(animView, anim);
anim.start();
}
@@ -393,21 +407,24 @@
// Do nothing
}
- public void snapChild(final View view, float velocity) {
- final View animView = mCallback.getChildContentView(view);
- final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(animView);
- ObjectAnimator anim = createTranslationAnimation(animView, 0);
+ public void snapChild(final View animView, final float targetLeft, float velocity) {
+ final boolean canBeDismissed = mCallback.canChildBeDismissed(animView);
+ AnimatorUpdateListener updateListener = new AnimatorUpdateListener() {
+ public void onAnimationUpdate(ValueAnimator animation) {
+ onTranslationUpdate(animView, (float) animation.getAnimatedValue(), canBeDismissed);
+ }
+ };
+
+ Animator anim = getViewTranslationAnimator(animView, targetLeft, updateListener);
+ if (anim == null) {
+ return;
+ }
int duration = SNAP_ANIM_LEN;
anim.setDuration(duration);
- anim.addUpdateListener(new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- updateSwipeProgressFromOffset(animView, canAnimViewBeDismissed);
- }
- });
anim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animator) {
- updateSwipeProgressFromOffset(animView, canAnimViewBeDismissed);
- mCallback.onChildSnappedBack(animView);
+ updateSwipeProgressFromOffset(animView, canBeDismissed);
+ mCallback.onChildSnappedBack(animView, targetLeft);
}
});
prepareSnapBackAnimation(animView, anim);
@@ -421,6 +438,28 @@
// Do nothing
}
+ /**
+ * Called when there's a down event.
+ */
+ public void onDownUpdate(View currView) {
+ // Do nothing
+ }
+
+ /**
+ * Called on a move event.
+ */
+ protected void onMoveUpdate(View view, float totalTranslation, float delta) {
+ // Do nothing
+ }
+
+ /**
+ * Called in {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)} when the current
+ * view is being animated to dismiss or snap.
+ */
+ public void onTranslationUpdate(View animView, float value, boolean canBeDismissed) {
+ updateSwipeProgressFromOffset(animView, canBeDismissed);
+ }
+
public boolean onTouchEvent(MotionEvent ev) {
if (mLongPressSent) {
return true;
@@ -456,17 +495,18 @@
// don't let items that can't be dismissed be dragged more than
// maxScrollDistance
if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissed(mCurrView)) {
- float size = getSize(mCurrAnimView);
- float maxScrollDistance = 0.15f * size;
+ float size = getSize(mCurrView);
+ float maxScrollDistance = 0.25f * size;
if (absDelta >= size) {
delta = delta > 0 ? maxScrollDistance : -maxScrollDistance;
} else {
delta = maxScrollDistance * (float) Math.sin((delta/size)*(Math.PI/2));
}
}
- setTranslation(mCurrAnimView, delta);
- updateSwipeProgressFromOffset(mCurrAnimView, mCanCurrViewBeDimissed);
+ setTranslation(mCurrView, mTranslation + delta);
+ updateSwipeProgressFromOffset(mCurrView, mCanCurrViewBeDimissed);
+ onMoveUpdate(mCurrView, mTranslation + delta, delta);
}
break;
case MotionEvent.ACTION_UP:
@@ -478,12 +518,13 @@
float velocity = getVelocity(mVelocityTracker);
float perpendicularVelocity = getPerpendicularVelocity(mVelocityTracker);
+ float translation = getTranslation(mCurrView);
// Decide whether to dismiss the current view
boolean childSwipedFarEnough = DISMISS_IF_SWIPED_FAR_ENOUGH &&
- Math.abs(getTranslation(mCurrAnimView)) > 0.4 * getSize(mCurrAnimView);
+ Math.abs(translation) > 0.4 * getSize(mCurrView);
boolean childSwipedFastEnough = (Math.abs(velocity) > escapeVelocity) &&
(Math.abs(velocity) > Math.abs(perpendicularVelocity)) &&
- (velocity > 0) == (getTranslation(mCurrAnimView) > 0);
+ (velocity > 0) == (translation > 0);
boolean falsingDetected = mCallback.isAntiFalsingNeeded();
if (mFalsingManager.isClassiferEnabled()) {
@@ -502,7 +543,7 @@
} else {
// snappity
mCallback.onDragCancelled(mCurrView);
- snapChild(mCurrView, velocity);
+ snapChild(mCurrView, 0 /* leftTarget */, velocity);
}
}
break;
@@ -518,8 +559,6 @@
public interface Callback {
View getChildAtPosition(MotionEvent ev);
- View getChildContentView(View v);
-
boolean canChildBeDismissed(View v);
boolean isAntiFalsingNeeded();
@@ -530,7 +569,13 @@
void onDragCancelled(View v);
- void onChildSnappedBack(View animView);
+ /**
+ * Called when the child is snapped to a position.
+ *
+ * @param animView the view that was snapped.
+ * @param targetLeft the left position the view was snapped to.
+ */
+ void onChildSnappedBack(View animView, float targetLeft);
/**
* Updates the swipe progress on a child.
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 472648a..b2b6127 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -54,7 +54,8 @@
com.android.systemui.power.PowerUI.class,
com.android.systemui.media.RingtonePlayer.class,
com.android.systemui.keyboard.KeyboardUI.class,
- com.android.systemui.tv.pip.PipUI.class
+ com.android.systemui.tv.pip.PipUI.class,
+ com.android.systemui.shortcut.ShortcutKeyDispatcher.class
};
/**
@@ -143,12 +144,14 @@
Class<?> cl = services[i];
if (DEBUG) Log.d(TAG, "loading: " + cl);
try {
- mServices[i] = (SystemUI) cl.newInstance();
+ Object newService = SystemUIFactory.getInstance().createInstance(cl);
+ mServices[i] = (SystemUI) ((newService == null) ? cl.newInstance() : newService);
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InstantiationException ex) {
throw new RuntimeException(ex);
}
+
mServices[i].mContext = this;
mServices[i].mComponents = mComponents;
if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 681b39e..913b2b3 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -18,11 +18,15 @@
import android.content.Context;
import android.util.Log;
+import android.view.View;
import android.view.ViewGroup;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.shortcut.ShortcutKeyDispatcher;
+import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
+import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.StatusBarWindowManager;
@@ -66,4 +70,13 @@
ViewGroup container) {
return new KeyguardBouncer(context, callback, lockPatternUtils, windowManager, container);
}
+
+ public ScrimController createScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
+ View headsUpScrim, boolean scrimSrcEnabled) {
+ return new ScrimController(scrimBehind, scrimInFront, headsUpScrim, scrimSrcEnabled);
+ }
+
+ public <T> T createInstance(Class<T> classType) {
+ return null;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
index 735a7c4..c09376b 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
@@ -23,6 +23,7 @@
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Handler;
+import android.os.PowerManager;
import android.os.UserHandle;
import android.provider.Settings;
import android.view.MotionEvent;
@@ -64,6 +65,7 @@
private boolean mBouncerOn = false;
private boolean mSessionActive = false;
private int mState = StatusBarState.SHADE;
+ private boolean mScreenOn;
protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
@Override
@@ -77,6 +79,7 @@
mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
mDataCollector = DataCollector.getInstance(mContext);
mHumanInteractionClassifier = HumanInteractionClassifier.getInstance(mContext);
+ mScreenOn = context.getSystemService(PowerManager.class).isInteractive();
mContext.getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(ENFORCE_BOUNCER), false,
@@ -98,17 +101,21 @@
ENFORCE_BOUNCER, 0);
}
+ private boolean shouldSessionBeActive() {
+ return isEnabled() && mScreenOn &&
+ (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED);
+ }
+
private boolean sessionEntrypoint() {
- if (!mSessionActive && isEnabled() &&
- (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)) {
+ if (!mSessionActive && shouldSessionBeActive()) {
onSessionStart();
return true;
}
return false;
}
- private void sessionExitpoint() {
- if (mSessionActive) {
+ private void sessionExitpoint(boolean force) {
+ if (mSessionActive && (force || !shouldSessionBeActive())) {
mSessionActive = false;
mSensorManager.unregisterListener(this);
}
@@ -167,15 +174,22 @@
public void setStatusBarState(int state) {
mState = state;
+ if (shouldSessionBeActive()) {
+ sessionEntrypoint();
+ } else {
+ sessionExitpoint(false /* force */);
+ }
}
public void onScreenTurningOn() {
+ mScreenOn = true;
if (sessionEntrypoint()) {
mDataCollector.onScreenTurningOn();
}
}
public void onScreenOnFromTouch() {
+ mScreenOn = true;
if (sessionEntrypoint()) {
mDataCollector.onScreenOnFromTouch();
}
@@ -183,12 +197,13 @@
public void onScreenOff() {
mDataCollector.onScreenOff();
- sessionExitpoint();
+ mScreenOn = false;
+ sessionExitpoint(false /* force */);
}
public void onSucccessfulUnlock() {
mDataCollector.onSucccessfulUnlock();
- sessionExitpoint();
+ sessionExitpoint(true /* force */);
}
public void onBouncerShown() {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
index 7ddbdf0..45eb9ad 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
@@ -119,7 +119,7 @@
return;
}
- // If the user is dragging down the notification, he might want to drag it down
+ // If the user is dragging down the notification, they might want to drag it down
// enough to see the content, read it for a while and then lift the finger to open
// the notification. This kind of motion scores very bad in the Classifier so the
// MotionEvents which are close to the current position of the finger are not
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
index ea7270d..4b775a5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
@@ -38,7 +38,9 @@
import android.os.UserHandle;
import android.provider.Settings.Secure;
import android.text.TextUtils;
+import android.util.Pair;
import android.util.Slog;
+import android.widget.Toast;
import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -46,6 +48,7 @@
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
+import com.android.settingslib.bluetooth.Utils;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
@@ -76,8 +79,9 @@
private static final int STATE_WAITING_FOR_BLUETOOTH = 4;
private static final int STATE_PAIRING = 5;
private static final int STATE_PAIRED = 6;
- private static final int STATE_USER_CANCELLED = 7;
- private static final int STATE_DEVICE_NOT_FOUND = 8;
+ private static final int STATE_PAIRING_FAILED = 7;
+ private static final int STATE_USER_CANCELLED = 8;
+ private static final int STATE_DEVICE_NOT_FOUND = 9;
private static final int MSG_INIT = 0;
private static final int MSG_ON_BOOT_COMPLETED = 1;
@@ -90,6 +94,7 @@
private static final int MSG_SHOW_BLUETOOTH_DIALOG = 8;
private static final int MSG_DISMISS_BLUETOOTH_DIALOG = 9;
private static final int MSG_BLE_ABORT_SCAN = 10;
+ private static final int MSG_SHOW_ERROR = 11;
private volatile KeyboardHandler mHandler;
private volatile KeyboardUIHandler mUIHandler;
@@ -178,6 +183,7 @@
mLocalBluetoothAdapter = bluetoothManager.getBluetoothAdapter();
mProfileManager = bluetoothManager.getProfileManager();
bluetoothManager.getEventManager().registerCallback(new BluetoothCallbackHandler());
+ Utils.setErrorListener(new BluetoothErrorListener());
InputManager im = context.getSystemService(InputManager.class);
im.registerOnTabletModeChangedListener(this, mHandler);
@@ -204,13 +210,15 @@
if (mInTabletMode != InputManager.SWITCH_STATE_OFF) {
if (mState == STATE_WAITING_FOR_DEVICE_DISCOVERY) {
stopScanning();
+ } else if (mState == STATE_WAITING_FOR_BLUETOOTH) {
+ mUIHandler.sendEmptyMessage(MSG_DISMISS_BLUETOOTH_DIALOG);
}
mState = STATE_WAITING_FOR_TABLET_MODE_EXIT;
return;
}
final int btState = mLocalBluetoothAdapter.getState();
- if (btState == BluetoothAdapter.STATE_TURNING_ON || btState == BluetoothAdapter.STATE_ON
+ if ((btState == BluetoothAdapter.STATE_TURNING_ON || btState == BluetoothAdapter.STATE_ON)
&& mState == STATE_WAITING_FOR_BLUETOOTH) {
// If we're waiting for bluetooth but it has come on in the meantime, or is coming
// on, just dismiss the dialog. This frequently happens during device startup.
@@ -334,7 +342,10 @@
private void stopScanning() {
if (mScanCallback != null) {
- mLocalBluetoothAdapter.getBluetoothLeScanner().stopScan(mScanCallback);
+ BluetoothLeScanner scanner = mLocalBluetoothAdapter.getBluetoothLeScanner();
+ if (scanner != null) {
+ scanner.stopScan(mScanCallback);
+ }
mScanCallback = null;
}
}
@@ -370,10 +381,14 @@
// Should only be called on the handler thread
private void onDeviceBondStateChangedInternal(CachedBluetoothDevice d, int bondState) {
- if (d.getName().equals(mKeyboardName) && bondState == BluetoothDevice.BOND_BONDED) {
- // We don't need to manually connect to the device here because it will automatically
- // try to connect after it has been paired.
- mState = STATE_PAIRED;
+ if (mState == STATE_PAIRING && d.getName().equals(mKeyboardName)) {
+ if (bondState == BluetoothDevice.BOND_BONDED) {
+ // We don't need to manually connect to the device here because it will
+ // automatically try to connect after it has been paired.
+ mState = STATE_PAIRED;
+ } else if (bondState == BluetoothDevice.BOND_NONE) {
+ mState = STATE_PAIRING_FAILED;
+ }
}
}
@@ -385,6 +400,17 @@
}
}
+ // Should only be called on the handler thread. We want to be careful not to show errors for
+ // pairings not initiated by this UI, so we only pop up the toast when we're at an appropriate
+ // point in our pairing flow and it's the expected device.
+ private void onShowErrorInternal(Context context, String name, int messageResId) {
+ if ((mState == STATE_PAIRING || mState == STATE_PAIRING_FAILED)
+ && mKeyboardName.equals(name)) {
+ String message = context.getString(messageResId, name);
+ Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
+ }
+ }
+
private final class KeyboardUIHandler extends Handler {
public KeyboardUIHandler() {
super(Looper.getMainLooper(), null, true /*async*/);
@@ -393,19 +419,27 @@
public void handleMessage(Message msg) {
switch(msg.what) {
case MSG_SHOW_BLUETOOTH_DIALOG: {
- DialogInterface.OnClickListener listener = new BluetoothDialogClickListener();
+ if (mDialog != null) {
+ // Don't show another dialog if one is already present
+ break;
+ }
+ DialogInterface.OnClickListener clickListener =
+ new BluetoothDialogClickListener();
+ DialogInterface.OnDismissListener dismissListener =
+ new BluetoothDialogDismissListener();
mDialog = new BluetoothDialog(mContext);
mDialog.setTitle(R.string.enable_bluetooth_title);
mDialog.setMessage(R.string.enable_bluetooth_message);
- mDialog.setPositiveButton(R.string.enable_bluetooth_confirmation_ok, listener);
- mDialog.setNegativeButton(android.R.string.cancel, listener);
+ mDialog.setPositiveButton(
+ R.string.enable_bluetooth_confirmation_ok, clickListener);
+ mDialog.setNegativeButton(android.R.string.cancel, clickListener);
+ mDialog.setOnDismissListener(dismissListener);
mDialog.show();
break;
}
case MSG_DISMISS_BLUETOOTH_DIALOG: {
if (mDialog != null) {
mDialog.dismiss();
- mDialog = null;
}
break;
}
@@ -469,6 +503,10 @@
onBleScanFailedInternal();
break;
}
+ case MSG_SHOW_ERROR: {
+ Pair<Context, String> p = (Pair<Context, String>) msg.obj;
+ onShowErrorInternal(p.first, p.second, msg.arg1);
+ }
}
}
}
@@ -482,6 +520,14 @@
}
}
+ private final class BluetoothDialogDismissListener
+ implements DialogInterface.OnDismissListener {
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ mDialog = null;
+ }
+ }
+
private final class KeyboardScanCallback extends ScanCallback {
private boolean isDeviceDiscoverable(ScanResult result) {
@@ -564,6 +610,13 @@
public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { }
}
+ private final class BluetoothErrorListener implements Utils.ErrorListener {
+ public void onShowError(Context context, String name, int messageResId) {
+ mHandler.obtainMessage(MSG_SHOW_ERROR, messageResId, 0 /*unused*/,
+ new Pair<>(context, name)).sendToTarget();
+ }
+ }
+
private static String stateToString(int state) {
switch (state) {
case STATE_NOT_ENABLED:
@@ -580,13 +633,15 @@
return "STATE_PAIRING";
case STATE_PAIRED:
return "STATE_PAIRED";
+ case STATE_PAIRING_FAILED:
+ return "STATE_PAIRING_FAILED";
case STATE_USER_CANCELLED:
return "STATE_USER_CANCELLED";
case STATE_DEVICE_NOT_FOUND:
return "STATE_DEVICE_NOT_FOUND";
case STATE_UNKNOWN:
default:
- return "STATE_UNKNOWN";
+ return "STATE_UNKNOWN (" + state + ")";
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
index f39f302..ab612dd 100644
--- a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
@@ -16,8 +16,10 @@
package com.android.systemui.media;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.database.Cursor;
import android.media.AudioAttributes;
import android.media.IAudioService;
import android.media.IRingtonePlayer;
@@ -25,15 +27,20 @@
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
+import android.provider.MediaStore;
+import android.provider.MediaStore.Audio.AudioColumns;
import android.util.Log;
+import com.android.internal.util.Preconditions;
import com.android.systemui.SystemUI;
import java.io.FileDescriptor;
+import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
@@ -180,6 +187,34 @@
return Ringtone.getTitle(getContextForUser(user), uri,
false /*followSettingsUri*/, false /*allowRemote*/);
}
+
+ @Override
+ public ParcelFileDescriptor openRingtone(Uri uri) {
+ final UserHandle user = Binder.getCallingUserHandle();
+ final ContentResolver resolver = getContextForUser(user).getContentResolver();
+
+ // Only open the requested Uri if it's a well-known ringtone or
+ // other sound from the platform media store, otherwise this opens
+ // up arbitrary access to any file on external storage.
+ if (uri.toString().startsWith(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI.toString())) {
+ try (Cursor c = resolver.query(uri, new String[] {
+ MediaStore.Audio.AudioColumns.IS_RINGTONE,
+ MediaStore.Audio.AudioColumns.IS_ALARM,
+ MediaStore.Audio.AudioColumns.IS_NOTIFICATION
+ }, null, null, null)) {
+ if (c.moveToFirst()) {
+ if (c.getInt(0) != 0 || c.getInt(1) != 0 || c.getInt(2) != 0) {
+ try {
+ return resolver.openFileDescriptor(uri, "r");
+ } catch (IOException e) {
+ throw new SecurityException(e);
+ }
+ }
+ }
+ }
+ }
+ throw new SecurityException("Uri is not ringtone, alarm, or notification: " + uri);
+ }
};
private Context getContextForUser(UserHandle user) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index 8e9857d..24b45cc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -27,6 +27,7 @@
private int mNumPages;
private View mDecorGroup;
+ private PageListener mPageListener;
public PagedTileLayout(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -36,12 +37,19 @@
public void onPageSelected(int position) {
if (mPageIndicator == null) return;
mPageIndicator.setLocation(position);
+ if (mPageListener != null) {
+ mPageListener.onPageChanged(position == 0);
+ }
}
@Override
- public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+ public void onPageScrolled(int position, float positionOffset,
+ int positionOffsetPixels) {
if (mPageIndicator == null) return;
mPageIndicator.setLocation(position + positionOffset);
+ if (mPageListener != null) {
+ mPageListener.onPageChanged(position == 0 && positionOffsetPixels == 0);
+ }
}
@Override
@@ -52,6 +60,11 @@
}
@Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
+
+ @Override
protected void onFinishInflate() {
super.onFinishInflate();
mPageIndicator = (PageIndicator) findViewById(R.id.page_indicator);
@@ -64,7 +77,9 @@
@Override
public int getOffsetTop(TileRecord tile) {
- return ((ViewGroup) tile.tileView.getParent()).getTop() + getTop();
+ final ViewGroup parent = (ViewGroup) tile.tileView.getParent();
+ if (parent == null) return 0;
+ return parent.getTop() + getTop();
}
@Override
@@ -80,6 +95,10 @@
}
}
+ public void setPageListener(PageListener listener) {
+ mPageListener = listener;
+ }
+
private void postDistributeTiles() {
removeCallbacks(mDistribute);
post(mDistribute);
@@ -148,6 +167,11 @@
}
};
+ public int getColumnCount() {
+ if (mPages.size() == 0) return 0;
+ return mPages.get(0).mColumns;
+ }
+
public static class TilePage extends TileLayout {
private int mMaxRows = 3;
@@ -198,4 +222,8 @@
return view == object;
}
};
+
+ public interface PageListener {
+ void onPageChanged(boolean isFirst);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
new file mode 100644
index 0000000..6137349
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.qs;
+
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnAttachStateChangeListener;
+import android.view.View.OnLayoutChangeListener;
+import android.view.animation.PathInterpolator;
+import android.widget.TextView;
+import com.android.systemui.qs.PagedTileLayout.PageListener;
+import com.android.systemui.qs.QSPanel.QSTileLayout;
+import com.android.systemui.qs.QSTile.Host.Callback;
+import com.android.systemui.qs.TouchAnimator.Builder;
+import com.android.systemui.qs.TouchAnimator.Listener;
+import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerService.Tunable;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class QSAnimator implements Callback, PageListener, Listener, OnLayoutChangeListener,
+ OnAttachStateChangeListener, Tunable {
+
+ private static final String TAG = "QSAnimator";
+
+ private static final String ALLOW_FANCY_ANIMATION = "sysui_qs_fancy_anim";
+ private static final String MOVE_FULL_ROWS = "sysui_qs_move_whole_rows";
+
+ public static final PathInterpolator TRANSLATION_Y_INTERPOLATOR =
+ new PathInterpolator(.1f, .3f, 1, 1);
+
+ public static final float EXPANDED_TILE_DELAY = .7f;
+
+ private final ArrayList<View> mAllViews = new ArrayList<>();
+ private final ArrayList<View> mTopFiveQs = new ArrayList<>();
+ private final QuickQSPanel mQuickQsPanel;
+ private final QSPanel mQsPanel;
+ private final QSContainer mQsContainer;
+
+ private PagedTileLayout mPagedLayout;
+
+ private boolean mOnFirstPage = true;
+ private TouchAnimator mFirstPageAnimator;
+ private TouchAnimator mFirstPageDelayedAnimator;
+ private TouchAnimator mTranslationYAnimator;
+ private TouchAnimator mNonfirstPageAnimator;
+
+ private boolean mOnKeyguard;
+
+ private boolean mAllowFancy;
+ private boolean mFullRows;
+ private int mNumQuickTiles;
+
+ public QSAnimator(QSContainer container, QuickQSPanel quickPanel, QSPanel panel) {
+ mQsContainer = container;
+ mQuickQsPanel = quickPanel;
+ mQsPanel = panel;
+ mQsPanel.addOnAttachStateChangeListener(this);
+ container.addOnLayoutChangeListener(this);
+ QSTileLayout tileLayout = mQsPanel.getTileLayout();
+ if (tileLayout instanceof PagedTileLayout) {
+ mPagedLayout = ((PagedTileLayout) tileLayout);
+ mPagedLayout.setPageListener(this);
+ } else {
+ Log.w(TAG, "QS Not using page layout");
+ }
+ }
+
+ public void setOnKeyguard(boolean onKeyguard) {
+ mOnKeyguard = onKeyguard;
+ if (mOnKeyguard) {
+ clearAnimationState();
+ }
+ }
+
+ public void setHost(QSTileHost qsh) {
+ qsh.addCallback(this);
+ }
+
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ TunerService.get(mQsContainer.getContext()).addTunable(this, ALLOW_FANCY_ANIMATION,
+ MOVE_FULL_ROWS, QuickQSPanel.NUM_QUICK_TILES);
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ TunerService.get(mQsContainer.getContext()).removeTunable(this);
+ }
+
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ if (ALLOW_FANCY_ANIMATION.equals(key)) {
+ mAllowFancy = newValue == null || Integer.parseInt(newValue) != 0;
+ if (!mAllowFancy) {
+ clearAnimationState();
+ }
+ } else if (MOVE_FULL_ROWS.equals(key)) {
+ mFullRows = newValue != null && Integer.parseInt(newValue) != 0;
+ } else if (QuickQSPanel.NUM_QUICK_TILES.equals(key)) {
+ mNumQuickTiles = QuickQSPanel.getNumQuickTiles(mQsContainer.getContext());
+ clearAnimationState();
+ }
+ updateAnimators();
+ }
+
+ @Override
+ public void onPageChanged(boolean isFirst) {
+ if (mOnFirstPage == isFirst) return;
+ if (!isFirst) {
+ clearAnimationState();
+ }
+ mOnFirstPage = isFirst;
+ }
+
+ private void updateAnimators() {
+ TouchAnimator.Builder firstPageBuilder = new Builder();
+ TouchAnimator.Builder translationYBuilder = new Builder();
+ TouchAnimator.Builder firstPageDelayedBuilder = new Builder();
+ Collection<QSTile<?>> tiles = mQsPanel.getHost().getTiles();
+ int count = 0;
+ int[] loc1 = new int[2];
+ int[] loc2 = new int[2];
+ int lastYDiff = 0;
+ firstPageDelayedBuilder.setStartDelay(EXPANDED_TILE_DELAY);
+ firstPageBuilder.setListener(this);
+ translationYBuilder.setInterpolator(TRANSLATION_Y_INTERPOLATOR);
+ // Fade in the tiles/labels as we reach the final position.
+ firstPageDelayedBuilder.addFloat(mQsPanel.getTileLayout(), "alpha", 0, 1);
+ mAllViews.clear();
+ mTopFiveQs.clear();
+ mAllViews.add((View) mQsPanel.getTileLayout());
+ for (QSTile<?> tile : tiles) {
+ QSTileBaseView tileView = mQsPanel.getTileView(tile);
+ final TextView label = ((QSTileView) tileView).getLabel();
+ final View tileIcon = tileView.getIcon();
+ if (count < mNumQuickTiles && mAllowFancy) {
+ // Quick tiles.
+ QSTileBaseView quickTileView = mQuickQsPanel.getTileView(tile);
+
+ getRelativePosition(loc1, quickTileView.getIcon(), mQsContainer);
+ getRelativePosition(loc2, tileIcon, mQsContainer);
+ final int xDiff = loc2[0] - loc1[0];
+ final int yDiff = loc2[1] - loc1[1];
+ lastYDiff = yDiff;
+ // Move the quick tile right from its location to the new one.
+ firstPageBuilder.addFloat(quickTileView, "translationX", 0, xDiff);
+ translationYBuilder.addFloat(quickTileView, "translationY", 0, yDiff);
+
+ // Counteract the parent translation on the tile. So we have a static base to
+ // animate the label position off from.
+ firstPageBuilder.addFloat(tileView, "translationY", mQsPanel.getHeight(), 0);
+
+ // Move the real tile's label from the quick tile position to its final
+ // location.
+ firstPageBuilder.addFloat(label, "translationX", -xDiff, 0);
+ translationYBuilder.addFloat(label, "translationY", -yDiff, 0);
+
+ mTopFiveQs.add(tileIcon);
+ mAllViews.add(tileIcon);
+ mAllViews.add(label);
+ mAllViews.add(quickTileView);
+ } else if (mFullRows && isIconInAnimatedRow(count)) {
+ firstPageBuilder.addFloat(tileView, "translationY", mQsPanel.getHeight(), 0);
+ translationYBuilder.addFloat(label, "translationY", -lastYDiff, 0);
+ translationYBuilder.addFloat(tileIcon, "translationY", -lastYDiff, 0);
+ mAllViews.add(tileIcon);
+ mAllViews.add(label);
+ }
+ mAllViews.add(tileView);
+ mAllViews.add(label);
+ count++;
+ }
+ if (mAllowFancy) {
+ mFirstPageAnimator = firstPageBuilder.build();
+ mFirstPageDelayedAnimator = firstPageDelayedBuilder.build();
+ mTranslationYAnimator = translationYBuilder.build();
+ }
+ mNonfirstPageAnimator = new TouchAnimator.Builder()
+ .addFloat(mQuickQsPanel, "alpha", 1, 0)
+ .setEndDelay(.5f)
+ .build();
+ }
+
+ private boolean isIconInAnimatedRow(int count) {
+ if (mPagedLayout == null) {
+ return false;
+ }
+ final int columnCount = mPagedLayout.getColumnCount();
+ return count < ((mNumQuickTiles + columnCount - 1) / columnCount) * columnCount;
+ }
+
+ private void getRelativePosition(int[] loc1, View view, View parent) {
+ loc1[0] = 0 + view.getWidth() / 2;
+ loc1[1] = 0;
+ getRelativePositionInt(loc1, view, parent);
+ }
+
+ private void getRelativePositionInt(int[] loc1, View view, View parent) {
+ if(view == parent || view == null) return;
+ loc1[0] += view.getLeft();
+ loc1[1] += view.getTop();
+ getRelativePositionInt(loc1, (View) view.getParent(), parent);
+ }
+
+ public void setPosition(float position) {
+ if (mFirstPageAnimator == null) return;
+ if (mOnKeyguard) {
+ return;
+ }
+ if (mOnFirstPage && mAllowFancy) {
+ mQuickQsPanel.setAlpha(1);
+ mFirstPageAnimator.setPosition(position);
+ mFirstPageDelayedAnimator.setPosition(position);
+ mTranslationYAnimator.setPosition(position);
+ } else {
+ mNonfirstPageAnimator.setPosition(position);
+ }
+ }
+
+ @Override
+ public void onAnimationAtStart() {
+ mQuickQsPanel.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void onAnimationAtEnd() {
+ mQuickQsPanel.setVisibility(View.INVISIBLE);
+ final int N = mTopFiveQs.size();
+ for (int i = 0; i < N; i++) {
+ mTopFiveQs.get(i).setVisibility(View.VISIBLE);
+ }
+ }
+
+ @Override
+ public void onAnimationStarted() {
+ mQuickQsPanel.setVisibility(View.VISIBLE);
+ if (mOnFirstPage) {
+ final int N = mTopFiveQs.size();
+ for (int i = 0; i < N; i++) {
+ mTopFiveQs.get(i).setVisibility(View.INVISIBLE);
+ }
+ }
+ }
+
+ private void clearAnimationState() {
+ final int N = mAllViews.size();
+ mQuickQsPanel.setAlpha(0);
+ mQuickQsPanel.setVisibility(View.VISIBLE);
+ for (int i = 0; i < N; i++) {
+ View v = mAllViews.get(i);
+ v.setAlpha(1);
+ v.setTranslationX(1);
+ v.setTranslationY(1);
+ }
+ final int N2 = mTopFiveQs.size();
+ for (int i = 0; i < N2; i++) {
+ mTopFiveQs.get(i).setVisibility(View.VISIBLE);
+ }
+ }
+
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
+ int oldTop, int oldRight, int oldBottom) {
+ updateAnimators();
+ }
+
+ @Override
+ public void onTilesChanged() {
+ // Give the QS panels a moment to generate their new tiles, then create all new animators
+ // hooked up to the new views.
+ mQsPanel.post(mUpdateAnimators);
+ }
+
+ private Runnable mUpdateAnimators = new Runnable() {
+ @Override
+ public void run() {
+ updateAnimators();
+ }
+ };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
index 34dfd6c..c0c1e4d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
@@ -27,6 +27,7 @@
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.BaseStatusBarHeader;
+import com.android.systemui.statusbar.phone.QSTileHost;
import com.android.systemui.statusbar.stack.StackStateAnimator;
/**
@@ -49,6 +50,7 @@
private boolean mStackScrollerOverscrolling;
private long mDelay;
+ private QSAnimator mQSAnimator;
public QSContainer(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -61,6 +63,23 @@
mQSDetail = (QSDetail) findViewById(R.id.qs_detail);
mQSDetail.setQsPanel(mQSPanel);
mHeader = (BaseStatusBarHeader) findViewById(R.id.header);
+ mQSAnimator = new QSAnimator(this, (QuickQSPanel) mHeader.findViewById(R.id.quick_qs_panel),
+ mQSPanel);
+ }
+
+ public void setHost(QSTileHost qsh) {
+ mQSPanel.setHost(qsh);
+ mHeader.setQSPanel(mQSPanel);
+ mQSDetail.setHost(qsh);
+ mQSAnimator.setHost(qsh);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ // Since we control our own bottom, be whatever size we want.
+ // Otherwise the QSPanel ends up with 0 height when the window is only the
+ // size of the status bar.
+ super.onMeasure(widthMeasureSpec, MeasureSpec.UNSPECIFIED);
}
@Override
@@ -137,6 +156,7 @@
public void setKeyguardShowing(boolean keyguardShowing) {
if (DEBUG) Log.d(TAG, "setKeyguardShowing " + keyguardShowing);
mKeyguardShowing = keyguardShowing;
+ mQSAnimator.setOnKeyguard(keyguardShowing);
updateQsState();
}
@@ -163,6 +183,7 @@
mHeader.setExpansion(mKeyguardShowing ? 1 : expansion);
mQSPanel.setTranslationY(translationScaleY * mQSPanel.getHeight());
mQSDetail.setFullyExpanded(expansion == 1);
+ mQSAnimator.setPosition(expansion);
updateBottom();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java b/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java
index 1df372b..546f8c3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java
@@ -23,7 +23,6 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
-
import android.widget.ImageView.ScaleType;
import com.android.systemui.R;
@@ -34,6 +33,7 @@
private final View mIcon;
private final int mIconSizePx;
private final int mTilePaddingBelowIconPx;
+ private boolean mAnimationEnabled = true;
public QSIconView(Context context) {
super(context);
@@ -46,6 +46,10 @@
addView(mIcon);
}
+ public void disableAnimation() {
+ mAnimationEnabled = false;
+ }
+
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int w = MeasureSpec.getSize(widthMeasureSpec);
@@ -69,13 +73,17 @@
protected void setIcon(ImageView iv, QSTile.State state) {
if (!Objects.equals(state.icon, iv.getTag(R.id.qs_icon_tag))) {
- Drawable d = state.icon != null ? state.icon.getDrawable(mContext) : null;
+ Drawable d = state.icon != null
+ ? iv.isShown() && mAnimationEnabled ? state.icon.getDrawable(mContext)
+ : state.icon.getInvisibleDrawable(mContext) : null;
+ int padding = state.icon != null ? state.icon.getPadding() : null;
if (d != null && state.autoMirrorDrawable) {
d.setAutoMirrored(true);
}
iv.setImageDrawable(d);
iv.setTag(R.id.qs_icon_tag, state.icon);
- if (d instanceof Animatable) {
+ iv.setPadding(0, padding, 0, padding);
+ if (d instanceof Animatable && iv.isShown()) {
Animatable a = (Animatable) d;
a.start();
if (!iv.isShown()) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 53abe37..71c1913 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -25,13 +25,13 @@
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
-import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile.DetailAdapter;
+import com.android.systemui.qs.QSTile.Host.Callback;
import com.android.systemui.qs.customize.QSCustomizer;
import com.android.systemui.qs.external.CustomTile;
import com.android.systemui.settings.BrightnessController;
@@ -45,7 +45,7 @@
import java.util.Collection;
/** View that represents the quick settings tile panel. **/
-public class QSPanel extends FrameLayout implements Tunable {
+public class QSPanel extends LinearLayout implements Tunable, Callback {
public static final String QS_SHOW_BRIGHTNESS = "qs_show_brightness";
@@ -66,7 +66,6 @@
protected QSFooter mFooter;
private boolean mGridContentVisible = true;
- protected LinearLayout mQsContainer;
protected QSTileLayout mTileLayout;
private QSCustomizer mCustomizePanel;
@@ -80,20 +79,15 @@
super(context, attrs);
mContext = context;
-
- mQsContainer = new LinearLayout(mContext);
- mQsContainer.setOrientation(LinearLayout.VERTICAL);
- mQsContainer.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
- LayoutParams.WRAP_CONTENT));
- addView(mQsContainer);
+ setOrientation(VERTICAL);
mBrightnessView = LayoutInflater.from(context).inflate(
R.layout.quick_settings_brightness_dialog, this, false);
- mQsContainer.addView(mBrightnessView);
+ addView(mBrightnessView);
mTileLayout = (QSTileLayout) LayoutInflater.from(mContext).inflate(
- R.layout.qs_paged_tile_layout, mQsContainer, false);
- mQsContainer.addView((View) mTileLayout);
+ R.layout.qs_paged_tile_layout, this, false);
+ addView((View) mTileLayout);
findViewById(android.R.id.edit).setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
@@ -107,7 +101,7 @@
});
mFooter = new QSFooter(this, context);
- mQsContainer.addView(mFooter.getView());
+ addView(mFooter.getView());
updateResources();
@@ -130,10 +124,16 @@
@Override
protected void onDetachedFromWindow() {
TunerService.get(mContext).removeTunable(this);
+ mHost.removeCallback(this);
super.onDetachedFromWindow();
}
@Override
+ public void onTilesChanged() {
+ setTiles(mHost.getTiles());
+ }
+
+ @Override
public void onTuningChanged(String key, String newValue) {
if (QS_SHOW_BRIGHTNESS.equals(key)) {
mBrightnessView.setVisibility(newValue == null || Integer.parseInt(newValue) != 0
@@ -175,6 +175,8 @@
public void setHost(QSTileHost host) {
mHost = host;
+ mHost.addCallback(this);
+ setTiles(mHost.getTiles());
mFooter.setHost(host);
createCustomizePanel();
}
@@ -187,7 +189,7 @@
final Resources res = mContext.getResources();
mPanelPaddingBottom = res.getDimensionPixelSize(R.dimen.qs_panel_padding_bottom);
mBrightnessPaddingTop = res.getDimensionPixelSize(R.dimen.qs_brightness_padding_top);
- mQsContainer.setPadding(0, mBrightnessPaddingTop, 0, mPanelPaddingBottom);
+ setPadding(0, mBrightnessPaddingTop, 0, mPanelPaddingBottom);
for (TileRecord r : mRecords) {
r.tile.clearState();
}
@@ -214,6 +216,9 @@
public void setExpanded(boolean expanded) {
if (mExpanded == expanded) return;
mExpanded = expanded;
+ if (!mExpanded && mTileLayout instanceof PagedTileLayout) {
+ ((PagedTileLayout) mTileLayout).setCurrentItem(0, false);
+ }
MetricsLogger.visibility(mContext, MetricsEvent.QS_PANEL, mExpanded);
if (!mExpanded) {
closeDetail();
@@ -276,7 +281,7 @@
}
}
- private void drawTile(TileRecord r, QSTile.State state) {
+ protected void drawTile(TileRecord r, QSTile.State state) {
r.tileView.onStateChanged(state);
}
@@ -329,7 +334,8 @@
final View.OnLongClickListener longClick = new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
- return false;
+ r.tile.longClick();
+ return true;
}
};
r.tileView.init(click, longClick);
@@ -376,7 +382,7 @@
}
public int getGridHeight() {
- return mQsContainer.getMeasuredHeight();
+ return getMeasuredHeight();
}
protected void handleShowDetail(Record r, boolean show) {
@@ -425,7 +431,7 @@
void setGridContentVisibility(boolean visible) {
int newVis = visible ? VISIBLE : INVISIBLE;
- mQsContainer.setVisibility(newVis);
+ setVisibility(newVis);
if (mGridContentVisible != visible) {
MetricsLogger.visibility(mContext, MetricsEvent.QS_PANEL, newVis);
}
@@ -468,6 +474,19 @@
}
}
+ QSTileLayout getTileLayout() {
+ return mTileLayout;
+ }
+
+ QSTileBaseView getTileView(QSTile<?> tile) {
+ for (TileRecord r : mRecords) {
+ if (r.tile == tile) {
+ return r.tileView;
+ }
+ }
+ return null;
+ }
+
private class H extends Handler {
private static final int SHOW_DETAIL = 1;
private static final int SET_TILE_VISIBILITY = 2;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index e363b76..42e98aa 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -36,7 +36,7 @@
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.CastController;
-import com.android.systemui.statusbar.policy.DisplayController;
+import com.android.systemui.statusbar.policy.NightModeController;
import com.android.systemui.statusbar.policy.FlashlightController;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
@@ -212,9 +212,11 @@
}
protected void handleLongClick() {
- // optional
+ mHost.startActivityDismissingKeyguard(getLongClickIntent());
}
+ public abstract Intent getLongClickIntent();
+
protected void handleClearState() {
mTmpState = newTileState();
mState = newTileState();
@@ -279,10 +281,11 @@
mCallbacks.clear();
}
- protected void checkIfRestrictionEnforced(State state, String userRestriction) {
+ protected void checkIfRestrictionEnforcedByAdminOnly(State state, String userRestriction) {
EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(mContext,
userRestriction, ActivityManager.getCurrentUser());
- if (admin != null) {
+ if (admin != null && !RestrictedLockUtils.hasBaseUserRestriction(mContext,
+ userRestriction, ActivityManager.getCurrentUser())) {
state.disabledByPolicy = true;
state.enforcedAdmin = admin;
} else {
@@ -387,6 +390,7 @@
Context getContext();
Collection<QSTile<?>> getTiles();
void addCallback(Callback callback);
+ void removeCallback(Callback callback);
BluetoothController getBluetoothController();
LocationController getLocationController();
RotationLockController getRotationLockController();
@@ -400,7 +404,7 @@
UserInfoController getUserInfoController();
BatteryController getBatteryController();
TileServices getTileServices();
- DisplayController getDisplayController();
+ NightModeController getNightModeController();
void removeTile(String tileSpec);
ManagedProfileController getManagedProfileController();
@@ -413,10 +417,18 @@
public static abstract class Icon {
abstract public Drawable getDrawable(Context context);
+ public Drawable getInvisibleDrawable(Context context) {
+ return getDrawable(context);
+ }
+
@Override
public int hashCode() {
return Icon.class.hashCode();
}
+
+ public int getPadding() {
+ return 0;
+ }
}
public static class DrawableIcon extends Icon {
@@ -430,6 +442,11 @@
public Drawable getDrawable(Context context) {
return mDrawable;
}
+
+ @Override
+ public Drawable getInvisibleDrawable(Context context) {
+ return mDrawable;
+ }
}
public static class ResourceIcon extends Icon {
@@ -456,6 +473,11 @@
}
@Override
+ public Drawable getInvisibleDrawable(Context context) {
+ return context.getDrawable(mResId);
+ }
+
+ @Override
public boolean equals(Object o) {
return o instanceof ResourceIcon && ((ResourceIcon) o).mResId == mResId;
}
@@ -467,14 +489,17 @@
}
protected class AnimationIcon extends ResourceIcon {
- public AnimationIcon(int resId) {
- super(resId);
+ private final int mAnimatedResId;
+
+ public AnimationIcon(int resId, int staticResId) {
+ super(staticResId);
+ mAnimatedResId = resId;
}
@Override
public Drawable getDrawable(Context context) {
// workaround: get a clean state for every new AVD
- return context.getDrawable(mResId).getConstantState().newDrawable();
+ return context.getDrawable(mAnimatedResId).getConstantState().newDrawable();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java
index 1a854c2..9e40cfd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java
@@ -48,7 +48,9 @@
// Default to Quick Tile padding, and QSTileView will specify its own padding.
int padding = context.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_padding);
- setPadding(padding, padding, padding, padding);
+ setPadding(0, padding, 0, padding);
+ setClipChildren(false);
+ setClipToPadding(false);
}
private Drawable newTileBackground() {
@@ -77,6 +79,7 @@
public void init(OnClickListener click, OnLongClickListener longClick) {
setClickable(true);
setOnClickListener(click);
+ setOnLongClickListener(longClick);
}
@Override
@@ -110,6 +113,10 @@
setContentDescription(state.contentDescription);
}
+ public QSIconView getIcon() {
+ return mIcon;
+ }
+
private class H extends Handler {
private static final int STATE_CHANGED = 1;
public H() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
index 0d5d115..98a1c23 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
@@ -28,6 +28,7 @@
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
+import libcore.util.Objects;
/** View that represents a standard quick settings tile. **/
public class QSTileView extends QSTileBaseView {
@@ -57,6 +58,10 @@
setGravity(Gravity.CENTER);
}
+ TextView getLabel() {
+ return mLabel;
+ }
+
private void updateTopPadding() {
Resources res = getResources();
int padding = res.getDimensionPixelSize(R.dimen.qs_tile_padding_top);
@@ -84,14 +89,11 @@
addView(view);
}
- public void init(OnClickListener clickPrimary, OnLongClickListener longClick) {
- setOnClickListener(clickPrimary);
- setOnLongClickListener(longClick);
- }
-
protected void handleStateChanged(QSTile.State state) {
super.handleStateChanged(state);
- mLabel.setText(state.label);
+ if (!Objects.equal(mLabel.getText(), state.label)) {
+ mLabel.setText(state.label);
+ }
mLabel.setEnabled(!state.disabledByPolicy);
mPadLock.setVisibility(state.disabledByPolicy ? View.VISIBLE : View.GONE);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index d0f7e6e..f8a57d0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -24,6 +24,10 @@
import android.widget.LinearLayout;
import android.widget.Space;
import com.android.systemui.R;
+import com.android.systemui.qs.QSTile.SignalState;
+import com.android.systemui.qs.QSTile.State;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerService.Tunable;
import java.util.ArrayList;
import java.util.Collection;
@@ -33,6 +37,8 @@
*/
public class QuickQSPanel extends QSPanel {
+ public static final String NUM_QUICK_TILES = "sysui_qqs_count";
+
private int mMaxTiles;
private QSPanel mFullPanel;
private View mHeader;
@@ -43,10 +49,22 @@
for (int i = 0; i < mRecords.size(); i++) {
mTileLayout.removeTile(mRecords.get(i));
}
- mQsContainer.removeView((View) mTileLayout);
+ removeView((View) mTileLayout);
}
mTileLayout = new HeaderTileLayout(context);
- mQsContainer.addView((View) mTileLayout, 1 /* Between brightness and footer */);
+ addView((View) mTileLayout, 1 /* Between brightness and footer */);
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ TunerService.get(mContext).addTunable(mNumTiles, NUM_QUICK_TILES);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ TunerService.get(mContext).removeTunable(mNumTiles);
}
@Override
@@ -60,6 +78,19 @@
}
@Override
+ protected void drawTile(TileRecord r, State state) {
+ if (state instanceof SignalState) {
+ State copy = r.tile.newTileState();
+ state.copyTo(copy);
+ // No activity shown in the quick panel.
+ ((SignalState) copy).activityIn = false;
+ ((SignalState) copy).activityOut = false;
+ state = copy;
+ }
+ super.drawTile(r, state);
+ }
+
+ @Override
protected void showDetail(boolean show, Record r) {
// Do nothing, will be handled by the QSPanel.
}
@@ -71,6 +102,7 @@
public void setMaxTiles(int maxTiles) {
mMaxTiles = maxTiles;
+ setTiles(mHost.getTiles());
}
@Override
@@ -99,6 +131,17 @@
super.setTiles(quickTiles);
}
+ private final Tunable mNumTiles = new Tunable() {
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ setMaxTiles(getNumQuickTiles(mContext));
+ }
+ };
+
+ public static int getNumQuickTiles(Context context) {
+ return TunerService.get(context).getValue(NUM_QUICK_TILES, 5);
+ }
+
private static class HeaderTileLayout extends LinearLayout implements QSTileLayout {
private final Space mEndSpacer;
@@ -183,5 +226,10 @@
// No resources here.
return false;
}
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index f7e2338..55eda98 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -81,7 +81,7 @@
record.tileView.measure(exactly(mCellWidth), exactly(mCellHeight));
previousView = record.tileView.updateAccessibilityOrder(previousView);
}
- setMeasuredDimension(width, (mCellHeight + mCellMargin) * rows + mCellMargin);
+ setMeasuredDimension(width, (mCellHeight + mCellMargin) * rows);
}
private static int exactly(int size) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java
index 5e6b52b..35ade58 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java
@@ -14,9 +14,9 @@
package com.android.systemui.qs;
-import android.animation.Keyframe;
import android.util.MathUtils;
import android.util.Property;
+import android.view.View;
import android.view.animation.Interpolator;
import java.util.ArrayList;
@@ -32,19 +32,17 @@
public class TouchAnimator {
private final Object[] mTargets;
- private final Property[] mProperties;
private final KeyframeSet[] mKeyframeSets;
private final float mStartDelay;
private final float mEndDelay;
private final float mSpan;
private final Interpolator mInterpolator;
private final Listener mListener;
- private float mLastT;
+ private float mLastT = -1;
- private TouchAnimator(Object[] targets, Property[] properties, KeyframeSet[] keyframeSets,
+ private TouchAnimator(Object[] targets, KeyframeSet[] keyframeSets,
float startDelay, float endDelay, Interpolator interpolator, Listener listener) {
mTargets = targets;
- mProperties = properties;
mKeyframeSets = keyframeSets;
mStartDelay = startDelay;
mEndDelay = endDelay;
@@ -58,21 +56,21 @@
if (mInterpolator != null) {
t = mInterpolator.getInterpolation(t);
}
+ if (t == mLastT) {
+ return;
+ }
if (mListener != null) {
- if (mLastT == 0 || mLastT == 1) {
- if (t != 0) {
- mListener.onAnimationStarted();
- }
- } else if (t == 1) {
+ if (t == 1) {
mListener.onAnimationAtEnd();
} else if (t == 0) {
mListener.onAnimationAtStart();
+ } else if (mLastT <= 0 || mLastT == 1) {
+ mListener.onAnimationStarted();
}
mLastT = t;
}
for (int i = 0; i < mTargets.length; i++) {
- Object value = mKeyframeSets[i].getValue(t);
- mProperties[i].set(mTargets[i], value);
+ mKeyframeSets[i].setValue(t, mTargets[i]);
}
}
@@ -109,7 +107,6 @@
public static class Builder {
private List<Object> mTargets = new ArrayList<>();
- private List<Property> mProperties = new ArrayList<>();
private List<KeyframeSet> mValues = new ArrayList<>();
private float mStartDelay;
@@ -118,22 +115,46 @@
private Listener mListener;
public Builder addFloat(Object target, String property, float... values) {
- add(target, property, KeyframeSet.ofFloat(values));
+ add(target, KeyframeSet.ofFloat(getProperty(target, property, float.class), values));
return this;
}
public Builder addInt(Object target, String property, int... values) {
- add(target, property, KeyframeSet.ofInt(values));
+ add(target, KeyframeSet.ofInt(getProperty(target, property, int.class), values));
return this;
}
- private void add(Object target, String property, KeyframeSet keyframeSet) {
+ private void add(Object target, KeyframeSet keyframeSet) {
mTargets.add(target);
- // TODO: Optimize the properties here, to use those in View when possible.
- mProperties.add(Property.of(target.getClass(), float.class, property));
mValues.add(keyframeSet);
}
+ private static Property getProperty(Object target, String property, Class<?> cls) {
+ if (target instanceof View) {
+ switch (property) {
+ case "translationX":
+ return View.TRANSLATION_X;
+ case "translationY":
+ return View.TRANSLATION_Y;
+ case "translationZ":
+ return View.TRANSLATION_Z;
+ case "alpha":
+ return View.ALPHA;
+ case "rotation":
+ return View.ROTATION;
+ case "x":
+ return View.X;
+ case "y":
+ return View.Y;
+ case "scaleX":
+ return View.SCALE_X;
+ case "scaleY":
+ return View.SCALE_Y;
+ }
+ }
+ return Property.of(target.getClass(), cls, property);
+ }
+
public Builder setStartDelay(float startDelay) {
mStartDelay = startDelay;
return this;
@@ -156,7 +177,6 @@
public TouchAnimator build() {
return new TouchAnimator(mTargets.toArray(new Object[mTargets.size()]),
- mProperties.toArray(new Property[mProperties.size()]),
mValues.toArray(new KeyframeSet[mValues.size()]),
mStartDelay, mEndDelay, mInterpolator, mListener);
}
@@ -164,78 +184,65 @@
private static abstract class KeyframeSet {
- private final Keyframe[] mKeyframes;
+ private final float mFrameWidth;
+ private final int mSize;
- public KeyframeSet(Keyframe[] keyframes) {
- mKeyframes = keyframes;
+ public KeyframeSet(int size) {
+ mSize = size;
+ mFrameWidth = 1 / (float) (size - 1);
}
- Object getValue(float fraction) {
+ void setValue(float fraction, Object target) {
int i;
- for (i = 1; i < mKeyframes.length && fraction > mKeyframes[i].getFraction(); i++) ;
- Keyframe first = mKeyframes[i - 1];
- Keyframe second = mKeyframes[i];
- float amount = (fraction - first.getFraction())
- / (second.getFraction() - first.getFraction());
- return interpolate(first, second, amount);
+ for (i = 1; i < mSize - 1 && fraction > mFrameWidth; i++);
+ float amount = fraction / mFrameWidth;
+ interpolate(i, amount, target);
}
- protected abstract Object interpolate(Keyframe first, Keyframe second, float amount);
+ protected abstract void interpolate(int index, float amount, Object target);
- public static KeyframeSet ofInt(int... values) {
- int numKeyframes = values.length;
- Keyframe keyframes[] = new Keyframe[Math.max(numKeyframes, 2)];
- if (numKeyframes == 1) {
- keyframes[0] = Keyframe.ofInt(0f);
- keyframes[1] = Keyframe.ofInt(1f, values[0]);
- } else {
- keyframes[0] = Keyframe.ofInt(0f, values[0]);
- for (int i = 1; i < numKeyframes; ++i) {
- keyframes[i] = Keyframe.ofInt((float) i / (numKeyframes - 1), values[i]);
- }
- }
- return new IntKeyframeSet(keyframes);
+ public static KeyframeSet ofInt(Property property, int... values) {
+ return new IntKeyframeSet((Property<?, Integer>) property, values);
}
- public static KeyframeSet ofFloat(float... values) {
- int numKeyframes = values.length;
- Keyframe keyframes[] = new Keyframe[Math.max(numKeyframes, 2)];
- if (numKeyframes == 1) {
- keyframes[0] = Keyframe.ofFloat(0f);
- keyframes[1] = Keyframe.ofFloat(1f, values[0]);
- } else {
- keyframes[0] = Keyframe.ofFloat(0f, values[0]);
- for (int i = 1; i < numKeyframes; ++i) {
- keyframes[i] = Keyframe.ofFloat((float) i / (numKeyframes - 1), values[i]);
- }
- }
- return new FloatKeyframeSet(keyframes);
+ public static KeyframeSet ofFloat(Property property, float... values) {
+ return new FloatKeyframeSet((Property<?, Float>) property, values);
}
}
- public static class FloatKeyframeSet extends KeyframeSet {
- public FloatKeyframeSet(Keyframe[] keyframes) {
- super(keyframes);
+ private static class FloatKeyframeSet<T> extends KeyframeSet {
+ private final float[] mValues;
+ private final Property<T, Float> mProperty;
+
+ public FloatKeyframeSet(Property<T, Float> property, float[] values) {
+ super(values.length);
+ mProperty = property;
+ mValues = values;
}
@Override
- protected Object interpolate(Keyframe first, Keyframe second, float amount) {
- float firstFloat = (float) first.getValue();
- float secondFloat = (float) second.getValue();
- return firstFloat + (secondFloat - firstFloat) * amount;
+ protected void interpolate(int index, float amount, Object target) {
+ float firstFloat = mValues[index - 1];
+ float secondFloat = mValues[index];
+ mProperty.set((T) target, firstFloat + (secondFloat - firstFloat) * amount);
}
}
- public static class IntKeyframeSet extends KeyframeSet {
- public IntKeyframeSet(Keyframe[] keyframes) {
- super(keyframes);
+ private static class IntKeyframeSet<T> extends KeyframeSet {
+ private final int[] mValues;
+ private final Property<T, Integer> mProperty;
+
+ public IntKeyframeSet(Property<T, Integer> property, int[] values) {
+ super(values.length);
+ mProperty = property;
+ mValues = values;
}
@Override
- protected Object interpolate(Keyframe first, Keyframe second, float amount) {
- int firstFloat = (int) first.getValue();
- int secondFloat = (int) second.getValue();
- return (int) (firstFloat + (secondFloat - firstFloat) * amount);
+ protected void interpolate(int index, float amount, Object target) {
+ int firstFloat = mValues[index - 1];
+ int secondFloat = mValues[index];
+ mProperty.set((T) target, (int) (firstFloat + (secondFloat - firstFloat) * amount));
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 81e1581..5e02428 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -17,16 +17,20 @@
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
+import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.AttributeSet;
+import android.util.TypedValue;
import android.view.ContextThemeWrapper;
+import android.view.Menu;
+import android.view.MenuItem;
import android.view.View;
-import android.view.View.OnClickListener;
import android.widget.LinearLayout;
+import android.widget.Toolbar;
+import android.widget.Toolbar.OnMenuItemClickListener;
import com.android.systemui.R;
import com.android.systemui.qs.QSDetailClipper;
import com.android.systemui.qs.QSTile;
@@ -42,7 +46,9 @@
* This adds itself to the status bar window, so it can appear on top of quick settings and
* *someday* do fancy animations to get into/out of it.
*/
-public class QSCustomizer extends LinearLayout implements AnimatorListener, OnClickListener {
+public class QSCustomizer extends LinearLayout implements OnMenuItemClickListener {
+
+ private static final int MENU_RESET = Menu.FIRST;
private final QSDetailClipper mClipper;
@@ -52,9 +58,7 @@
private QSTileHost mHost;
private RecyclerView mRecyclerView;
private TileAdapter mTileAdapter;
- private View mClose;
- private View mSave;
- private View mReset;
+ private Toolbar mToolbar;
public QSCustomizer(Context context, AttributeSet attrs) {
super(new ContextThemeWrapper(context, android.R.style.Theme_Material), attrs);
@@ -69,17 +73,26 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mClose = findViewById(R.id.close);
- mSave = findViewById(R.id.save);
- mReset = findViewById(R.id.reset);
- mClose.setOnClickListener(this);
- mSave.setOnClickListener(this);
- mReset.setOnClickListener(this);
+ mToolbar = (Toolbar) findViewById(com.android.internal.R.id.action_bar);
+ TypedValue value = new TypedValue();
+ mContext.getTheme().resolveAttribute(android.R.attr.homeAsUpIndicator, value, true);
+ mToolbar.setNavigationIcon(
+ getResources().getDrawable(value.resourceId, mContext.getTheme()));
+ mToolbar.setNavigationOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ hide((int) v.getX() + v.getWidth() / 2, (int) v.getY() + v.getHeight() / 2);
+ }
+ });
+ mToolbar.setOnMenuItemClickListener(this);
+ mToolbar.getMenu().add(Menu.NONE, MENU_RESET, 0,
+ mContext.getString(com.android.internal.R.string.reset));
+ mToolbar.setTitle(R.string.qs_edit);
mRecyclerView = (RecyclerView) findViewById(android.R.id.list);
mTileAdapter = new TileAdapter(getContext());
mRecyclerView.setAdapter(mTileAdapter);
- new ItemTouchHelper(mTileAdapter.getCallback()).attachToRecyclerView(mRecyclerView);
+ mTileAdapter.getItemTouchHelper().attachToRecyclerView(mRecyclerView);
GridLayoutManager layout = new GridLayoutManager(getContext(), 3);
layout.setSpanSizeLookup(mTileAdapter.getSizeLookup());
mRecyclerView.setLayoutManager(layout);
@@ -94,7 +107,7 @@
isShown = true;
mPhoneStatusBar.getStatusBarWindow().addView(this);
setTileSpecs();
- mClipper.animateCircularClip(x, y, true, this);
+ mClipper.animateCircularClip(x, y, true, null);
new TileQueryHelper(mContext, mHost).setListener(mTileAdapter);
}
}
@@ -102,7 +115,8 @@
public void hide(int x, int y) {
if (isShown) {
isShown = false;
- mClipper.animateCircularClip(x, y, false, this);
+ save();
+ mClipper.animateCircularClip(x, y, false, mCollapseAnimationListener);
}
}
@@ -110,6 +124,16 @@
return isShown;
}
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ switch (item.getItemId()) {
+ case MENU_RESET:
+ reset();
+ break;
+ }
+ return false;
+ }
+
private void reset() {
ArrayList<String> tiles = new ArrayList<>();
String defTiles = mContext.getString(R.string.quick_settings_tiles_default);
@@ -129,42 +153,21 @@
private void save() {
mTileAdapter.saveSpecs(mHost);
- hide((int) mSave.getX() + mSave.getWidth() / 2, (int) mSave.getY() + mSave.getHeight() / 2);
}
- @Override
- public void onClick(View v) {
- if (v == mClose) {
- hide((int) mClose.getX() + mClose.getWidth() / 2,
- (int) mClose.getY() + mClose.getHeight() / 2);
- } else if (v == mSave) {
- save();
- } else if (v == mReset) {
- reset();
+ private final AnimatorListener mCollapseAnimationListener = new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!isShown) {
+ mPhoneStatusBar.getStatusBarWindow().removeView(QSCustomizer.this);
+ }
}
- }
- @Override
- public void onAnimationEnd(Animator animation) {
- if (!isShown) {
- mPhoneStatusBar.getStatusBarWindow().removeView(this);
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ if (!isShown) {
+ mPhoneStatusBar.getStatusBarWindow().removeView(QSCustomizer.this);
+ }
}
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- if (!isShown) {
- mPhoneStatusBar.getStatusBarWindow().removeView(this);
- }
- }
-
- @Override
- public void onAnimationStart(Animator animation) {
- // Don't care.
- }
-
- @Override
- public void onAnimationRepeat(Animator animation) {
- // Don't care.
- }
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index fb3818c..d9b3b3f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -24,7 +24,6 @@
import android.support.v7.widget.RecyclerView.State;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.support.v7.widget.helper.ItemTouchHelper;
-import android.support.v7.widget.helper.ItemTouchHelper.Callback;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -52,6 +51,7 @@
private final Context mContext;
private final List<TileInfo> mTiles = new ArrayList<>();
+ private final ItemTouchHelper mItemTouchHelper;
private int mDividerIndex;
private List<String> mCurrentSpecs;
private List<TileInfo> mOtherTiles;
@@ -61,6 +61,7 @@
public TileAdapter(Context context) {
mContext = context;
+ mItemTouchHelper = new ItemTouchHelper(mCallbacks);
setHasStableIds(true);
}
@@ -69,8 +70,8 @@
return mTiles.get(position) != null ? mAllTiles.indexOf(mTiles.get(position)) : -1;
}
- public Callback getCallback() {
- return mCallbacks;
+ public ItemTouchHelper getItemTouchHelper() {
+ return mItemTouchHelper;
}
public ItemDecoration getItemDecoration() {
@@ -104,7 +105,10 @@
mOtherTiles = new ArrayList<TileInfo>(mAllTiles);
mTiles.clear();
for (int i = 0; i < mCurrentSpecs.size(); i++) {
- mTiles.add(getAndRemoveOther(mCurrentSpecs.get(i)));
+ final TileInfo tile = getAndRemoveOther(mCurrentSpecs.get(i));
+ if (tile != null) {
+ mTiles.add(tile);
+ }
}
mTiles.add(null);
mTiles.addAll(mOtherTiles);
@@ -148,7 +152,7 @@
}
@Override
- public void onBindViewHolder(Holder holder, int position) {
+ public void onBindViewHolder(final Holder holder, int position) {
if (holder.getItemViewType() == TYPE_EDIT) return;
TileInfo info = mTiles.get(position);
@@ -166,6 +170,8 @@
super(itemView);
if (itemView instanceof FrameLayout) {
mTileView = (QSTileView) ((FrameLayout) itemView).getChildAt(0);
+ mTileView.setBackground(null);
+ mTileView.getIcon().disableAnimation();
}
}
@@ -266,15 +272,10 @@
int from = viewHolder.getAdapterPosition();
int to = target.getAdapterPosition();
if (to > mDividerIndex) {
- if (from < mDividerIndex) {
- to = mDividerIndex;
- } else {
+ if (from >= mDividerIndex) {
return false;
}
}
- if (target.getItemViewType() == TYPE_EDIT && from < mDividerIndex) {
- to++;
- }
move(from, to, mTiles);
mDividerIndex = mTiles.indexOf(null);
notifyItemMoved(from, to);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index 5c34ceb..d95d3ef 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -16,6 +16,7 @@
package com.android.systemui.qs.customize;
+import android.Manifest.permission;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
@@ -32,6 +33,7 @@
import com.android.systemui.qs.QSTile.DrawableIcon;
import com.android.systemui.qs.external.CustomTile;
import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.tuner.TunerService;
import java.util.ArrayList;
import java.util.Collection;
@@ -53,9 +55,8 @@
}
private void addSystemTiles(QSTileHost host) {
- boolean hasColorMod = host.getDisplayController().isEnabled();
String possible = mContext.getString(R.string.quick_settings_tiles_default)
- + ",hotspot,inversion,saver,work,cast" + (hasColorMod ? ",colors" : "");
+ + ",hotspot,inversion,saver,work,cast,night";
String[] possibleTiles = possible.split(",");
final Handler qsHandler = new Handler(host.getLooper());
final Handler mainHandler = new Handler(Looper.getMainLooper());
@@ -87,7 +88,12 @@
qsHandler.post(new Runnable() {
@Override
public void run() {
- new QueryTilesTask().execute();
+ mainHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ new QueryTilesTask().execute();
+ }
+ });
}
});
}
@@ -132,6 +138,9 @@
ComponentName componentName = new ComponentName(packageName, info.serviceInfo.name);
String spec = CustomTile.toSpec(componentName);
Drawable icon = info.serviceInfo.loadIcon(pm);
+ if (!permission.BIND_QUICK_SETTINGS_TILE.equals(info.serviceInfo.permission)) {
+ continue;
+ }
if (icon != null) {
icon.mutate();
icon.setTint(mContext.getColor(android.R.color.white));
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 3cd9e67..0709992 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -15,13 +15,18 @@
*/
package com.android.systemui.qs.external;
+import android.app.ActivityManager;
import android.content.ComponentName;
+import android.content.Intent;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.graphics.drawable.Drawable;
+import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
+import android.provider.Settings;
import android.service.quicksettings.IQSTileService;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
@@ -156,8 +161,22 @@
}
@Override
- protected void handleUserSwitch(int newUserId) {
- super.handleUserSwitch(newUserId);
+ public Intent getLongClickIntent() {
+ Intent i = new Intent(TileService.ACTION_QS_TILE_PREFERENCES);
+ i.setPackage(mComponent.getPackageName());
+ i = resolveIntent(i);
+ if (i != null) {
+ return i;
+ }
+ return new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).setData(
+ Uri.fromParts("package", mComponent.getPackageName(), null));
+ }
+
+ private Intent resolveIntent(Intent i) {
+ ResolveInfo result = mContext.getPackageManager().resolveActivityAsUser(i, 0,
+ ActivityManager.getCurrentUser());
+ return result != null ? new Intent(TileService.ACTION_QS_TILE_PREFERENCES)
+ .setClassName(result.activityInfo.packageName, result.activityInfo.name) : null;
}
@Override
@@ -184,10 +203,6 @@
}
@Override
- protected void handleLongClick() {
- }
-
- @Override
protected void handleUpdateState(State state, Object arg) {
Drawable drawable = mTile.getIcon().loadDrawable(mContext);
int color = mContext.getColor(getColor(mTile.getState()));
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 5222e61..89f1985b 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.provider.Settings;
import android.provider.Settings.Global;
import com.android.internal.logging.MetricsLogger;
@@ -32,9 +33,11 @@
/** Quick settings tile: Airplane mode **/
public class AirplaneModeTile extends QSTile<QSTile.BooleanState> {
private final AnimationIcon mEnable =
- new AnimationIcon(R.drawable.ic_signal_airplane_enable_animation);
+ new AnimationIcon(R.drawable.ic_signal_airplane_enable_animation,
+ R.drawable.ic_signal_airplane_disable);
private final AnimationIcon mDisable =
- new AnimationIcon(R.drawable.ic_signal_airplane_disable_animation);
+ new AnimationIcon(R.drawable.ic_signal_airplane_disable_animation,
+ R.drawable.ic_signal_airplane_enable);
private final GlobalSetting mSetting;
private boolean mListening;
@@ -68,6 +71,11 @@
}
@Override
+ public Intent getLongClickIntent() {
+ return new Intent(Settings.ACTION_AIRPLANE_MODE_SETTINGS);
+ }
+
+ @Override
protected void handleUpdateState(BooleanState state, Object arg) {
final int value = arg instanceof Integer ? (Integer)arg : mSetting.getValue();
final boolean airplaneMode = value != 0;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
index 6a9d826..2e87525 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
@@ -15,8 +15,10 @@
*/
package com.android.systemui.qs.tiles;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.text.SpannableStringBuilder;
@@ -24,6 +26,8 @@
import android.text.style.RelativeSizeSpan;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.View.OnAttachStateChangeListener;
+import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Checkable;
import android.widget.ImageView;
@@ -47,6 +51,7 @@
private int mLevel;
private boolean mPowerSave;
private boolean mCharging;
+ private boolean mDetailShown;
public BatteryTile(Host host) {
super(host);
@@ -91,6 +96,11 @@
}
@Override
+ public Intent getLongClickIntent() {
+ return new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
+ }
+
+ @Override
protected void handleClick() {
showDetail(true);
}
@@ -105,6 +115,12 @@
public Drawable getDrawable(Context context) {
return mDrawable;
}
+
+ @Override
+ public int getPadding() {
+ return mHost.getContext().getResources().getDimensionPixelSize(
+ R.dimen.qs_battery_padding);
+ }
};
state.label = percentage;
}
@@ -114,20 +130,21 @@
mLevel = level;
mCharging = charging;
refreshState((Integer) level);
- if (mBatteryDetail.mCurrentView != null) {
- mBatteryDetail.bindView();
+ if (mDetailShown) {
+ mBatteryDetail.postBindView();
}
}
@Override
public void onPowerSaveChanged(boolean isPowerSave) {
mPowerSave = isPowerSave;
- if (mBatteryDetail.mCurrentView != null) {
- mBatteryDetail.bindView();
+ if (mDetailShown) {
+ mBatteryDetail.postBindView();
}
}
- private final class BatteryDetail implements DetailAdapter, View.OnClickListener {
+ private final class BatteryDetail implements DetailAdapter, OnClickListener,
+ OnAttachStateChangeListener {
private final BatteryMeterDrawable mDrawable = new BatteryMeterDrawable(mHost.getContext(),
new Handler(), mHost.getContext().getColor(R.color.batterymeter_frame_color));
private View mCurrentView;
@@ -149,26 +166,40 @@
false);
}
mCurrentView = convertView;
+ mCurrentView.addOnAttachStateChangeListener(this);
bindView();
return convertView;
}
+ private void postBindView() {
+ if (mCurrentView == null) return;
+ mCurrentView.post(new Runnable() {
+ @Override
+ public void run() {
+ bindView();
+ }
+ });
+ }
+
private void bindView() {
+ if (mCurrentView == null) {
+ return;
+ }
mDrawable.onBatteryLevelChanged(100, false, false);
mDrawable.onPowerSaveChanged(true);
mDrawable.disableShowPercent();
((ImageView) mCurrentView.findViewById(android.R.id.icon)).setImageDrawable(mDrawable);
Checkable checkbox = (Checkable) mCurrentView.findViewById(android.R.id.toggle);
checkbox.setChecked(mPowerSave);
- if (mCharging) {
- BatteryInfo.getBatteryInfo(mContext, new BatteryInfo.Callback() {
- @Override
- public void onBatteryInfoLoaded(BatteryInfo info) {
- if (mCurrentView != null) {
- bindBatteryInfo(info);
- }
+ BatteryInfo.getBatteryInfo(mContext, new BatteryInfo.Callback() {
+ @Override
+ public void onBatteryInfoLoaded(BatteryInfo info) {
+ if (mCurrentView != null) {
+ bindBatteryInfo(info);
}
- });
+ }
+ });
+ if (mCharging) {
((TextView) mCurrentView.findViewById(android.R.id.title)).setText(
R.string.battery_detail_charging_summary);
mCurrentView.findViewById(android.R.id.icon).setVisibility(View.INVISIBLE);
@@ -222,5 +253,29 @@
public int getMetricsCategory() {
return MetricsEvent.QS_BATTERY_DETAIL;
}
+
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ if (!mDetailShown) {
+ mDetailShown = true;
+ v.getContext().registerReceiver(mReceiver,
+ new IntentFilter(Intent.ACTION_TIME_TICK));
+ }
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ if (mDetailShown) {
+ mDetailShown = false;
+ v.getContext().unregisterReceiver(mReceiver);
+ }
+ }
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ postBindView();
+ }
+ };
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index c4b7944..80f667c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -78,6 +78,11 @@
}
@Override
+ public Intent getLongClickIntent() {
+ return new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
+ }
+
+ @Override
protected void handleClick() {
if (!mController.canConfigBluetooth()) {
mHost.startActivityDismissingKeyguard(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 15e082a..e0ad002 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -86,6 +86,11 @@
}
@Override
+ public Intent getLongClickIntent() {
+ return new Intent(Settings.ACTION_CAST_SETTINGS);
+ }
+
+ @Override
protected void handleClick() {
if (mKeyguard.isSecure() && !mKeyguard.canSkipBouncer()) {
mHost.startRunnableDismissingKeyguard(new Runnable() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 15617c7f..5f87741 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -37,7 +37,7 @@
/** Quick settings tile: Cellular **/
public class CellularTile extends QSTile<QSTile.SignalState> {
- private static final Intent CELLULAR_SETTINGS = new Intent().setComponent(new ComponentName(
+ static final Intent CELLULAR_SETTINGS = new Intent().setComponent(new ComponentName(
"com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity"));
private final NetworkController mController;
@@ -78,6 +78,11 @@
}
@Override
+ public Intent getLongClickIntent() {
+ return CELLULAR_SETTINGS;
+ }
+
+ @Override
protected void handleClick() {
MetricsLogger.action(mContext, getMetricsCategory());
if (mDataController.isMobileDataSupported()) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index e98734c..a608316 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -16,6 +16,8 @@
package com.android.systemui.qs.tiles;
+import android.content.Intent;
+import android.provider.Settings;
import android.provider.Settings.Secure;
import com.android.internal.logging.MetricsLogger;
@@ -28,9 +30,11 @@
public class ColorInversionTile extends QSTile<QSTile.BooleanState> {
private final AnimationIcon mEnable
- = new AnimationIcon(R.drawable.ic_invert_colors_enable_animation);
+ = new AnimationIcon(R.drawable.ic_invert_colors_enable_animation,
+ R.drawable.ic_invert_colors_disable);
private final AnimationIcon mDisable
- = new AnimationIcon(R.drawable.ic_invert_colors_disable_animation);
+ = new AnimationIcon(R.drawable.ic_invert_colors_disable_animation,
+ R.drawable.ic_invert_colors_enable);
private final SecureSetting mSetting;
private boolean mListening;
@@ -70,6 +74,11 @@
}
@Override
+ public Intent getLongClickIntent() {
+ return new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
+ }
+
+ @Override
protected void handleClick() {
MetricsLogger.action(mContext, getMetricsCategory(), !mState.value);
mSetting.setValue(mState.value ? 0 : 1);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
index c6a98b4..fa235d3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
@@ -14,6 +14,7 @@
package com.android.systemui.qs.tiles;
+import android.content.Intent;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
@@ -44,6 +45,11 @@
}
@Override
+ public Intent getLongClickIntent() {
+ return CellularTile.CELLULAR_SETTINGS;
+ }
+
+ @Override
protected void handleClick() {
mState.value = !mDataSaverController.isDataSaverEnabled();
mDataSaverController.setDataSaverEnabled(mState.value);
@@ -55,8 +61,8 @@
state.value = arg instanceof Boolean ? (Boolean) arg
: mDataSaverController.isDataSaverEnabled();
state.label = mContext.getString(R.string.data_saver);
- state.contentDescription = mContext.getString(state.value ?
- R.string.accessibility_data_saver_on : R.string.accessibility_data_saver_off);
+ state.contentDescription = mContext.getString(state.value
+ ? R.string.accessibility_data_saver_on : R.string.accessibility_data_saver_off);
state.icon = ResourceIcon.get(state.value ? R.drawable.ic_data_saver
: R.drawable.ic_data_saver_off);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 29ca06b..8b22868 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -29,11 +29,13 @@
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.ViewGroup;
+import android.widget.Toast;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.Prefs;
import com.android.systemui.R;
+import com.android.systemui.SysUIToast;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.volume.ZenModePanel;
@@ -54,9 +56,11 @@
ResourceIcon.get(R.drawable.ic_qs_dnd_on_total_silence);
private final AnimationIcon mDisable =
- new AnimationIcon(R.drawable.ic_dnd_disable_animation);
+ new AnimationIcon(R.drawable.ic_dnd_disable_animation,
+ R.drawable.ic_qs_dnd_off);
private final AnimationIcon mDisableTotalSilence =
- new AnimationIcon(R.drawable.ic_dnd_total_silence_disable_animation);
+ new AnimationIcon(R.drawable.ic_dnd_total_silence_disable_animation,
+ R.drawable.ic_qs_dnd_off);
private final ZenModeController mController;
private final DndDetailAdapter mDetailAdapter;
@@ -99,7 +103,20 @@
}
@Override
+ public Intent getLongClickIntent() {
+ return ZEN_SETTINGS;
+ }
+
+ @Override
public void handleClick() {
+ if (mController.isVolumeRestricted()) {
+ // Collapse the panels, so the user can see the toast.
+ mHost.collapsePanels();
+ SysUIToast.makeText(mContext, mContext.getString(
+ com.android.internal.R.string.error_message_change_not_allowed),
+ Toast.LENGTH_LONG).show();
+ return;
+ }
MetricsLogger.action(mContext, getMetricsCategory(), !mState.value);
if (mState.value) {
mController.setZen(Global.ZEN_MODE_OFF, null, TAG);
@@ -116,8 +133,7 @@
final boolean newValue = zen != Global.ZEN_MODE_OFF;
final boolean valueChanged = state.value != newValue;
state.value = newValue;
- state.disabledByPolicy = mController.isVolumeRestricted();
- checkIfRestrictionEnforced(state, UserManager.DISALLOW_ADJUST_VOLUME);
+ checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_ADJUST_VOLUME);
switch (zen) {
case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index f06634e..a01a9a5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -17,7 +17,11 @@
package com.android.systemui.qs.tiles;
import android.app.ActivityManager;
-
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.provider.MediaStore;
+import android.text.SpannableStringBuilder;
+import android.text.style.ForegroundColorSpan;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
@@ -29,9 +33,11 @@
FlashlightController.FlashlightListener {
private final AnimationIcon mEnable
- = new AnimationIcon(R.drawable.ic_signal_flashlight_enable_animation);
+ = new AnimationIcon(R.drawable.ic_signal_flashlight_enable_animation,
+ R.drawable.ic_signal_flashlight_disable);
private final AnimationIcon mDisable
- = new AnimationIcon(R.drawable.ic_signal_flashlight_disable_animation);
+ = new AnimationIcon(R.drawable.ic_signal_flashlight_disable_animation,
+ R.drawable.ic_signal_flashlight_enable);
private final FlashlightController mFlashlightController;
public FlashlightTile(Host host) {
@@ -60,6 +66,16 @@
}
@Override
+ public Intent getLongClickIntent() {
+ return new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return mFlashlightController.hasFlashlight();
+ }
+
+ @Override
protected void handleClick() {
if (ActivityManager.isUserAMonkey()) {
return;
@@ -72,9 +88,19 @@
@Override
protected void handleUpdateState(BooleanState state, Object arg) {
- // TODO: Flashlight available handling...
-// state.visible = mFlashlightController.isAvailable();
state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label);
+ if (!mFlashlightController.isAvailable()) {
+ Drawable icon = mHost.getContext().getDrawable(R.drawable.ic_signal_flashlight_disable);
+ final int disabledColor = mHost.getContext().getColor(R.color.qs_tile_tint_unavailable);
+ icon.setTint(disabledColor);
+ state.icon = new DrawableIcon(icon);
+ state.label = new SpannableStringBuilder().append(state.label,
+ new ForegroundColorSpan(disabledColor),
+ SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE);
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_flashlight_unavailable);
+ return;
+ }
if (arg instanceof Boolean) {
boolean value = (Boolean) arg;
if (value == state.value) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 943b502..da93120 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -16,8 +16,10 @@
package com.android.systemui.qs.tiles;
+import android.content.Intent;
import android.os.UserManager;
+import android.provider.Settings;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
@@ -27,9 +29,11 @@
/** Quick settings tile: Hotspot **/
public class HotspotTile extends QSTile<QSTile.BooleanState> {
private final AnimationIcon mEnable =
- new AnimationIcon(R.drawable.ic_hotspot_enable_animation);
+ new AnimationIcon(R.drawable.ic_hotspot_enable_animation,
+ R.drawable.ic_hotspot_disable);
private final AnimationIcon mDisable =
- new AnimationIcon(R.drawable.ic_hotspot_disable_animation);
+ new AnimationIcon(R.drawable.ic_hotspot_disable_animation,
+ R.drawable.ic_hotspot_enable);
private final HotspotController mController;
private final Callback mCallback = new Callback();
@@ -58,6 +62,11 @@
}
@Override
+ public Intent getLongClickIntent() {
+ return new Intent(Settings.ACTION_WIRELESS_SETTINGS);
+ }
+
+ @Override
protected void handleClick() {
final boolean isEnabled = (Boolean) mState.value;
MetricsLogger.action(mContext, getMetricsCategory(), !isEnabled);
@@ -68,8 +77,7 @@
protected void handleUpdateState(BooleanState state, Object arg) {
state.label = mContext.getString(R.string.quick_settings_hotspot_label);
- state.disabledByPolicy = mController.isTetheringAllowed();
- checkIfRestrictionEnforced(state, UserManager.DISALLOW_CONFIG_TETHERING);
+ checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_CONFIG_TETHERING);
if (arg instanceof Boolean) {
state.value = (boolean) arg;
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
index bdf95d8..bb5ff8e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
@@ -92,6 +92,11 @@
}
@Override
+ public Intent getLongClickIntent() {
+ return null;
+ }
+
+ @Override
protected void handleLongClick() {
sendIntent("long-click", mOnLongClick, mOnLongClickUri);
}
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 9f41f9a..b1d1c77 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -16,8 +16,10 @@
package com.android.systemui.qs.tiles;
+import android.content.Intent;
import android.os.UserManager;
+import android.provider.Settings;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
@@ -30,9 +32,11 @@
public class LocationTile extends QSTile<QSTile.BooleanState> {
private final AnimationIcon mEnable =
- new AnimationIcon(R.drawable.ic_signal_location_enable_animation);
+ new AnimationIcon(R.drawable.ic_signal_location_enable_animation,
+ R.drawable.ic_signal_location_disable);
private final AnimationIcon mDisable =
- new AnimationIcon(R.drawable.ic_signal_location_disable_animation);
+ new AnimationIcon(R.drawable.ic_signal_location_disable_animation,
+ R.drawable.ic_signal_location_enable);
private final LocationController mController;
private final KeyguardMonitor mKeyguard;
@@ -61,6 +65,11 @@
}
@Override
+ public Intent getLongClickIntent() {
+ return new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
+ }
+
+ @Override
protected void handleClick() {
if (mKeyguard.isSecure() && mKeyguard.isShowing()) {
mHost.startRunnableDismissingKeyguard(new Runnable() {
@@ -87,8 +96,7 @@
// bug is fixed, this should be reverted to only hiding it on secure lock screens:
// state.visible = !(mKeyguard.isSecure() && mKeyguard.isShowing());
state.value = locationEnabled;
- state.disabledByPolicy = mController.isUserLocationRestricted();
- checkIfRestrictionEnforced(state, UserManager.DISALLOW_SHARE_LOCATION);
+ checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_SHARE_LOCATION);
if (locationEnabled) {
state.icon = mEnable;
state.label = mContext.getString(R.string.quick_settings_location_label);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index c94cf5a..d80ca10 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -17,8 +17,10 @@
package com.android.systemui.qs.tiles;
import android.content.Context;
+import android.content.Intent;
import android.content.res.Configuration;
+import android.provider.Settings;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
@@ -29,14 +31,18 @@
/** Quick settings tile: Rotation **/
public class RotationLockTile extends QSTile<QSTile.BooleanState> {
private final AnimationIcon mPortraitToAuto
- = new AnimationIcon(R.drawable.ic_portrait_to_auto_rotate_animation);
+ = new AnimationIcon(R.drawable.ic_portrait_to_auto_rotate_animation,
+ R.drawable.ic_portrait_from_auto_rotate);
private final AnimationIcon mAutoToPortrait
- = new AnimationIcon(R.drawable.ic_portrait_from_auto_rotate_animation);
+ = new AnimationIcon(R.drawable.ic_portrait_from_auto_rotate_animation,
+ R.drawable.ic_portrait_to_auto_rotate);
private final AnimationIcon mLandscapeToAuto
- = new AnimationIcon(R.drawable.ic_landscape_to_auto_rotate_animation);
+ = new AnimationIcon(R.drawable.ic_landscape_to_auto_rotate_animation,
+ R.drawable.ic_landscape_from_auto_rotate);
private final AnimationIcon mAutoToLandscape
- = new AnimationIcon(R.drawable.ic_landscape_from_auto_rotate_animation);
+ = new AnimationIcon(R.drawable.ic_landscape_from_auto_rotate_animation,
+ R.drawable.ic_landscape_to_auto_rotate);
private final RotationLockController mController;
@@ -60,6 +66,11 @@
}
@Override
+ public Intent getLongClickIntent() {
+ return new Intent(Settings.ACTION_DISPLAY_SETTINGS);
+ }
+
+ @Override
protected void handleClick() {
if (mController == null) return;
MetricsLogger.action(mContext, getMetricsCategory(), !mState.value);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
index 33befd0..fcf758b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
@@ -103,6 +103,11 @@
mAvatar.setDisabled(disabled);
}
+ public void setEnabled(boolean enabled) {
+ mName.setEnabled(enabled);
+ mAvatar.setDisabled(!enabled);
+ }
+
@Override
protected void onFinishInflate() {
mAvatar = (UserAvatarView) findViewById(R.id.user_picture);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
index 2c8a478..da98762 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
@@ -82,6 +82,9 @@
}
v.setActivated(item.isCurrent);
v.setDisabledByAdmin(item.isDisabledByAdmin);
+ if (!item.isSwitchToEnabled) {
+ v.setEnabled(false);
+ }
v.setTag(item);
return v;
}
@@ -94,7 +97,7 @@
final Intent intent = RestrictedLockUtils.getShowAdminSupportDetailsIntent(
mContext, tag.enforcedAdmin);
mController.startActivity(intent);
- } else {
+ } else if (tag.isSwitchToEnabled) {
MetricsLogger.action(mContext, MetricsEvent.QS_SWITCH_USER);
switchTo(tag);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
index ba7ea4d..f1066c1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
@@ -16,7 +16,9 @@
package com.android.systemui.qs.tiles;
import android.content.Context;
+import android.content.Intent;
import android.graphics.drawable.Drawable;
+import android.provider.Settings;
import android.util.Pair;
import com.android.internal.logging.MetricsProto.MetricsEvent;
@@ -42,6 +44,11 @@
}
@Override
+ public Intent getLongClickIntent() {
+ return new Intent(Settings.ACTION_USER_SETTINGS);
+ }
+
+ @Override
protected void handleClick() {
showDetail(true);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 7a58f15..7ee795f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -93,6 +93,11 @@
}
@Override
+ public Intent getLongClickIntent() {
+ return WIFI_SETTINGS;
+ }
+
+ @Override
protected void handleSecondaryClick() {
// Secondary clicks are header clicks, just toggle.
mState.copyTo(mStateBeforeClick);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
index 053a98a..421a2cf 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
@@ -16,6 +16,8 @@
package com.android.systemui.qs.tiles;
+import android.content.Intent;
+import android.provider.Settings;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
@@ -26,9 +28,11 @@
public class WorkModeTile extends QSTile<QSTile.BooleanState> implements
ManagedProfileController.Callback {
private final AnimationIcon mEnable =
- new AnimationIcon(R.drawable.ic_signal_workmode_enable_animation);
+ new AnimationIcon(R.drawable.ic_signal_workmode_enable_animation,
+ R.drawable.ic_signal_workmode_disable);
private final AnimationIcon mDisable =
- new AnimationIcon(R.drawable.ic_signal_workmode_disable_animation);
+ new AnimationIcon(R.drawable.ic_signal_workmode_disable_animation,
+ R.drawable.ic_signal_workmode_enable);
private final ManagedProfileController mProfileController;
@@ -52,6 +56,11 @@
}
@Override
+ public Intent getLongClickIntent() {
+ return new Intent(Settings.ACTION_SYNC_SETTINGS);
+ }
+
+ @Override
public void handleClick() {
MetricsLogger.action(mContext, getMetricsCategory(), !mState.value);
mProfileController.setWorkModeEnabled(!mState.value);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index f5ae351..54bf68b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -513,8 +513,9 @@
* Handle Recents activity visibility changed.
*/
public final void onBusEvent(final RecentsVisibilityChangedEvent event) {
- int processUser = event.systemServicesProxy.getProcessUser();
- if (event.systemServicesProxy.isSystemUser(processUser)) {
+ SystemServicesProxy ssp = Recents.getSystemServices();
+ int processUser = ssp.getProcessUser();
+ if (ssp.isSystemUser(processUser)) {
mImpl.onVisibilityChanged(event.applicationContext, event.visible);
} else {
postToSystemUser(new Runnable() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index c2a6108..cd1a27f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -43,6 +43,7 @@
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.AppWidgetProviderChangedEvent;
import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
+import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
import com.android.systemui.recents.events.activity.DebugFlagsChangedEvent;
import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
@@ -54,7 +55,7 @@
import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
import com.android.systemui.recents.events.activity.LaunchTaskSucceededEvent;
import com.android.systemui.recents.events.activity.ShowHistoryEvent;
-import com.android.systemui.recents.events.activity.TaskStackUpdatedEvent;
+import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
@@ -96,6 +97,7 @@
private long mLastTabKeyEventTime;
private boolean mFinishedOnStartup;
private boolean mIgnoreAltTabRelease;
+ private boolean mIsVisible;
// Top level views
private RecentsView mRecentsView;
@@ -107,7 +109,7 @@
private RecentsAppWidgetHostView mSearchWidgetHostView;
// Runnables to finish the Recents activity
- private FinishRecentsRunnable mFinishLaunchHomeRunnable;
+ private Intent mHomeIntent;
// The trigger to automatically launch the current task
private int mFocusTimerDuration;
@@ -119,7 +121,7 @@
* last activity launch state. Generally we always launch home when we exit Recents rather than
* just finishing the activity since we don't know what is behind Recents in the task stack.
*/
- class FinishRecentsRunnable implements Runnable {
+ class LaunchHomeRunnable implements Runnable {
Intent mLaunchIntent;
ActivityOptions mOpts;
@@ -127,7 +129,7 @@
/**
* Creates a finish runnable that starts the specified intent.
*/
- public FinishRecentsRunnable(Intent launchIntent, ActivityOptions opts) {
+ public LaunchHomeRunnable(Intent launchIntent, ActivityOptions opts) {
mLaunchIntent = launchIntent;
mOpts = opts;
}
@@ -173,59 +175,6 @@
}
};
- /** Updates the set of recent tasks */
- void updateRecentsTasks() {
- // If AlternateRecentsComponent has preloaded a load plan, then use that to prevent
- // reconstructing the task stack
- RecentsTaskLoader loader = Recents.getTaskLoader();
- RecentsTaskLoadPlan plan = RecentsImpl.consumeInstanceLoadPlan();
- if (plan == null) {
- plan = loader.createLoadPlan(this);
- }
-
- // Start loading tasks according to the load plan
- RecentsConfiguration config = Recents.getConfiguration();
- RecentsActivityLaunchState launchState = config.getLaunchState();
- if (!plan.hasTasks()) {
- loader.preloadTasks(plan, -1, launchState.launchedFromHome);
- }
- RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
- loadOpts.runningTaskId = launchState.launchedToTaskId;
- loadOpts.numVisibleTasks = launchState.launchedNumVisibleTasks;
- loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails;
- loader.loadTasks(this, plan, loadOpts);
-
- TaskStack stack = plan.getTaskStack();
- mRecentsView.setTaskStack(stack);
-
- // Animate the SystemUI scrims into view
- Task launchTarget = stack.getLaunchTarget();
- int taskCount = stack.getTaskCount();
- int launchTaskIndexInStack = launchTarget != null
- ? stack.indexOfStackTask(launchTarget)
- : 0;
- boolean hasNavBarScrim = (taskCount > 0) && !config.hasTransposedNavBar;
- boolean animateNavBarScrim = !launchState.launchedWhileDocking;
- mScrimViews.prepareEnterRecentsAnimation(hasNavBarScrim, animateNavBarScrim);
-
- // Keep track of whether we launched from the nav bar button or via alt-tab
- if (launchState.launchedWithAltTab) {
- MetricsLogger.count(this, "overview_trigger_alttab", 1);
- } else {
- MetricsLogger.count(this, "overview_trigger_nav_btn", 1);
- }
- // Keep track of whether we launched from an app or from home
- if (launchState.launchedFromAppWithThumbnail) {
- MetricsLogger.count(this, "overview_source_app", 1);
- // If from an app, track the stack index of the app in the stack (for affiliated tasks)
- MetricsLogger.histogram(this, "overview_source_app_index", launchTaskIndexInStack);
- } else {
- MetricsLogger.count(this, "overview_source_home", 1);
- }
- // Keep track of the total stack task count
- MetricsLogger.histogram(this, "overview_task_count", taskCount);
- }
-
/**
* Dismisses the history view back into the stack view.
*/
@@ -294,12 +243,8 @@
void dismissRecentsToHome(boolean animateTaskViews, ActivityOptions overrideAnimation) {
DismissRecentsToHomeAnimationStarted dismissEvent =
new DismissRecentsToHomeAnimationStarted(animateTaskViews);
- if (overrideAnimation != null) {
- dismissEvent.addPostAnimationCallback(new FinishRecentsRunnable(
- mFinishLaunchHomeRunnable.mLaunchIntent, overrideAnimation));
- } else {
- dismissEvent.addPostAnimationCallback(mFinishLaunchHomeRunnable);
- }
+ dismissEvent.addPostAnimationCallback(new LaunchHomeRunnable(mHomeIntent,
+ overrideAnimation));
dismissEvent.addPostAnimationCallback(new Runnable() {
@Override
public void run() {
@@ -348,6 +293,7 @@
// Set the Recents layout
setContentView(R.layout.recents);
+ takeKeyEvents(true);
mRecentsView = (RecentsView) findViewById(R.id.recents_view);
mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
@@ -365,11 +311,10 @@
});
// Create the home intent runnable
- Intent homeIntent = new Intent(Intent.ACTION_MAIN, null);
- homeIntent.addCategory(Intent.CATEGORY_HOME);
- homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+ mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
+ mHomeIntent.addCategory(Intent.CATEGORY_HOME);
+ mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
- mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent, null);
// Bind the search app widget when we first start up
if (RecentsDebugFlags.Static.EnableSearchBar) {
@@ -386,45 +331,12 @@
}
@Override
- protected void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
- setIntent(intent);
- }
-
- @Override
protected void onStart() {
super.onStart();
- // Update the recent tasks
- updateRecentsTasks();
-
- // If this is a new instance from a configuration change, then we have to manually trigger
- // the enter animation state, or if recents was relaunched by AM, without going through
- // the normal mechanisms
- RecentsConfiguration config = Recents.getConfiguration();
- RecentsActivityLaunchState launchState = config.getLaunchState();
- boolean wasLaunchedByAm = !launchState.launchedFromHome &&
- !launchState.launchedFromAppWithThumbnail;
- if (launchState.launchedHasConfigurationChanged || wasLaunchedByAm) {
- EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
- }
-
// Notify that recents is now visible
- SystemServicesProxy ssp = Recents.getSystemServices();
- EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, ssp, true));
-
+ EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, true));
MetricsLogger.visible(this, MetricsEvent.OVERVIEW_ACTIVITY);
-
- mRecentsView.getViewTreeObserver().addOnPreDrawListener(
- new ViewTreeObserver.OnPreDrawListener() {
-
- @Override
- public boolean onPreDraw() {
- mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
- EventBus.getDefault().post(new RecentsDrawnEvent());
- return true;
- }
- });
}
@Override
@@ -434,26 +346,91 @@
}
@Override
- protected void onPause() {
- super.onPause();
+ protected void onResume() {
+ super.onResume();
- // Stop the fast-toggle dozer
- mIterateTrigger.stopDozing();
+ // If the Recents component has preloaded a load plan, then use that to prevent
+ // reconstructing the task stack
+ RecentsTaskLoader loader = Recents.getTaskLoader();
+ RecentsTaskLoadPlan loadPlan = RecentsImpl.consumeInstanceLoadPlan();
+ if (loadPlan == null) {
+ loadPlan = loader.createLoadPlan(this);
+ }
+
+ // Start loading tasks according to the load plan
+ RecentsConfiguration config = Recents.getConfiguration();
+ RecentsActivityLaunchState launchState = config.getLaunchState();
+ if (!loadPlan.hasTasks()) {
+ loader.preloadTasks(loadPlan, -1, launchState.launchedFromHome);
+ }
+
+ RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
+ loadOpts.runningTaskId = launchState.launchedToTaskId;
+ loadOpts.numVisibleTasks = launchState.launchedNumVisibleTasks;
+ loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails;
+ loader.loadTasks(this, loadPlan, loadOpts);
+ TaskStack stack = loadPlan.getTaskStack();
+ mRecentsView.onResume(mIsVisible, stack);
+
+ // Animate the SystemUI scrims into view
+ Task launchTarget = stack.getLaunchTarget();
+ int taskCount = stack.getTaskCount();
+ int launchTaskIndexInStack = launchTarget != null
+ ? stack.indexOfStackTask(launchTarget)
+ : 0;
+ boolean hasNavBarScrim = (taskCount > 0) && !config.hasTransposedNavBar;
+ boolean animateNavBarScrim = !launchState.launchedWhileDocking;
+ mScrimViews.prepareEnterRecentsAnimation(hasNavBarScrim, animateNavBarScrim);
+
+ // If this is a new instance from a configuration change, then we have to manually trigger
+ // the enter animation state, or if recents was relaunched by AM, without going through
+ // the normal mechanisms
+ boolean wasLaunchedByAm = !launchState.launchedFromHome &&
+ !launchState.launchedFromApp;
+ if (launchState.launchedHasConfigurationChanged || wasLaunchedByAm) {
+ EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
+ }
+
+ mRecentsView.getViewTreeObserver().addOnPreDrawListener(
+ new ViewTreeObserver.OnPreDrawListener() {
+
+ @Override
+ public boolean onPreDraw() {
+ mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
+ EventBus.getDefault().post(new RecentsDrawnEvent());
+ return true;
+ }
+ });
+
+ // Keep track of whether we launched from the nav bar button or via alt-tab
+ if (launchState.launchedWithAltTab) {
+ MetricsLogger.count(this, "overview_trigger_alttab", 1);
+ } else {
+ MetricsLogger.count(this, "overview_trigger_nav_btn", 1);
+ }
+
+ // Keep track of whether we launched from an app or from home
+ if (launchState.launchedFromApp) {
+ MetricsLogger.count(this, "overview_source_app", 1);
+ // If from an app, track the stack index of the app in the stack (for affiliated tasks)
+ MetricsLogger.histogram(this, "overview_source_app_index", launchTaskIndexInStack);
+ } else {
+ MetricsLogger.count(this, "overview_source_home", 1);
+ }
+
+ // Keep track of the total stack task count
+ MetricsLogger.histogram(this, "overview_task_count", taskCount);
+
+ // After we have resumed, set the visible state until the next onStop() call
+ mIsVisible = true;
}
@Override
- protected void onStop() {
- super.onStop();
+ protected void onPause() {
+ super.onPause();
- // Reset some states
mIgnoreAltTabRelease = false;
- if (RecentsDebugFlags.Static.EnableHistory && mRecentsView.isHistoryVisible()) {
- EventBus.getDefault().send(new HideHistoryEvent(false /* animate */));
- }
-
- // Notify that recents is now hidden
- SystemServicesProxy ssp = Recents.getSystemServices();
- EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, ssp, false));
+ mIterateTrigger.stopDozing();
// Workaround for b/22542869, if the RecentsActivity is started again, but without going
// through SystemUI, we need to reset the config launch flags to ensure that we do not
@@ -461,7 +438,20 @@
RecentsConfiguration config = Recents.getConfiguration();
RecentsActivityLaunchState launchState = config.getLaunchState();
launchState.reset();
+ }
+ @Override
+ protected void onStop() {
+ super.onStop();
+
+ // Only hide the history if Recents is completely hidden
+ if (RecentsDebugFlags.Static.EnableHistory && mRecentsView.isHistoryVisible()) {
+ EventBus.getDefault().send(new HideHistoryEvent(false /* animate */));
+ }
+
+ // Notify that recents is now hidden
+ mIsVisible = false;
+ EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, false));
MetricsLogger.hidden(this, MetricsEvent.OVERVIEW_ACTIVITY);
}
@@ -528,17 +518,23 @@
@Override
public void onMultiWindowChanged(boolean inMultiWindow) {
super.onMultiWindowChanged(inMultiWindow);
- if (!inMultiWindow) {
- RecentsTaskLoader loader = Recents.getTaskLoader();
- RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options();
- launchOpts.loadIcons = false;
- launchOpts.loadThumbnails = false;
- launchOpts.onlyLoadForCache = true;
- RecentsTaskLoadPlan loadPlan = loader.createLoadPlan(this);
- loader.preloadTasks(loadPlan, -1, false);
- loader.loadTasks(this, loadPlan, launchOpts);
- EventBus.getDefault().send(new TaskStackUpdatedEvent(loadPlan.getTaskStack()));
- }
+ EventBus.getDefault().send(new ConfigurationChangedEvent());
+
+ // Reload the task stack completely
+ RecentsConfiguration config = Recents.getConfiguration();
+ RecentsActivityLaunchState launchState = config.getLaunchState();
+ RecentsTaskLoader loader = Recents.getTaskLoader();
+ RecentsTaskLoadPlan loadPlan = loader.createLoadPlan(this);
+ loader.preloadTasks(loadPlan, -1 /* topTaskId */, false /* isTopTaskHome */);
+
+ RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
+ loadOpts.numVisibleTasks = launchState.launchedNumVisibleTasks;
+ loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails;
+ loader.loadTasks(this, loadPlan, loadOpts);
+
+ mRecentsView.onResume(mIsVisible, loadPlan.getTaskStack());
+
+ EventBus.getDefault().send(new MultiWindowStateChangedEvent(inMultiWindow));
}
@Override
@@ -637,7 +633,7 @@
// Focus the next task
EventBus.getDefault().send(new FocusNextTaskViewEvent(timerIndicatorDuration));
- MetricsLogger.action(this, MetricsEvent.OVERVIEW_PAGE);
+ MetricsLogger.action(this, MetricsEvent.ACTION_OVERVIEW_PAGE);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
index aa1437b..ec4820a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
@@ -28,7 +28,8 @@
public class RecentsActivityLaunchState {
public boolean launchedWithAltTab;
- public boolean launchedFromAppWithThumbnail;
+ public boolean launchedFromApp;
+ public boolean launchedFromAppDocked;
public boolean launchedFromHome;
public boolean launchedFromSearchHome;
public boolean launchedReuseTaskStackViews;
@@ -42,7 +43,8 @@
public void reset() {
launchedFromHome = false;
launchedFromSearchHome = false;
- launchedFromAppWithThumbnail = false;
+ launchedFromApp = false;
+ launchedFromAppDocked = false;
launchedToTaskId = -1;
launchedWithAltTab = false;
launchedHasConfigurationChanged = false;
@@ -67,7 +69,7 @@
public int getInitialFocusTaskIndex(int numTasks) {
RecentsDebugFlags debugFlags = Recents.getDebugFlags();
RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
- if (launchedFromAppWithThumbnail) {
+ if (launchedFromApp) {
if (!launchState.launchedWithAltTab && debugFlags.isFastToggleRecentsEnabled()) {
// If fast toggling, focus the front most task so that the next tap will focus the
// N-1 task
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 9e43bb4..eec0411 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -69,7 +69,6 @@
public final int smallestWidth;
/** Misc **/
- public boolean useHardwareLayers;
public boolean fakeShadows;
public int svelteLevel;
public int searchBarSpaceHeightPx;
@@ -80,7 +79,6 @@
SystemServicesProxy ssp = Recents.getSystemServices();
Context appContext = context.getApplicationContext();
Resources res = appContext.getResources();
- useHardwareLayers = res.getBoolean(R.bool.config_recents_use_hardware_layers);
fakeShadows = res.getBoolean(R.bool.config_recents_fake_shadows);
svelteLevel = res.getInteger(R.integer.recents_svelte_level);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
index cd64323..6feda81 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
@@ -39,8 +39,8 @@
public static final boolean EnableAffiliatedTaskGroups = true;
// Enables the history
public static final boolean EnableHistory = false;
- // Overrides the Tuner flags and enables the fast toggle and timeout
- public static final boolean EnableFastToggleTimeoutOverride = true;
+ // Overrides the Tuner flags and enables the timeout
+ private static final boolean EnableFastToggleTimeout = false;
// Enables us to create mock recents tasks
public static final boolean EnableMockTasks = false;
@@ -54,9 +54,9 @@
public static final int MockTaskGroupsTaskCount = 12;
}
- private static final String KEY_DISABLE_FAST_TOGGLE = "overview_disable_fast_toggle_via_button";
+ private static final String KEY_ENABLE_PAGING = "overview_enable_paging";
- private boolean mDisableFastToggleRecents;
+ private boolean mEnablePaging;
/**
* We read the prefs once when we start the activity, then update them as the tuner changes
@@ -65,31 +65,32 @@
public RecentsDebugFlags(Context context) {
// Register all our flags, this will also call onTuningChanged() for each key, which will
// initialize the current state of each flag
- TunerService.get(context).addTunable(this, KEY_DISABLE_FAST_TOGGLE);
+ TunerService.get(context).addTunable(this, KEY_ENABLE_PAGING);
}
/**
* @return whether we are enabling fast toggling.
*/
public boolean isFastToggleRecentsEnabled() {
- // These checks EnableFastToggleTimeoutOverride
SystemServicesProxy ssp = Recents.getSystemServices();
- if (mDisableFastToggleRecents || ssp.hasFreeformWorkspaceSupport() || ssp.hasDockedTask()
- || ssp.isTouchExplorationEnabled()) {
+ if (ssp.hasFreeformWorkspaceSupport() || ssp.isTouchExplorationEnabled()) {
return false;
}
- if (Static.EnableFastToggleTimeoutOverride) {
- return true;
- }
- return true;
+ return Static.EnableFastToggleTimeout;
+ }
+
+ /**
+ * @return whether we are enabling paging.
+ */
+ public boolean isPagingEnabled() {
+ return mEnablePaging;
}
@Override
public void onTuningChanged(String key, String newValue) {
switch (key) {
- case KEY_DISABLE_FAST_TOGGLE:
- mDisableFastToggleRecents = (newValue != null) &&
- (Integer.parseInt(newValue) != 0);
+ case KEY_ENABLE_PAGING:
+ mEnablePaging = (newValue != null) && (Integer.parseInt(newValue) != 0);
break;
}
EventBus.getDefault().send(new DebugFlagsChangedEvent());
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 8de964b..ac23f44 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -16,6 +16,8 @@
package com.android.systemui.recents;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.ITaskStackListener;
@@ -64,8 +66,10 @@
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskGrouping;
import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.recents.tv.views.TaskStackHorizontalGridView;
import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
import com.android.systemui.recents.views.TaskStackView;
+import com.android.systemui.recents.views.TaskStackViewScroller;
import com.android.systemui.recents.views.TaskViewHeader;
import com.android.systemui.recents.views.TaskViewTransform;
import com.android.systemui.statusbar.BaseStatusBar;
@@ -74,8 +78,6 @@
import java.util.ArrayList;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-
/**
* An implementation of the Recents component for the current user. For secondary users, this can
* be called remotely from the system user.
@@ -98,6 +100,7 @@
//Used to store tv or non-tv activty for use in creating intents.
private final String mRecentsIntentActivityName;
+
/**
* An implementation of ITaskStackListener, that allows us to listen for changes to the system
* task stacks and update recents accordingly.
@@ -161,10 +164,8 @@
Handler mHandler;
TaskStackListenerImpl mTaskStackListener;
RecentsAppWidgetHost mAppWidgetHost;
- boolean mBootCompleted;
boolean mCanReuseTaskStackViews = true;
boolean mDraggingInRecents;
- boolean mReloadTasks;
boolean mLaunchedWhileDocking;
// Task launching
@@ -236,7 +237,6 @@
}
public void onBootCompleted() {
- mBootCompleted = true;
updateHeaderBarLayout(true /* tryAndBindSearchWidget */, null /* stack */);
}
@@ -279,28 +279,24 @@
mTriggeredFromAltTab = triggeredFromAltTab;
mDraggingInRecents = draggingInRecents;
mLaunchedWhileDocking = launchedWhileDockingTask;
- if (mFastAltTabTrigger.hasTriggered()) {
- // We are calling this from the doze trigger, so just fall through to show Recents
- mFastAltTabTrigger.resetTrigger();
+ if (mFastAltTabTrigger.isAsleep()) {
+ // Fast alt-tab duration has elapsed, fall through to showing Recents and reset
+ mFastAltTabTrigger.stopDozing();
} else if (mFastAltTabTrigger.isDozing()) {
- // We are dozing but haven't yet triggered, ignore this if this is not another alt-tab,
- // otherwise, this is an additional tab (alt-tab*), which means that we should trigger
- // immediately (fall through and disable the pending trigger)
- // TODO: This is tricky, we need to handle the tab key, but Recents has not yet started
- // so we may actually additional signal to handle multiple quick tab cases. The
- // severity of this is inversely proportional to the FAST_ALT_TAB_DELAY_MS
- // duration though
+ // Fast alt-tab duration has not elapsed. If this is triggered by a different
+ // showRecents() call, then ignore that call for now.
+ // TODO: We can not handle quick tabs that happen between the initial showRecents() call
+ // that started the activity and the activity starting up. The severity of this
+ // is inversely proportional to the FAST_ALT_TAB_DELAY_MS duration though.
if (!triggeredFromAltTab) {
return;
}
mFastAltTabTrigger.stopDozing();
- } else {
- // Otherwise, the doze trigger is not running, and if this is an alt tab, we should
- // start the trigger and then wait for the hide (or for it to elapse)
- if (triggeredFromAltTab) {
- mFastAltTabTrigger.startDozing();
- return;
- }
+ } else if (triggeredFromAltTab) {
+ // The fast alt-tab detector is not yet running, so start the trigger and wait for the
+ // hideRecents() call, or for the fast alt-tab duration to elapse
+ mFastAltTabTrigger.startDozing();
+ return;
}
try {
@@ -317,23 +313,20 @@
}
public void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
- if (mBootCompleted) {
- if (triggeredFromAltTab && mFastAltTabTrigger.isDozing()) {
- // The user has released alt-tab before the trigger has run, so just show the next
- // task immediately
- showNextTask();
+ if (triggeredFromAltTab && mFastAltTabTrigger.isDozing()) {
+ // The user has released alt-tab before the trigger has run, so just show the next
+ // task immediately
+ showNextTask();
- // Cancel the fast alt-tab trigger
- mFastAltTabTrigger.stopDozing();
- mFastAltTabTrigger.resetTrigger();
- return;
- }
-
- // Defer to the activity to handle hiding recents, if it handles it, then it must still
- // be visible
- EventBus.getDefault().post(new HideRecentsEvent(triggeredFromAltTab,
- triggeredFromHomeKey));
+ // Cancel the fast alt-tab trigger
+ mFastAltTabTrigger.stopDozing();
+ return;
}
+
+ // Defer to the activity to handle hiding recents, if it handles it, then it must still
+ // be visible
+ EventBus.getDefault().post(new HideRecentsEvent(triggeredFromAltTab,
+ triggeredFromHomeKey));
}
public void toggleRecents() {
@@ -347,19 +340,20 @@
mTriggeredFromAltTab = false;
try {
- ViewConfiguration viewConfig = ViewConfiguration.get(mContext);
SystemServicesProxy ssp = Recents.getSystemServices();
ActivityManager.RunningTaskInfo topTask = ssp.getTopMostTask();
MutableBoolean isTopTaskHome = new MutableBoolean(true);
long elapsedTime = SystemClock.elapsedRealtime() - mLastToggleTime;
if (topTask != null && ssp.isRecentsTopMost(topTask, isTopTaskHome)) {
+ RecentsDebugFlags debugFlags = Recents.getDebugFlags();
RecentsConfiguration config = Recents.getConfiguration();
RecentsActivityLaunchState launchState = config.getLaunchState();
if (!launchState.launchedWithAltTab) {
// If the user taps quickly
- if (ViewConfiguration.getDoubleTapMinTime() < elapsedTime &&
- elapsedTime < ViewConfiguration.getDoubleTapTimeout()) {
+ if (!debugFlags.isPagingEnabled() ||
+ (ViewConfiguration.getDoubleTapMinTime() < elapsedTime &&
+ elapsedTime < ViewConfiguration.getDoubleTapTimeout())) {
// Launch the next focused task
EventBus.getDefault().post(new LaunchNextTaskRequestEvent());
} else {
@@ -574,11 +568,14 @@
// Make sure we inform DividerView before we actually start the activity so we can change
// the resize mode already.
- EventBus.getDefault().send(new DockingTopTaskEvent(dragMode));
- ssp.moveTaskToDockedStack(topTaskId, stackCreateMode, initialBounds);
- showRecents(false /* triggeredFromAltTab */,
- dragMode == NavigationBarGestureHelper.DRAG_MODE_RECENTS, false /* animate */,
- true /* reloadTasks*/);
+ if (ssp.moveTaskToDockedStack(topTaskId, stackCreateMode, initialBounds)) {
+ EventBus.getDefault().send(new DockingTopTaskEvent(dragMode));
+ showRecents(
+ false /* triggeredFromAltTab */,
+ dragMode == NavigationBarGestureHelper.DRAG_MODE_RECENTS,
+ false /* animate */,
+ true /* launchedWhileDockingTask*/);
+ }
}
/**
@@ -605,7 +602,7 @@
com.android.internal.R.dimen.navigation_bar_width);
mTaskBarHeight = res.getDimensionPixelSize(
R.dimen.recents_task_bar_height);
- mDummyStackView = new TaskStackView(mContext, new TaskStack());
+ mDummyStackView = new TaskStackView(mContext);
mHeaderBar = (TaskViewHeader) inflater.inflate(R.layout.recents_task_view_header,
null, false);
}
@@ -618,8 +615,7 @@
* is not already bound (can be expensive)
* @param stack the stack to initialize the stack layout with
*/
- private void updateHeaderBarLayout(boolean tryAndBindSearchWidget,
- TaskStack stack) {
+ private void updateHeaderBarLayout(boolean tryAndBindSearchWidget, TaskStack stack) {
RecentsConfiguration config = Recents.getConfiguration();
SystemServicesProxy ssp = Recents.getSystemServices();
Rect systemInsets = new Rect();
@@ -643,14 +639,15 @@
mSearchBarBounds, mTaskStackBounds);
// Rebind the header bar and draw it for the transition
- TaskStackLayoutAlgorithm algo = mDummyStackView.getStackAlgorithm();
+ TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm();
Rect taskStackBounds = new Rect(mTaskStackBounds);
- algo.setSystemInsets(systemInsets);
+ stackLayout.setSystemInsets(systemInsets);
if (stack != null) {
- algo.initialize(taskStackBounds,
+ stackLayout.initialize(taskStackBounds,
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(stack));
+ mDummyStackView.setTasks(stack, false /* notifyStackChanges */);
}
- Rect taskViewBounds = algo.getUntransformedTaskViewBounds();
+ Rect taskViewBounds = stackLayout.getUntransformedTaskViewBounds();
if (!taskViewBounds.equals(mLastTaskViewBounds)) {
mLastTaskViewBounds.set(taskViewBounds);
@@ -708,10 +705,8 @@
updateHeaderBarLayout(false /* tryAndBindSearchWidget */, stack);
// Update the destination rect
- mDummyStackView.updateLayoutForStack(stack);
final Task toTask = new Task();
- final TaskViewTransform toTransform = getThumbnailTransitionTransform(stack, stackView,
- toTask);
+ final TaskViewTransform toTransform = getThumbnailTransitionTransform(stackView, toTask);
ForegroundThread.getHandler().postAtFrontOfQueue(new Runnable() {
@Override
public void run() {
@@ -757,17 +752,20 @@
* Creates the activity options for an app->recents transition.
*/
private ActivityOptions getThumbnailTransitionActivityOptions(
- ActivityManager.RunningTaskInfo topTask, TaskStack stack, TaskStackView stackView) {
+ ActivityManager.RunningTaskInfo topTask, TaskStackView stackView) {
if (topTask.stackId == FREEFORM_WORKSPACE_STACK_ID) {
ArrayList<AppTransitionAnimationSpec> specs = new ArrayList<>();
- stackView.getScroller().setStackScrollToInitialState();
- ArrayList<Task> tasks = stack.getStackTasks();
+ ArrayList<Task> tasks = stackView.getStack().getStackTasks();
+ TaskStackLayoutAlgorithm stackLayout = stackView.getStackAlgorithm();
+ TaskStackViewScroller stackScroller = stackView.getScroller();
+
+ stackView.updateToInitialState();
+
for (int i = tasks.size() - 1; i >= 0; i--) {
Task task = tasks.get(i);
if (task.isFreeformTask()) {
- mTmpTransform = stackView.getStackAlgorithm()
- .getStackTransformScreenCoordinates(task,
- stackView.getScroller().getStackScroll(), mTmpTransform, null);
+ mTmpTransform = stackLayout.getStackTransformScreenCoordinates(task,
+ stackScroller.getStackScroll(), mTmpTransform, null);
Rect toTaskRect = new Rect();
mTmpTransform.rect.round(toTaskRect);
Bitmap thumbnail = getThumbnailBitmap(topTask, task, mTmpTransform);
@@ -781,8 +779,7 @@
} else {
// Update the destination rect
Task toTask = new Task();
- TaskViewTransform toTransform = getThumbnailTransitionTransform(stack, stackView,
- toTask);
+ TaskViewTransform toTransform = getThumbnailTransitionTransform(stackView, toTask);
RectF toTaskRect = toTransform.rect;
Bitmap thumbnail = getThumbnailBitmap(topTask, toTask, toTransform);
if (thumbnail != null) {
@@ -814,9 +811,10 @@
/**
* Returns the transition rect for the given task id.
*/
- private TaskViewTransform getThumbnailTransitionTransform(TaskStack stack,
- TaskStackView stackView, Task runningTaskOut) {
+ private TaskViewTransform getThumbnailTransitionTransform(TaskStackView stackView,
+ Task runningTaskOut) {
// Find the running task in the TaskStack
+ TaskStack stack = stackView.getStack();
Task launchTask = stack.getLaunchTarget();
if (launchTask != null) {
runningTaskOut.copyFrom(launchTask);
@@ -827,7 +825,7 @@
}
// Get the transform for the running task
- stackView.getScroller().setStackScrollToInitialState();
+ stackView.updateToInitialState();
mTmpTransform = stackView.getStackAlgorithm().getStackTransformScreenCoordinates(launchTask,
stackView.getScroller().getStackScroll(), mTmpTransform, null);
return mTmpTransform;
@@ -855,6 +853,7 @@
c.scale(toTransform.scale, toTransform.scale);
mHeaderBar.rebindToTask(toTask, false /* touchExplorationEnabled */,
disabledInSafeMode);
+ mHeaderBar.setDimAlpha(toTransform.dimAlpha);
mHeaderBar.draw(c);
c.setBitmap(null);
}
@@ -887,7 +886,6 @@
updateHeaderBarLayout(false /* tryAndBindSearchWidget */, stack);
// Prepare the dummy stack for the transition
- mDummyStackView.updateLayoutForStack(stack);
TaskStackLayoutAlgorithm.VisibilityReport stackVr =
mDummyStackView.computeStackVisibilityReport();
@@ -903,8 +901,7 @@
if (useThumbnailTransition) {
// Try starting with a thumbnail transition
- ActivityOptions opts = getThumbnailTransitionActivityOptions(topTask, stack,
- mDummyStackView);
+ ActivityOptions opts = getThumbnailTransitionActivityOptions(topTask, mDummyStackView);
if (opts != null) {
startRecentsActivity(topTask, opts, false /* fromHome */,
false /* fromSearchHome */, true /* fromThumbnail */, stackVr);
@@ -951,14 +948,15 @@
* Starts the recents activity.
*/
private void startRecentsActivity(ActivityManager.RunningTaskInfo topTask,
- ActivityOptions opts, boolean fromHome, boolean fromSearchHome, boolean fromThumbnail,
- TaskStackLayoutAlgorithm.VisibilityReport vr) {
+ ActivityOptions opts, boolean fromHome, boolean fromSearchHome,
+ boolean fromThumbnail, TaskStackLayoutAlgorithm.VisibilityReport vr) {
// Update the configuration based on the launch options
RecentsConfiguration config = Recents.getConfiguration();
RecentsActivityLaunchState launchState = config.getLaunchState();
launchState.launchedFromHome = fromSearchHome || fromHome;
launchState.launchedFromSearchHome = fromSearchHome;
- launchState.launchedFromAppWithThumbnail = fromThumbnail;
+ launchState.launchedFromApp = fromThumbnail || mLaunchedWhileDocking;
+ launchState.launchedFromAppDocked = mLaunchedWhileDocking;
launchState.launchedToTaskId = (topTask != null) ? topTask.id : -1;
launchState.launchedWithAltTab = mTriggeredFromAltTab;
launchState.launchedReuseTaskStackViews = mCanReuseTaskStackViews;
diff --git a/media/mca/effect/java/android/media/effect/package-info.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java
similarity index 63%
copy from media/mca/effect/java/android/media/effect/package-info.java
copy to packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java
index b2c14ff..0ad4681 100644
--- a/media/mca/effect/java/android/media/effect/package-info.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,15 +14,13 @@
* limitations under the License.
*/
+package com.android.systemui.recents.events.activity;
-package android.media.effect;
+import com.android.systemui.recents.events.EventBus;
/**
- * <h1>Effect Framework</h1>
- *
- * This package includes a collection of high-performance visual effects that make use of the
- * mobile filter framework subsystem.
- *
- * TODO: More Documentation
- *
+ * This is sent when the Recents activity configuration has changed.
*/
+public class ConfigurationChangedEvent extends EventBus.AnimatedEvent {
+ // Simple event
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTvTaskEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTvTaskEvent.java
new file mode 100644
index 0000000..04ca68f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTvTaskEvent.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.recents.events.activity;
+
+
+import android.graphics.Rect;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.model.Task;
+import com.android.systemui.recents.tv.views.TaskCardView;
+
+public class LaunchTvTaskEvent extends EventBus.Event {
+
+ public final TaskCardView taskView;
+ public final Task task;
+ public final Rect targetTaskBounds;
+ public final int targetTaskStack;
+
+ public LaunchTvTaskEvent(TaskCardView taskView, Task task, Rect targetTaskBounds,
+ int targetTaskStack) {
+ this.taskView = taskView;
+ this.task = task;
+ this.targetTaskBounds = targetTaskBounds;
+ this.targetTaskStack = targetTaskStack;
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTvTaskStartedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTvTaskStartedEvent.java
new file mode 100644
index 0000000..75d3efa
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTvTaskStartedEvent.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.events.activity;
+
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.tv.views.TaskCardView;
+
+/**
+ * This event is sent following {@link LaunchTvTaskEvent} after the call to the system is made to
+ * start the task, only used on TV.
+ */
+public class LaunchTvTaskStartedEvent extends EventBus.AnimatedEvent {
+
+ public final TaskCardView taskView;
+
+ public LaunchTvTaskStartedEvent(TaskCardView taskView) {
+ this.taskView = taskView;
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/MultiWindowStateChangedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/MultiWindowStateChangedEvent.java
new file mode 100644
index 0000000..19245d9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/MultiWindowStateChangedEvent.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.events.activity;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This is sent by the activity whenever the multi-window state has changed.
+ */
+public class MultiWindowStateChangedEvent extends EventBus.Event {
+
+ public final boolean inMultiWindow;
+
+ public MultiWindowStateChangedEvent(boolean inMultiWindow) {
+ this.inMultiWindow = inMultiWindow;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/TaskStackUpdatedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/TaskStackUpdatedEvent.java
index f87f6de..0d614e8c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/TaskStackUpdatedEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/TaskStackUpdatedEvent.java
@@ -28,8 +28,10 @@
* A new TaskStack instance representing the latest stack state.
*/
public final TaskStack stack;
+ public final boolean inMultiWindow;
- public TaskStackUpdatedEvent(TaskStack stack) {
+ public TaskStackUpdatedEvent(TaskStack stack, boolean inMultiWindow) {
this.stack = stack;
+ this.inMultiWindow = inMultiWindow;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/RecentsVisibilityChangedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/RecentsVisibilityChangedEvent.java
index 4140bcd..8843eb4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/component/RecentsVisibilityChangedEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/component/RecentsVisibilityChangedEvent.java
@@ -19,21 +19,18 @@
import android.content.Context;
import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.misc.SystemServicesProxy;
/**
- * This is sent when the visibility of the RecentsActivity for the current user changes.
+ * This is sent when the visibility of the RecentsActivity for the current user changes. Handlers
+ * of this event should not alter the UI, as the activity may still be visible.
*/
public class RecentsVisibilityChangedEvent extends EventBus.Event {
public final Context applicationContext;
- public final SystemServicesProxy systemServicesProxy;
public final boolean visible;
- public RecentsVisibilityChangedEvent(Context context, SystemServicesProxy systemServicesProxy,
- boolean visible) {
+ public RecentsVisibilityChangedEvent(Context context, boolean visible) {
this.applicationContext = context.getApplicationContext();
- this.systemServicesProxy = systemServicesProxy;
this.visible = visible;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
index d7b9b9e..5eeda72 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
@@ -161,7 +161,7 @@
ssp.startActivityFromRecents(v.getContext(), task.key.id, task.title,
ActivityOptions.makeBasic());
- MetricsLogger.action(v.getContext(), MetricsEvent.OVERVIEW_SELECT,
+ MetricsLogger.action(v.getContext(), MetricsEvent.ACTION_OVERVIEW_SELECT,
task.key.getComponent().toString());
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java b/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java
index 95aa10f..574ea03 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java
@@ -30,7 +30,7 @@
@ViewDebug.ExportedProperty(category="recents")
boolean mIsDozing;
@ViewDebug.ExportedProperty(category="recents")
- boolean mHasTriggered;
+ boolean mIsAsleep;
@ViewDebug.ExportedProperty(category="recents")
int mDozeDurationMilliseconds;
Runnable mOnSleepRunnable;
@@ -40,7 +40,7 @@
@Override
public void run() {
mIsDozing = false;
- mHasTriggered = true;
+ mIsAsleep = true;
mOnSleepRunnable.run();
}
};
@@ -56,7 +56,7 @@
*/
public void startDozing() {
forcePoke();
- mHasTriggered = false;
+ mIsAsleep = false;
}
/**
@@ -65,6 +65,7 @@
public void stopDozing() {
mHandler.removeCallbacks(mDozeRunnable);
mIsDozing = false;
+ mIsAsleep = false;
}
/**
@@ -99,12 +100,7 @@
}
/** Returns whether the trigger has fired at least once. */
- public boolean hasTriggered() {
- return mHasTriggered;
- }
-
- /** Resets the doze trigger state. */
- public void resetTrigger() {
- mHasTriggered = false;
+ public boolean isAsleep() {
+ return mIsAsleep;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 8b4474f..532e796 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -338,15 +338,18 @@
}
/** Docks an already resumed task to the side of the screen. */
- public void moveTaskToDockedStack(int taskId, int createMode, Rect initialBounds) {
- if (mIam == null) return;
+ public boolean moveTaskToDockedStack(int taskId, int createMode, Rect initialBounds) {
+ if (mIam == null) {
+ return false;
+ }
try {
- mIam.moveTaskToDockedStack(taskId, createMode, true /* onTop */, false /* animate */,
- initialBounds);
+ return mIam.moveTaskToDockedStack(
+ taskId, createMode, true /* onTop */, false /* animate */, initialBounds);
} catch (RemoteException e) {
e.printStackTrace();
}
+ return false;
}
/** Returns the focused stack id. */
@@ -692,6 +695,37 @@
}
/**
+ * Returns a banner used on TV for the specified Activity.
+ */
+ public Drawable getActivityBanner(ActivityInfo info) {
+ if (mPm == null) return null;
+
+ // If we are mocking, then return a mock banner
+ if (RecentsDebugFlags.Static.EnableMockTasks) {
+ return new ColorDrawable(0xFF666666);
+ }
+
+ Drawable banner = info.loadBanner(mPm);
+ return banner;
+ }
+
+ /**
+ * Returns a logo used on TV for the specified Activity.
+ */
+ public Drawable getActivityLogo(ActivityInfo info) {
+ if (mPm == null) return null;
+
+ // If we are mocking, then return a mock logo
+ if (RecentsDebugFlags.Static.EnableMockTasks) {
+ return new ColorDrawable(0xFF666666);
+ }
+
+ Drawable logo = info.loadLogo(mPm);
+ return logo;
+ }
+
+
+ /**
* Returns the given label for a user, badging if necessary.
*/
private String getBadgedLabel(String label, int userId) {
@@ -998,20 +1032,4 @@
e.printStackTrace();
}
}
-
- public void focusPinnedStack() {
- try {
- mIam.setFocusedStack(PINNED_STACK_ID);
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- }
-
- public void focusHomeStack() {
- try {
- mIam.setFocusedStack(HOME_STACK_ID);
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
index e86b92d..72b1cab 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
@@ -196,7 +196,7 @@
* are not called.
*/
public static void cancelAnimationWithoutCallbacks(Animator animator) {
- if (animator != null) {
+ if (animator != null && animator.isStarted()) {
removeAnimationListenersRecursive(animator);
animator.cancel();
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index 824231a..6ae07fc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -133,7 +133,6 @@
SparseIntArray affiliatedTaskCounts = new SparseIntArray();
String dismissDescFormat = mContext.getString(
R.string.accessibility_recents_item_will_be_dismissed);
- Formatter dismissDescFormatter = new Formatter();
long lastStackActiveTime = Prefs.getLong(mContext,
Prefs.Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME, 0);
if (RecentsDebugFlags.Static.EnableMockTasks) {
@@ -184,8 +183,7 @@
ActivityInfo info = loader.getAndUpdateActivityInfo(taskKey);
String title = loader.getAndUpdateActivityTitle(taskKey, t.taskDescription);
String contentDescription = loader.getAndUpdateContentDescription(taskKey, res);
- String dismissDescription = dismissDescFormatter.format(dismissDescFormat,
- contentDescription).toString();
+ String dismissDescription = String.format(dismissDescFormat, contentDescription);
Drawable icon = isStackTask
? loader.getAndUpdateActivityIcon(taskKey, t.taskDescription, res, false)
: null;
@@ -198,8 +196,8 @@
// Add the task to the stack
Task task = new Task(taskKey, t.affiliatedTaskId, t.affiliatedTaskColor, icon,
thumbnail, title, contentDescription, dismissDescription, activityColor,
- backgroundColor, !isStackTask, isLaunchTarget, isSystemApp, t.bounds,
- t.taskDescription);
+ backgroundColor, !isStackTask, isLaunchTarget, isSystemApp, t.isDockable,
+ t.bounds, t.taskDescription);
allTasks.add(task);
affiliatedTaskCounts.put(taskKey.id, affiliatedTaskCounts.get(taskKey.id, 0) + 1);
@@ -214,8 +212,7 @@
// Initialize the stacks
mStack = new TaskStack();
- mStack.setTasks(allTasks, false /* notifyStackChanges */);
- mStack.createAffiliatedGroupings(mContext);
+ mStack.setTasks(mContext, allTasks, false /* notifyStackChanges */);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index 8ed6dd7..b5a5949 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -100,11 +100,7 @@
@Override
public String toString() {
- return "Task.Key: " + id + ", "
- + "s: " + stackId + ", "
- + "u: " + userId + ", "
- + "lat: " + lastActiveTime + ", "
- + getComponent().getPackageName();
+ return "t" + id + ", s" + stackId + ", u" + userId;
}
private void updateHashCode() {
@@ -168,6 +164,8 @@
public boolean isHistorical;
@ViewDebug.ExportedProperty(category="recents")
public boolean isSystemApp;
+ @ViewDebug.ExportedProperty(category="recents")
+ public boolean isDockable;
private ArrayList<TaskCallbacks> mCallbacks = new ArrayList<>();
@@ -178,8 +176,8 @@
public Task(TaskKey key, int affiliationTaskId, int affiliationColor, Drawable icon,
Bitmap thumbnail, String title, String contentDescription,
String dismissDescription, int colorPrimary, int colorBackground,
- boolean isHistorical, boolean isLaunchTarget, boolean isSystemApp, Rect bounds,
- ActivityManager.TaskDescription taskDescription) {
+ boolean isHistorical, boolean isLaunchTarget, boolean isSystemApp,
+ boolean isDockable, Rect bounds, ActivityManager.TaskDescription taskDescription) {
boolean isInAffiliationGroup = (affiliationTaskId != key.id);
boolean hasAffiliationGroupColor = isInAffiliationGroup && (affiliationColor != 0);
this.key = key;
@@ -199,9 +197,12 @@
this.isLaunchTarget = isLaunchTarget;
this.isHistorical = isHistorical;
this.isSystemApp = isSystemApp;
+ this.isDockable = isDockable;
}
- /** Copies the other task. */
+ /**
+ * Copies the metadata from another task, but retains the current callbacks.
+ */
public void copyFrom(Task o) {
this.key = o.key;
this.group = o.group;
@@ -219,6 +220,7 @@
this.isLaunchTarget = o.isLaunchTarget;
this.isHistorical = o.isHistorical;
this.isSystemApp = o.isSystemApp;
+ this.isDockable = o.isDockable;
}
/**
@@ -296,11 +298,6 @@
@Override
public String toString() {
- String groupAffiliation = "no group";
- if (group != null) {
- groupAffiliation = Integer.toString(group.affiliation);
- }
- return "Task (" + groupAffiliation + "): " + key +
- " [" + super.toString() + "]";
+ return "[" + key.toString() + "] " + title;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index 1f91dce..4d1c552 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -92,15 +92,6 @@
}
}
- /**
- * Resets the task list, but does not remove the filter.
- */
- void reset() {
- mTasks.clear();
- mFilteredTasks.clear();
- mTaskIndices.clear();
- }
-
/** Removes the task filter and returns the previous touch state */
void removeFilter() {
mFilter = null;
@@ -481,15 +472,6 @@
mCb = cb;
}
- /** Resets this TaskStack. */
- public void reset() {
- mCb = null;
- mStackTaskList.reset();
- mHistoryTaskList.reset();
- mGroups.clear();
- mAffinitiesGroups.clear();
- }
-
/**
* Moves the given task to either the front of the freeform workspace or the stack.
*/
@@ -556,12 +538,12 @@
* @param tasks the new set of tasks to replace the current set.
* @param notifyStackChanges whether or not to callback on specific changes to the list of tasks.
*/
- public void setTasks(List<Task> tasks, boolean notifyStackChanges) {
+ public void setTasks(Context context, List<Task> tasks, boolean notifyStackChanges) {
// Compute a has set for each of the tasks
ArrayMap<Task.TaskKey, Task> currentTasksMap = createTaskKeyMapFromList(mRawTaskList);
ArrayMap<Task.TaskKey, Task> newTasksMap = createTaskKeyMapFromList(tasks);
-
- ArrayList<Task> newTasks = new ArrayList<>();
+ ArrayList<Task> addedTasks = new ArrayList<>();
+ ArrayList<Task> allTasks = new ArrayList<>();
// Disable notifications if there are no callbacks
if (mCb == null) {
@@ -570,10 +552,13 @@
// Remove any tasks that no longer exist
int taskCount = mRawTaskList.size();
- for (int i = 0; i < taskCount; i++) {
+ for (int i = taskCount - 1; i >= 0; i--) {
Task task = mRawTaskList.get(i);
if (!newTasksMap.containsKey(task.key)) {
if (notifyStackChanges) {
+ // If we are notifying, then remove the task now, otherwise the raw task list
+ // will be reset at the end of this method
+ removeTask(task, AnimationProps.IMMEDIATE);
mCb.onStackTaskRemoved(this, task, i == (taskCount - 1), null,
AnimationProps.IMMEDIATE);
}
@@ -584,26 +569,28 @@
// Add any new tasks
taskCount = tasks.size();
for (int i = 0; i < taskCount; i++) {
- Task task = tasks.get(i);
- if (!currentTasksMap.containsKey(task.key)) {
- if (notifyStackChanges) {
- mCb.onStackTaskAdded(this, task);
- }
- newTasks.add(task);
- } else {
- newTasks.add(currentTasksMap.get(task.key));
+ Task newTask = tasks.get(i);
+ Task currentTask = currentTasksMap.get(newTask.key);
+ if (currentTask == null && notifyStackChanges) {
+ addedTasks.add(newTask);
+ } else if (currentTask != null) {
+ // The current task has bound callbacks, so just copy the data from the new task
+ // state and add it back into the list
+ currentTask.copyFrom(newTask);
+ newTask = currentTask;
}
+ allTasks.add(newTask);
}
// Sort all the tasks to ensure they are ordered correctly
- Collections.sort(newTasks, FREEFORM_LAST_ACTIVE_TIME_COMPARATOR);
+ Collections.sort(allTasks, FREEFORM_LAST_ACTIVE_TIME_COMPARATOR);
// Filter out the historical tasks from this new list
ArrayList<Task> stackTasks = new ArrayList<>();
ArrayList<Task> historyTasks = new ArrayList<>();
- int newTaskCount = newTasks.size();
+ int newTaskCount = allTasks.size();
for (int i = 0; i < newTaskCount; i++) {
- Task task = newTasks.get(i);
+ Task task = allTasks.get(i);
if (task.isHistorical) {
historyTasks.add(task);
} else {
@@ -613,10 +600,16 @@
mStackTaskList.set(stackTasks);
mHistoryTaskList.set(historyTasks);
- mRawTaskList.clear();
- mRawTaskList.addAll(newTasks);
- mGroups.clear();
- mAffinitiesGroups.clear();
+ mRawTaskList = allTasks;
+
+ // Only callback for the newly added tasks after this stack has been updated
+ int addedTaskCount = addedTasks.size();
+ for (int i = 0; i < addedTaskCount; i++) {
+ mCb.onStackTaskAdded(this, addedTasks.get(i));
+ }
+
+ // Update the affiliated groupings
+ createAffiliatedGroupings(context);
}
/**
@@ -779,9 +772,12 @@
}
/**
- * Temporary: This method will simulate affiliation groups by
+ * Temporary: This method will simulate affiliation groups
*/
- public void createAffiliatedGroupings(Context context) {
+ void createAffiliatedGroupings(Context context) {
+ mGroups.clear();
+ mAffinitiesGroups.clear();
+
if (RecentsDebugFlags.Static.EnableMockTaskGroups) {
ArrayMap<Task.TaskKey, Task> taskMap = new ArrayMap<>();
// Sort all tasks by increasing firstActiveTime of the task
@@ -926,13 +922,13 @@
@Override
public String toString() {
- String str = "Stack Tasks:\n";
+ String str = "Stack Tasks (" + mStackTaskList.size() + "):\n";
for (Task t : mStackTaskList.getTasks()) {
- str += " " + t.toString() + "\n";
+ str += " " + t.toString() + "\n";
}
- str += "Historical Tasks:\n";
+ str += "Historical Tasks(" + mHistoryTaskList.size() + "):\n";
for (Task t : mHistoryTaskList.getTasks()) {
- str += " " + t.toString() + "\n";
+ str += " " + t.toString() + "\n";
}
return str;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
index f3201d0..dae522f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
@@ -18,6 +18,7 @@
import android.app.Activity;
import android.app.ActivityOptions;
import android.content.Intent;
+import android.graphics.Rect;
import android.os.Bundle;
import android.os.UserHandle;
import android.util.Log;
@@ -25,6 +26,7 @@
import android.view.View;
import android.view.ViewTreeObserver.OnPreDrawListener;
import android.view.WindowManager;
+import android.widget.FrameLayout.LayoutParams;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
@@ -38,7 +40,6 @@
import com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent;
import com.android.systemui.recents.events.activity.HideRecentsEvent;
import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
-import com.android.systemui.recents.events.activity.TaskStackUpdatedEvent;
import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
@@ -58,6 +59,9 @@
import com.android.systemui.tv.pip.PipManager;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
/**
* The main TV recents activity started by the RecentsImpl.
*/
@@ -73,9 +77,31 @@
private boolean mIgnoreAltTabRelease;
private RecentsTvView mRecentsView;
+ private View mPipView;
+ private View mPipShadeView;
private TaskStackHorizontalViewAdapter mTaskStackViewAdapter;
private FinishRecentsRunnable mFinishLaunchHomeRunnable;
+ private PipManager mPipManager;
+ private PipManager.Listener mPipListener = new PipManager.Listener() {
+ @Override
+ public void onPipActivityClosed() {
+ mPipView.setVisibility(View.GONE);
+ mPipShadeView.setVisibility(View.GONE);
+ }
+
+ @Override
+ public void onShowPipMenu() { }
+
+ @Override
+ public void onMoveToFullscreen() { }
+
+ @Override
+ public void onPipResizeAboutToStart() { }
+
+ @Override
+ public void onMediaControllerChanged() { }
+ };
/**
* A common Runnable to finish Recents by launching Home with an animation depending on the
@@ -132,11 +158,13 @@
mRecentsView.setTaskStack(stack);
+ List stackTasks = stack.getStackTasks();
+ Collections.reverse(stackTasks);
if (mTaskStackViewAdapter == null) {
- mTaskStackViewAdapter = new TaskStackHorizontalViewAdapter(stack.getStackTasks());
+ mTaskStackViewAdapter = new TaskStackHorizontalViewAdapter(stackTasks);
mRecentsView.setTaskStackViewAdapter(mTaskStackViewAdapter);
} else {
- mTaskStackViewAdapter.setNewStackTasks(stack.getStackTasks());
+ mTaskStackViewAdapter.setNewStackTasks(stackTasks);
}
if (launchState.launchedToTaskId != -1) {
@@ -212,6 +240,7 @@
finish();
return;
}
+ mPipManager = PipManager.getInstance();
// Register this activity with the event bus
EventBus.getDefault().register(this, EVENT_BUS_PRIORITY);
@@ -226,7 +255,8 @@
mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
-
+ mPipView = findViewById(R.id.pip);
+ mPipShadeView = findViewById(R.id.pip_shade);
getWindow().getAttributes().privateFlags |=
WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
@@ -257,14 +287,46 @@
RecentsConfiguration config = Recents.getConfiguration();
RecentsActivityLaunchState launchState = config.getLaunchState();
boolean wasLaunchedByAm = !launchState.launchedFromHome &&
- !launchState.launchedFromAppWithThumbnail;
+ !launchState.launchedFromApp;
if (launchState.launchedHasConfigurationChanged || wasLaunchedByAm) {
EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
}
// Notify that recents is now visible
SystemServicesProxy ssp = Recents.getSystemServices();
- EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, ssp, true));
+ EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, true));
+
+ if (mPipManager.isPipShown()) {
+ // Place mPipView at the PIP bounds for fine tuned focus handling.
+ Rect pipBounds = mPipManager.getPipBounds();
+ LayoutParams lp = (LayoutParams) mPipView.getLayoutParams();
+ lp.width = pipBounds.width();
+ lp.height = pipBounds.height();
+ lp.leftMargin = pipBounds.left;
+ lp.topMargin = pipBounds.top;
+ mPipView.setLayoutParams(lp);
+
+ mPipView.setVisibility(View.VISIBLE);
+ mPipView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mPipManager.resizePinnedStack(PipManager.STATE_PIP_MENU);
+ }
+ });
+ mPipView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ mPipManager.onPipViewFocusChangedInRecents(hasFocus);
+ mPipShadeView.setVisibility(hasFocus ? View.VISIBLE : View.INVISIBLE);
+ }
+ });
+ mPipManager.addListener(mPipListener);
+ } else {
+ mPipView.setVisibility(View.GONE);
+ }
+ mPipManager.onRecentsStarted();
+ // Give focus to the recents row whenever its visible to an user.
+ mRecentsView.requestFocus();
}
@Override
@@ -277,10 +339,11 @@
protected void onStop() {
super.onStop();
+ mPipManager.onRecentsStopped();
+ mPipManager.removeListener(mPipListener);
mIgnoreAltTabRelease = false;
// Notify that recents is now hidden
- SystemServicesProxy ssp = Recents.getSystemServices();
- EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, ssp, false));
+ EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, false));
// Workaround for b/22542869, if the RecentsActivity is started again, but without going
// through SystemUI, we need to reset the config launch flags to ensure that we do not
@@ -316,18 +379,6 @@
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_UP: {
- SystemServicesProxy ssp = Recents.getSystemServices();
- PipManager.getInstance().resizePinnedStack(PipManager.STATE_PIP_MENU);
- ssp.focusPinnedStack();
- return true;
- }
- case KeyEvent.KEYCODE_DPAD_DOWN: {
- SystemServicesProxy ssp = Recents.getSystemServices();
- PipManager.getInstance().resizePinnedStack(PipManager.STATE_PIP_OVERLAY);
- ssp.focusHomeStack();
- return true;
- }
case KeyEvent.KEYCODE_DEL:
case KeyEvent.KEYCODE_FORWARD_DEL: {
EventBus.getDefault().send(new DismissFocusedTaskViewEvent());
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java
new file mode 100644
index 0000000..ef8d48e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.recents.tv.views;
+
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.ActivityOptions;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IRemoteCallback;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.WindowManagerGlobal;
+import com.android.internal.annotations.GuardedBy;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.*;
+import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.recents.model.Task;
+import com.android.systemui.recents.model.TaskStack;
+
+
+public class RecentsTvTransitionHelper {
+ private static final String TAG = "RecentsTvTransitionHelper";
+
+ private Context mContext;
+ private Handler mHandler;
+
+ public RecentsTvTransitionHelper(Context context, Handler handler) {
+ mContext = context;
+ mHandler = handler;
+ }
+
+ public void launchTaskFromRecents(final TaskStack stack, @Nullable final Task task,
+ final TaskStackHorizontalGridView stackView, final TaskCardView taskView,
+ final Rect bounds, int destinationStack) {
+ final ActivityOptions opts = ActivityOptions.makeBasic();
+ if (bounds != null) {
+ opts.setLaunchBounds(bounds.isEmpty() ? null : bounds);
+ }
+
+ final ActivityOptions.OnAnimationStartedListener animStartedListener;
+ if (task.thumbnail != null && task.thumbnail.getWidth() > 0 &&
+ task.thumbnail.getHeight() > 0) {
+ animStartedListener = new ActivityOptions.OnAnimationStartedListener() {
+ @Override
+ public void onAnimationStarted() {
+ // If we are launching into another task, cancel the previous task's
+ // window transition
+ EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
+ EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
+ }
+ };
+ } else {
+ // This is only the case if the task is not on screen (scrolled offscreen for example)
+ animStartedListener = new ActivityOptions.OnAnimationStartedListener() {
+ @Override
+ public void onAnimationStarted() {
+ EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
+ }
+ };
+ }
+
+ if (taskView == null) {
+ // If there is no task view, then we do not need to worry about animating out occluding
+ // task views, and we can launch immediately
+ startTaskActivity(stack, task, taskView, opts, animStartedListener);
+ } else {
+ LaunchTvTaskStartedEvent launchStartedEvent = new LaunchTvTaskStartedEvent(taskView);
+ EventBus.getDefault().send(launchStartedEvent);
+ startTaskActivity(stack, task, taskView, opts, animStartedListener);
+ }
+ }
+
+ private void startTaskActivity(TaskStack stack, Task task, @Nullable TaskCardView taskView,
+ ActivityOptions opts,final ActivityOptions.OnAnimationStartedListener animStartedListener) {
+ SystemServicesProxy ssp = Recents.getSystemServices();
+ if (ssp.startActivityFromRecents(mContext, task.key.id, task.title, opts)) {
+ // Keep track of the index of the task launch
+ int taskIndexFromFront = 0;
+ int taskIndex = stack.indexOfStackTask(task);
+ if (taskIndex > -1) {
+ taskIndexFromFront = stack.getTaskCount() - taskIndex - 1;
+ }
+ EventBus.getDefault().send(new LaunchTaskSucceededEvent(taskIndexFromFront));
+ } else {
+ // Keep track of failed launches
+ EventBus.getDefault().send(new LaunchTaskFailedEvent());
+ }
+
+ IRemoteCallback.Stub callback = null;
+ if (animStartedListener != null) {
+ callback = new IRemoteCallback.Stub() {
+ @Override
+ public void sendResult(Bundle data) throws RemoteException {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (animStartedListener != null) {
+ animStartedListener.onAnimationStarted();
+ }
+ }
+ });
+ }
+ };
+ }
+ try {
+ Rect taskRect = taskView.getGlobalRect();
+ WindowManagerGlobal.getWindowManagerService()
+ .overridePendingAppTransitionThumb(task.thumbnail, taskRect.left,
+ taskRect.top, callback, true);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to override transition: " + e);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java
index b175855..bf6229c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java
@@ -17,6 +17,7 @@
import android.content.Context;
import android.graphics.Rect;
+import android.os.Handler;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
@@ -31,7 +32,7 @@
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
-import com.android.systemui.recents.events.activity.TaskStackUpdatedEvent;
+import com.android.systemui.recents.events.activity.LaunchTvTaskEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.model.Task;
@@ -53,7 +54,8 @@
private View mEmptyView;
private boolean mAwaitingFirstLayout = true;
private Rect mSystemInsets = new Rect();
-
+ private RecentsTvTransitionHelper mTransitionHelper;
+ private Handler mHandler;
public RecentsTvView(Context context) {
this(context, null);
@@ -75,6 +77,8 @@
LayoutInflater inflater = LayoutInflater.from(context);
mEmptyView = inflater.inflate(R.layout.recents_empty, this, false);
addView(mEmptyView);
+ mHandler = new Handler();
+ mTransitionHelper = new RecentsTvTransitionHelper(mContext, mHandler);
}
public void setTaskStack(TaskStack stack) {
@@ -200,19 +204,6 @@
EventBus.getDefault().unregister(this);
}
- /**
- * This is called with the full size of the window since we are handling our own insets.
- */
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- if (mTaskStackHorizontalView != null && mTaskStackHorizontalView.getVisibility() != GONE) {
- mTaskStackHorizontalView.layout(left, top, left + getMeasuredWidth(), top + getMeasuredHeight());
- }
-
- // Layout the empty view
- mEmptyView.layout(left, top, right, bottom);
- }
-
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
mSystemInsets.set(insets.getSystemWindowInsets());
@@ -222,6 +213,11 @@
/**** EventBus Events ****/
+ public final void onBusEvent(LaunchTvTaskEvent event) {
+ mTransitionHelper.launchTaskFromRecents(mStack, event.task, mTaskStackHorizontalView,
+ event.taskView, event.targetTaskBounds, event.targetTaskStack);
+ }
+
public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
// If we are going home, cancel the previous task's window transition
EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(null));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
index e275f22..7d8a3ce 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
@@ -16,20 +16,20 @@
package com.android.systemui.recents.tv.views;
import android.content.Context;
+import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.ImageView;
-import android.widget.RelativeLayout;
+import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.systemui.R;
-import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.tv.animations.ViewFocusAnimator;
+import com.android.systemui.recents.model.Task;
-public class TaskCardView extends RelativeLayout {
+public class TaskCardView extends LinearLayout {
private ImageView mThumbnailView;
private TextView mTitleTextView;
- private TextView mContentTextView;
private ImageView mBadgeView;
private Task mTask;
@@ -52,7 +52,6 @@
protected void onFinishInflate() {
mThumbnailView = (ImageView) findViewById(R.id.card_view_thumbnail);
mTitleTextView = (TextView) findViewById(R.id.card_title_text);
- mContentTextView = (TextView) findViewById(R.id.card_content_text);
mBadgeView = (ImageView) findViewById(R.id.card_extra_badge);
}
@@ -60,11 +59,27 @@
mTask = task;
mThumbnailView.setImageBitmap(task.thumbnail);
mTitleTextView.setText(task.title);
- mContentTextView.setText(task.contentDescription);
mBadgeView.setImageDrawable(task.icon);
}
public Task getTask() {
return mTask;
}
+
+ @Override
+ public void getFocusedRect(Rect r) {
+ mThumbnailView.getFocusedRect(r);
+ }
+
+ public Rect getFocusedRect() {
+ Rect r = new Rect();
+ getFocusedRect(r);
+ return r;
+ }
+
+ public Rect getGlobalRect() {
+ Rect r = new Rect();
+ getGlobalVisibleRect(r);
+ return r;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
index 58ec852..4458639 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
@@ -15,7 +15,6 @@
*/
package com.android.systemui.recents.tv.views;
-
import android.content.Context;
import android.support.v17.leanback.widget.HorizontalGridView;
import android.util.AttributeSet;
@@ -36,13 +35,17 @@
/**
* Horizontal Grid View Implementation to show the Task Stack for TV.
*/
-public class TaskStackHorizontalGridView extends HorizontalGridView implements TaskStackCallbacks{
+public class TaskStackHorizontalGridView extends HorizontalGridView implements TaskStackCallbacks {
private TaskStack mStack;
private ArrayList<TaskCardView> mTaskViews = new ArrayList<>();
private Task mFocusedTask;
+ public TaskStackHorizontalGridView(Context context) {
+ this(context, null);
+ }
+
public TaskStackHorizontalGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -64,8 +67,6 @@
* Resets this view for reuse.
*/
public void reset() {
- // Reset the focused task
- resetFocusedTask(getFocusedTask());
requestLayout();
}
@@ -73,12 +74,6 @@
* @param task - Task to reset
*/
private void resetFocusedTask(Task task) {
- if (task != null) {
- TaskCardView tv = getChildViewForTask(task);
- if (tv != null) {
- tv.requestFocus();
- }
- }
mFocusedTask = null;
}
@@ -107,6 +102,9 @@
* @return - The focused task.
*/
public Task getFocusedTask() {
+ if (findFocus() != null) {
+ mFocusedTask = ((TaskCardView)findFocus()).getTask();
+ }
return mFocusedTask;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java
index f154331..fba424e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java
@@ -16,7 +16,6 @@
package com.android.systemui.recents.tv.views;
import android.app.Activity;
-import android.app.ActivityManagerNative;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
@@ -24,15 +23,20 @@
import android.view.ViewGroup;
import com.android.systemui.R;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.LaunchTvTaskEvent;
import com.android.systemui.recents.model.Task;
import java.util.ArrayList;
import java.util.List;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+
public class TaskStackHorizontalViewAdapter extends
RecyclerView.Adapter<TaskStackHorizontalViewAdapter.ViewHolder> {
- private static final String TAG = "TaskStackHorizontalViewAdapter";
+ //Full class name is 30 characters
+ private static final String TAG = "TaskStackViewAdapter";
private List<Task> mTaskList;
static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
@@ -54,7 +58,8 @@
@Override
public void onClick(View v) {
try {
- ActivityManagerNative.getDefault().startActivityFromRecents(mTask.key.id, null);
+ EventBus.getDefault().send(new LaunchTvTaskEvent(mTaskCardView, mTask,
+ null, INVALID_STACK_ID));
((Activity)(v.getContext())).finish();
} catch (Exception e) {
Log.e(TAG, v.getContext()
@@ -73,11 +78,12 @@
mTaskList.addAll(tasks);
notifyDataSetChanged();
}
+
@Override
public TaskStackHorizontalViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View view = LayoutInflater.from(parent.getContext())
- .inflate(R.layout.recents_task_card_view, parent, false);
+ .inflate(R.layout.recents_tv_task_card_view, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
index 4359101..72b914c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
@@ -37,6 +37,13 @@
private int mTaskPadding;
public FreeformWorkspaceLayoutAlgorithm(Context context) {
+ reloadOnConfigurationChange(context);
+ }
+
+ /**
+ * Reloads the layout for the current configuration.
+ */
+ public void reloadOnConfigurationChange(Context context) {
// This is applied to the edges of each task
mTaskPadding = context.getResources().getDimensionPixelSize(
R.dimen.recents_freeform_workspace_task_padding) / 2;
@@ -72,8 +79,7 @@
}
// Bound the task width to the workspace width so that at the worst case, it will
// fit its own row
- normalizedTaskWidths[i] = Math.min(rowTaskWidth,
- normalizedWorkspaceWidth);
+ normalizedTaskWidths[i] = Math.min(rowTaskWidth, normalizedWorkspaceWidth);
}
// Determine the scale to best fit each of the tasks in the workspace
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
index 37b2859..dd825cb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -105,9 +105,6 @@
animStartedListener = new ActivityOptions.OnAnimationStartedListener() {
@Override
public void onAnimationStarted() {
- // If we are launching into another task, cancel the previous task's
- // window transition
- EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
if (screenPinningRequested) {
@@ -149,6 +146,10 @@
animStartedListener);
}
}
+
+ // If we are launching into another task, cancel the previous task's
+ // window transition
+ EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
}
/**
@@ -176,6 +177,7 @@
// Keep track of failed launches
EventBus.getDefault().send(new LaunchTaskFailedEvent());
}
+
if (transitionFuture != null) {
IRemoteCallback.Stub callback = null;
if (animStartedListener != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 2e45627..1af5a55 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -60,9 +60,7 @@
import com.android.systemui.recents.events.activity.LaunchTaskEvent;
import com.android.systemui.recents.events.activity.ShowHistoryButtonEvent;
import com.android.systemui.recents.events.activity.ShowHistoryEvent;
-import com.android.systemui.recents.events.activity.TaskStackUpdatedEvent;
import com.android.systemui.recents.events.activity.ToggleHistoryEvent;
-import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent;
import com.android.systemui.recents.events.ui.DraggingInRecentsEvent;
import com.android.systemui.recents.events.ui.ResetBackgroundScrimEvent;
@@ -168,35 +166,39 @@
}
/** Set/get the bsp root node */
- public void setTaskStack(TaskStack stack) {
+ public void onResume(boolean isResumingFromVisible, TaskStack stack) {
RecentsConfiguration config = Recents.getConfiguration();
RecentsActivityLaunchState launchState = config.getLaunchState();
- mStack = stack;
- if (launchState.launchedReuseTaskStackViews) {
- if (mTaskStackView != null) {
- // If onRecentsHidden is not triggered, we need to the stack view again here
- mTaskStackView.reset();
- mTaskStackView.setStack(stack);
- } else {
- mTaskStackView = new TaskStackView(getContext(), stack);
- addView(mTaskStackView);
- }
- } else {
- if (mTaskStackView != null) {
- removeView(mTaskStackView);
- }
- mTaskStackView = new TaskStackView(getContext(), stack);
+
+ if (mTaskStackView == null || !launchState.launchedReuseTaskStackViews) {
+ isResumingFromVisible = false;
+ removeView(mTaskStackView);
+ mTaskStackView = new TaskStackView(getContext());
+ mStack = mTaskStackView.getStack();
addView(mTaskStackView);
}
- // If we are already occluded by the app, then just set the default background scrim now.
- // Otherwise, defer until the enter animation completes to animate the scrim with the
- // tasks for the home animation.
- if (launchState.launchedWhileDocking || launchState.launchedFromAppWithThumbnail
- || mStack.getTaskCount() == 0) {
- mBackgroundScrim.setAlpha((int) (DEFAULT_SCRIM_ALPHA * 255));
+ // Reset the state
+ mAwaitingFirstLayout = !isResumingFromVisible;
+ mLastTaskLaunchedWasFreeform = false;
+
+ // Update the stack
+ mTaskStackView.onResume(isResumingFromVisible);
+ mTaskStackView.setTasks(stack, isResumingFromVisible /* notifyStackChanges */);
+
+ if (isResumingFromVisible) {
+ // If we are already visible, then restore the background scrim
+ animateBackgroundScrim(DEFAULT_SCRIM_ALPHA, DEFAULT_UPDATE_SCRIM_DURATION);
} else {
- mBackgroundScrim.setAlpha(0);
+ // If we are already occluded by the app, then set the final background scrim alpha now.
+ // Otherwise, defer until the enter animation completes to animate the scrim alpha with
+ // the tasks for the home animation.
+ if (launchState.launchedWhileDocking || launchState.launchedFromApp
+ || mStack.getTaskCount() == 0) {
+ mBackgroundScrim.setAlpha((int) (DEFAULT_SCRIM_ALPHA * 255));
+ } else {
+ mBackgroundScrim.setAlpha(0);
+ }
}
// Update the top level view's visibilities
@@ -205,9 +207,6 @@
} else {
showEmptyView();
}
-
- // Trigger a new layout
- requestLayout();
}
/**
@@ -662,14 +661,9 @@
animator.start();
}
- public final void onBusEvent(TaskStackUpdatedEvent event) {
- mStack.setTasks(event.stack.computeAllTasksList(), true /* notifyStackChanges */);
- mStack.createAffiliatedGroupings(getContext());
- }
-
public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
- if (!launchState.launchedWhileDocking && !launchState.launchedFromAppWithThumbnail
+ if (!launchState.launchedWhileDocking && !launchState.launchedFromApp
&& mStack.getTaskCount() > 0) {
animateBackgroundScrim(DEFAULT_SCRIM_ALPHA,
TaskStackAnimationHelper.ENTER_FROM_HOME_TRANSLATION_DURATION);
@@ -684,17 +678,6 @@
animateBackgroundScrim(DEFAULT_SCRIM_ALPHA, DEFAULT_UPDATE_SCRIM_DURATION);
}
- public final void onBusEvent(RecentsVisibilityChangedEvent event) {
- if (!event.visible) {
- // Reset the view state
- mAwaitingFirstLayout = true;
- mLastTaskLaunchedWasFreeform = false;
- if (RecentsDebugFlags.Static.EnableHistory) {
- hideHistoryButton(0, false /* translate */);
- }
- }
- }
-
public final void onBusEvent(ToggleHistoryEvent event) {
if (!RecentsDebugFlags.Static.EnableHistory) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
index 016d937..079d7b9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
@@ -21,7 +21,9 @@
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.ViewDebug;
+import android.widget.Toast;
+import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.events.EventBus;
@@ -148,11 +150,16 @@
mVisibleDockStates.clear();
if (!ssp.hasDockedTask() && mRv.getTaskStack().getTaskCount() > 1) {
- // Add the dock state drop targets (these take priority)
- TaskStack.DockState[] dockStates = getDockStatesForCurrentOrientation();
- for (TaskStack.DockState dockState : dockStates) {
- registerDropTargetForCurrentDrag(dockState);
- mVisibleDockStates.add(dockState);
+ if (!event.task.isDockable) {
+ Toast.makeText(mRv.getContext(), R.string.recents_drag_non_dockable_task_message,
+ Toast.LENGTH_SHORT).show();
+ } else {
+ // Add the dock state drop targets (these take priority)
+ TaskStack.DockState[] dockStates = getDockStatesForCurrentOrientation();
+ for (TaskStack.DockState dockState : dockStates) {
+ registerDropTargetForCurrentDrag(dockState);
+ mVisibleDockStates.add(dockState);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
index 1cd0850..19b219a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
@@ -16,9 +16,11 @@
package com.android.systemui.recents.views;
+import android.animation.AnimatorListenerAdapter;
import android.app.Activity;
import android.content.Context;
import android.view.View;
+import android.view.ViewPropertyAnimator;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -56,25 +58,41 @@
View.VISIBLE : View.INVISIBLE);
}
+ /**
+ * Animates the nav bar scrim visibility.
+ */
+ public void animateNavBarScrimVisibility(boolean visible, AnimationProps animation) {
+ int toY = 0;
+ if (visible) {
+ mNavBarScrimView.setVisibility(View.VISIBLE);
+ mNavBarScrimView.setTranslationY(mNavBarScrimView.getMeasuredHeight());
+ } else {
+ toY = mNavBarScrimView.getMeasuredHeight();
+ }
+ if (animation != AnimationProps.IMMEDIATE) {
+ mNavBarScrimView.animate()
+ .translationY(toY)
+ .setDuration(animation.getDuration(AnimationProps.BOUNDS))
+ .setInterpolator(animation.getInterpolator(AnimationProps.BOUNDS))
+ .start();
+ } else {
+ mNavBarScrimView.setTranslationY(toY);
+ }
+ }
+
/**** EventBus events ****/
/**
* Starts animating the scrim views when entering Recents.
*/
public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
- if (mHasNavBarScrim && mShouldAnimateNavBarScrim) {
- mNavBarScrimView.setTranslationY(mNavBarScrimView.getMeasuredHeight());
- mNavBarScrimView.animate()
- .translationY(0)
- .setDuration(mNavBarScrimEnterDuration)
- .setInterpolator(Interpolators.DECELERATE_QUINT)
- .withStartAction(new Runnable() {
- @Override
- public void run() {
- mNavBarScrimView.setVisibility(View.VISIBLE);
- }
- })
- .start();
+ if (mHasNavBarScrim) {
+ AnimationProps animation = mShouldAnimateNavBarScrim
+ ? new AnimationProps()
+ .setDuration(AnimationProps.BOUNDS, mNavBarScrimEnterDuration)
+ .setInterpolator(AnimationProps.BOUNDS, Interpolators.DECELERATE_QUINT)
+ : AnimationProps.IMMEDIATE;
+ animateNavBarScrimVisibility(true, animation);
}
}
@@ -83,13 +101,12 @@
* going home).
*/
public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
- if (mHasNavBarScrim && mShouldAnimateNavBarScrim) {
- mNavBarScrimView.animate()
- .translationY(mNavBarScrimView.getMeasuredHeight())
- .setStartDelay(0)
- .setDuration(TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION)
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .start();
+ if (mHasNavBarScrim) {
+ AnimationProps animation = new AnimationProps()
+ .setDuration(AnimationProps.BOUNDS,
+ TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION)
+ .setInterpolator(AnimationProps.BOUNDS, Interpolators.FAST_OUT_SLOW_IN);
+ animateNavBarScrimVisibility(false, animation);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
index 2cd0c19..758f4d82 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
@@ -20,8 +20,8 @@
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.content.res.Resources;
-import android.graphics.Path;
import android.graphics.RectF;
+import android.util.Log;
import android.view.View;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
@@ -56,8 +56,8 @@
/**
* Callback to start the animation for the launch target {@link TaskView}.
*/
- void onStartLaunchTargetEnterAnimation(int duration, boolean screenPinningEnabled,
- ReferenceCountedTrigger postAnimationTrigger);
+ void onStartLaunchTargetEnterAnimation(TaskViewTransform transform, int duration,
+ boolean screenPinningEnabled, ReferenceCountedTrigger postAnimationTrigger);
/**
* Callback to start the animation for the launch target {@link TaskView} when it is
@@ -141,7 +141,7 @@
tv.setVisibility(View.INVISIBLE);
} else if (launchState.launchedHasConfigurationChanged) {
// Just load the views as-is
- } else if (launchState.launchedFromAppWithThumbnail) {
+ } else if (launchState.launchedFromApp) {
if (task.isLaunchTarget) {
tv.onPrepareLaunchTargetForEnterAnimation();
} else if (currentTaskOccludesLaunchTarget) {
@@ -205,10 +205,11 @@
stackLayout.getStackTransform(task, stackScroller.getStackScroll(), mTmpTransform,
null);
- if (launchState.launchedFromAppWithThumbnail) {
+ if (launchState.launchedFromApp) {
if (task.isLaunchTarget) {
- tv.onStartLaunchTargetEnterAnimation(taskViewEnterFromAppDuration,
- mStackView.mScreenPinningEnabled, postAnimationTrigger);
+ tv.onStartLaunchTargetEnterAnimation(mTmpTransform,
+ taskViewEnterFromAppDuration, mStackView.mScreenPinningEnabled,
+ postAnimationTrigger);
} else {
// Animate the task up if it was occluding the launch target
if (currentTaskOccludesLaunchTarget) {
@@ -441,11 +442,13 @@
TaskStackViewScroller stackScroller = mStackView.getScroller();
TaskStack stack = mStackView.getStack();
+ final float curScroll = stackScroller.getStackScroll();
final float newScroll = stackLayout.getStackScrollForTask(newFocusedTask);
- boolean willScrollToFront = newScroll > stackScroller.getStackScroll();
- boolean willScroll = Float.compare(newScroll, stackScroller.getStackScroll()) != 0;
+ boolean willScrollToFront = newScroll > curScroll;
+ boolean willScroll = Float.compare(newScroll, curScroll) != 0;
// Get the current set of task transforms
+ int taskViewCount = mStackView.getTaskViews().size();
ArrayList<Task> stackTasks = stack.getStackTasks();
mStackView.getCurrentTaskTransforms(stackTasks, mTmpCurrentTaskTransforms);
@@ -463,6 +466,13 @@
// Focus the task view
TaskView newFocusedTaskView = mStackView.getChildViewForTask(newFocusedTask);
+ if (newFocusedTaskView == null) {
+ // Log the error if we have no task view, and skip the animation
+ Log.e("TaskStackAnimationHelper", "b/27389156 null-task-view prebind:" + taskViewCount +
+ " postbind:" + mStackView.getTaskViews().size() + " prescroll:" + curScroll +
+ " postscroll: " + newScroll);
+ return false;
+ }
newFocusedTaskView.setFocusedState(true, requestViewFocus);
// Setup the end listener to return all the hidden views to the view pool after the
@@ -476,7 +486,7 @@
});
List<TaskView> taskViews = mStackView.getTaskViews();
- int taskViewCount = taskViews.size();
+ taskViewCount = taskViews.size();
int newFocusTaskViewIndex = taskViews.indexOf(newFocusedTaskView);
for (int i = 0; i < taskViewCount; i++) {
TaskView tv = taskViews.get(i);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index 88bebdb..699b85e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -16,24 +16,20 @@
package com.android.systemui.recents.views;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Path;
import android.graphics.Rect;
-import android.util.ArrayMap;
import android.util.ArraySet;
-import android.util.FloatProperty;
-import android.util.Property;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
import android.view.ViewDebug;
-import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsActivityLaunchState;
import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.RecentsDebugFlags;
import com.android.systemui.recents.misc.FreePathInterpolator;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
@@ -41,6 +37,7 @@
import com.android.systemui.recents.model.TaskStack;
import java.util.ArrayList;
+import java.util.List;
/**
* Used to describe a visible range that can be normalized to [0, 1].
@@ -105,41 +102,20 @@
*/
public class TaskStackLayoutAlgorithm {
- // The scale factor to apply to the user movement in the stack to unfocus it
- private static final float UNFOCUS_MULTIPLIER = 0.8f;
-
// The distribution of view bounds alpha
// XXX: This is a hack because you can currently set the max alpha to be > 1f
public static final float OUTLINE_ALPHA_MIN_VALUE = 0f;
public static final float OUTLINE_ALPHA_MAX_VALUE = 2f;
- // The distribution of dim to apply to tasks in the stack
- private static final float DIM_MAX_VALUE = 0.35f;
- private static final Path UNFOCUSED_DIM_PATH = new Path();
- private static final Path FOCUSED_DIM_PATH = new Path();
- static {
- // The unfocused dim interpolator peaks to 1 at 0.5 (the focused task), then slowly drops
- // back to 0.5 at the front of the stack
- UNFOCUSED_DIM_PATH.moveTo(0f, 0f);
- UNFOCUSED_DIM_PATH.cubicTo(0f, 0.1f, 0.4f, 0.8f, 0.5f, 1f);
- UNFOCUSED_DIM_PATH.cubicTo(0.6f, 1f, 0.9f, 0.6f, 1f, 0.5f);
- // The focused dim interpolator peaks to 1 at 0.5 (the focused task), then drops back to 0
- // at the front of the stack
- FOCUSED_DIM_PATH.moveTo(0f, 0f);
- FOCUSED_DIM_PATH.cubicTo(0.1f, 0f, 0.4f, 1f, 0.5f, 1f);
- FOCUSED_DIM_PATH.cubicTo(0.6f, 1f, 0.9f, 0f, 1f, 0f);
- }
- private static final FreePathInterpolator UNFOCUSED_DIM_INTERPOLATOR =
- new FreePathInterpolator(UNFOCUSED_DIM_PATH);
- private static final FreePathInterpolator FOCUSED_DIM_INTERPOLATOR =
- new FreePathInterpolator(FOCUSED_DIM_PATH);
+ // The maximum dim on the tasks
+ private static final float MAX_DIM = 0.25f;
// The various focus states
- public static final float STATE_FOCUSED = 1f;
- public static final float STATE_UNFOCUSED = 0f;
+ public static final int STATE_FOCUSED = 1;
+ public static final int STATE_UNFOCUSED = 0;
public interface TaskStackLayoutAlgorithmCallbacks {
- void onFocusStateChanged(float prevFocusState, float curFocusState);
+ void onFocusStateChanged(int prevFocusState, int curFocusState);
}
/**
@@ -209,24 +185,6 @@
}
}
- /**
- * A Property wrapper around the <code>focusState</code> functionality handled by the
- * {@link TaskStackLayoutAlgorithm#setFocusState(float)} and
- * {@link TaskStackLayoutAlgorithm#getFocusState()} methods.
- */
- private static final Property<TaskStackLayoutAlgorithm, Float> FOCUS_STATE =
- new FloatProperty<TaskStackLayoutAlgorithm>("focusState") {
- @Override
- public void setValue(TaskStackLayoutAlgorithm object, float value) {
- object.setFocusState(value);
- }
-
- @Override
- public Float get(TaskStackLayoutAlgorithm object) {
- return object.getFocusState();
- }
- };
-
// A report of the visibility state of the stack
public class VisibilityReport {
public int numVisibleTasks;
@@ -264,6 +222,10 @@
private Range mUnfocusedRange;
private Range mFocusedRange;
+ // The initial offset from the top of the stack
+ @ViewDebug.ExportedProperty(category="recents")
+ private int mInitialTopPeekHeight;
+
// The offset from the top when scrolled to the top of the stack
@ViewDebug.ExportedProperty(category="recents")
private int mFocusedTopPeekHeight;
@@ -275,6 +237,10 @@
@ViewDebug.ExportedProperty(category="recents")
private int mStackTopOffset;
+ // The height of the header bar
+ @ViewDebug.ExportedProperty(category="recents")
+ private int mHeaderBarHeight;
+
// The offset from the bottom of the stack to the bottom of the bounds when the stack is
// scrolled to the front
@ViewDebug.ExportedProperty(category="recents")
@@ -286,13 +252,20 @@
private FreePathInterpolator mUnfocusedCurveInterpolator;
private FreePathInterpolator mFocusedCurveInterpolator;
+ // The paths defining the distribution of the dim to apply to tasks in the stack when focused
+ // and unfocused
+ private Path mUnfocusedDimCurve;
+ private Path mFocusedDimCurve;
+ private FreePathInterpolator mUnfocusedDimCurveInterpolator;
+ private FreePathInterpolator mFocusedDimCurveInterpolator;
+
+ // Indexed from the front of the stack, the normalized x in the unfocused range for each task
+ private float[] mInitialNormX;
+
// The state of the stack focus (0..1), which controls the transition of the stack from the
// focused to non-focused state
@ViewDebug.ExportedProperty(category="recents")
- private float mFocusState;
-
- // The animator used to reset the focused state
- private ObjectAnimator mFocusStateAnimator;
+ private int mFocusState;
// The smallest scroll progress, at this value, the back most task will be visible
@ViewDebug.ExportedProperty(category="recents")
@@ -321,7 +294,8 @@
int mMaxTranslationZ;
// Optimization, allows for quick lookup of task -> index
- private ArrayMap<Task.TaskKey, Integer> mTaskIndexMap = new ArrayMap<>();
+ private SparseIntArray mTaskIndexMap = new SparseIntArray();
+ private SparseArray<Float> mTaskIndexOverrideMap = new SparseArray<>();
// The freeform workspace layout
FreeformWorkspaceLayoutAlgorithm mFreeformLayoutAlgorithm;
@@ -331,30 +305,40 @@
TaskViewTransform mFrontOfStackTransform = new TaskViewTransform();
public TaskStackLayoutAlgorithm(Context context, TaskStackLayoutAlgorithmCallbacks cb) {
- Resources res = context.getResources();
mContext = context;
mCb = cb;
+ mFreeformLayoutAlgorithm = new FreeformWorkspaceLayoutAlgorithm(context);
+ reloadOnConfigurationChange(context);
+ }
+ /**
+ * Reloads the layout for the current configuration.
+ */
+ public void reloadOnConfigurationChange(Context context) {
+ Resources res = context.getResources();
mFocusedRange = new Range(res.getFloat(R.integer.recents_layout_focused_range_min),
res.getFloat(R.integer.recents_layout_focused_range_max));
mUnfocusedRange = new Range(res.getFloat(R.integer.recents_layout_unfocused_range_min),
res.getFloat(R.integer.recents_layout_unfocused_range_max));
- mFocusState = getDefaultFocusState();
+ mFocusState = getInitialFocusState();
+ mInitialTopPeekHeight = res.getDimensionPixelSize(R.dimen.recents_initial_top_peek_size);
mFocusedTopPeekHeight =
res.getDimensionPixelSize(R.dimen.recents_layout_focused_top_peek_size);
mFocusedBottomTaskPeekHeight =
res.getDimensionPixelSize(R.dimen.recents_layout_focused_bottom_task_peek_size);
+ mHeaderBarHeight = res.getDimensionPixelSize(R.dimen.recents_task_bar_height);
mMinTranslationZ = res.getDimensionPixelSize(R.dimen.recents_task_view_z_min);
mMaxTranslationZ = res.getDimensionPixelSize(R.dimen.recents_task_view_z_max);
- mFreeformLayoutAlgorithm = new FreeformWorkspaceLayoutAlgorithm(context);
+ mFreeformLayoutAlgorithm.reloadOnConfigurationChange(context);
}
/**
* Resets this layout when the stack view is reset.
*/
public void reset() {
- setFocusState(getDefaultFocusState());
+ mTaskIndexOverrideMap.clear();
+ setFocusState(getInitialFocusState());
}
/**
@@ -367,8 +351,8 @@
/**
* Sets the focused state.
*/
- public void setFocusState(float focusState) {
- float prevFocusState = mFocusState;
+ public void setFocusState(int focusState) {
+ int prevFocusState = mFocusState;
mFocusState = focusState;
updateFrontBackTransforms();
if (mCb != null) {
@@ -379,7 +363,7 @@
/**
* Gets the focused state.
*/
- public float getFocusState() {
+ public int getFocusState() {
return mFocusState;
}
@@ -424,6 +408,11 @@
mUnfocusedCurveInterpolator = new FreePathInterpolator(mUnfocusedCurve);
mFocusedCurve = constructFocusedCurve();
mFocusedCurveInterpolator = new FreePathInterpolator(mFocusedCurve);
+ mUnfocusedDimCurve = constructUnfocusedDimCurve();
+ mUnfocusedDimCurveInterpolator = new FreePathInterpolator(mUnfocusedDimCurve);
+ mFocusedDimCurve = constructFocusedDimCurve();
+ mFocusedDimCurveInterpolator = new FreePathInterpolator(mFocusedDimCurve);
+
updateFrontBackTransforms();
}
@@ -469,83 +458,157 @@
int taskCount = stackTasks.size();
for (int i = 0; i < taskCount; i++) {
Task task = stackTasks.get(i);
- mTaskIndexMap.put(task.key, i);
+ mTaskIndexMap.put(task.key.id, i);
}
- // Calculate the min/max scroll
- if (getDefaultFocusState() > 0f) {
- mMinScrollP = 0;
- mMaxScrollP = Math.max(mMinScrollP, mNumStackTasks - 1);
- } else {
- if (!ssp.hasFreeformWorkspaceSupport() && mNumStackTasks == 1) {
- mMinScrollP = mMaxScrollP = 0;
- } else {
- float bottomOffsetPct = (float) (mStackBottomOffset + mTaskRect.height()) /
- mStackRect.height();
- float normX = mUnfocusedCurveInterpolator.getX(bottomOffsetPct);
- mMinScrollP = 0;
- mMaxScrollP = Math.max(mMinScrollP, (mNumStackTasks - 1) -
- Math.max(0, mUnfocusedRange.getAbsoluteX(normX)));
- }
- }
-
+ // Update the freeform tasks
if (!freeformTasks.isEmpty()) {
mFreeformLayoutAlgorithm.update(freeformTasks, this);
- mInitialScrollP = mMaxScrollP;
- } else {
- Task launchTask = stack.getLaunchTarget();
- int launchTaskIndex = launchTask != null
- ? stack.indexOfStackTask(launchTask)
- : mNumStackTasks - 1;
- if (!ssp.hasFreeformWorkspaceSupport() && mNumStackTasks == 1) {
- mInitialScrollP = mMinScrollP;
- } else if (getDefaultFocusState() > 0f) {
- if (launchState.launchedFromHome) {
- mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
- } else {
- mInitialScrollP = Utilities.clamp(launchTaskIndex - 1, mMinScrollP,
- mMaxScrollP);
- }
+ }
+
+ // Calculate the min/max/initial scroll
+ Task launchTask = stack.getLaunchTarget();
+ int launchTaskIndex = launchTask != null
+ ? stack.indexOfStackTask(launchTask)
+ : mNumStackTasks - 1;
+ if (getInitialFocusState() == STATE_FOCUSED) {
+ mMinScrollP = 0;
+ mMaxScrollP = Math.max(mMinScrollP, mNumStackTasks - 1);
+ if (launchState.launchedFromHome) {
+ mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
} else {
- float offsetPct = (float) (mTaskRect.height() / 3) / mStackRect.height();
- float normX = mUnfocusedCurveInterpolator.getX(offsetPct);
- mInitialScrollP = Utilities.clamp(launchTaskIndex -
- mUnfocusedRange.getAbsoluteX(normX), mMinScrollP, mMaxScrollP);
+ mInitialScrollP = Utilities.clamp(launchTaskIndex - 1, mMinScrollP, mMaxScrollP);
+ }
+ } else if (!ssp.hasFreeformWorkspaceSupport() && mNumStackTasks == 1) {
+ // If there is one stack task, ignore the min/max/initial scroll positions
+ mMinScrollP = 0;
+ mMaxScrollP = 0;
+ mInitialScrollP = 0;
+ } else {
+ // Set the max scroll to be the point where the front most task is visible with the
+ // stack bottom offset
+ int maxBottomOffset = mStackBottomOffset + mTaskRect.height();
+ float maxBottomOffsetPct = (float) maxBottomOffset / mStackRect.height();
+ float maxBottomNormX = mUnfocusedCurveInterpolator.getX(maxBottomOffsetPct);
+ mUnfocusedRange.offset(0f);
+ mMinScrollP = 0;
+ mMaxScrollP = Math.max(mMinScrollP, (mNumStackTasks - 1) -
+ Math.max(0, mUnfocusedRange.getAbsoluteX(maxBottomNormX)));
+ boolean scrollToFront = launchState.launchedFromHome ||
+ launchState.launchedFromAppDocked;
+ if (scrollToFront) {
+ mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
+ } else {
+ mInitialScrollP = Utilities.clamp(launchTaskIndex - 1, mMinScrollP, mMaxScrollP);
+ }
+
+ // Set the initial scroll to the predefined state (which differs from the stack)
+ int initialPeekOffset = mStackRect.height() - mInitialTopPeekHeight;
+ float initialPeekOffsetPct = (float) initialPeekOffset / mStackRect.height();
+ float initialPeekOffsetNormX = mUnfocusedCurveInterpolator.getX(initialPeekOffsetPct);
+ float initialFocusedOffset = mStackRect.height() - mInitialTopPeekHeight -
+ (mHeaderBarHeight * 1f) + 1;
+ float initialFocusedOffsetPct = (float) initialFocusedOffset / mStackRect.height();
+ float initialFocusedNormX = mUnfocusedCurveInterpolator.getX(initialFocusedOffsetPct);
+ int initialBottomOffset = mStackBottomOffset + mHeaderBarHeight;
+ float initialBottomOffsetPct = (float) initialBottomOffset / mStackRect.height();
+ float initialBottomNormX = mUnfocusedCurveInterpolator.getX(initialBottomOffsetPct);
+ /*
+ // If we want to offset the top card slightly
+ mInitialNormX = scrollToFront
+ ? new float[] { initialFocusedNormX, initialPeekOffsetNormX, 0f }
+ : new float[] { initialBottomNormX, initialFocusedNormX,
+ initialPeekOffsetNormX, 0f };
+ */
+ mInitialNormX = scrollToFront
+ ? new float[] { initialFocusedNormX, initialPeekOffsetNormX, 0f }
+ : new float[] { initialBottomNormX, 0.5f, 0f };
+ }
+ }
+
+ public void updateToInitialState(List<Task> tasks) {
+ if (mInitialNormX == null) {
+ return;
+ }
+
+ mUnfocusedRange.offset(0f);
+ int taskCount = tasks.size();
+ for (int i = taskCount - 1; i >= 0; i--) {
+ int indexFromFront = taskCount - i - 1;
+ if (indexFromFront >= mInitialNormX.length) {
+ break;
+ }
+ float newTaskProgress = mInitialScrollP +
+ mUnfocusedRange.getAbsoluteX(mInitialNormX[indexFromFront]);
+ mTaskIndexOverrideMap.put(tasks.get(i).key.id, newTaskProgress);
+ }
+ }
+
+ /**
+ * Adds and override task progress for the given task when transitioning from focused to
+ * unfocused state.
+ */
+ public void addUnfocusedTaskOverride(Task task, float stackScroll) {
+ if (mFocusState != STATE_UNFOCUSED) {
+ mFocusedRange.offset(stackScroll);
+ mUnfocusedRange.offset(stackScroll);
+ float focusedRangeX = mFocusedRange.getNormalizedX(mTaskIndexMap.get(task.key.id));
+ float focusedY = mFocusedCurveInterpolator.getInterpolation(focusedRangeX);
+ float unfocusedRangeX = mUnfocusedCurveInterpolator.getX(focusedY);
+ float unfocusedTaskProgress = stackScroll + mUnfocusedRange.getAbsoluteX(unfocusedRangeX);
+ if (Float.compare(focusedRangeX, unfocusedRangeX) != 0) {
+ mTaskIndexOverrideMap.put(task.key.id, unfocusedTaskProgress);
}
}
}
+ public void clearUnfocusedTaskOverrides() {
+ mTaskIndexOverrideMap.clear();
+ }
+
/**
* Updates this stack when a scroll happens.
*/
- public void updateFocusStateOnScroll(int yMovement) {
- Utilities.cancelAnimationWithoutCallbacks(mFocusStateAnimator);
- if (mFocusState > STATE_UNFOCUSED) {
- float delta = (float) yMovement / (UNFOCUS_MULTIPLIER * mStackRect.height());
- setFocusState(mFocusState - Math.min(mFocusState, Math.abs(delta)));
+ public void updateFocusStateOnScroll(float stackScroll, float deltaScroll) {
+ if (deltaScroll == 0f) {
+ return;
}
- }
- /**
- * Aniamtes the focused state back to its orginal state.
- */
- public void animateFocusState(float newState) {
- Utilities.cancelAnimationWithoutCallbacks(mFocusStateAnimator);
- if (Float.compare(newState, getFocusState()) != 0) {
- mFocusStateAnimator = ObjectAnimator.ofFloat(this, FOCUS_STATE, getFocusState(),
- newState);
- mFocusStateAnimator.setDuration(mContext.getResources().getInteger(
- R.integer.recents_animate_task_stack_scroll_duration));
- mFocusStateAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
- mFocusStateAnimator.start();
+ for (int i = mTaskIndexOverrideMap.size() - 1; i >= 0; i--) {
+ int taskId = mTaskIndexOverrideMap.keyAt(i);
+ float x = mTaskIndexMap.get(taskId);
+ float overrideX = mTaskIndexOverrideMap.get(taskId, 0f);
+ float newOverrideX = overrideX + deltaScroll;
+ mUnfocusedRange.offset(stackScroll);
+ boolean outOfBounds = mUnfocusedRange.getNormalizedX(newOverrideX) < 0f ||
+ mUnfocusedRange.getNormalizedX(newOverrideX) > 1f;
+ if (outOfBounds || (overrideX >= x && x >= newOverrideX) ||
+ (overrideX <= x && x <= newOverrideX)) {
+ // Remove the override once we reach the original task index
+ mTaskIndexOverrideMap.removeAt(i);
+ } else if ((overrideX >= x && deltaScroll <= 0f) ||
+ (overrideX <= x && deltaScroll >= 0f)) {
+ // Scrolling from override x towards x, then lock the task in place
+ mTaskIndexOverrideMap.put(taskId, newOverrideX);
+ } else {
+ // Scrolling override x away from x, we should still move the scroll towards x
+ float deltaX = overrideX - x;
+ newOverrideX = Math.signum(deltaX) * (Math.abs(deltaX) - Math.abs(deltaScroll));
+ mTaskIndexOverrideMap.put(taskId, x + newOverrideX);
+ }
}
}
/**
* Returns the default focus state.
*/
- public float getDefaultFocusState() {
- return STATE_FOCUSED;
+ public int getInitialFocusState() {
+ RecentsDebugFlags debugFlags = Recents.getDebugFlags();
+ if (debugFlags.isPagingEnabled()) {
+ return STATE_FOCUSED;
+ } else {
+ return STATE_UNFOCUSED;
+ }
}
/**
@@ -571,6 +634,13 @@
}
/**
+ * Returns whether this stack layout has been initialized.
+ */
+ public boolean isInitialized() {
+ return !mStackRect.isEmpty();
+ }
+
+ /**
* Computes the maximum number of visible tasks and thumbnails when the scroll is at the initial
* stack scroll. Requires that update() is called first.
*/
@@ -589,7 +659,7 @@
// Otherwise, walk backwards in the stack and count the number of tasks and visible
// thumbnails and add that to the total freeform task count
TaskViewTransform tmpTransform = new TaskViewTransform();
- Range currentRange = getDefaultFocusState() > 0f ? mFocusedRange : mUnfocusedRange;
+ Range currentRange = getInitialFocusState() > 0f ? mFocusedRange : mUnfocusedRange;
currentRange.offset(mInitialScrollP);
int taskBarHeight = mContext.getResources().getDimensionPixelSize(
R.dimen.recents_task_bar_height);
@@ -612,8 +682,9 @@
boolean isFrontMostTaskInGroup = task.group == null || task.group.isFrontMostTask(task);
if (isFrontMostTaskInGroup) {
- getStackTransform(taskProgress, mInitialScrollP, mFocusState, tmpTransform, null,
- false /* ignoreSingleTaskCase */, false /* forceUpdate */);
+ getStackTransform(taskProgress, taskProgress, mInitialScrollP, mFocusState,
+ tmpTransform, null, false /* ignoreSingleTaskCase */,
+ false /* forceUpdate */);
float screenY = tmpTransform.rect.top;
boolean hasVisibleThumbnail = (prevScreenY - screenY) > taskBarHeight;
if (hasVisibleThumbnail) {
@@ -647,22 +718,34 @@
public TaskViewTransform getStackTransform(Task task, float stackScroll,
TaskViewTransform transformOut, TaskViewTransform frontTransform) {
return getStackTransform(task, stackScroll, mFocusState, transformOut, frontTransform,
- false /* forceUpdate */);
+ false /* forceUpdate */, false /* ignoreTaskOverrides */);
}
- public TaskViewTransform getStackTransform(Task task, float stackScroll, float focusState,
- TaskViewTransform transformOut, TaskViewTransform frontTransform, boolean forceUpdate) {
+ public TaskViewTransform getStackTransform(Task task, float stackScroll,
+ TaskViewTransform transformOut, TaskViewTransform frontTransform,
+ boolean ignoreTaskOverrides) {
+ return getStackTransform(task, stackScroll, mFocusState, transformOut, frontTransform,
+ false /* forceUpdate */, ignoreTaskOverrides);
+ }
+
+ public TaskViewTransform getStackTransform(Task task, float stackScroll, int focusState,
+ TaskViewTransform transformOut, TaskViewTransform frontTransform, boolean forceUpdate,
+ boolean ignoreTaskOverrides) {
if (mFreeformLayoutAlgorithm.isTransformAvailable(task, this)) {
mFreeformLayoutAlgorithm.getTransform(task, transformOut, this);
return transformOut;
} else {
// Return early if we have an invalid index
- if (task == null || !mTaskIndexMap.containsKey(task.key)) {
+ int nonOverrideTaskProgress = mTaskIndexMap.get(task.key.id, -1);
+ if (task == null || nonOverrideTaskProgress == -1) {
transformOut.reset();
return transformOut;
}
- getStackTransform(mTaskIndexMap.get(task.key), stackScroll, focusState, transformOut,
- frontTransform, false /* ignoreSingleTaskCase */, forceUpdate);
+ float taskProgress = ignoreTaskOverrides
+ ? nonOverrideTaskProgress
+ : getStackScrollForTask(task);
+ getStackTransform(taskProgress, nonOverrideTaskProgress, stackScroll, focusState,
+ transformOut, frontTransform, false /* ignoreSingleTaskCase */, forceUpdate);
return transformOut;
}
}
@@ -687,9 +770,9 @@
* internally to ensure that we can calculate the transform for any
* position in the stack.
*/
- public void getStackTransform(float taskProgress, float stackScroll, float focusState,
- TaskViewTransform transformOut, TaskViewTransform frontTransform,
- boolean ignoreSingleTaskCase, boolean forceUpdate) {
+ public void getStackTransform(float taskProgress, float nonOverrideTaskProgress,
+ float stackScroll, int focusState, TaskViewTransform transformOut,
+ TaskViewTransform frontTransform, boolean ignoreSingleTaskCase, boolean forceUpdate) {
SystemServicesProxy ssp = Recents.getSystemServices();
// Compute the focused and unfocused offset
@@ -698,6 +781,8 @@
mFocusedRange.offset(boundedStackScroll);
float boundedScrollUnfocusedRangeX = mUnfocusedRange.getNormalizedX(taskProgress);
float boundedScrollFocusedRangeX = mFocusedRange.getNormalizedX(taskProgress);
+ float boundedScrollUnfocusedNonOverrideRangeX =
+ mUnfocusedRange.getNormalizedX(nonOverrideTaskProgress);
mUnfocusedRange.offset(stackScroll);
mFocusedRange.offset(stackScroll);
boolean unfocusedVisible = mUnfocusedRange.isInRange(taskProgress);
@@ -734,16 +819,16 @@
unfocusedRangeX)) * mStackRect.height());
int focusedY = (int) ((1f - mFocusedCurveInterpolator.getInterpolation(
focusedRangeX)) * mStackRect.height());
- float unfocusedDim = 1f - UNFOCUSED_DIM_INTERPOLATOR.getInterpolation(
+ float unfocusedDim = mUnfocusedDimCurveInterpolator.getInterpolation(
boundedScrollUnfocusedRangeX);
- float focusedDim = 1f - FOCUSED_DIM_INTERPOLATOR.getInterpolation(
+ float focusedDim = mFocusedDimCurveInterpolator.getInterpolation(
boundedScrollFocusedRangeX);
y = (mStackRect.top - mTaskRect.top) +
(int) Utilities.mapRange(focusState, unfocusedY, focusedY);
- z = Utilities.mapRange(Utilities.clamp01(boundedScrollUnfocusedRangeX),
+ z = Utilities.mapRange(Utilities.clamp01(boundedScrollUnfocusedNonOverrideRangeX),
mMinTranslationZ, mMaxTranslationZ);
- dimAlpha = DIM_MAX_VALUE * Utilities.mapRange(focusState, unfocusedDim, focusedDim);
+ dimAlpha = Utilities.mapRange(focusState, unfocusedDim, focusedDim);
viewOutlineAlpha = Utilities.mapRange(Utilities.clamp01(boundedScrollUnfocusedRangeX),
OUTLINE_ALPHA_MIN_VALUE, OUTLINE_ALPHA_MAX_VALUE);
}
@@ -773,8 +858,7 @@
* stack.
*/
float getStackScrollForTask(Task t) {
- if (!mTaskIndexMap.containsKey(t.key)) return 0f;
- return mTaskIndexMap.get(t.key);
+ return mTaskIndexOverrideMap.get(t.key.id, (float) mTaskIndexMap.get(t.key.id, 0));
}
/**
@@ -842,6 +926,34 @@
}
/**
+ * Creates a new path for the focused dim curve.
+ */
+ private Path constructFocusedDimCurve() {
+ Path p = new Path();
+ // The focused dim interpolator starts at max dim, reduces to zero at 0.5 (the focused
+ // task), then goes back to max dim at the next task
+ p.moveTo(0f, MAX_DIM);
+ p.lineTo(0.5f, 0f);
+ p.lineTo(0.5f + (0.5f / mFocusedRange.relativeMax), MAX_DIM);
+ p.lineTo(1f, MAX_DIM);
+ return p;
+ }
+
+ /**
+ * Creates a new path for the unfocused dim curve.
+ */
+ private Path constructUnfocusedDimCurve() {
+ Path p = new Path();
+ // The unfocused dim interpolator starts at max dim, reduces to zero at 0.5 (the focused
+ // task), then goes back to max dim towards the front of the stack
+ p.moveTo(0f, MAX_DIM);
+ p.cubicTo(0.1f, MAX_DIM, 0.4f, 0.0f, 0.5f, 0f);
+ p.cubicTo(0.6f, 0f, 0.9f, MAX_DIM / 2f, 1f, MAX_DIM / 2f);
+ return p;
+ }
+
+
+ /**
* Updates the current transforms that would put a TaskView at the front and back of the stack.
*/
private void updateFrontBackTransforms() {
@@ -854,9 +966,9 @@
mFocusedRange.relativeMin);
float max = Utilities.mapRange(mFocusState, mUnfocusedRange.relativeMax,
mFocusedRange.relativeMax);
- getStackTransform(min, 0f, mFocusState, mBackOfStackTransform, null,
+ getStackTransform(min, min, 0f, mFocusState, mBackOfStackTransform, null,
true /* ignoreSingleTaskCase */, true /* forceUpdate */);
- getStackTransform(max, 0f, mFocusState, mFrontOfStackTransform, null,
+ getStackTransform(max, max, 0f, mFocusState, mFrontOfStackTransform, null,
true /* ignoreSingleTaskCase */, true /* forceUpdate */);
mBackOfStackTransform.visible = true;
mFrontOfStackTransform.visible = true;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 1707c4f..6abb826 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -55,6 +55,7 @@
import com.android.systemui.recents.RecentsDebugFlags;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
+import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
import com.android.systemui.recents.events.activity.EnterRecentsTaskStackAnimationCompletedEvent;
import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
@@ -64,15 +65,13 @@
import com.android.systemui.recents.events.activity.LaunchNextTaskRequestEvent;
import com.android.systemui.recents.events.activity.LaunchTaskEvent;
import com.android.systemui.recents.events.activity.LaunchTaskStartedEvent;
+import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
import com.android.systemui.recents.events.activity.PackagesChangedEvent;
import com.android.systemui.recents.events.activity.ShowHistoryButtonEvent;
import com.android.systemui.recents.events.activity.ShowHistoryEvent;
-import com.android.systemui.recents.events.activity.TaskStackUpdatedEvent;
-import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
-import com.android.systemui.recents.events.ui.StackViewScrolledEvent;
import com.android.systemui.recents.events.ui.TaskViewDismissedEvent;
import com.android.systemui.recents.events.ui.UpdateFreeformTaskViewVisibilityEvent;
import com.android.systemui.recents.events.ui.UserInteractionEvent;
@@ -117,7 +116,7 @@
private static final ArraySet<Task.TaskKey> EMPTY_TASK_SET = new ArraySet<>();
LayoutInflater mInflater;
- TaskStack mStack;
+ TaskStack mStack = new TaskStack();
@ViewDebug.ExportedProperty(deepExport=true, prefix="layout_")
TaskStackLayoutAlgorithm mLayoutAlgorithm;
@ViewDebug.ExportedProperty(deepExport=true, prefix="scroller_")
@@ -163,12 +162,11 @@
@ViewDebug.ExportedProperty(category="recents")
private Rect mStackBounds = new Rect();
- @ViewDebug.ExportedProperty(category="recents")
- private int[] mTmpVisibleRange = new int[2];
private Rect mTmpRect = new Rect();
private ArrayMap<Task.TaskKey, TaskView> mTmpTaskViewMap = new ArrayMap<>();
private List<TaskView> mTmpTaskViews = new ArrayList<>();
private TaskViewTransform mTmpTransform = new TaskViewTransform();
+ private int[] mTmpIntPair = new int[2];
// A convenience update listener to request updating clipping of tasks
private ValueAnimator.AnimatorUpdateListener mRequestUpdateClippingListener =
@@ -207,13 +205,13 @@
}
};
- public TaskStackView(Context context, TaskStack stack) {
+ public TaskStackView(Context context) {
super(context);
SystemServicesProxy ssp = Recents.getSystemServices();
Resources res = context.getResources();
// Set the stack first
- setStack(stack);
+ mStack.setCallbacks(this);
mViewPool = new ViewPool<>(context, this);
mInflater = LayoutInflater.from(context);
mLayoutAlgorithm = new TaskStackLayoutAlgorithm(context, this);
@@ -249,6 +247,41 @@
}
}
+ /**
+ * Called only if we are resuming Recents.
+ */
+ void onResume(boolean isResumingFromVisible) {
+ if (!isResumingFromVisible) {
+ // Reset the focused task
+ resetFocusedTask(getFocusedTask());
+ }
+
+ // Reset the state of each of the task views
+ List<TaskView> taskViews = new ArrayList<>();
+ taskViews.addAll(getTaskViews());
+ taskViews.addAll(mViewPool.getViews());
+ for (int i = taskViews.size() - 1; i >= 0; i--) {
+ taskViews.get(i).onResume(isResumingFromVisible);
+ }
+
+ // Reset the stack state
+ readSystemFlags();
+ mTaskViewsClipDirty = true;
+ mEnterAnimationComplete = false;
+ mUIDozeTrigger.stopDozing();
+ if (isResumingFromVisible) {
+ // Animate in the freeform workspace
+ int ffBgAlpha = mLayoutAlgorithm.getStackState().freeformBackgroundAlpha;
+ animateFreeformWorkspaceBackgroundAlpha(ffBgAlpha, new AnimationProps(150,
+ Interpolators.FAST_OUT_SLOW_IN));
+ } else {
+ mStackScroller.reset();
+ mLayoutAlgorithm.reset();
+ mAwaitingFirstLayout = true;
+ requestLayout();
+ }
+ }
+
@Override
protected void onAttachedToWindow() {
EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1);
@@ -262,22 +295,35 @@
EventBus.getDefault().unregister(this);
}
- /** Sets the task stack */
- void setStack(TaskStack stack) {
- // Set the new stack
- mStack = stack;
- if (mStack != null) {
- mStack.setCallbacks(this);
+ /**
+ * Sets the stack tasks of this TaskStackView from the given TaskStack.
+ */
+ public void setTasks(TaskStack stack, boolean notifyStackChanges) {
+ boolean isInitialized = mLayoutAlgorithm.isInitialized();
+ mStack.setTasks(getContext(), stack.computeAllTasksList(),
+ notifyStackChanges && isInitialized);
+ if (isInitialized) {
+ // Only update the layout if we are notifying, otherwise, we will update it in the next
+ // measure/layout pass
+ updateLayoutAlgorithm(false /* boundScroll */, EMPTY_TASK_SET);
+ updateToInitialState();
+ relayoutTaskViewsOnNextFrame(AnimationProps.IMMEDIATE);
}
- // Layout again with the new stack
- requestLayout();
}
/** Returns the task stack. */
- TaskStack getStack() {
+ public TaskStack getStack() {
return mStack;
}
+ /**
+ * Updates this TaskStackView to the initial state.
+ */
+ public void updateToInitialState() {
+ mStackScroller.setStackScrollToInitialState();
+ mLayoutAlgorithm.updateToInitialState(mStack.getStackTasks());
+ }
+
/** Updates the list of task views */
void updateTaskViewsList() {
mTaskViews.clear();
@@ -331,37 +377,6 @@
return null;
}
- /** Resets this TaskStackView for reuse. */
- void reset() {
- // Reset the focused task
- resetFocusedTask(getFocusedTask());
-
- // Return all the views to the pool
- List<TaskView> taskViews = getTaskViews();
- int taskViewCount = taskViews.size();
- for (int i = taskViewCount - 1; i >= 0; i--) {
- mViewPool.returnViewToPool(taskViews.get(i));
- }
-
- // Mark each task view for relayout
- List<TaskView> poolViews = mViewPool.getViews();
- for (TaskView tv : poolViews) {
- tv.reset();
- }
-
- // Reset the stack state
- mStack.reset();
- mTaskViewsClipDirty = true;
- mAwaitingFirstLayout = true;
- mEnterAnimationComplete = false;
- mUIDozeTrigger.stopDozing();
- mUIDozeTrigger.resetTrigger();
- mStackScroller.reset();
- mLayoutAlgorithm.reset();
- readSystemFlags();
- requestLayout();
- }
-
/** Returns the stack algorithm for this task stack. */
public TaskStackLayoutAlgorithm getStackAlgorithm() {
return mLayoutAlgorithm;
@@ -405,15 +420,17 @@
* target stack scrolls will be returned.
* @param ignoreTasksSet The set of tasks to skip for purposes of calculaing the visible range.
* Transforms will still be calculated for the ignore tasks.
+ * @return the front and back most visible task indices (there may be non visible tasks in
+ * between this range)
*/
- boolean computeVisibleTaskTransforms(ArrayList<TaskViewTransform> taskTransforms,
+ int[] computeVisibleTaskTransforms(ArrayList<TaskViewTransform> taskTransforms,
ArrayList<Task> tasks, float curStackScroll, float targetStackScroll,
- int[] visibleRangeOut, ArraySet<Task.TaskKey> ignoreTasksSet) {
+ ArraySet<Task.TaskKey> ignoreTasksSet, boolean ignoreTaskOverrides) {
int taskCount = tasks.size();
- int frontMostVisibleIndex = -1;
- int backMostVisibleIndex = -1;
+ int[] visibleTaskRange = mTmpIntPair;
+ visibleTaskRange[0] = -1;
+ visibleTaskRange[1] = -1;
boolean useTargetStackScroll = Float.compare(curStackScroll, targetStackScroll) != 0;
- boolean targetScrollIsInFront = targetStackScroll > curStackScroll;
// We can reuse the task transforms where possible to reduce object allocation
Utilities.matchTaskListSize(tasks, taskTransforms);
@@ -428,7 +445,7 @@
// Calculate the current and (if necessary) the target transform for the task
transform = mLayoutAlgorithm.getStackTransform(task, curStackScroll,
- taskTransforms.get(i), frontTransform);
+ taskTransforms.get(i), frontTransform, ignoreTaskOverrides);
if (useTargetStackScroll && !transform.visible) {
// If we have a target stack scroll and the task is not currently visible, then we
// just update the transform at the new scroll
@@ -452,40 +469,27 @@
continue;
}
- if (transform.visible) {
- if (frontMostVisibleIndex < 0) {
- frontMostVisibleIndex = i;
- }
- backMostVisibleIndex = i;
- } else if (!targetScrollIsInFront) {
- if (backMostVisibleIndex != -1) {
- // We've reached the end of the visible range, so going down the rest of the
- // stack, we can just reset the transforms accordingly
- while (i >= 0) {
- taskTransforms.get(i).reset();
- i--;
- }
- break;
- }
- }
-
frontTransform = transform;
frontTransformAtTarget = transformAtTarget;
+ if (transform.visible) {
+ if (visibleTaskRange[0] < 0) {
+ visibleTaskRange[0] = i;
+ }
+ visibleTaskRange[1] = i;
+ }
}
- if (visibleRangeOut != null) {
- visibleRangeOut[0] = frontMostVisibleIndex;
- visibleRangeOut[1] = backMostVisibleIndex;
- }
- return frontMostVisibleIndex != -1 && backMostVisibleIndex != -1;
+ return visibleTaskRange;
}
/**
* Binds the visible {@link TaskView}s at the given target scroll.
- *
- * @see #bindVisibleTaskViews(float, ArraySet<Task.TaskKey>)
*/
void bindVisibleTaskViews(float targetStackScroll) {
- bindVisibleTaskViews(targetStackScroll, mIgnoreTasks);
+ bindVisibleTaskViews(targetStackScroll, mIgnoreTasks, false /* ignoreTaskOverrides */);
+ }
+
+ void bindVisibleTaskViews(float targetStackScroll, boolean ignoreTaskOverrides) {
+ bindVisibleTaskViews(targetStackScroll, mIgnoreTasks, ignoreTaskOverrides);
}
/**
@@ -500,15 +504,16 @@
* target stack scroll.
* @param ignoreTasksSet The set of tasks to ignore in this rebinding of the visible
* {@link TaskView}s
+ * @param ignoreTaskOverrides If set, the visible task computation will get the transforms for
+ * tasks at their non-overridden task progress
*/
- void bindVisibleTaskViews(float targetStackScroll, ArraySet<Task.TaskKey> ignoreTasksSet) {
- final int[] visibleStackRange = mTmpVisibleRange;
-
+ void bindVisibleTaskViews(float targetStackScroll, ArraySet<Task.TaskKey> ignoreTasksSet,
+ boolean ignoreTaskOverrides) {
// Get all the task transforms
- final ArrayList<Task> tasks = mStack.getStackTasks();
- final boolean isValidVisibleRange = computeVisibleTaskTransforms(mCurrentTaskTransforms,
- tasks, mStackScroller.getStackScroll(), targetStackScroll, visibleStackRange,
- ignoreTasksSet);
+ ArrayList<Task> tasks = mStack.getStackTasks();
+ int[] visibleTaskRange = computeVisibleTaskTransforms(mCurrentTaskTransforms, tasks,
+ mStackScroller.getStackScroll(), targetStackScroll, ignoreTasksSet,
+ ignoreTaskOverrides);
// Return all the invisible children to the pool
mTmpTaskViewMap.clear();
@@ -518,15 +523,22 @@
for (int i = taskViewCount - 1; i >= 0; i--) {
TaskView tv = taskViews.get(i);
Task task = tv.getTask();
- int taskIndex = mStack.indexOfStackTask(task);
// Skip ignored tasks
if (ignoreTasksSet.contains(task.key)) {
continue;
}
- if (task.isFreeformTask() ||
- visibleStackRange[1] <= taskIndex && taskIndex <= visibleStackRange[0]) {
+ // It is possible for the set of lingering TaskViews to differ from the stack if the
+ // stack was updated before the relayout. If the task view is no longer in the stack,
+ // then just return it back to the view pool.
+ int taskIndex = mStack.indexOfStackTask(task);
+ TaskViewTransform transform = null;
+ if (taskIndex != -1) {
+ transform = mCurrentTaskTransforms.get(taskIndex);
+ }
+
+ if (task.isFreeformTask() || (transform != null && transform.visible)) {
mTmpTaskViewMap.put(task.key, tv);
} else {
if (mTouchExplorationEnabled) {
@@ -538,8 +550,7 @@
}
// Pick up all the newly visible children
- int lastVisStackIndex = isValidVisibleRange ? visibleStackRange[1] : 0;
- for (int i = tasks.size() - 1; i >= lastVisStackIndex; i--) {
+ for (int i = tasks.size() - 1; i >= 0; i--) {
Task task = tasks.get(i);
TaskViewTransform transform = mCurrentTaskTransforms.get(i);
@@ -584,11 +595,11 @@
// Update the focus if the previous focused task was returned to the view pool
if (lastFocusedTaskIndex != -1) {
- if (lastFocusedTaskIndex < visibleStackRange[1]) {
- setFocusedTask(visibleStackRange[1], false /* scrollToTask */,
+ if (lastFocusedTaskIndex < visibleTaskRange[1]) {
+ setFocusedTask(visibleTaskRange[1], false /* scrollToTask */,
true /* requestViewFocus */);
} else {
- setFocusedTask(visibleStackRange[0], false /* scrollToTask */,
+ setFocusedTask(visibleTaskRange[0], false /* scrollToTask */,
true /* requestViewFocus */);
}
}
@@ -622,7 +633,8 @@
cancelAllTaskViewAnimations();
// Synchronize the current set of TaskViews
- bindVisibleTaskViews(mStackScroller.getStackScroll(), ignoreTasksSet);
+ bindVisibleTaskViews(mStackScroller.getStackScroll(), ignoreTasksSet,
+ false /* ignoreTaskOverrides */);
// Animate them to their final transforms with the given animation
List<TaskView> taskViews = getTaskViews();
@@ -665,7 +677,7 @@
public void getCurrentTaskTransforms(ArrayList<Task> tasks,
ArrayList<TaskViewTransform> transformsOut) {
Utilities.matchTaskListSize(tasks, transformsOut);
- float focusState = mLayoutAlgorithm.getFocusState();
+ int focusState = mLayoutAlgorithm.getFocusState();
for (int i = tasks.size() - 1; i >= 0; i--) {
Task task = tasks.get(i);
TaskViewTransform transform = transformsOut.get(i);
@@ -674,7 +686,8 @@
transform.fillIn(tv);
} else {
mLayoutAlgorithm.getStackTransform(task, mStackScroller.getStackScroll(),
- focusState, transform, null, true /* forceUpdate */);
+ focusState, transform, null, true /* forceUpdate */,
+ false /* ignoreTaskOverrides */);
}
transform.visible = true;
}
@@ -684,14 +697,14 @@
* Returns the task transforms for all the tasks in the stack if the stack was at the given
* {@param stackScroll} and {@param focusState}.
*/
- public void getLayoutTaskTransforms(float stackScroll, float focusState, ArrayList<Task> tasks,
+ public void getLayoutTaskTransforms(float stackScroll, int focusState, ArrayList<Task> tasks,
ArrayList<TaskViewTransform> transformsOut) {
Utilities.matchTaskListSize(tasks, transformsOut);
for (int i = tasks.size() - 1; i >= 0; i--) {
Task task = tasks.get(i);
TaskViewTransform transform = transformsOut.get(i);
mLayoutAlgorithm.getStackTransform(task, stackScroll, focusState, transform, null,
- true /* forceUpdate */);
+ true /* forceUpdate */, true /* ignoreTaskOverrides */);
transform.visible = true;
}
}
@@ -776,9 +789,7 @@
}
}
tv.getViewBounds().setClipBottom(clipBottom);
- if (!config.useHardwareLayers) {
- tv.mThumbnailView.updateThumbnailVisibility(clipBottom - tv.getPaddingBottom());
- }
+ tv.mThumbnailView.updateThumbnailVisibility(clipBottom - tv.getPaddingBottom());
prevVisibleTv = tv;
}
mTaskViewsClipDirty = false;
@@ -877,6 +888,7 @@
cancelAllTaskViewAnimations();
}
+ mLayoutAlgorithm.clearUnfocusedTaskOverrides();
willScroll = mAnimationHelper.startScrollToFocusedTaskAnimation(newFocusedTask,
requestViewFocus);
} else {
@@ -1055,7 +1067,7 @@
protected Parcelable onSaveInstanceState() {
Bundle savedState = new Bundle();
savedState.putParcelable(KEY_SAVED_STATE_SUPER, super.onSaveInstanceState());
- savedState.putFloat(KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE, mLayoutAlgorithm.getFocusState());
+ savedState.putInt(KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE, mLayoutAlgorithm.getFocusState());
savedState.putFloat(KEY_SAVED_STATE_LAYOUT_STACK_SCROLL, mStackScroller.getStackScroll());
return super.onSaveInstanceState();
}
@@ -1065,7 +1077,7 @@
Bundle savedState = (Bundle) state;
super.onRestoreInstanceState(savedState.getParcelable(KEY_SAVED_STATE_SUPER));
- mLayoutAlgorithm.setFocusState(savedState.getFloat(KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE));
+ mLayoutAlgorithm.setFocusState(savedState.getInt(KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE));
mStackScroller.setStackScroll(savedState.getFloat(KEY_SAVED_STATE_LAYOUT_STACK_SCROLL));
}
@@ -1124,15 +1136,6 @@
}
/**
- * This is ONLY used from the Recents component to update the dummy stack view for purposes
- * of getting the task rect to animate to.
- */
- public void updateLayoutForStack(TaskStack stack) {
- mStack = stack;
- updateLayoutAlgorithm(false /* boundScroll */, EMPTY_TASK_SET);
- }
-
- /**
* Computes the maximum number of visible tasks and thumbnails. Requires that
* updateLayoutForStack() is called first.
*/
@@ -1179,11 +1182,16 @@
// If this is the first layout, then scroll to the front of the stack, then update the
// TaskViews with the stack so that we can lay them out
- if (mAwaitingFirstLayout) {
- mStackScroller.setStackScrollToInitialState();
+ // TODO: The second check is a workaround for wacky layouts that we get while docking via
+ // long pressing the recents button
+ if (mAwaitingFirstLayout ||
+ (mStackScroller.getStackScroll() == mLayoutAlgorithm.mInitialScrollP)) {
+ updateToInitialState();
}
+
// Rebind all the views, including the ignore ones
- bindVisibleTaskViews(mStackScroller.getStackScroll(), EMPTY_TASK_SET);
+ bindVisibleTaskViews(mStackScroller.getStackScroll(), EMPTY_TASK_SET,
+ false /* ignoreTaskOverrides */);
// Measure each of the TaskViews
mTmpTaskViews.clear();
@@ -1422,7 +1430,7 @@
public void onReturnViewToPool(TaskView tv) {
final Task task = tv.getTask();
- // Report that this tasks's data is no longer being used
+ // Report that this task's data is no longer being used
Recents.getTaskLoader().unloadTaskData(task);
// Reset the view properties and view state
@@ -1475,7 +1483,7 @@
Recents.getTaskLoader().loadTaskData(task, true /* fetchAndInvalidateThumbnails */);
// If the doze trigger has already fired, then update the state for this task view
- if (mUIDozeTrigger.hasTriggered()) {
+ if (mUIDozeTrigger.isAsleep()) {
tv.setNoUserInteractionState();
}
@@ -1517,7 +1525,7 @@
/**** TaskStackLayoutAlgorithm.TaskStackLayoutAlgorithmCallbacks ****/
@Override
- public void onFocusStateChanged(float prevFocusState, float curFocusState) {
+ public void onFocusStateChanged(int prevFocusState, int curFocusState) {
if (mDeferredTaskViewLayoutAnimation == null) {
mUIDozeTrigger.poke();
relayoutTaskViewsOnNextFrame(AnimationProps.IMMEDIATE);
@@ -1532,6 +1540,7 @@
if (animation != null) {
relayoutTaskViewsOnNextFrame(animation);
}
+ mLayoutAlgorithm.updateFocusStateOnScroll(curScroll, curScroll - prevScroll);
if (mEnterAnimationComplete) {
if (shouldShowHistoryButton() &&
@@ -1589,6 +1598,9 @@
Task launchTask = mStack.getStackTasks().get(launchTaskIndex);
EventBus.getDefault().send(new LaunchTaskEvent(getChildViewForTask(launchTask),
launchTask, null, INVALID_STACK_ID, false /* screenPinningRequested */));
+
+ MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_LAUNCH_PREVIOUS_TASK,
+ launchTask.key.getComponent().toString());
}
}
@@ -1636,11 +1648,19 @@
}
public final void onBusEvent(FocusNextTaskViewEvent event) {
+ // Stop any scrolling
+ mStackScroller.stopScroller();
+ mStackScroller.stopBoundScrollAnimation();
+
setRelativeFocusedTask(true, false /* stackTasksOnly */, true /* animated */, false,
event.timerIndicatorDuration);
}
public final void onBusEvent(FocusPreviousTaskViewEvent event) {
+ // Stop any scrolling
+ mStackScroller.stopScroller();
+ mStackScroller.stopBoundScrollAnimation();
+
setRelativeFocusedTask(false, false /* stackTasksOnly */, true /* animated */);
}
@@ -1657,12 +1677,6 @@
}
}
- public final void onBusEvent(RecentsVisibilityChangedEvent event) {
- if (!event.visible) {
- reset();
- }
- }
-
public final void onBusEvent(DragStartEvent event) {
// Ensure that the drag task is not animated
addIgnoreTask(event.task);
@@ -1759,22 +1773,20 @@
event.taskView.setLeftTopRightBottom(taskViewRect.left, taskViewRect.top,
taskViewRect.right, taskViewRect.bottom);
- // Animate all the TaskViews back into position
+ // Animate the non-drag TaskViews back into position
mLayoutAlgorithm.getStackTransform(event.task, getScroller().getStackScroll(),
mTmpTransform, null);
event.getAnimationTrigger().increment();
relayoutTaskViews(new AnimationProps(DEFAULT_SYNC_STACK_DURATION,
Interpolators.FAST_OUT_SLOW_IN));
+
+ // Animate the drag TaskView back into position
updateTaskViewToTransform(event.taskView, mTmpTransform,
new AnimationProps(DEFAULT_SYNC_STACK_DURATION, Interpolators.FAST_OUT_SLOW_IN,
event.getAnimationTrigger().decrementOnAnimationEnd()));
removeIgnoreTask(event.task);
}
- public final void onBusEvent(StackViewScrolledEvent event) {
- mLayoutAlgorithm.updateFocusStateOnScroll(event.yMovement.value);
- }
-
public final void onBusEvent(IterateRecentsEvent event) {
if (!mEnterAnimationComplete) {
// Cancel the previous task's window transition before animating the focused state
@@ -1841,15 +1853,28 @@
mAnimationHelper.startHideHistoryAnimation();
}
- public final void onBusEvent(TaskStackUpdatedEvent event) {
- // Scroll the stack to the front after it has been updated
- event.addPostAnimationCallback(new Runnable() {
- @Override
- public void run() {
- mStackScroller.animateScroll(mLayoutAlgorithm.mMaxScrollP,
- null /* postScrollRunnable */);
- }
- });
+ public final void onBusEvent(MultiWindowStateChangedEvent event) {
+ if (!event.inMultiWindow) {
+ // Scroll the stack to the front to see the undocked task
+ mStackScroller.animateScroll(mLayoutAlgorithm.mMaxScrollP, new Runnable() {
+ @Override
+ public void run() {
+ List<TaskView> taskViews = getTaskViews();
+ int taskViewCount = taskViews.size();
+ for (int i = 0; i < taskViewCount; i++) {
+ TaskView tv = taskViews.get(i);
+ tv.getHeaderView().rebindToTask(tv.getTask(), tv.mTouchExplorationEnabled,
+ tv.mIsDisabledInSafeMode);
+ }
+ }
+ });
+ }
+ }
+
+ public final void onBusEvent(ConfigurationChangedEvent event) {
+ mLayoutAlgorithm.reloadOnConfigurationChange(getContext());
+ mLayoutAlgorithm.initialize(mStackBounds,
+ TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
index 333df9d..ad46abd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
@@ -115,13 +115,8 @@
* @return whether the stack progress changed.
*/
public boolean setStackScrollToInitialState() {
- SystemServicesProxy ssp = Recents.getSystemServices();
float prevStackScrollP = mStackScrollP;
- if (ssp.hasDockedTask()) {
- setStackScroll(mLayoutAlgorithm.mMaxScrollP);
- } else {
- setStackScroll(mLayoutAlgorithm.mInitialScrollP);
- }
+ setStackScroll(mLayoutAlgorithm.mInitialScrollP);
return Float.compare(prevStackScrollP, mStackScrollP) != 0;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index fe504fe..52f8fc8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -223,6 +223,13 @@
int xDiff = Math.abs(x - mDownX);
if (Math.abs(y - mDownY) > mScrollTouchSlop && yDiff > xDiff) {
mIsScrolling = true;
+ float stackScroll = mScroller.getStackScroll();
+ List<TaskView> taskViews = mSv.getTaskViews();
+ for (int i = taskViews.size() - 1; i >= 0; i--) {
+ layoutAlgorithm.addUnfocusedTaskOverride(taskViews.get(i).getTask(),
+ stackScroll);
+ }
+ layoutAlgorithm.setFocusState(TaskStackLayoutAlgorithm.STATE_UNFOCUSED);
// Disallow parents from intercepting touch events
final ViewParent parent = mSv.getParent();
@@ -429,8 +436,7 @@
// Otherwise, offset the scroll by the movement of the anchor task
float anchorTaskScroll = layoutAlgorithm.getStackScrollForTask(anchorTask);
float stackScrollOffset = (anchorTaskScroll - prevAnchorTaskScroll);
- if (layoutAlgorithm.getFocusState() !=
- TaskStackLayoutAlgorithm.STATE_FOCUSED) {
+ if (layoutAlgorithm.getFocusState() != TaskStackLayoutAlgorithm.STATE_FOCUSED) {
// If we are focused, we don't want the front task to move, but otherwise, we
// allow the back task to move up, and the front task to move back
stackScrollOffset /= 2;
@@ -440,7 +446,7 @@
}
// Pick up the newly visible views, not including the deleting tasks
- mSv.bindVisibleTaskViews(newStackScroll);
+ mSv.bindVisibleTaskViews(newStackScroll, true /* ignoreTaskOverrides */);
// Get the final set of task transforms (with task removed)
mSv.getLayoutTaskTransforms(newStackScroll, TaskStackLayoutAlgorithm.STATE_UNFOCUSED,
@@ -480,6 +486,7 @@
mSv.getScroller().setStackScroll(mTargetStackScroll, null);
// Update the focus state to the final focus state
mSv.getStackAlgorithm().setFocusState(TaskStackLayoutAlgorithm.STATE_UNFOCUSED);
+ mSv.getStackAlgorithm().clearUnfocusedTaskOverrides();
// Remove the task view from the stack
EventBus.getDefault().send(new TaskViewDismissedEvent(tv.getTask(), tv));
// Stop tracking this deletion animation
@@ -494,7 +501,7 @@
* onChildDismissed() calls.
*/
@Override
- public void onChildSnappedBack(View v) {
+ public void onChildSnappedBack(View v, float targetLeft) {
TaskView tv = (TaskView) v;
// Re-enable clipping with the stack
@@ -517,11 +524,6 @@
}
@Override
- public View getChildContentView(View v) {
- return v;
- }
-
- @Override
public boolean isAntiFalsingNeeded() {
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 0c78e6a..0bc7f89 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -77,6 +77,24 @@
/**
* The dim overlay is generally calculated from the task progress, but occasionally (like when
+ * launching) needs to be animated independently of the task progress. This call is only used
+ * when animating the task into Recents, when the header dim is already applied
+ */
+ public static final Property<TaskView, Float> DIM_ALPHA_WITHOUT_HEADER =
+ new FloatProperty<TaskView>("dimAlphaWithoutHeader") {
+ @Override
+ public void setValue(TaskView tv, float dimAlpha) {
+ tv.setDimAlphaWithoutHeader(dimAlpha);
+ }
+
+ @Override
+ public Float get(TaskView tv) {
+ return tv.getDimAlpha();
+ }
+ };
+
+ /**
+ * The dim overlay is generally calculated from the task progress, but occasionally (like when
* launching) needs to be animated independently of the task progress.
*/
public static final Property<TaskView, Float> DIM_ALPHA =
@@ -175,11 +193,13 @@
}
/** Resets this TaskView for reuse. */
- void reset() {
- resetViewProperties();
+ void onResume(boolean isResumingFromVisible) {
resetNoUserInteractionState();
readSystemFlags();
- setClipViewInStack(false);
+ if (!isResumingFromVisible) {
+ resetViewProperties();
+ setClipViewInStack(false);
+ }
setCallbacks(null);
}
@@ -388,21 +408,17 @@
* Sets the current dim.
*/
public void setDimAlpha(float dimAlpha) {
- RecentsConfiguration config = Recents.getConfiguration();
-
- int dimAlphaInt = (int) (dimAlpha * 255);
mDimAlpha = dimAlpha;
- if (config.useHardwareLayers) {
- // Defer setting hardware layers if we have not yet measured, or there is no dim to draw
- if (getMeasuredWidth() > 0 && getMeasuredHeight() > 0) {
- mDimColorFilter.setColor(Color.argb(dimAlphaInt, 0, 0, 0));
- mDimLayerPaint.setColorFilter(mDimColorFilter);
- mContent.setLayerType(LAYER_TYPE_HARDWARE, mDimLayerPaint);
- }
- } else {
- mThumbnailView.setDimAlpha(dimAlpha);
- mHeaderView.setDimAlpha(dimAlpha);
- }
+ mThumbnailView.setDimAlpha(dimAlpha);
+ mHeaderView.setDimAlpha(dimAlpha);
+ }
+
+ /**
+ * Sets the current dim without updating the header's dim.
+ */
+ public void setDimAlphaWithoutHeader(float dimAlpha) {
+ mDimAlpha = dimAlpha;
+ mThumbnailView.setDimAlpha(dimAlpha);
}
/**
@@ -413,25 +429,6 @@
}
/**
- * Animates the dim to the given value.
- */
- void animateDimAlpha(float toDimAlpha, AnimationProps animation) {
- // Animate the dim into view as well
- if (Float.compare(toDimAlpha, getDimAlpha()) != 0) {
- Animator anim = animation.apply(AnimationProps.DIM_ALPHA, ObjectAnimator.ofFloat(this,
- DIM_ALPHA, getDimAlpha(), toDimAlpha));
- if (animation.getListener() != null) {
- anim.addListener(animation.getListener());
- }
- anim.start();
- } else {
- if (animation.getListener() != null) {
- animation.getListener().onAnimationEnd(null);
- }
- }
- }
-
- /**
* Explicitly sets the focused state of this task.
*/
public void setFocusedState(boolean isFocused, boolean requestViewFocus) {
@@ -517,18 +514,20 @@
@Override
public void onPrepareLaunchTargetForEnterAnimation() {
// These values will be animated in when onStartLaunchTargetEnterAnimation() is called
- setDimAlpha(0);
+ setDimAlphaWithoutHeader(0);
mActionButtonView.setAlpha(0f);
}
@Override
- public void onStartLaunchTargetEnterAnimation(int duration, boolean screenPinningEnabled,
- ReferenceCountedTrigger postAnimationTrigger) {
- // Un-dim the view before/while launching the target
- AnimationProps animation = new AnimationProps(duration, Interpolators.ALPHA_OUT)
- .setListener(postAnimationTrigger.decrementOnAnimationEnd());
+ public void onStartLaunchTargetEnterAnimation(TaskViewTransform transform, int duration,
+ boolean screenPinningEnabled, ReferenceCountedTrigger postAnimationTrigger) {
+ // Dim the view after the app window transitions down into recents
postAnimationTrigger.increment();
- animateDimAlpha(0, animation);
+ AnimationProps animation = new AnimationProps(duration, Interpolators.ALPHA_OUT);
+ Animator anim = animation.apply(AnimationProps.DIM_ALPHA, ObjectAnimator.ofFloat(this,
+ DIM_ALPHA_WITHOUT_HEADER, getDimAlpha(), transform.dimAlpha));
+ anim.addListener(postAnimationTrigger.decrementOnAnimationEnd());
+ anim.start();
if (screenPinningEnabled) {
showActionButton(true /* fadeIn */, duration /* fadeInDuration */);
@@ -540,7 +539,9 @@
ReferenceCountedTrigger postAnimationTrigger) {
// Un-dim the view before/while launching the target
AnimationProps animation = new AnimationProps(duration, Interpolators.ALPHA_OUT);
- animateDimAlpha(0, animation);
+ Animator anim = animation.apply(AnimationProps.DIM_ALPHA, ObjectAnimator.ofFloat(this,
+ DIM_ALPHA, getDimAlpha(), 0));
+ anim.start();
postAnimationTrigger.increment();
hideActionButton(true /* fadeOut */, duration,
@@ -603,7 +604,7 @@
EventBus.getDefault().send(new LaunchTaskEvent(this, mTask, null, INVALID_STACK_ID,
screenPinningRequested));
- MetricsLogger.action(v.getContext(), MetricsEvent.OVERVIEW_SELECT,
+ MetricsLogger.action(v.getContext(), MetricsEvent.ACTION_OVERVIEW_SELECT,
mTask.key.getComponent().toString());
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index bb56a52..b2a7d90 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -63,7 +63,7 @@
public class TaskViewHeader extends FrameLayout
implements View.OnClickListener, View.OnLongClickListener {
- private static final float HIGHLIGHT_LIGHTNESS_INCREMENT = 0.125f;
+ private static final float HIGHLIGHT_LIGHTNESS_INCREMENT = 0.075f;
private static final float OVERLAY_LIGHTNESS_INCREMENT = -0.0625f;
private static final int OVERLAY_REVEAL_DURATION = 250;
private static final long FOCUS_INDICATOR_INTERVAL_MS = 30;
@@ -139,6 +139,7 @@
// Header views
ImageView mIconView;
TextView mTitleView;
+ TextView mSubTitleView;
ImageView mMoveTaskButton;
ImageView mDismissButton;
ViewStub mAppOverlayViewStub;
@@ -237,6 +238,7 @@
mIconView.setClickable(false);
mIconView.setOnLongClickListener(this);
mTitleView = (TextView) findViewById(R.id.title);
+ mSubTitleView = (TextView) findViewById(R.id.sub_title);
mDismissButton = (ImageView) findViewById(R.id.dismiss_task);
if (ssp.hasFreeformWorkspaceSupport()) {
mMoveTaskButton = (ImageView) findViewById(R.id.move_task);
@@ -345,9 +347,11 @@
* Sets the dim alpha, only used when we are not using hardware layers.
* (see RecentsConfiguration.useHardwareLayers)
*/
- void setDimAlpha(float dimAlpha) {
- mDimAlpha = dimAlpha;
- updateBackgroundColor(mBackground.getColor(), dimAlpha);
+ public void setDimAlpha(float dimAlpha) {
+ if (Float.compare(mDimAlpha, dimAlpha) != 0) {
+ mDimAlpha = dimAlpha;
+ updateBackgroundColor(mBackground.getColor(), dimAlpha);
+ }
}
/**
@@ -367,6 +371,7 @@
/** Binds the bar view to the task */
public void rebindToTask(Task t, boolean touchExplorationEnabled, boolean disabledInSafeMode) {
+ SystemServicesProxy ssp = Recents.getSystemServices();
mTask = t;
// If an activity icon is defined, then we use that as the primary icon to show in the bar,
@@ -374,7 +379,9 @@
int primaryColor = disabledInSafeMode
? mDisabledTaskBarBackgroundColor
: t.colorPrimary;
- updateBackgroundColor(primaryColor, mDimAlpha);
+ if (mBackground.getColor() != primaryColor) {
+ updateBackgroundColor(primaryColor, mDimAlpha);
+ }
if (t.icon != null) {
mIconView.setImageDrawable(t.icon);
}
@@ -384,6 +391,13 @@
mTitleView.setContentDescription(t.contentDescription);
mTitleView.setTextColor(t.useLightOnPrimaryColor ?
mTaskBarViewLightTextColor : mTaskBarViewDarkTextColor);
+ if (!t.isDockable && ssp.hasDockedTask()) {
+ mSubTitleView.setVisibility(View.VISIBLE);
+ mSubTitleView.setTextColor(t.useLightOnPrimaryColor ?
+ mTaskBarViewLightTextColor : mTaskBarViewDarkTextColor);
+ } else {
+ mSubTitleView.setVisibility(View.GONE);
+ }
mDismissButton.setImageDrawable(t.useLightOnPrimaryColor ?
mLightDismissDrawable : mDarkDismissDrawable);
mDismissButton.setContentDescription(t.dismissDescription);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index 0fec9c3..e46708e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -183,9 +183,9 @@
mat[0] = scale;
mat[6] = scale;
mat[12] = scale;
- mat[4] = mDimAlpha;
- mat[9] = mDimAlpha;
- mat[14] = mDimAlpha;
+ mat[4] = mDimAlpha * 255f;
+ mat[9] = mDimAlpha * 255f;
+ mat[14] = mDimAlpha * 255f;
TMP_FILTER_COLOR_MATRIX.preConcat(TMP_BRIGHTNESS_COLOR_MATRIX);
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(TMP_FILTER_COLOR_MATRIX);
mDrawPaint.setColorFilter(filter);
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index e6a291c..a06700d 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -75,9 +75,9 @@
Uri imageUri;
Runnable finisher;
int iconSize;
- int result;
int previewWidth;
int previewheight;
+ int errorMsgResId;
void clearImage() {
image = null;
@@ -94,13 +94,11 @@
*/
class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Void,
SaveImageInBackgroundData> {
- private static final String TAG = "SaveImageInBackgroundTask";
private static final String SCREENSHOTS_DIR_NAME = "Screenshots";
private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
private static final String SCREENSHOT_SHARE_SUBJECT_TEMPLATE = "Screenshot (%s)";
- private final int mNotificationId;
private final NotificationManager mNotificationManager;
private final Notification.Builder mNotificationBuilder, mPublicNotificationBuilder;
private final File mScreenshotDir;
@@ -119,7 +117,7 @@
private static boolean mTickerAddSpace;
SaveImageInBackgroundTask(Context context, SaveImageInBackgroundData data,
- NotificationManager nManager, int nId) {
+ NotificationManager nManager) {
Resources r = context.getResources();
// Prepare all the output metadata
@@ -166,25 +164,14 @@
// Show the intermediate notification
mTickerAddSpace = !mTickerAddSpace;
- mNotificationId = nId;
mNotificationManager = nManager;
final long now = System.currentTimeMillis();
- mNotificationBuilder = new Notification.Builder(context)
- .setTicker(r.getString(R.string.screenshot_saving_ticker)
- + (mTickerAddSpace ? " " : ""))
- .setContentTitle(r.getString(R.string.screenshot_saving_title))
- .setContentText(r.getString(R.string.screenshot_saving_text))
- .setSmallIcon(R.drawable.stat_notify_image)
- .setWhen(now)
- .setColor(r.getColor(com.android.internal.R.color.system_notification_accent_color));
-
+ // Setup the notification
mNotificationStyle = new Notification.BigPictureStyle()
- .bigPicture(picture.createAshmemBitmap());
- mNotificationBuilder.setStyle(mNotificationStyle);
+ .bigPicture(picture.createAshmemBitmap());
- // For "public" situations we want to show all the same info but
- // omit the actual screenshot image.
+ // The public notification will show similar info but with the actual screenshot omitted
mPublicNotificationBuilder = new Notification.Builder(context)
.setContentTitle(r.getString(R.string.screenshot_saving_title))
.setContentText(r.getString(R.string.screenshot_saving_text))
@@ -194,11 +181,24 @@
.setColor(r.getColor(
com.android.internal.R.color.system_notification_accent_color));
- mNotificationBuilder.setPublicVersion(mPublicNotificationBuilder.build());
+ mNotificationBuilder = new Notification.Builder(context)
+ .setTicker(r.getString(R.string.screenshot_saving_ticker)
+ + (mTickerAddSpace ? " " : ""))
+ .setContentTitle(r.getString(R.string.screenshot_saving_title))
+ .setContentText(r.getString(R.string.screenshot_saving_text))
+ .setSmallIcon(R.drawable.stat_notify_image)
+ .setWhen(now)
+ .setColor(r.getColor(com.android.internal.R.color.system_notification_accent_color))
+ .setStyle(mNotificationStyle)
+ .setPublicVersion(mPublicNotificationBuilder.build());
+ mNotificationBuilder.setFlag(Notification.FLAG_NO_CLEAR, true);
- Notification n = mNotificationBuilder.build();
- n.flags |= Notification.FLAG_NO_CLEAR;
- mNotificationManager.notify(nId, n);
+ mNotificationManager.notify(R.id.notification_screenshot, mNotificationBuilder.build());
+
+ /**
+ * NOTE: The following code prepares the notification builder for updating the notification
+ * after the screenshot has been written to disk.
+ */
// On the tablet, the large icon makes the notification appear as if it is clickable (and
// on small devices, the large icon is not shown) so defer showing the large icon until
@@ -210,11 +210,8 @@
@Override
protected SaveImageInBackgroundData doInBackground(SaveImageInBackgroundData... params) {
- if (params.length != 1) return null;
if (isCancelled()) {
- params[0].clearImage();
- params[0].clearContext();
- return null;
+ return params[0];
}
// By default, AsyncTask sets the worker thread to have background thread priority, so bump
@@ -263,36 +260,37 @@
sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
// Create a share action for the notification
- final PendingIntent callback = PendingIntent.getBroadcast(context, 0,
- new Intent(context, GlobalScreenshot.TargetChosenReceiver.class)
- .putExtra(GlobalScreenshot.CANCEL_ID, mNotificationId),
+ PendingIntent chooseAction = PendingIntent.getBroadcast(context, 0,
+ new Intent(context, GlobalScreenshot.TargetChosenReceiver.class),
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
Intent chooserIntent = Intent.createChooser(sharingIntent, null,
- callback.getIntentSender());
- chooserIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK
- | Intent.FLAG_ACTIVITY_NEW_TASK);
- mNotificationBuilder.addAction(R.drawable.ic_screenshot_share,
- r.getString(com.android.internal.R.string.share),
- PendingIntent.getActivity(context, 0, chooserIntent,
- PendingIntent.FLAG_CANCEL_CURRENT));
+ chooseAction.getIntentSender())
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
+ PendingIntent shareAction = PendingIntent.getActivity(context, 0, chooserIntent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+ Notification.Action.Builder shareActionBuilder = new Notification.Action.Builder(
+ R.drawable.ic_screenshot_share,
+ r.getString(com.android.internal.R.string.share), shareAction);
+ mNotificationBuilder.addAction(shareActionBuilder.build());
// Create a delete action for the notification
- final PendingIntent deleteAction = PendingIntent.getBroadcast(context, 0,
+ PendingIntent deleteAction = PendingIntent.getBroadcast(context, 0,
new Intent(context, GlobalScreenshot.DeleteScreenshotReceiver.class)
- .putExtra(GlobalScreenshot.CANCEL_ID, mNotificationId)
.putExtra(GlobalScreenshot.SCREENSHOT_URI_ID, uri.toString()),
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
- mNotificationBuilder.addAction(R.drawable.ic_screenshot_delete,
+ Notification.Action.Builder deleteActionBuilder = new Notification.Action.Builder(
+ R.drawable.ic_screenshot_delete,
r.getString(com.android.internal.R.string.delete), deleteAction);
+ mNotificationBuilder.addAction(deleteActionBuilder.build());
params[0].imageUri = uri;
params[0].image = null;
- params[0].result = 0;
+ params[0].errorMsgResId = 0;
} catch (Exception e) {
// IOException/UnsupportedOperationException may be thrown if external storage is not
// mounted
params[0].clearImage();
- params[0].result = 1;
+ params[0].errorMsgResId = R.string.screenshot_failed_to_save_text;
}
// Recycle the bitmap data
@@ -305,19 +303,14 @@
@Override
protected void onPostExecute(SaveImageInBackgroundData params) {
- if (isCancelled()) {
- params.finisher.run();
- params.clearImage();
- params.clearContext();
- return;
- }
-
- if (params.result > 0) {
+ if (params.errorMsgResId != 0) {
// Show a message that we've failed to save the image to disk
- GlobalScreenshot.notifyScreenshotError(params.context, mNotificationManager);
+ GlobalScreenshot.notifyScreenshotError(params.context, mNotificationManager,
+ params.errorMsgResId);
} else {
// Show the final notification to indicate screenshot saved
- Resources r = params.context.getResources();
+ Context context = params.context;
+ Resources r = context.getResources();
// Create the intent to show the screenshot in gallery
Intent launchIntent = new Intent(Intent.ACTION_VIEW);
@@ -326,34 +319,41 @@
final long now = System.currentTimeMillis();
+ // Update the text and the icon for the existing notification
+ mPublicNotificationBuilder
+ .setContentTitle(r.getString(R.string.screenshot_saved_title))
+ .setContentText(r.getString(R.string.screenshot_saved_text))
+ .setContentIntent(PendingIntent.getActivity(params.context, 0, launchIntent, 0))
+ .setWhen(now)
+ .setAutoCancel(true)
+ .setColor(context.getColor(
+ com.android.internal.R.color.system_notification_accent_color));
mNotificationBuilder
.setContentTitle(r.getString(R.string.screenshot_saved_title))
.setContentText(r.getString(R.string.screenshot_saved_text))
.setContentIntent(PendingIntent.getActivity(params.context, 0, launchIntent, 0))
.setWhen(now)
.setAutoCancel(true)
- .setColor(r.getColor(
- com.android.internal.R.color.system_notification_accent_color));;
+ .setColor(context.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setPublicVersion(mPublicNotificationBuilder.build())
+ .setFlag(Notification.FLAG_NO_CLEAR, false);
- // Update the text in the public version as well
- mPublicNotificationBuilder
- .setContentTitle(r.getString(R.string.screenshot_saved_title))
- .setContentText(r.getString(R.string.screenshot_saved_text))
- .setContentIntent(PendingIntent.getActivity(params.context, 0, launchIntent, 0))
- .setWhen(now)
- .setAutoCancel(true)
- .setColor(r.getColor(
- com.android.internal.R.color.system_notification_accent_color));
-
- mNotificationBuilder.setPublicVersion(mPublicNotificationBuilder.build());
-
- Notification n = mNotificationBuilder.build();
- n.flags &= ~Notification.FLAG_NO_CLEAR;
- mNotificationManager.notify(mNotificationId, n);
+ mNotificationManager.notify(R.id.notification_screenshot, mNotificationBuilder.build());
}
params.finisher.run();
params.clearContext();
}
+
+ @Override
+ protected void onCancelled(SaveImageInBackgroundData params) {
+ params.finisher.run();
+ params.clearImage();
+ params.clearContext();
+
+ // Cancel the posted notification
+ mNotificationManager.cancel(R.id.notification_screenshot);
+ }
}
/**
@@ -379,16 +379,7 @@
}
}
-/**
- * TODO:
- * - Performance when over gl surfaces? Ie. Gallery
- * - what do we say in the Toast? Which icon do we get if the user uses another
- * type of gallery?
- */
class GlobalScreenshot {
- private static final String TAG = "GlobalScreenshot";
-
- static final String CANCEL_ID = "android:cancel_id";
static final String SCREENSHOT_URI_ID = "android:screenshot_uri_id";
private static final int SCREENSHOT_FLASH_TO_PEAK_DURATION = 130;
@@ -512,8 +503,8 @@
if (mSaveInBgTask != null) {
mSaveInBgTask.cancel(false);
}
- mSaveInBgTask = new SaveImageInBackgroundTask(mContext, data, mNotificationManager,
- R.id.notification_screenshot).execute(data);
+ mSaveInBgTask = new SaveImageInBackgroundTask(mContext, data, mNotificationManager)
+ .execute(data);
}
/**
@@ -553,7 +544,8 @@
// Take the screenshot
mScreenBitmap = SurfaceControl.screenshot((int) dims[0], (int) dims[1]);
if (mScreenBitmap == null) {
- notifyScreenshotError(mContext, mNotificationManager);
+ notifyScreenshotError(mContext, mNotificationManager,
+ R.string.screenshot_failed_to_capture_text);
finisher.run();
return;
}
@@ -763,14 +755,15 @@
return anim;
}
- static void notifyScreenshotError(Context context, NotificationManager nManager) {
+ static void notifyScreenshotError(Context context, NotificationManager nManager, int msgResId) {
Resources r = context.getResources();
+ String errorMsg = r.getString(msgResId);
- // Clear all existing notification, compose the new notification and show it
+ // Repurpose the existing notification to notify the user of the error
Notification.Builder b = new Notification.Builder(context)
.setTicker(r.getString(R.string.screenshot_failed_title))
.setContentTitle(r.getString(R.string.screenshot_failed_title))
- .setContentText(r.getString(R.string.screenshot_failed_text))
+ .setContentText(errorMsg)
.setSmallIcon(R.drawable.stat_notify_image_error)
.setWhen(System.currentTimeMillis())
.setVisibility(Notification.VISIBILITY_PUBLIC) // ok to show outside lockscreen
@@ -778,9 +771,9 @@
.setAutoCancel(true)
.setColor(context.getColor(
com.android.internal.R.color.system_notification_accent_color));
- Notification n =
- new Notification.BigTextStyle(b)
- .bigText(r.getString(R.string.screenshot_failed_text))
+
+ Notification n = new Notification.BigTextStyle(b)
+ .bigText(errorMsg)
.build();
nManager.notify(R.id.notification_screenshot, n);
}
@@ -791,15 +784,10 @@
public static class TargetChosenReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- if (!intent.hasExtra(CANCEL_ID)) {
- return;
- }
-
// Clear the notification
final NotificationManager nm =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
- final int id = intent.getIntExtra(CANCEL_ID, 0);
- nm.cancel(id);
+ nm.cancel(R.id.notification_screenshot);
}
}
@@ -809,16 +797,15 @@
public static class DeleteScreenshotReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- if (!intent.hasExtra(CANCEL_ID) || !intent.hasExtra(SCREENSHOT_URI_ID)) {
+ if (!intent.hasExtra(SCREENSHOT_URI_ID)) {
return;
}
// Clear the notification
final NotificationManager nm =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
- final int id = intent.getIntExtra(CANCEL_ID, 0);
final Uri uri = Uri.parse(intent.getStringExtra(SCREENSHOT_URI_ID));
- nm.cancel(id);
+ nm.cancel(R.id.notification_screenshot);
// And delete the image from the media store
new DeleteImageInBackgroundTask(context).execute(uri);
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
new file mode 100644
index 0000000..8f8683b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.shortcut;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ServiceInfo;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.IWindowManager;
+import android.view.KeyEvent;
+import android.view.WindowManagerGlobal;
+import android.view.accessibility.AccessibilityManager;
+import com.android.settingslib.accessibility.AccessibilityUtils;
+import com.android.systemui.R;
+import com.android.systemui.SystemUI;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Dispatches shortcut to System UI components
+ */
+public class ShortcutKeyDispatcher extends SystemUI
+ implements ShortcutKeyServiceProxy.Callbacks {
+
+ private static final String TAG = "ShortcutKeyDispatcher";
+
+ private ShortcutKeyServiceProxy mShortcutKeyServiceProxy = new ShortcutKeyServiceProxy(this);
+ private IWindowManager windowManagerService = WindowManagerGlobal.getWindowManagerService();
+
+ protected final long META_MASK = ((long) KeyEvent.META_META_ON) << Integer.SIZE;
+ protected final long ALT_MASK = ((long) KeyEvent.META_ALT_ON) << Integer.SIZE;
+ protected final long CTRL_MASK = ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE;
+ protected final long SHIFT_MASK = ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE;
+
+ /**
+ * Registers a shortcut key to window manager.
+ * @param shortcutCode packed representation of shortcut key code and meta information
+ */
+ public void registerShortcutKey(long shortcutCode) {
+ try {
+ windowManagerService.registerShortcutKey(shortcutCode, mShortcutKeyServiceProxy);
+ } catch (RemoteException e) {
+ // Do nothing
+ }
+ }
+
+ @Override
+ public void onShortcutKeyPressed(long shortcutCode) {}
+
+ @Override
+ public void start() {}
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyServiceProxy.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyServiceProxy.java
new file mode 100644
index 0000000..8ec862e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyServiceProxy.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.shortcut;
+
+import android.os.Handler;
+import android.os.Message;
+import android.os.RemoteException;
+import com.android.internal.policy.IShortcutService;
+
+/**
+ * This class takes functions from IShortcutService that come in binder pool threads and
+ * post them onto shortcut handlers.
+ */
+public class ShortcutKeyServiceProxy extends IShortcutService.Stub {
+ private static final int MSG_SHORTCUT_RECEIVED = 1;
+
+ private final Object mLock = new Object();
+ private Callbacks mCallbacks;
+ private final Handler mHandler = new H();
+
+ public interface Callbacks {
+ void onShortcutKeyPressed(long shortcutCode);
+ }
+
+ public ShortcutKeyServiceProxy(Callbacks callbacks) { mCallbacks = callbacks; }
+
+ @Override
+ public void notifyShortcutKeyPressed(long shortcutCode) throws RemoteException {
+ synchronized (mLock) {
+ mHandler.obtainMessage(MSG_SHORTCUT_RECEIVED, shortcutCode).sendToTarget();
+ }
+ }
+
+ private final class H extends Handler {
+ public void handleMessage(Message msg) {
+ final int what = msg.what;
+ switch (what) {
+ case MSG_SHORTCUT_RECEIVED:
+ mCallbacks.onShortcutKeyPressed((Long)msg.obj);
+ break;
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index 189e651..dd59fac 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -40,6 +40,7 @@
private DividerView mView;
private DockDividerVisibilityListener mDockDividerVisibilityListener;
private boolean mVisible = false;
+ private boolean mMinimized = false;
@Override
public void start() {
@@ -81,6 +82,10 @@
private void update(Configuration configuration) {
removeDivider();
addDivider(configuration);
+ if (mMinimized) {
+ mView.setMinimizedDockStack(true);
+ mWindowManager.setTouchable(false);
+ }
}
private void updateVisibility(final boolean visible) {
@@ -95,6 +100,23 @@
});
}
+ private void updateMinimizedDockedStack(final boolean minimized, final long animDuration) {
+ mView.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mMinimized != minimized) {
+ mMinimized = minimized;
+ mWindowManager.setTouchable(!minimized);
+ if (animDuration > 0) {
+ mView.setMinimizedDockStack(minimized, animDuration);
+ } else {
+ mView.setMinimizedDockStack(minimized);
+ }
+ }
+ }
+ });
+ }
+
class DockDividerVisibilityListener extends IDockedStackListener.Stub {
@Override
@@ -105,5 +127,11 @@
@Override
public void onDockedStackExistsChanged(boolean exists) throws RemoteException {
}
+
+ @Override
+ public void onDockedStackMinimizedChanged(boolean minimized, long animDuration)
+ throws RemoteException {
+ updateMinimizedDockedStack(minimized, animDuration);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java
index 36cfac8..d5f7b39 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java
@@ -26,7 +26,7 @@
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Property;
-import android.widget.ImageButton;
+import android.view.View;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -34,7 +34,7 @@
/**
* View for the handle in the docked stack divider.
*/
-public class DividerHandleView extends ImageButton {
+public class DividerHandleView extends View {
private final static Property<DividerHandleView, Integer> WIDTH_PROPERTY
= new Property<DividerHandleView, Integer>(Integer.class, "width") {
@@ -140,4 +140,9 @@
canvas.drawRoundRect(left, top, left + mCurrentWidth, top + mCurrentHeight,
radius, radius, mPaint);
}
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 1bdf5a1..da5cbe7 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -27,6 +27,7 @@
import android.graphics.Rect;
import android.graphics.Region.Op;
import android.hardware.display.DisplayManager;
+import android.os.Bundle;
import android.util.AttributeSet;
import android.view.Display;
import android.view.DisplayInfo;
@@ -40,7 +41,8 @@
import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
import android.view.WindowInsets;
import android.view.WindowManager;
-import android.view.animation.AnimationUtils;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
import android.widget.FrameLayout;
@@ -86,6 +88,11 @@
*/
private static final float BOTTOM_RIGHT_SWITCH_BIGGER_FRACTION = 0.2f;
+ /**
+ * How much the background gets scaled when we are in the minimized dock state.
+ */
+ private static final float MINIMIZE_DOCK_SCALE = 0.375f;
+
private static final PathInterpolator SLOWDOWN_INTERPOLATOR =
new PathInterpolator(0.5f, 1f, 0.5f, 1f);
private static final PathInterpolator DIM_INTERPOLATOR =
@@ -126,6 +133,43 @@
private boolean mAnimateAfterRecentsDrawn;
private boolean mGrowAfterRecentsDrawn;
private boolean mGrowRecents;
+ private Animator mCurrentAnimator;
+
+ private final AccessibilityDelegate mHandleDelegate = new AccessibilityDelegate() {
+ @Override
+ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(host, info);
+ if (isHorizontalDivision()) {
+ info.addAction(new AccessibilityAction(R.id.action_move_up,
+ mContext.getString(R.string.accessibility_action_divider_move_up)));
+ info.addAction(new AccessibilityAction(R.id.action_move_down,
+ mContext.getString(R.string.accessibility_action_divider_move_down)));
+ } else {
+ info.addAction(new AccessibilityAction(R.id.action_move_left,
+ mContext.getString(R.string.accessibility_action_divider_move_left)));
+ info.addAction(new AccessibilityAction(R.id.action_move_right,
+ mContext.getString(R.string.accessibility_action_divider_move_right)));
+ }
+ }
+
+ @Override
+ public boolean performAccessibilityAction(View host, int action, Bundle args) {
+ if (action == R.id.action_move_up || action == R.id.action_move_down
+ || action == R.id.action_move_left || action == R.id.action_move_right) {
+ int position = getCurrentPosition();
+ SnapTarget currentTarget = mSnapAlgorithm.calculateSnapTarget(
+ position, 0 /* velocity */);
+ SnapTarget nextTarget =
+ action == R.id.action_move_up || action == R.id.action_move_left
+ ? mSnapAlgorithm.getPreviousTarget(currentTarget)
+ : mSnapAlgorithm.getNextTarget(currentTarget);
+ startDragging(true /* animate */, false /* touching */);
+ stopDragging(getCurrentPosition(), nextTarget, 250, Interpolators.FAST_OUT_SLOW_IN);
+ return true;
+ }
+ return super.performAccessibilityAction(host, action, args);
+ }
+ };
public DividerView(Context context) {
super(context);
@@ -166,6 +210,7 @@
mHandle.setPointerIcon(PointerIcon.getSystemIcon(getContext(),
landscape ? STYLE_HORIZONTAL_DOUBLE_ARROW : STYLE_VERTICAL_DOUBLE_ARROW));
getViewTreeObserver().addOnComputeInternalInsetsListener(this);
+ mHandle.setAccessibilityDelegate(mHandleDelegate);
}
@Override
@@ -205,6 +250,7 @@
}
public boolean startDragging(boolean animate, boolean touching) {
+ cancelFlingAnimation();
if (touching) {
mHandle.setTouching(true, animate);
}
@@ -364,11 +410,19 @@
commitSnapFlags(snapTarget);
mWindowManagerProxy.setResizing(false);
mDockSide = WindowManager.DOCKED_INVALID;
+ mCurrentAnimator = null;
}
});
+ mCurrentAnimator = anim;
return anim;
}
+ private void cancelFlingAnimation() {
+ if (mCurrentAnimator != null) {
+ mCurrentAnimator.cancel();
+ }
+ }
+
private void commitSnapFlags(SnapTarget target) {
if (target.flag == SnapTarget.FLAG_NONE) {
return;
@@ -433,6 +487,47 @@
mBackgroundLifted = false;
}
+
+ public void setMinimizedDockStack(boolean minimized) {
+ updateDockSide();
+ mHandle.setAlpha(minimized ? 0f : 1f);
+ if (mDockSide == WindowManager.DOCKED_TOP) {
+ mBackground.setPivotY(0);
+ mBackground.setScaleY(minimized ? MINIMIZE_DOCK_SCALE : 1f);
+ } else if (mDockSide == WindowManager.DOCKED_LEFT
+ || mDockSide == WindowManager.DOCKED_RIGHT) {
+ mBackground.setPivotX(mDockSide == WindowManager.DOCKED_LEFT
+ ? 0
+ : mBackground.getWidth());
+ mBackground.setScaleX(minimized ? MINIMIZE_DOCK_SCALE : 1f);
+ }
+ }
+
+ public void setMinimizedDockStack(boolean minimized, long animDuration) {
+ updateDockSide();
+ mHandle.animate()
+ .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+ .setDuration(animDuration)
+ .alpha(minimized ? 0f : 1f)
+ .start();
+ if (mDockSide == WindowManager.DOCKED_TOP) {
+ mBackground.setPivotY(0);
+ mBackground.animate()
+ .scaleY(minimized ? MINIMIZE_DOCK_SCALE : 1f);
+ } else if (mDockSide == WindowManager.DOCKED_LEFT
+ || mDockSide == WindowManager.DOCKED_RIGHT) {
+ mBackground.setPivotX(mDockSide == WindowManager.DOCKED_LEFT
+ ? 0
+ : mBackground.getWidth());
+ mBackground.animate()
+ .scaleX(minimized ? MINIMIZE_DOCK_SCALE : 1f);
+ }
+ mBackground.animate()
+ .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+ .setDuration(animDuration)
+ .start();
+ }
+
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java
index 2294d40..3db03d0 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java
@@ -22,6 +22,7 @@
import android.view.WindowManager;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
@@ -79,4 +80,18 @@
mWindowManager.updateViewLayout(mView, mLp);
}
}
+
+ public void setTouchable(boolean touchable) {
+ boolean changed = false;
+ if (!touchable && (mLp.flags & FLAG_NOT_TOUCHABLE) == 0) {
+ mLp.flags |= FLAG_NOT_TOUCHABLE;
+ changed = true;
+ } else if (touchable && (mLp.flags & FLAG_NOT_TOUCHABLE) != 0) {
+ mLp.flags &= ~FLAG_NOT_TOUCHABLE;
+ changed = true;
+ }
+ if (changed) {
+ mWindowManager.updateViewLayout(mView, mLp);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 874defa..effe581 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -35,6 +35,7 @@
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.statusbar.notification.FakeShadowView;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
/**
@@ -155,6 +156,7 @@
}
};
private float mShadowAlpha = 1.0f;
+ private FakeShadowView mFakeShadow;
public ActivatableNotificationView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -180,6 +182,7 @@
protected void onFinishInflate() {
super.onFinishInflate();
mBackgroundNormal = (NotificationBackgroundView) findViewById(R.id.backgroundNormal);
+ mFakeShadow = (FakeShadowView) findViewById(R.id.fake_shadow);
mBackgroundDimmed = (NotificationBackgroundView) findViewById(R.id.backgroundDimmed);
mBackgroundNormal.setCustomBackground(R.drawable.notification_material_bg);
mBackgroundDimmed.setCustomBackground(R.drawable.notification_material_bg_dim);
@@ -208,6 +211,10 @@
return false;
}
+ protected boolean handleSlideBack() {
+ return false;
+ }
+
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean result;
@@ -260,6 +267,9 @@
break;
case MotionEvent.ACTION_UP:
if (isWithinTouchSlop(event)) {
+ if (handleSlideBack()) {
+ return true;
+ }
if (!mActivated) {
makeActive();
postDelayed(mTapTimeoutRunnable, DOUBLETAP_TIMEOUT_MS);
@@ -845,6 +855,14 @@
}
}
+ @Override
+ public void setFakeShadowIntensity(float shadowIntensity, float outlineAlpha, int shadowYEnd,
+ int outlineTranslation) {
+ mFakeShadow.setFakeShadowTranslationZ(shadowIntensity * (getTranslationZ()
+ + FakeShadowView.SHADOW_SIBLING_TRESHOLD), outlineAlpha, shadowYEnd,
+ outlineTranslation);
+ }
+
public interface OnActivatedListener {
void onActivated(ActivatableNotificationView view);
void onActivationReset(ActivatableNotificationView view);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 2bebac2..143f160 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -103,19 +103,20 @@
import com.android.systemui.statusbar.policy.PreviewInflater;
import com.android.systemui.statusbar.policy.RemoteInputView;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.GearDisplayedListener;
import com.android.systemui.statusbar.stack.StackStateAnimator;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_MAX;
+import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
import static com.android.keyguard.KeyguardHostView.OnDismissAction;
public abstract class BaseStatusBar extends SystemUI implements
CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment,
- ExpandableNotificationRow.OnExpandClickListener {
+ ExpandableNotificationRow.OnExpandClickListener, GearDisplayedListener {
public static final String TAG = "StatusBar";
public static final boolean DEBUG = false;
public static final boolean MULTIUSER_DEBUG = false;
@@ -193,6 +194,7 @@
// public mode, private notifications, etc
private boolean mLockscreenPublicMode = false;
private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray();
+ private final SparseBooleanArray mUsersAllowingNotifications = new SparseBooleanArray();
private UserManager mUserManager;
private int mDensity;
@@ -220,6 +222,7 @@
// which notification is currently being longpress-examined by the user
private NotificationGuts mNotificationGutsExposed;
+ private ExpandableNotificationRow mNotificationGearDisplayed;
private KeyboardShortcuts mKeyboardShortcuts;
@@ -957,7 +960,7 @@
}, false /* afterKeyguardGone */);
}
- private void bindGuts(ExpandableNotificationRow row) {
+ private void bindGuts(final ExpandableNotificationRow row) {
row.inflateGuts();
final StatusBarNotification sbn = row.getStatusBarNotification();
PackageManager pmUser = getPackageManagerForUser(mContext, sbn.getUser().getIdentifier());
@@ -981,7 +984,7 @@
pkgicon = pmUser.getDefaultActivityIcon();
}
- ((ImageView) row.findViewById(android.R.id.icon)).setImageDrawable(pkgicon);
+ ((ImageView) row.findViewById(R.id.app_icon)).setImageDrawable(pkgicon);
((TextView) row.findViewById(R.id.pkgname)).setText(appname);
final View settingsButton = guts.findViewById(R.id.more_settings);
@@ -1001,11 +1004,25 @@
@Override
public void onClick(View v) {
guts.saveImportance(sbn);
- dismissPopups();
+
+ int[] rowLocation = new int[2];
+ int[] doneLocation = new int[2];
+ row.getLocationOnScreen(rowLocation);
+ v.getLocationOnScreen(doneLocation);
+
+ final int centerX = v.getWidth() / 2;
+ final int centerY = v.getHeight() / 2;
+ final int x = doneLocation[0] - rowLocation[0] + centerX;
+ final int y = doneLocation[1] - rowLocation[1] + centerY;
+ dismissPopups(x, y);
}
});
- guts.bindImportance(sbn, row, mNotificationData.getImportance(sbn.getKey()));
+ guts.bindImportance(pmUser, sbn, row, mNotificationData.getImportance(sbn.getKey()));
+ }
+
+ protected GearDisplayedListener getGearDisplayedListener() {
+ return this;
}
protected SwipeHelper.LongPressListener getNotificationLongClicker() {
@@ -1020,7 +1037,7 @@
return false;
}
- ExpandableNotificationRow row = (ExpandableNotificationRow) v;
+ final ExpandableNotificationRow row = (ExpandableNotificationRow) v;
bindGuts(row);
// Assume we are a status_bar_notification_row
@@ -1038,12 +1055,12 @@
MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTE_CONTROLS);
- // ensure that it's layouted but not visible until actually laid out
+ // ensure that it's laid but not visible until actually laid out
guts.setVisibility(View.INVISIBLE);
- // Post to ensure the the guts are properly layed out.
+ // Post to ensure the the guts are properly laid out.
guts.post(new Runnable() {
public void run() {
- dismissPopups();
+ dismissPopups(-1 /* x */, -1 /* y */, false /* resetGear */);
guts.setVisibility(View.VISIBLE);
final double horz = Math.max(guts.getWidth() - x, x);
final double vert = Math.max(guts.getHeight() - y, y);
@@ -1052,6 +1069,14 @@
= ViewAnimationUtils.createCircularReveal(guts, x, y, 0, r);
a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
a.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+ a.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ // Move the notification view back over the gear
+ row.resetTranslation();
+ }
+ });
a.start();
guts.setExposed(true);
mStackScroller.onHeightChanged(null, true /* needsAnimation */);
@@ -1063,11 +1088,22 @@
};
}
+ @Override
+ public void onGearDisplayed(ExpandableNotificationRow row) {
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_REVEAL_GEAR,
+ row.getStatusBarNotification().getPackageName());
+ mNotificationGearDisplayed = row;
+ }
+
public void dismissPopups() {
- dismissPopups(-1, -1);
+ dismissPopups(-1 /* x */, -1 /* y */, true /* resetGear */);
}
private void dismissPopups(int x, int y) {
+ dismissPopups(x, y, true /* resetGear */);
+ }
+
+ public void dismissPopups(int x, int y, boolean resetGear) {
if (mNotificationGutsExposed != null) {
final NotificationGuts v = mNotificationGutsExposed;
mNotificationGutsExposed = null;
@@ -1095,6 +1131,10 @@
v.setExposed(false);
mStackScroller.onHeightChanged(null, true /* needsAnimation */);
}
+ if (resetGear && mNotificationGearDisplayed != null) {
+ mNotificationGearDisplayed.resetTranslation();
+ mNotificationGearDisplayed = null;
+ }
}
@Override
@@ -1118,6 +1158,11 @@
}
@Override
+ public void toggleSplitScreen() {
+ toggleSplitScreenMode();
+ }
+
+ @Override
public void preloadRecentApps() {
int msg = MSG_PRELOAD_RECENT_APPS;
mHandler.removeMessages(msg);
@@ -1187,6 +1232,13 @@
}
};
+ /**
+ * Toggle docking the app window
+ *
+ * @return {@code true} if the app window is docked after the toggle, {@code false} otherwise.
+ */
+ protected abstract boolean toggleSplitScreenMode();
+
/** Proxy for RecentsComponent */
protected void showRecents(boolean triggeredFromAltTab) {
@@ -1253,6 +1305,26 @@
}
/**
+ * Has the given user chosen to allow notifications to be shown even when the lockscreen is in
+ * "public" (secure & locked) mode?
+ */
+ public boolean userAllowsNotificationsInPublic(int userHandle) {
+ if (userHandle == UserHandle.USER_ALL) {
+ return true;
+ }
+
+ if (mUsersAllowingNotifications.indexOfKey(userHandle) < 0) {
+ final boolean allowed = 0 != Settings.Secure.getIntForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, userHandle);
+ mUsersAllowingNotifications.append(userHandle, allowed);
+ return allowed;
+ }
+
+ return mUsersAllowingNotifications.get(userHandle);
+ }
+
+ /**
* Has the given user chosen to allow their private (full) notifications to be shown even
* when the lockscreen is in "public" (secure & locked) mode?
*/
@@ -1284,13 +1356,30 @@
}
/**
- * Returns true if we're on a secure lockscreen and the user wants to hide "sensitive"
- * notification data. If so, private notifications should show their (possibly
- * auto-generated) publicVersion, and secret notifications should be totally invisible.
+ * Returns true if we're on a secure lockscreen and the user wants to hide notification data.
+ * If so, notifications should be hidden.
*/
@Override // NotificationData.Environment
- public boolean shouldHideSensitiveContents(int userid) {
- return isLockscreenPublicMode() && !userAllowsPrivateNotificationsInPublic(userid);
+ public boolean shouldHideNotifications(int userid) {
+ return isLockscreenPublicMode() && !userAllowsNotificationsInPublic(userid);
+ }
+
+ /**
+ * Returns true if we're on a secure lockscreen and the user wants to hide notifications via
+ * package-specific override.
+ */
+ @Override // NotificationDate.Environment
+ public boolean shouldHideNotifications(String key) {
+ return isLockscreenPublicMode()
+ && mNotificationData.getVisibilityOverride(key) == Notification.VISIBILITY_SECRET;
+ }
+
+ /**
+ * Returns true if we're on a secure lockscreen.
+ */
+ @Override // NotificationData.Environment
+ public boolean onSecureLockScreen() {
+ return isLockscreenPublicMode();
}
public void onNotificationClear(StatusBarNotification notification) {
@@ -1633,6 +1722,12 @@
return;
}
+ // Check if the notification is displaying the gear, if so slide notification back
+ if (row.getSettingsRow() != null && row.getSettingsRow().isVisible()) {
+ row.animateTranslateNotification(0);
+ return;
+ }
+
Notification notification = sbn.getNotification();
final PendingIntent intent = notification.contentIntent != null
? notification.contentIntent
@@ -1796,7 +1891,7 @@
}
}
- protected abstract boolean isPanelFullyCollapsed();
+ public abstract boolean isPanelFullyCollapsed();
/**
* Cancel this notification and tell the StatusBarManagerService / NotificationManagerService
@@ -1842,7 +1937,7 @@
return entry;
}
- protected StatusBarIconView createIcon(StatusBarNotification sbn) {
+ public StatusBarIconView createIcon(StatusBarNotification sbn) {
// Construct the icon.
Notification n = sbn.getNotification();
final StatusBarIconView iconView = new StatusBarIconView(mContext,
@@ -2109,15 +2204,21 @@
protected void updatePublicContentView(Entry entry,
StatusBarNotification sbn) {
final RemoteViews publicContentView = entry.cachedPublicContentView;
- if (publicContentView != null && entry.getPublicContentView() != null) {
+ View inflatedView = entry.getPublicContentView();
+ if (entry.autoRedacted && publicContentView != null && inflatedView != null) {
final boolean disabledByPolicy =
!adminAllowsUnredactedNotifications(entry.notification.getUserId());
- publicContentView.setTextViewText(android.R.id.title,
- mContext.getString(disabledByPolicy
- ? com.android.internal.R.string.notification_hidden_by_policy_text
- : com.android.internal.R.string.notification_hidden_text));
- publicContentView.reapply(sbn.getPackageContext(mContext),
- entry.getPublicContentView(), mOnClickHandler);
+ String notificationHiddenText = mContext.getString(disabledByPolicy
+ ? com.android.internal.R.string.notification_hidden_by_policy_text
+ : com.android.internal.R.string.notification_hidden_text);
+ TextView titleView = (TextView) inflatedView.findViewById(android.R.id.title);
+ if (titleView != null
+ && !titleView.getText().toString().equals(notificationHiddenText)) {
+ publicContentView.setTextViewText(android.R.id.title, notificationHiddenText);
+ publicContentView.reapply(sbn.getPackageContext(mContext),
+ inflatedView, mOnClickHandler);
+ entry.row.onNotificationUpdated(entry);
+ }
}
}
@@ -2167,6 +2268,16 @@
return false;
}
+ if (isSnoozedPackage(sbn)) {
+ if (DEBUG) Log.d(TAG, "No peeking: snoozed package: " + sbn.getKey());
+ return false;
+ }
+
+ if (mNotificationData.getImportance(sbn.getKey()) < IMPORTANCE_HIGH) {
+ if (DEBUG) Log.d(TAG, "No peeking: unimportant notification: " + sbn.getKey());
+ return false;
+ }
+
if (sbn.getNotification().fullScreenIntent != null) {
if (mAccessibilityManager.isTouchExplorationEnabled()) {
if (DEBUG) Log.d(TAG, "No peeking: accessible fullscreen: " + sbn.getKey());
@@ -2176,16 +2287,6 @@
}
}
- if (isSnoozedPackage(sbn)) {
- if (DEBUG) Log.d(TAG, "No peeking: snoozed package: " + sbn.getKey());
- return false;
- }
-
- if (mNotificationData.getImportance(sbn.getKey()) < IMPORTANCE_MAX) {
- if (DEBUG) Log.d(TAG, "No peeking: unimportant notification: " + sbn.getKey());
- return false;
- }
-
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 3b960ee..6a98488 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -72,6 +72,7 @@
private static final int MSG_ADD_QS_TILE = 27 << MSG_SHIFT;
private static final int MSG_REMOVE_QS_TILE = 28 << MSG_SHIFT;
private static final int MSG_CLICK_QS_TILE = 29 << MSG_SHIFT;
+ private static final int MSG_TOGGLE_APP_SPLIT_SCREEN = 30 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -104,6 +105,7 @@
public void showRecentApps(boolean triggeredFromAltTab);
public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
public void toggleRecentApps();
+ public void toggleSplitScreen();
public void preloadRecentApps();
public void toggleKeyboardShortcutsMenu();
public void cancelPreloadRecentApps();
@@ -223,6 +225,13 @@
}
}
+ public void toggleSplitScreen() {
+ synchronized (mLock) {
+ mHandler.removeMessages(MSG_TOGGLE_APP_SPLIT_SCREEN);
+ mHandler.obtainMessage(MSG_TOGGLE_APP_SPLIT_SCREEN, 0, 0, null).sendToTarget();
+ }
+ }
+
public void toggleRecentApps() {
synchronized (mLock) {
mHandler.removeMessages(MSG_TOGGLE_RECENT_APPS);
@@ -464,6 +473,9 @@
case MSG_CLICK_QS_TILE:
mCallbacks.clickTile((ComponentName) msg.obj);
break;
+ case MSG_TOGGLE_APP_SPLIT_SCREEN:
+ mCallbacks.toggleSplitScreen();
+ break;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java
index 212d290..123dc69 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java
@@ -19,6 +19,7 @@
import android.view.View;
import com.android.systemui.Interpolators;
+import com.android.systemui.statusbar.stack.StackStateAnimator;
/**
* A helper to fade views in and out.
@@ -44,7 +45,34 @@
if (view.hasOverlappingRendering()) {
view.animate().withLayer();
}
+ }
+ public static void fadeOut(View view, float fadeOutAmount) {
+ view.animate().cancel();
+ if (fadeOutAmount == 1.0f) {
+ view.setVisibility(View.INVISIBLE);
+ } else if (view.getVisibility() == View.INVISIBLE) {
+ view.setVisibility(View.VISIBLE);
+ }
+ fadeOutAmount = mapToFadeDuration(fadeOutAmount);
+ float alpha = Interpolators.ALPHA_OUT.getInterpolation(1.0f - fadeOutAmount);
+ view.setAlpha(alpha);
+ updateLayerType(view, alpha);
+ }
+
+ private static float mapToFadeDuration(float fadeOutAmount) {
+ // Assuming a linear interpolator, we can easily map it to our new duration
+ float endPoint = (float) ANIMATION_DURATION_LENGTH
+ / (float) StackStateAnimator.ANIMATION_DURATION_STANDARD;
+ return Math.min(fadeOutAmount / endPoint, 1.0f);
+ }
+
+ private static void updateLayerType(View view, float alpha) {
+ if (view.hasOverlappingRendering() && alpha > 0.0f && alpha < 1.0f) {
+ view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ } else if (view.getLayerType() == View.LAYER_TYPE_HARDWARE) {
+ view.setLayerType(View.LAYER_TYPE_NONE, null);
+ }
}
public static void fadeIn(final View view) {
@@ -62,4 +90,15 @@
view.animate().withLayer();
}
}
+
+ public static void fadeIn(View view, float fadeInAmount) {
+ view.animate().cancel();
+ if (view.getVisibility() == View.INVISIBLE) {
+ view.setVisibility(View.VISIBLE);
+ }
+ fadeInAmount = mapToFadeDuration(fadeInAmount);
+ float alpha = Interpolators.ALPHA_IN.getInterpolation(fadeInAmount);
+ view.setAlpha(alpha);
+ updateLayerType(view, alpha);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
index b326552..7f87c3c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
@@ -169,21 +169,23 @@
? RUBBERBAND_FACTOR_EXPANDABLE
: RUBBERBAND_FACTOR_STATIC;
float rubberband = heightDelta * rubberbandFactor;
- if (expandable && (rubberband + child.getMinHeight()) > child.getMaxContentHeight()) {
- float overshoot = (rubberband + child.getMinHeight()) - child.getMaxContentHeight();
+ if (expandable
+ && (rubberband + child.getMinExpandHeight()) > child.getMaxContentHeight()) {
+ float overshoot =
+ (rubberband + child.getMinExpandHeight()) - child.getMaxContentHeight();
overshoot *= (1 - RUBBERBAND_FACTOR_STATIC);
rubberband -= overshoot;
}
- child.setActualHeight((int) (child.getMinHeight() + rubberband));
+ child.setActualHeight((int) (child.getMinExpandHeight() + rubberband));
}
private void cancelExpansion(final ExpandableView child) {
- if (child.getActualHeight() == child.getMinHeight()) {
+ if (child.getActualHeight() == child.getMinExpandHeight()) {
mCallback.setUserLockedChild(child, false);
return;
}
ObjectAnimator anim = ObjectAnimator.ofInt(child, "actualHeight",
- child.getActualHeight(), child.getMinHeight());
+ child.getActualHeight(), child.getMinExpandHeight());
anim.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
anim.setDuration(SPRING_BACK_ANIMATION_LENGTH_MS);
anim.addListener(new AnimatorListenerAdapter() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 7422902..12a83fd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -16,6 +16,12 @@
package com.android.systemui.statusbar;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.app.Notification;
import android.content.Context;
import android.graphics.drawable.AnimatedVectorDrawable;
@@ -45,6 +51,7 @@
import com.android.systemui.statusbar.stack.StackStateAnimator;
import com.android.systemui.statusbar.stack.StackViewState;
+import java.util.ArrayList;
import java.util.List;
public class ExpandableNotificationRow extends ActivatableNotificationView {
@@ -73,6 +80,7 @@
/** Are we showing the "public" version */
private boolean mShowingPublic;
private boolean mSensitive;
+ private boolean mSensitiveHiddenInGeneral;
private boolean mShowingPublicInitialized;
private boolean mHideSensitiveForIntrinsicHeight;
@@ -87,6 +95,8 @@
*/
private boolean mOnKeyguard;
+ private AnimatorSet mTranslateAnim;
+ private ArrayList<View> mTranslateableViews;
private NotificationContentView mPublicLayout;
private NotificationContentView mPrivateLayout;
private int mMaxExpandHeight;
@@ -95,7 +105,7 @@
private boolean mClearable;
private ExpansionLogger mLogger;
private String mLoggingKey;
- private boolean mWasReset;
+ private NotificationSettingsIconRow mSettingsIconRow;
private NotificationGuts mGuts;
private NotificationData.Entry mEntry;
private StatusBarNotification mStatusBarNotification;
@@ -108,6 +118,7 @@
private boolean mChildrenExpanded;
private boolean mIsSummaryWithChildren;
private NotificationChildrenContainer mChildrenContainer;
+ private ViewStub mSettingsIconRowStub;
private ViewStub mGutsStub;
private boolean mIsSystemChildExpanded;
private boolean mIsPinned;
@@ -240,7 +251,6 @@
!= com.android.internal.R.id.status_bar_latest_event_content;
int headsUpheight = headsUpCustom && beforeN ? mMaxHeadsUpHeightLegacy
: mMaxHeadsUpHeight;
- mMaxViewHeight = mNotificationMaxHeight;
mPrivateLayout.setHeights(minHeight, headsUpheight, mNotificationMaxHeight);
mPublicLayout.setHeights(minHeight, headsUpheight, mNotificationMaxHeight);
}
@@ -329,6 +339,15 @@
}
@Override
+ protected boolean handleSlideBack() {
+ if (mSettingsIconRow != null && mSettingsIconRow.isVisible()) {
+ animateTranslateNotification(0 /* targetLeft */);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
protected boolean shouldHideBackground() {
return super.shouldHideBackground() || mShowNoBackground;
}
@@ -392,7 +411,8 @@
}
public ExpandableNotificationRow getViewAtPosition(float y) {
- if (!mIsSummaryWithChildren || !mChildrenExpanded) {
+ if (!mIsSummaryWithChildren || !mChildrenExpanded
+ || (getNotificationChildren().size() == 1 && isClearable())) {
return this;
} else {
ExpandableNotificationRow view = mChildrenContainer.getViewAtPosition(y);
@@ -500,6 +520,13 @@
return mPrivateLayout.getNotificationHeader();
}
+ private NotificationHeaderView getVisibleNotificationHeader() {
+ if (mNotificationHeader != null) {
+ return mNotificationHeader;
+ }
+ return getShowingLayout().getVisibleNotificationHeader();
+ }
+
public void setOnExpandClickListener(OnExpandClickListener onExpandClickListener) {
mOnExpandClickListener = onExpandClickListener;
}
@@ -527,6 +554,17 @@
mGuts.setVisibility(oldGuts.getVisibility());
addView(mGuts, index);
}
+ if (mSettingsIconRow != null) {
+ View oldSettings = mSettingsIconRow;
+ int settingsIndex = indexOfChild(oldSettings);
+ removeView(oldSettings);
+ mSettingsIconRow = (NotificationSettingsIconRow) LayoutInflater.from(mContext).inflate(
+ R.layout.notification_settings_icon_row, this, false);
+ mSettingsIconRow.setNotificationRowParent(ExpandableNotificationRow.this);
+ mSettingsIconRow.setVisibility(oldSettings.getVisibility());
+ addView(mSettingsIconRow, settingsIndex);
+
+ }
mPrivateLayout.reInflateViews();
mPublicLayout.reInflateViews();
}
@@ -542,16 +580,23 @@
}
private void initDimens() {
- mNotificationMinHeightLegacy = getResources().getDimensionPixelSize(
- R.dimen.notification_min_height_legacy);
- mNotificationMinHeight = getResources().getDimensionPixelSize(
- R.dimen.notification_min_height);
- mNotificationMaxHeight = getResources().getDimensionPixelSize(
- R.dimen.notification_max_height);
- mMaxHeadsUpHeightLegacy = getResources().getDimensionPixelSize(
+ mNotificationMinHeightLegacy = getFontScaledHeight(R.dimen.notification_min_height_legacy);
+ mNotificationMinHeight = getFontScaledHeight(R.dimen.notification_min_height);
+ mNotificationMaxHeight = getFontScaledHeight(R.dimen.notification_max_height);
+ mMaxHeadsUpHeightLegacy = getFontScaledHeight(
R.dimen.notification_max_heads_up_height_legacy);
- mMaxHeadsUpHeight = getResources().getDimensionPixelSize(
- R.dimen.notification_max_heads_up_height);
+ mMaxHeadsUpHeight = getFontScaledHeight(R.dimen.notification_max_heads_up_height);
+ }
+
+ /**
+ * @param dimenId the dimen to look up
+ * @return the font scaled dimen as if it were in sp but doesn't shrink sizes below dp
+ */
+ private int getFontScaledHeight(int dimenId) {
+ int dimensionPixelSize = getResources().getDimensionPixelSize(dimenId);
+ float factor = Math.max(1.0f, getResources().getDisplayMetrics().scaledDensity /
+ getResources().getDisplayMetrics().density);
+ return (int) (dimensionPixelSize * factor);
}
/**
@@ -561,7 +606,6 @@
public void reset() {
super.reset();
final boolean wasExpanded = isExpanded();
- mMaxViewHeight = 0;
mExpandable = false;
mHasUserChangedExpansion = false;
mUserLocked = false;
@@ -570,19 +614,16 @@
mShowingPublicInitialized = false;
mIsSystemExpanded = false;
mOnKeyguard = false;
- mPublicLayout.reset(mIsHeadsUp);
- mPrivateLayout.reset(mIsHeadsUp);
+ mPublicLayout.reset();
+ mPrivateLayout.reset();
resetHeight();
+ resetTranslation();
logExpansionEvent(false, wasExpanded);
}
public void resetHeight() {
- if (mIsHeadsUp) {
- resetActualHeight();
- }
mMaxExpandHeight = 0;
mHeadsUpHeight = 0;
- mWasReset = true;
onHeightReset();
requestLayout();
}
@@ -596,6 +637,14 @@
mPrivateLayout.setExpandClickListener(mExpandClickListener);
mPrivateLayout.setContainingNotification(this);
mPublicLayout.setExpandClickListener(mExpandClickListener);
+ mSettingsIconRowStub = (ViewStub) findViewById(R.id.settings_icon_row_stub);
+ mSettingsIconRowStub.setOnInflateListener(new ViewStub.OnInflateListener() {
+ @Override
+ public void onInflate(ViewStub stub, View inflated) {
+ mSettingsIconRow = (NotificationSettingsIconRow) inflated;
+ mSettingsIconRow.setNotificationRowParent(ExpandableNotificationRow.this);
+ }
+ });
mGutsStub = (ViewStub) findViewById(R.id.notification_guts_stub);
mGutsStub.setOnInflateListener(new ViewStub.OnInflateListener() {
@Override
@@ -613,9 +662,131 @@
public void onInflate(ViewStub stub, View inflated) {
mChildrenContainer = (NotificationChildrenContainer) inflated;
mChildrenContainer.setNotificationParent(ExpandableNotificationRow.this);
+ mTranslateableViews.add(mChildrenContainer);
}
});
mVetoButton = findViewById(R.id.veto);
+
+ // Add the views that we translate to reveal the gear
+ mTranslateableViews = new ArrayList<View>();
+ for (int i = 0; i < getChildCount(); i++) {
+ mTranslateableViews.add(getChildAt(i));
+ }
+ // Remove views that don't translate
+ mTranslateableViews.remove(mVetoButton);
+ mTranslateableViews.remove(mSettingsIconRowStub);
+ mTranslateableViews.remove(mChildrenContainerStub);
+ mTranslateableViews.remove(mGutsStub);
+ }
+
+ private void setTranslationForOutline(float translationX) {
+ setOutlineRect(false, translationX, getTop(), getRight() + translationX, getBottom());
+ }
+
+ public void resetTranslation() {
+ if (mTranslateableViews != null) {
+ for (int i = 0; i < mTranslateableViews.size(); i++) {
+ mTranslateableViews.get(i).setTranslationX(0);
+ }
+ setTranslationForOutline(0);
+ }
+ if (mSettingsIconRow != null) {
+ mSettingsIconRow.resetState();
+ }
+ }
+
+ public void animateTranslateNotification(final float leftTarget) {
+ if (mTranslateAnim != null) {
+ mTranslateAnim.cancel();
+ }
+ mTranslateAnim = (AnimatorSet) getTranslateViewAnimator(leftTarget,
+ null /* updateListener */);
+ if (mTranslateAnim != null) {
+ mTranslateAnim.start();
+ }
+ }
+
+ @Override
+ public void setTranslation(float translationX) {
+ if (areGutsExposed()) {
+ // Don't translate if guts are showing.
+ return;
+ }
+ // Translate the group of views
+ for (int i = 0; i < mTranslateableViews.size(); i++) {
+ if (mTranslateableViews.get(i) != null) {
+ mTranslateableViews.get(i).setTranslationX(translationX);
+ }
+ }
+ setTranslationForOutline(translationX);
+ if (mSettingsIconRow != null) {
+ mSettingsIconRow.updateSettingsIcons(translationX, getMeasuredWidth());
+ }
+ }
+
+ @Override
+ public float getTranslation() {
+ if (mTranslateableViews != null && mTranslateableViews.size() > 0) {
+ // All of the views in the list should have same translation, just use first one.
+ return mTranslateableViews.get(0).getTranslationX();
+ }
+ return 0;
+ }
+
+ public Animator getTranslateViewAnimator(final float leftTarget,
+ AnimatorUpdateListener listener) {
+ if (areGutsExposed()) {
+ // No translation if guts are exposed.
+ return null;
+ }
+ AnimatorSet set = new AnimatorSet();
+ if (mTranslateableViews != null) {
+ for (int i = 0; i < mTranslateableViews.size(); i++) {
+ final View animView = mTranslateableViews.get(i);
+ final ObjectAnimator translateAnim = ObjectAnimator.ofFloat(
+ animView, "translationX", leftTarget);
+ if (i == 0) {
+ translateAnim.addUpdateListener(new AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ setTranslationForOutline((float) animation.getAnimatedValue());
+ if (mSettingsIconRow != null) {
+ mSettingsIconRow.updateSettingsIcons(
+ (float) animation.getAnimatedValue(), getMeasuredWidth());
+ }
+ }
+ });
+ if (listener != null) {
+ translateAnim.addUpdateListener(listener);
+ }
+ }
+ translateAnim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator anim) {
+ if (mSettingsIconRow != null && leftTarget == 0) {
+ mSettingsIconRow.resetState();
+ }
+ mTranslateAnim = null;
+ }
+ });
+ set.play(translateAnim);
+ }
+ }
+ return set;
+ }
+
+ public float getSpaceForGear() {
+ if (mSettingsIconRow != null) {
+ return mSettingsIconRow.getSpaceForGear();
+ }
+ return 0;
+ }
+
+ public NotificationSettingsIconRow getSettingsRow() {
+ if (mSettingsIconRow == null) {
+ mSettingsIconRowStub.inflate();
+ }
+ return mSettingsIconRow;
}
public void inflateGuts() {
@@ -734,6 +905,10 @@
public void setUserLocked(boolean userLocked) {
mUserLocked = userLocked;
+ mPrivateLayout.setUserExpanding(userLocked);
+ if (mIsSummaryWithChildren) {
+ mChildrenContainer.setUserLocked(userLocked);
+ }
}
/**
@@ -772,7 +947,7 @@
if (mIsSummaryWithChildren) {
mChildrenContainer.updateGroupOverflow();
}
- notifyHeightChanged(false /* needsAnimation */);
+ notifyHeightChanged(false /* needsAnimation */);
}
}
}
@@ -784,18 +959,6 @@
return mStatusBarNotification != null && mStatusBarNotification.isClearable();
}
- /**
- * Apply an expansion state to the layout.
- */
- public void applyExpansionToLayout() {
- boolean expand = isExpanded();
- if (expand && mExpandable) {
- setActualHeight(mMaxExpandHeight);
- } else {
- setActualHeight(getMinHeight());
- }
- }
-
@Override
public int getIntrinsicHeight() {
if (isUserLocked()) {
@@ -877,12 +1040,7 @@
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
- boolean updateExpandHeight = mMaxExpandHeight == 0 && !mWasReset;
updateMaxHeights();
- if (updateExpandHeight) {
- applyExpansionToLayout();
- }
- mWasReset = false;
}
private void updateMaxHeights() {
@@ -908,12 +1066,21 @@
getShowingLayout().requestSelectLayout(needsAnimation || isUserLocked());
}
- public void setSensitive(boolean sensitive) {
+ public void setSensitive(boolean sensitive, boolean hideSensitive) {
mSensitive = sensitive;
+ mSensitiveHiddenInGeneral = hideSensitive;
}
public void setHideSensitiveForIntrinsicHeight(boolean hideSensitive) {
mHideSensitiveForIntrinsicHeight = hideSensitive;
+ if (mIsSummaryWithChildren) {
+ List<ExpandableNotificationRow> notificationChildren =
+ mChildrenContainer.getNotificationChildren();
+ for (int i = 0; i < notificationChildren.size(); i++) {
+ ExpandableNotificationRow child = notificationChildren.get(i);
+ child.setHideSensitiveForIntrinsicHeight(hideSensitive);
+ }
+ }
}
public void setHideSensitive(boolean hideSensitive, boolean animated, long delay,
@@ -981,7 +1148,8 @@
private void updateClearability() {
// public versions cannot be dismissed
- mVetoButton.setVisibility(isClearable() && !mShowingPublic ? View.VISIBLE : View.GONE);
+ mVetoButton.setVisibility(isClearable() && (!mShowingPublic
+ || !mSensitiveHiddenInGeneral) ? View.VISIBLE : View.GONE);
}
public void setChildrenExpanded(boolean expanded, boolean animate) {
@@ -1021,6 +1189,10 @@
return mMaxExpandHeight;
}
+ public boolean areGutsExposed() {
+ return (mGuts != null && mGuts.areGutsExposed());
+ }
+
@Override
public boolean isContentExpandable() {
NotificationContentView showingLayout = getShowingLayout();
@@ -1035,13 +1207,19 @@
@Override
public void setActualHeight(int height, boolean notifyListeners) {
super.setActualHeight(height, notifyListeners);
+ if (mGuts != null && mGuts.areGutsExposed()) {
+ mGuts.setActualHeight(height);
+ return;
+ }
int contentHeight = Math.max(getMinHeight(), height);
mPrivateLayout.setContentHeight(contentHeight);
mPublicLayout.setContentHeight(contentHeight);
+ if (mIsSummaryWithChildren) {
+ mChildrenContainer.setActualHeight(height);
+ }
if (mGuts != null) {
mGuts.setActualHeight(height);
}
- invalidate();
}
@Override
@@ -1068,8 +1246,8 @@
@Override
public int getMinExpandHeight() {
- if (mIsSummaryWithChildren && !mOnKeyguard) {
- return mChildrenContainer.getMinExpandHeight();
+ if (mIsSummaryWithChildren && !mShowingPublic) {
+ return mChildrenContainer.getMinExpandHeight(mOnKeyguard);
}
return getMinHeight();
}
@@ -1097,6 +1275,7 @@
mNotificationHeaderWrapper = NotificationViewWrapper.wrap(getContext(),
mNotificationHeader);
addView(mNotificationHeader, indexOfChild(mChildrenContainer) + 1);
+ mTranslateableViews.add(mNotificationHeader);
} else {
header.reapply(getContext(), mNotificationHeader);
mNotificationHeaderWrapper.notifyContentUpdated(mEntry.notification);
@@ -1122,7 +1301,7 @@
return mMaxExpandHeight != 0;
}
- private NotificationContentView getShowingLayout() {
+ public NotificationContentView getShowingLayout() {
return mShowingPublic ? mPublicLayout : mPrivateLayout;
}
@@ -1158,15 +1337,22 @@
}
@Override
- public boolean needsIncreasedPadding() {
- return mIsSummaryWithChildren && isGroupExpanded();
+ public float getIncreasedPaddingAmount() {
+ if (mIsSummaryWithChildren) {
+ if (isGroupExpanded()) {
+ return 1.0f;
+ } else if (isUserLocked()) {
+ return mChildrenContainer.getChildExpandFraction();
+ }
+ }
+ return 0.0f;
}
@Override
protected boolean disallowSingleClick(MotionEvent event) {
float x = event.getX();
float y = event.getY();
- NotificationHeaderView header = getNotificationHeader();
+ NotificationHeaderView header = getVisibleNotificationHeader();
if (header != null) {
return header.isInTouchRect(x, y);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
index 44c6a5d..f98e87d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
@@ -70,6 +70,11 @@
}
}
+ @Override
+ public float getOutlineAlpha() {
+ return mOutlineAlpha;
+ }
+
protected void setOutlineRect(RectF rect) {
if (rect != null) {
setOutlineRect(rect.left, rect.top, rect.right, rect.bottom);
@@ -80,9 +85,19 @@
}
}
+ @Override
+ public int getOutlineTranslation() {
+ return mCustomOutline ? mOutlineRect.left : 0;
+ }
+
protected void setOutlineRect(float left, float top, float right, float bottom) {
+ setOutlineRect(true, left, top, right, bottom);
+ }
+
+ protected void setOutlineRect(boolean clipToOutline, float left, float top, float right,
+ float bottom) {
mCustomOutline = true;
- setClipToOutline(true);
+ setClipToOutline(clipToOutline);
mOutlineRect.set((int) left, (int) top, (int) right, (int) bottom);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 8042b60..c0e4340 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -24,7 +24,6 @@
import android.view.ViewGroup;
import android.widget.FrameLayout;
-import com.android.systemui.R;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import java.util.ArrayList;
@@ -35,10 +34,8 @@
public abstract class ExpandableView extends FrameLayout {
protected OnHeightChangedListener mOnHeightChangedListener;
- protected int mMaxViewHeight;
private int mActualHeight;
protected int mClipTopAmount;
- private boolean mActualHeightInitialized;
private boolean mDark;
private ArrayList<View> mMatchParentViews = new ArrayList<View>();
private int mClipTopOptimization;
@@ -49,8 +46,6 @@
public ExpandableView(Context context, AttributeSet attrs) {
super(context, attrs);
- mMaxViewHeight = getResources().getDimensionPixelSize(
- R.dimen.notification_max_height);
}
@Override
@@ -103,28 +98,9 @@
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
- if (!mActualHeightInitialized && mActualHeight == 0) {
- int initialHeight = getInitialHeight();
- if (initialHeight != 0) {
- setActualHeight(initialHeight);
- }
- }
updateClipping();
}
- /**
- * Resets the height of the view on the next layout pass
- */
- protected void resetActualHeight() {
- mActualHeight = 0;
- mActualHeightInitialized = false;
- requestLayout();
- }
-
- protected int getInitialHeight() {
- return getHeight();
- }
-
@Override
public boolean pointInView(float localX, float localY, float slop) {
float top = mClipTopAmount;
@@ -141,7 +117,6 @@
* @param notifyListeners Whether the listener should be informed about the change.
*/
public void setActualHeight(int actualHeight, boolean notifyListeners) {
- mActualHeightInitialized = true;
mActualHeight = actualHeight;
updateClipping();
if (notifyListeners) {
@@ -287,6 +262,20 @@
public void setBelowSpeedBump(boolean below) {
}
+ /**
+ * Sets the translation of the view.
+ */
+ public void setTranslation(float translation) {
+ setTranslationX(translation);
+ }
+
+ /**
+ * Gets the translation of the view.
+ */
+ public float getTranslation() {
+ return getTranslationX();
+ }
+
public void onHeightReset() {
if (mOnHeightChangedListener != null) {
mOnHeightChangedListener.onReset(this);
@@ -395,14 +384,29 @@
public void setShadowAlpha(float shadowAlpha) {
}
- public boolean needsIncreasedPadding() {
- return false;
+ /**
+ * @return an amount between 0 and 1 of increased padding that this child needs
+ */
+ public float getIncreasedPaddingAmount() {
+ return 0.0f;
}
public boolean mustStayOnScreen() {
return false;
}
+ public void setFakeShadowIntensity(float shadowIntensity, float outlineAlpha, int shadowYEnd,
+ int outlineTranslation) {
+ }
+
+ public float getOutlineAlpha() {
+ return 0.0f;
+ }
+
+ public int getOutlineTranslation() {
+ return 0;
+ }
+
/**
* A listener notifying when {@link #getActualHeight} changes.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index d5361dd..b94c15b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -48,6 +48,7 @@
private static final int VISIBLE_TYPE_EXPANDED = 1;
private static final int VISIBLE_TYPE_HEADSUP = 2;
private static final int VISIBLE_TYPE_SINGLELINE = 3;
+ private static final int UNDEFINED = -1;
private final Rect mClipBounds = new Rect();
private final int mMinContractedHeight;
@@ -91,7 +92,14 @@
= new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
- mAnimate = true;
+ // We need to post since we don't want the notification to animate on the very first
+ // frame
+ post(new Runnable() {
+ @Override
+ public void run() {
+ mAnimate = true;
+ }
+ });
getViewTreeObserver().removeOnPreDrawListener(this);
return true;
}
@@ -102,6 +110,8 @@
private boolean mExpandable;
private boolean mClipToActualHeight = true;
private ExpandableNotificationRow mContainingNotification;
+ private int mTransformationStartVisibleType;
+ private boolean mUserExpanding;
public NotificationContentView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -110,7 +120,7 @@
R.dimen.min_notification_layout_height);
mNotificationContentMarginEnd = getResources().getDimensionPixelSize(
com.android.internal.R.dimen.notification_content_margin_end);
- reset(true);
+ reset();
}
public void setHeights(int smallHeight, int headsUpMaxHeight, int maxHeight) {
@@ -144,11 +154,11 @@
}
if (mContractedChild != null) {
int heightSpec;
+ int size = Math.min(maxSize, mSmallHeight);
if (shouldContractedBeFixedSize()) {
- int size = Math.min(maxSize, mSmallHeight);
heightSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
} else {
- heightSpec = MeasureSpec.makeMeasureSpec(maxSize, MeasureSpec.AT_MOST);
+ heightSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST);
}
mContractedChild.measure(widthMeasureSpec, heightSpec);
int measuredHeight = mContractedChild.getMeasuredHeight();
@@ -245,7 +255,7 @@
updateVisibility();
}
- public void reset(boolean resetActualHeight) {
+ public void reset() {
if (mContractedChild != null) {
mContractedChild.animate().cancel();
removeView(mContractedChild);
@@ -261,10 +271,6 @@
mContractedChild = null;
mExpandedChild = null;
mHeadsUpChild = null;
- mVisibleType = VISIBLE_TYPE_CONTRACTED;
- if (resetActualHeight) {
- mContentHeight = mSmallHeight;
- }
}
public View getContractedChild() {
@@ -349,6 +355,41 @@
invalidateOutline();
}
+ private void updateContentTransformation() {
+ int visibleType = calculateVisibleType();
+ if (visibleType != mVisibleType) {
+ // A new transformation starts
+ mTransformationStartVisibleType = mVisibleType;
+ final TransformableView shownView = getTransformableViewForVisibleType(visibleType);
+ final TransformableView hiddenView = getTransformableViewForVisibleType(
+ mTransformationStartVisibleType);
+ shownView.transformFrom(hiddenView, 0.0f);
+ getViewForVisibleType(visibleType).setVisibility(View.VISIBLE);
+ hiddenView.transformTo(shownView, 0.0f);
+ mVisibleType = visibleType;
+ }
+ if (mTransformationStartVisibleType != UNDEFINED
+ && mVisibleType != mTransformationStartVisibleType) {
+ final TransformableView shownView = getTransformableViewForVisibleType(mVisibleType);
+ final TransformableView hiddenView = getTransformableViewForVisibleType(
+ mTransformationStartVisibleType);
+ float transformationAmount = calculateTransformationAmount();
+ shownView.transformFrom(hiddenView, transformationAmount);
+ hiddenView.transformTo(shownView, transformationAmount);
+ } else {
+ updateViewVisibilities(visibleType);
+ }
+ }
+
+ private float calculateTransformationAmount() {
+ int startHeight = getViewForVisibleType(mTransformationStartVisibleType).getHeight();
+ int endHeight = getViewForVisibleType(mVisibleType).getHeight();
+ int progress = Math.abs(mContentHeight - startHeight);
+ int totalDistance = Math.abs(endHeight - startHeight);
+ float amount = (float) progress / (float) totalDistance;
+ return Math.min(1.0f, amount);
+ }
+
public int getContentHeight() {
return mContentHeight;
}
@@ -363,10 +404,14 @@
}
public int getMinHeight() {
- if (mIsChildInGroup && !isGroupExpanded()) {
- return mSingleLineView.getHeight();
- } else {
+ return getMinHeight(false /* likeGroupExpanded */);
+ }
+
+ public int getMinHeight(boolean likeGroupExpanded) {
+ if (likeGroupExpanded || !mIsChildInGroup || isGroupExpanded()) {
return mContractedChild.getHeight();
+ } else {
+ return mSingleLineView.getHeight();
}
}
@@ -397,6 +442,10 @@
if (mContractedChild == null) {
return;
}
+ if (mUserExpanding) {
+ updateContentTransformation();
+ return;
+ }
int visibleType = calculateVisibleType();
if (visibleType != mVisibleType || force) {
if (animate && ((visibleType == VISIBLE_TYPE_EXPANDED && mExpandedChild != null)
@@ -431,12 +480,18 @@
private void animateToVisibleType(int visibleType) {
final TransformableView shownView = getTransformableViewForVisibleType(visibleType);
final TransformableView hiddenView = getTransformableViewForVisibleType(mVisibleType);
+ if (shownView == hiddenView) {
+ shownView.setVisible(true);
+ return;
+ }
shownView.transformFrom(hiddenView);
getViewForVisibleType(visibleType).setVisibility(View.VISIBLE);
hiddenView.transformTo(shownView, new Runnable() {
@Override
public void run() {
- hiddenView.setVisible(false);
+ if (hiddenView != getTransformableViewForVisibleType(mVisibleType)) {
+ hiddenView.setVisible(false);
+ }
}
});
}
@@ -475,17 +530,53 @@
}
}
+ private NotificationViewWrapper getCurrentVisibleWrapper() {
+ switch (mVisibleType) {
+ case VISIBLE_TYPE_EXPANDED:
+ return mExpandedWrapper;
+ case VISIBLE_TYPE_HEADSUP:
+ return mHeadsUpWrapper;
+ case VISIBLE_TYPE_CONTRACTED:
+ return mContractedWrapper;
+ default:
+ return null;
+ }
+ }
+
/**
* @return one of the static enum types in this view, calculated form the current state
*/
private int calculateVisibleType() {
- boolean noExpandedChild = mExpandedChild == null;
+ if (mUserExpanding) {
+ int height = !mIsChildInGroup || isGroupExpanded()
+ || mContainingNotification.isExpanded()
+ ? mContainingNotification.getMaxContentHeight()
+ : mContainingNotification.getShowingLayout().getMinHeight();
+ if (height == 0) {
+ height = mContentHeight;
+ }
+ int expandedVisualType = getVisualTypeForHeight(height);
+ int collapsedVisualType = getVisualTypeForHeight(
+ mContainingNotification.getMinExpandHeight());
+ return mTransformationStartVisibleType == collapsedVisualType
+ ? expandedVisualType
+ : collapsedVisualType;
+ }
+ int intrinsicHeight = mContainingNotification.getIntrinsicHeight();
+ int viewHeight = mContentHeight;
+ if (intrinsicHeight != 0) {
+ // the intrinsicHeight might be 0 because it was just reset.
+ viewHeight = Math.min(mContentHeight, intrinsicHeight);
+ }
+ return getVisualTypeForHeight(viewHeight);
+ }
- int viewHeight = Math.min(mContentHeight, mContainingNotification.getIntrinsicHeight());
+ private int getVisualTypeForHeight(float viewHeight) {
+ boolean noExpandedChild = mExpandedChild == null;
if (!noExpandedChild && viewHeight == mExpandedChild.getHeight()) {
return VISIBLE_TYPE_EXPANDED;
}
- if (mIsChildInGroup && !isGroupExpanded()) {
+ if (!mUserExpanding && mIsChildInGroup && !isGroupExpanded()) {
return VISIBLE_TYPE_SINGLELINE;
}
@@ -510,7 +601,9 @@
}
public void setDark(boolean dark, boolean fade, long delay) {
- if (mDark == dark || mContractedChild == null) return;
+ if (mContractedChild == null) {
+ return;
+ }
mDark = dark;
dark = dark && !mShowingLegacyBackground;
if (mVisibleType == VISIBLE_TYPE_CONTRACTED || !dark) {
@@ -555,10 +648,8 @@
mBeforeN = entry.targetSdk < Build.VERSION_CODES.N;
updateSingleLineView();
applyRemoteInput(entry);
- selectLayout(false /* animate */, true /* force */);
if (mContractedChild != null) {
mContractedWrapper.notifyContentUpdated(entry.notification);
- mContractedWrapper.setDark(mDark, false /* animate */, 0 /* delay */);
}
if (mExpandedChild != null) {
mExpandedWrapper.notifyContentUpdated(entry.notification);
@@ -566,6 +657,8 @@
if (mHeadsUpChild != null) {
mHeadsUpWrapper.notifyContentUpdated(entry.notification);
}
+ selectLayout(false /* animate */, true /* force */);
+ setDark(mDark, false /* animate */, 0 /* delay */);
}
private void updateSingleLineView() {
@@ -684,6 +777,11 @@
return header;
}
+ public NotificationHeaderView getVisibleNotificationHeader() {
+ NotificationViewWrapper wrapper = getCurrentVisibleWrapper();
+ return wrapper == null ? null : wrapper.getNotificationHeader();
+ }
+
public void setContainingNotification(ExpandableNotificationRow containingNotification) {
mContainingNotification = containingNotification;
}
@@ -699,4 +797,15 @@
updateSingleLineView();
}
}
+
+ public void setUserExpanding(boolean userExpanding) {
+ mUserExpanding = userExpanding;
+ if (userExpanding) {
+ mTransformationStartVisibleType = mVisibleType;
+ } else {
+ mTransformationStartVisibleType = UNDEFINED;
+ mVisibleType = calculateVisibleType();
+ updateViewVisibilities(mVisibleType);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 2cacb8a..c9fe2bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -34,6 +34,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.Objects;
/**
* The list of currently displaying notifications.
@@ -110,18 +111,24 @@
if (updatedNotification != null) {
final Notification.Builder updatedNotificationBuilder
= Notification.Builder.recoverBuilder(ctx, updatedNotification);
- final RemoteViews newContentView = updatedNotificationBuilder.makeContentView();
+ final RemoteViews newContentView = updatedNotificationBuilder.createContentView();
final RemoteViews newBigContentView =
- updatedNotificationBuilder.makeBigContentView();
+ updatedNotificationBuilder.createBigContentView();
final RemoteViews newHeadsUpContentView =
- updatedNotificationBuilder.makeHeadsUpContentView();
+ updatedNotificationBuilder.createHeadsUpContentView();
final RemoteViews newPublicNotification
= updatedNotificationBuilder.makePublicContentView();
+ boolean sameCustomView = Objects.equals(
+ notification.getNotification().extras.getBoolean(
+ Notification.EXTRA_CONTAINS_CUSTOM_VIEW),
+ updatedNotification.extras.getBoolean(
+ Notification.EXTRA_CONTAINS_CUSTOM_VIEW));
applyInPlace = compareRemoteViews(cachedContentView, newContentView)
&& compareRemoteViews(cachedBigContentView, newBigContentView)
&& compareRemoteViews(cachedHeadsUpContentView, newHeadsUpContentView)
- && compareRemoteViews(cachedPublicContentView, newPublicNotification);
+ && compareRemoteViews(cachedPublicContentView, newPublicNotification)
+ && sameCustomView;
cachedPublicContentView = newPublicNotification;
cachedHeadsUpContentView = newHeadsUpContentView;
cachedBigContentView = newBigContentView;
@@ -130,9 +137,9 @@
final Notification.Builder builder
= Notification.Builder.recoverBuilder(ctx, notification.getNotification());
- cachedContentView = builder.makeContentView();
- cachedBigContentView = builder.makeBigContentView();
- cachedHeadsUpContentView = builder.makeHeadsUpContentView();
+ cachedContentView = builder.createContentView();
+ cachedBigContentView = builder.createBigContentView();
+ cachedHeadsUpContentView = builder.createHeadsUpContentView();
cachedPublicContentView = builder.makePublicContentView();
applyInPlace = false;
@@ -196,11 +203,11 @@
String mediaNotification = mEnvironment.getCurrentMediaNotificationKey();
- // PRIORITY_MIN media streams are allowed to drift to the bottom
+ // IMPORTANCE_MIN media streams are allowed to drift to the bottom
final boolean aMedia = a.key.equals(mediaNotification)
- && aImportance > Ranking.IMPORTANCE_LOW;
+ && aImportance > Ranking.IMPORTANCE_MIN;
final boolean bMedia = b.key.equals(mediaNotification)
- && bImportance > Ranking.IMPORTANCE_LOW;
+ && bImportance > Ranking.IMPORTANCE_MIN;
boolean aSystemMax = aImportance >= Ranking.IMPORTANCE_MAX &&
isSystemNotification(na);
@@ -346,8 +353,10 @@
return true;
}
- if (sbn.getNotification().visibility == Notification.VISIBILITY_SECRET &&
- mEnvironment.shouldHideSensitiveContents(sbn.getUserId())) {
+ if (mEnvironment.onSecureLockScreen() &&
+ (sbn.getNotification().visibility == Notification.VISIBILITY_SECRET
+ || mEnvironment.shouldHideNotifications(sbn.getUserId())
+ || mEnvironment.shouldHideNotifications(sbn.getKey()))) {
return true;
}
@@ -426,7 +435,9 @@
* Provides access to keyguard state and user settings dependent data.
*/
public interface Environment {
- public boolean shouldHideSensitiveContents(int userid);
+ public boolean onSecureLockScreen();
+ public boolean shouldHideNotifications(int userid);
+ public boolean shouldHideNotifications(String key);
public boolean isDeviceProvisioned();
public boolean isNotificationForCurrentProfiles(StatusBarNotification sbn);
public String getCurrentMediaNotificationKey();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index 7346bec..45a24a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar;
import android.app.INotificationManager;
-import android.app.Notification;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -39,25 +38,31 @@
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settingslib.Utils;
import com.android.systemui.R;
+import com.android.systemui.tuner.TunerService;
/**
* The guts of a notification revealed when performing a long press.
*/
-public class NotificationGuts extends LinearLayout {
+public class NotificationGuts extends LinearLayout implements TunerService.Tunable {
+ public static final String SHOW_SLIDER = "show_importance_slider";
private Drawable mBackground;
private int mClipTopAmount;
private int mActualHeight;
private boolean mExposed;
- private RadioButton mApplyToTopic;
- private SeekBar mSeekBar;
- private Notification.Topic mTopic;
private INotificationManager mINotificationManager;
private int mStartingImportance;
+ private boolean mShowSlider;
+
+ private SeekBar mSeekBar;
+ private RadioButton mBlock;
+ private RadioButton mSilent;
+ private RadioButton mReset;
public NotificationGuts(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(false);
+ TunerService.get(mContext).addTunable(this, SHOW_SLIDER);
}
@Override
@@ -104,46 +109,90 @@
}
}
- void bindImportance(final StatusBarNotification sbn, final ExpandableNotificationRow row,
- final int importance) {
+ void bindImportance(final PackageManager pm, final StatusBarNotification sbn,
+ final ExpandableNotificationRow row, final int importance) {
mStartingImportance = importance;
mINotificationManager = INotificationManager.Stub.asInterface(
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
- mTopic = sbn.getNotification().getTopic() == null
- ? new Notification.Topic(Notification.TOPIC_DEFAULT, mContext.getString(
- com.android.internal.R.string.default_notification_topic_label))
- : sbn.getNotification().getTopic();
- boolean doesUserUseTopics = false;
- try {
- doesUserUseTopics =
- mINotificationManager.doesUserUseTopics(sbn.getPackageName(), sbn.getUid());
- } catch (RemoteException e) {}
- final boolean userUsesTopics = doesUserUseTopics;
-
- mApplyToTopic = (RadioButton) row.findViewById(R.id.apply_to_topic);
- if (userUsesTopics) {
- mApplyToTopic.setChecked(true);
- }
- final View applyToApp = row.findViewById(R.id.apply_to_app);
- final TextView topicSummary = ((TextView) row.findViewById(R.id.summary));
- final TextView topicTitle = ((TextView) row.findViewById(R.id.title));
- mSeekBar = (SeekBar) row.findViewById(R.id.seekbar);
boolean systemApp = false;
try {
- final PackageManager pm = BaseStatusBar.getPackageManagerForUser(
- getContext(), sbn.getUser().getIdentifier());
final PackageInfo info =
pm.getPackageInfo(sbn.getPackageName(), PackageManager.GET_SIGNATURES);
systemApp = Utils.isSystemPackage(pm, info);
} catch (PackageManager.NameNotFoundException e) {
// unlikely.
}
+
+ final View importanceSlider = row.findViewById(R.id.importance_slider);
+ final View importanceButtons = row.findViewById(R.id.importance_buttons);
+ if (mShowSlider) {
+ bindSlider(importanceSlider, sbn, systemApp);
+ importanceSlider.setVisibility(View.VISIBLE);
+ importanceButtons.setVisibility(View.GONE);
+ } else {
+ int userImportance = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
+ try {
+ userImportance =
+ mINotificationManager.getImportance(sbn.getPackageName(), sbn.getUid());
+ } catch (RemoteException e) {}
+ bindToggles(importanceButtons, userImportance, systemApp);
+ importanceButtons.setVisibility(View.VISIBLE);
+ importanceSlider.setVisibility(View.GONE);
+ }
+ }
+
+ void saveImportance(final StatusBarNotification sbn) {
+ int progress;
+ if (mSeekBar!= null && mSeekBar.isShown()) {
+ progress = mSeekBar.getProgress();
+ } else {
+ if (mBlock.isChecked()) {
+ progress = NotificationListenerService.Ranking.IMPORTANCE_NONE;
+ } else if (mSilent.isChecked()) {
+ progress = NotificationListenerService.Ranking.IMPORTANCE_LOW;
+ } else {
+ progress = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
+ }
+ }
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
+ progress - mStartingImportance);
+ try {
+ mINotificationManager.setImportance(sbn.getPackageName(), sbn.getUid(), progress);
+ } catch (RemoteException e) {
+ // :(
+ }
+ }
+
+ private void bindToggles(final View importanceButtons, final int importance,
+ final boolean systemApp) {
+ mBlock = (RadioButton) importanceButtons.findViewById(R.id.block_importance);
+ mSilent = (RadioButton) importanceButtons.findViewById(R.id.silent_importance);
+ mReset = (RadioButton) importanceButtons.findViewById(R.id.reset_importance);
if (systemApp) {
- ((ImageView) row.findViewById(R.id.low_importance)).getDrawable().setTint(
+ mBlock.setVisibility(View.GONE);
+ mReset.setText(mContext.getString(R.string.do_not_silence));
+ } else {
+ mReset.setText(mContext.getString(R.string.do_not_silence_block));
+ }
+ if (importance == NotificationListenerService.Ranking.IMPORTANCE_LOW) {
+ mSilent.setChecked(true);
+ } else {
+ mReset.setChecked(true);
+ }
+ }
+
+ private void bindSlider(final View importanceSlider, final StatusBarNotification sbn,
+ final boolean systemApp) {
+ final TextView importanceSummary = ((TextView) importanceSlider.findViewById(R.id.summary));
+ final TextView importanceTitle = ((TextView) importanceSlider.findViewById(R.id.title));
+ mSeekBar = (SeekBar) importanceSlider.findViewById(R.id.seekbar);
+
+ if (systemApp) {
+ ((ImageView) importanceSlider.findViewById(R.id.low_importance)).getDrawable().setTint(
mContext.getColor(R.color.notification_guts_disabled_icon_tint));
}
final int minProgress = systemApp ?
- NotificationListenerService.Ranking.IMPORTANCE_LOW
+ NotificationListenerService.Ranking.IMPORTANCE_MIN
: NotificationListenerService.Ranking.IMPORTANCE_NONE;
mSeekBar.setMax(NotificationListenerService.Ranking.IMPORTANCE_MAX);
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@@ -156,12 +205,6 @@
updateTitleAndSummary(progress);
if (fromUser) {
MetricsLogger.action(mContext, MetricsEvent.ACTION_MODIFY_IMPORTANCE_SLIDER);
- if (userUsesTopics) {
- mApplyToTopic.setVisibility(View.VISIBLE);
- mApplyToTopic.setText(
- mContext.getString(R.string.apply_to_topic, mTopic.getLabel()));
- applyToApp.setVisibility(View.VISIBLE);
- }
}
}
@@ -178,46 +221,39 @@
private void updateTitleAndSummary(int progress) {
switch (progress) {
case NotificationListenerService.Ranking.IMPORTANCE_NONE:
- topicSummary.setText(mContext.getString(
+ importanceSummary.setText(mContext.getString(
R.string.notification_importance_blocked));
- topicTitle.setText(mContext.getString(R.string.blocked_importance));
+ importanceTitle.setText(mContext.getString(R.string.blocked_importance));
+ break;
+ case NotificationListenerService.Ranking.IMPORTANCE_MIN:
+ importanceSummary.setText(mContext.getString(
+ R.string.notification_importance_min));
+ importanceTitle.setText(mContext.getString(R.string.min_importance));
break;
case NotificationListenerService.Ranking.IMPORTANCE_LOW:
- topicSummary.setText(mContext.getString(
+ importanceSummary.setText(mContext.getString(
R.string.notification_importance_low));
- topicTitle.setText(mContext.getString(R.string.low_importance));
+ importanceTitle.setText(mContext.getString(R.string.low_importance));
break;
case NotificationListenerService.Ranking.IMPORTANCE_DEFAULT:
- topicSummary.setText(mContext.getString(
+ importanceSummary.setText(mContext.getString(
R.string.notification_importance_default));
- topicTitle.setText(mContext.getString(R.string.default_importance));
+ importanceTitle.setText(mContext.getString(R.string.default_importance));
break;
case NotificationListenerService.Ranking.IMPORTANCE_HIGH:
- topicSummary.setText(mContext.getString(
+ importanceSummary.setText(mContext.getString(
R.string.notification_importance_high));
- topicTitle.setText(mContext.getString(R.string.high_importance));
+ importanceTitle.setText(mContext.getString(R.string.high_importance));
break;
case NotificationListenerService.Ranking.IMPORTANCE_MAX:
- topicSummary.setText(mContext.getString(
+ importanceSummary.setText(mContext.getString(
R.string.notification_importance_max));
- topicTitle.setText(mContext.getString(R.string.max_importance));
+ importanceTitle.setText(mContext.getString(R.string.max_importance));
break;
}
}
});
- mSeekBar.setProgress(importance);
- }
-
- void saveImportance(final StatusBarNotification sbn) {
- int progress = mSeekBar.getProgress();
- MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
- progress - mStartingImportance);
- try {
- mINotificationManager.setImportance(sbn.getPackageName(), sbn.getUid(),
- mApplyToTopic.isChecked() ? mTopic : null, progress);
- } catch (RemoteException e) {
- // :(
- }
+ mSeekBar.setProgress(mStartingImportance);
}
public void setActualHeight(int actualHeight) {
@@ -248,4 +284,11 @@
public boolean areGutsExposed() {
return mExposed;
}
+
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ if (SHOW_SLIDER.equals(key)) {
+ mShowSlider = newValue != null && Integer.parseInt(newValue) != 0;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
new file mode 100644
index 0000000..375459f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+
+public class NotificationSettingsIconRow extends FrameLayout implements View.OnClickListener {
+
+ public interface SettingsIconRowListener {
+ /**
+ * Called when the gear behind a notification is touched.
+ */
+ public void onGearTouched(ExpandableNotificationRow row, int x, int y);
+ }
+
+ private ExpandableNotificationRow mParent;
+ private AlphaOptimizedImageView mGearIcon;
+ private float mHorizSpaceForGear;
+ private SettingsIconRowListener mListener;
+
+ private ValueAnimator mFadeAnimator;
+ private boolean mSettingsFadedIn = false;
+ private boolean mAnimating = false;
+ private boolean mOnLeft = true;
+ private int[] mGearLocation = new int[2];
+ private int[] mParentLocation = new int[2];
+
+ public NotificationSettingsIconRow(Context context) {
+ this(context, null);
+ }
+
+ public NotificationSettingsIconRow(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public NotificationSettingsIconRow(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public NotificationSettingsIconRow(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mGearIcon = (AlphaOptimizedImageView) findViewById(R.id.gear_icon);
+ mGearIcon.setOnClickListener(this);
+ setOnClickListener(this);
+ mHorizSpaceForGear =
+ getResources().getDimensionPixelOffset(R.dimen.notification_gear_width);
+ resetState();
+ }
+
+ public void resetState() {
+ setGearAlpha(0f);
+ mAnimating = false;
+ setIconLocation(true /* on left */);
+ }
+
+ public void setGearListener(SettingsIconRowListener listener) {
+ mListener = listener;
+ }
+
+ public void setNotificationRowParent(ExpandableNotificationRow parent) {
+ mParent = parent;
+ }
+
+ public ExpandableNotificationRow getNotificationParent() {
+ return mParent;
+ }
+
+ private void setGearAlpha(float alpha) {
+ if (alpha == 0) {
+ mSettingsFadedIn = false; // Can fade in again once it's gone.
+ setVisibility(View.INVISIBLE);
+ } else {
+ if (alpha == 1) {
+ mSettingsFadedIn = true;
+ }
+ setVisibility(View.VISIBLE);
+ }
+ mGearIcon.setAlpha(alpha);
+ }
+
+ /**
+ * Returns the horizontal space in pixels required to display the gear behind a notification.
+ */
+ public float getSpaceForGear() {
+ return mHorizSpaceForGear;
+ }
+
+ /**
+ * Indicates whether the gear is visible at 1 alpha. Does not indicate
+ * if entire view is visible.
+ */
+ public boolean isVisible() {
+ return mSettingsFadedIn;
+ }
+
+ public void cancelFadeAnimator() {
+ if (mFadeAnimator != null) {
+ mFadeAnimator.cancel();
+ }
+ }
+
+ public void updateSettingsIcons(final float transX, final float size) {
+ if (mAnimating || (mGearIcon.getAlpha() == 0)) {
+ // Don't adjust when animating or settings aren't visible
+ return;
+ }
+ setIconLocation(transX > 0 /* fromLeft */);
+ final float fadeThreshold = size * 0.3f;
+ final float absTrans = Math.abs(transX);
+ float desiredAlpha = 0;
+
+ if (absTrans <= fadeThreshold) {
+ desiredAlpha = 1;
+ } else {
+ desiredAlpha = 1 - ((absTrans - fadeThreshold) / (size - fadeThreshold));
+ }
+ setGearAlpha(desiredAlpha);
+ }
+
+ public void fadeInSettings(final boolean fromLeft, final float transX,
+ final float notiThreshold) {
+ setIconLocation(transX > 0 /* fromLeft */);
+ mFadeAnimator = ValueAnimator.ofFloat(mGearIcon.getAlpha(), 1);
+ mFadeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ final float absTrans = Math.abs(transX);
+
+ boolean pastGear = (fromLeft && transX <= notiThreshold)
+ || (!fromLeft && absTrans <= notiThreshold);
+ if (pastGear && !mSettingsFadedIn) {
+ setGearAlpha((float) animation.getAnimatedValue());
+ }
+ }
+ });
+ mFadeAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ super.onAnimationCancel(animation);
+ mAnimating = false;
+ mSettingsFadedIn = false;
+ }
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ super.onAnimationStart(animation);
+ mAnimating = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ mAnimating = false;
+ mSettingsFadedIn = true;
+ }
+ });
+ mFadeAnimator.setInterpolator(Interpolators.ALPHA_IN);
+ mFadeAnimator.setDuration(200);
+ mFadeAnimator.start();
+ }
+
+ private void setIconLocation(boolean onLeft) {
+ if (onLeft == mOnLeft) {
+ // Same side? Do nothing.
+ return;
+ }
+
+ setTranslationX(onLeft ? 0 : (mParent.getWidth() - mHorizSpaceForGear));
+ mOnLeft = onLeft;
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (v.getId() == R.id.gear_icon) {
+ if (mListener != null) {
+ mGearIcon.getLocationOnScreen(mGearLocation);
+ mParent.getLocationOnScreen(mParentLocation);
+
+ final int centerX = (int) (mHorizSpaceForGear / 2);
+ // Top / bottom padding are not equal, need to subtract them to get center of gear.
+ final int centerY = (int) (mGearIcon.getHeight() - mGearIcon.getPaddingTop()
+ - mGearIcon.getPaddingBottom()) / 2 + mGearIcon.getPaddingTop();
+ final int x = mGearLocation[0] - mParentLocation[0] + centerX;
+ final int y = mGearLocation[1] - mParentLocation[1] + centerY;
+ mListener.onGearTouched(mParent, x, y);
+ }
+ } else {
+ // Do nothing when the background is touched.
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 9aa5ea0..988d537 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -23,6 +23,7 @@
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Animatable;
+import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.telephony.SubscriptionInfo;
import android.util.ArraySet;
@@ -90,6 +91,8 @@
View mWifiSignalSpacer;
LinearLayout mMobileSignalGroup;
+ private final int mMobileSignalGroupEndPadding;
+ private final int mMobileDataIconStartPadding;
private final int mWideTypeIconStartPadding;
private final int mSecondaryTelephonyPadding;
private final int mEndPadding;
@@ -113,6 +116,10 @@
super(context, attrs, defStyle);
Resources res = getResources();
+ mMobileSignalGroupEndPadding =
+ res.getDimensionPixelSize(R.dimen.mobile_signal_group_end_padding);
+ mMobileDataIconStartPadding =
+ res.getDimensionPixelSize(R.dimen.mobile_data_icon_start_padding);
mWideTypeIconStartPadding = res.getDimensionPixelSize(R.dimen.wide_type_icon_start_padding);
mSecondaryTelephonyPadding = res.getDimensionPixelSize(R.dimen.secondary_telephony_padding);
mEndPadding = res.getDimensionPixelSize(R.dimen.signal_cluster_battery_padding);
@@ -206,16 +213,23 @@
for (PhoneState state : mPhoneStates) {
mMobileSignalGroup.addView(state.mMobileGroup);
}
+
+ int endPadding = mMobileSignalGroup.getChildCount() > 0 ? mMobileSignalGroupEndPadding : 0;
+ mMobileSignalGroup.setPaddingRelative(0, 0, endPadding, 0);
+
TunerService.get(mContext).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
apply();
applyIconTint();
+ mNC.addSignalCallback(this);
}
@Override
protected void onDetachedFromWindow() {
mMobileSignalGroup.removeAllViews();
TunerService.get(mContext).removeTunable(this);
+ mSC.removeCallback(this);
+ mNC.removeSignalCallback(this);
super.onDetachedFromWindow();
}
@@ -577,9 +591,11 @@
// When this isn't next to wifi, give it some extra padding between the signals.
mMobileGroup.setPaddingRelative(isSecondaryIcon ? mSecondaryTelephonyPadding : 0,
0, 0, 0);
- mMobile.setPaddingRelative(mIsMobileTypeIconWide ? mWideTypeIconStartPadding : 0,
+ mMobile.setPaddingRelative(
+ mIsMobileTypeIconWide ? mWideTypeIconStartPadding : mMobileDataIconStartPadding,
0, 0, 0);
- mMobileDark.setPaddingRelative(mIsMobileTypeIconWide ? mWideTypeIconStartPadding : 0,
+ mMobileDark.setPaddingRelative(
+ mIsMobileTypeIconWide ? mWideTypeIconStartPadding : mMobileDataIconStartPadding,
0, 0, 0);
if (DEBUG) Log.d(TAG, String.format("mobile: %s sig=%d typ=%d",
@@ -592,12 +608,19 @@
private void updateAnimatableIcon(ImageView view, int resId) {
maybeStopAnimatableDrawable(view);
- view.setImageResource(resId);
+ setIconForView(view, resId);
maybeStartAnimatableDrawable(view);
}
private void maybeStopAnimatableDrawable(ImageView view) {
Drawable drawable = view.getDrawable();
+
+ // Check if the icon has been scaled. If it has retrieve the actual drawable out of the
+ // wrapper.
+ if (drawable instanceof ScalingDrawableWrapper) {
+ drawable = ((ScalingDrawableWrapper) drawable).getDrawable();
+ }
+
if (drawable instanceof Animatable) {
Animatable ad = (Animatable) drawable;
if (ad.isRunning()) {
@@ -608,8 +631,18 @@
private void maybeStartAnimatableDrawable(ImageView view) {
Drawable drawable = view.getDrawable();
+
+ // Check if the icon has been scaled. If it has retrieve the actual drawable out of the
+ // wrapper.
+ if (drawable instanceof ScalingDrawableWrapper) {
+ drawable = ((ScalingDrawableWrapper) drawable).getDrawable();
+ }
+
if (drawable instanceof Animatable) {
Animatable ad = (Animatable) drawable;
+ if (ad instanceof AnimatedVectorDrawable) {
+ ((AnimatedVectorDrawable) ad).forceAnimationOnUI();
+ }
if (!ad.isRunning()) {
ad.start();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/TransformableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/TransformableView.java
index 38b6497..dd7c4c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/TransformableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/TransformableView.java
@@ -27,9 +27,11 @@
int TRANSFORMING_VIEW_TEXT = 2;
int TRANSFORMING_VIEW_IMAGE = 3;
int TRANSFORMING_VIEW_PROGRESS = 4;
+ int TRANSFORMING_VIEW_ACTIONS = 5;
/**
* Get the current state of a view in a transform animation
+ *
* @param fadingView which view we are interested in
* @return the current transform state of this viewtype
*/
@@ -37,18 +39,37 @@
/**
* Transform to the given view
+ *
* @param notification the view to transform to
*/
void transformTo(TransformableView notification, Runnable endRunnable);
/**
+ * Transform to the given view by a specified amount.
+ *
+ * @param notification the view to transform to
+ * @param transformationAmount how much transformation should be done
+ */
+ void transformTo(TransformableView notification, float transformationAmount);
+
+ /**
* Transform to this view from the given view
+ *
* @param notification the view to transform from
*/
void transformFrom(TransformableView notification);
/**
+ * Transform to this view from the given view by a specified amount.
+ *
+ * @param notification the view to transform from
+ * @param transformationAmount how much transformation should be done
+ */
+ void transformFrom(TransformableView notification, float transformationAmount);
+
+ /**
* Set this view to be fully visible or gone
+ *
* @param visible
*/
void setVisible(boolean visible);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
index 63ff5aa..66f945e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
@@ -16,13 +16,17 @@
package com.android.systemui.statusbar;
-import android.os.Handler;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
import android.util.ArrayMap;
import android.view.View;
import android.view.ViewGroup;
+import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.TransformState;
+import com.android.systemui.statusbar.stack.StackStateAnimator;
import java.util.Stack;
@@ -33,9 +37,9 @@
private static final int TAG_CONTAINS_TRANSFORMED_VIEW = R.id.contains_transformed_view;
- private final Handler mHandler = new Handler();
private ArrayMap<Integer, View> mTransformedViews = new ArrayMap<>();
private ArrayMap<Integer, CustomTransformation> mCustomTransformations = new ArrayMap<>();
+ private ValueAnimator mViewTransformationAnimation;
public void addTransformedView(int key, View transformedView) {
mTransformedViews.put(key, transformedView);
@@ -59,61 +63,123 @@
}
@Override
- public void transformTo(TransformableView notification, Runnable endRunnable) {
- Runnable runnable = endRunnable;
+ public void transformTo(final TransformableView notification, final Runnable endRunnable) {
+ if (mViewTransformationAnimation != null) {
+ mViewTransformationAnimation.cancel();
+ }
+ mViewTransformationAnimation = ValueAnimator.ofFloat(0.0f, 1.0f);
+ mViewTransformationAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ transformTo(notification, animation.getAnimatedFraction());
+ }
+ });
+ mViewTransformationAnimation.setInterpolator(Interpolators.LINEAR);
+ mViewTransformationAnimation.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+ mViewTransformationAnimation.addListener(new AnimatorListenerAdapter() {
+ public boolean mCancelled;
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!mCancelled) {
+ if (endRunnable != null) {
+ endRunnable.run();
+ }
+ setVisible(false);
+ } else {
+ abortTransformations();
+ }
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mCancelled = true;
+ }
+ });
+ mViewTransformationAnimation.start();
+ }
+
+ @Override
+ public void transformTo(TransformableView notification, float transformationAmount) {
for (Integer viewType : mTransformedViews.keySet()) {
TransformState ownState = getCurrentState(viewType);
if (ownState != null) {
CustomTransformation customTransformation = mCustomTransformations.get(viewType);
if (customTransformation != null && customTransformation.transformTo(
- ownState, notification, runnable)) {
+ ownState, notification, transformationAmount)) {
ownState.recycle();
- runnable = null;
continue;
}
TransformState otherState = notification.getCurrentState(viewType);
if (otherState != null) {
- boolean run = ownState.transformViewTo(otherState, runnable);
+ ownState.transformViewTo(otherState, transformationAmount);
otherState.recycle();
- if (run) {
- runnable = null;
- }
} else {
// there's no other view available
- CrossFadeHelper.fadeOut(mTransformedViews.get(viewType), runnable);
- runnable = null;
+ CrossFadeHelper.fadeOut(mTransformedViews.get(viewType), transformationAmount);
}
ownState.recycle();
}
}
- if (runnable != null) {
- // We need to post, since the visible type is only set after the transformation is
- // started
- mHandler.post(runnable);
- }
}
@Override
- public void transformFrom(TransformableView notification) {
+ public void transformFrom(final TransformableView notification) {
+ if (mViewTransformationAnimation != null) {
+ mViewTransformationAnimation.cancel();
+ }
+ mViewTransformationAnimation = ValueAnimator.ofFloat(0.0f, 1.0f);
+ mViewTransformationAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ transformFrom(notification, animation.getAnimatedFraction());
+ }
+ });
+ mViewTransformationAnimation.addListener(new AnimatorListenerAdapter() {
+ public boolean mCancelled;
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!mCancelled) {
+ setVisible(true);
+ } else {
+ abortTransformations();
+ }
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mCancelled = true;
+ }
+ });
+ mViewTransformationAnimation.setInterpolator(Interpolators.LINEAR);
+ mViewTransformationAnimation.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+ mViewTransformationAnimation.start();
+ }
+
+ @Override
+ public void transformFrom(TransformableView notification, float transformationAmount) {
for (Integer viewType : mTransformedViews.keySet()) {
TransformState ownState = getCurrentState(viewType);
if (ownState != null) {
CustomTransformation customTransformation = mCustomTransformations.get(viewType);
if (customTransformation != null && customTransformation.transformFrom(
- ownState, notification)) {
+ ownState, notification, transformationAmount)) {
ownState.recycle();
continue;
}
TransformState otherState = notification.getCurrentState(viewType);
if (otherState != null) {
- ownState.transformViewFrom(otherState);
+ ownState.transformViewFrom(otherState, transformationAmount);
otherState.recycle();
} else {
// There's no other view, lets fade us in
// Certain views need to prepare the fade in and make sure its children are
// completely visible. An example is the notification header.
- ownState.prepareFadeIn();
- CrossFadeHelper.fadeIn(mTransformedViews.get(viewType));
+ if (transformationAmount == 0.0f) {
+ ownState.prepareFadeIn();
+ }
+ CrossFadeHelper.fadeIn(mTransformedViews.get(viewType), transformationAmount);
}
ownState.recycle();
}
@@ -131,6 +197,16 @@
}
}
+ private void abortTransformations() {
+ for (Integer viewType : mTransformedViews.keySet()) {
+ TransformState ownState = getCurrentState(viewType);
+ if (ownState != null) {
+ ownState.abortTransformation();
+ ownState.recycle();
+ }
+ }
+ }
+
/**
* Add the remaining transformation views such that all views are being transformed correctly
* @param viewRoot the root below which all elements need to be transformed
@@ -173,22 +249,44 @@
}
}
- public interface CustomTransformation {
+ public static abstract class CustomTransformation {
/**
* Transform a state to the given view
* @param ownState the state to transform
* @param notification the view to transform to
+ * @param transformationAmount how much transformation should be done
* @return whether a custom transformation is performed
*/
- boolean transformTo(TransformState ownState, TransformableView notification,
- Runnable endRunnable);
+ public abstract boolean transformTo(TransformState ownState,
+ TransformableView notification,
+ float transformationAmount);
/**
* Transform to this state from the given view
* @param ownState the state to transform to
* @param notification the view to transform from
+ * @param transformationAmount how much transformation should be done
* @return whether a custom transformation is performed
*/
- boolean transformFrom(TransformState ownState, TransformableView notification);
+ public abstract boolean transformFrom(TransformState ownState,
+ TransformableView notification,
+ float transformationAmount);
+
+ /**
+ * Perform a custom initialisation before transforming.
+ *
+ * @param ownState our own state
+ * @param otherState the other state
+ * @return whether a custom initialization is done
+ */
+ public boolean initTransformation(TransformState ownState,
+ TransformState otherState) {
+ return false;
+ }
+
+ public boolean customTransformTarget(TransformState ownState,
+ TransformState otherState) {
+ return false;
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/FakeShadowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/FakeShadowView.java
new file mode 100644
index 0000000..32c26ba
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/FakeShadowView.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.Outline;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewOutlineProvider;
+import android.widget.LinearLayout;
+
+import com.android.systemui.statusbar.AlphaOptimizedFrameLayout;
+
+/**
+ * A view used to cast a shadow of a certain size on another view
+ */
+public class FakeShadowView extends AlphaOptimizedFrameLayout {
+ public static final float SHADOW_SIBLING_TRESHOLD = 0.1f;
+
+ private View mFakeShadow;
+ private float mOutlineAlpha;
+
+ public FakeShadowView(Context context) {
+ this(context, null);
+ }
+
+ public FakeShadowView(Context context, @Nullable AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public FakeShadowView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public FakeShadowView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ mFakeShadow = new View(context);
+ mFakeShadow.setVisibility(INVISIBLE);
+ mFakeShadow.setLayoutParams(new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ (int) (48 * getResources().getDisplayMetrics().density)));
+ mFakeShadow.setOutlineProvider(new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ outline.setRect(0, 0, getWidth(), mFakeShadow.getHeight());
+ outline.setAlpha(mOutlineAlpha);
+ }
+ });
+ addView(mFakeShadow);
+ }
+
+ public void setFakeShadowTranslationZ(float fakeShadowTranslationZ, float outlineAlpha,
+ int shadowYEnd, int outlineTranslation) {
+ if (fakeShadowTranslationZ == 0.0f) {
+ mFakeShadow.setVisibility(INVISIBLE);
+ } else {
+ mFakeShadow.setVisibility(VISIBLE);
+ mFakeShadow.setTranslationZ(fakeShadowTranslationZ);
+ mFakeShadow.setTranslationX(outlineTranslation);
+ mFakeShadow.setTranslationY(shadowYEnd - mFakeShadow.getHeight());
+ if (outlineAlpha != mOutlineAlpha) {
+ mOutlineAlpha = outlineAlpha;
+ mFakeShadow.invalidateOutline();
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HeaderTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HeaderTransformState.java
index 81483c6..b66e9f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HeaderTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HeaderTransformState.java
@@ -46,7 +46,7 @@
}
@Override
- public boolean transformViewTo(TransformState otherState, Runnable endRunnable) {
+ public boolean transformViewTo(TransformState otherState, float transformationAmount) {
// if the transforming notification has a header, we have ensured that it looks the same
// but the expand button, so lets fade just that one and transform the work profile icon.
if (!(mTransformedView instanceof NotificationHeaderView)) {
@@ -62,14 +62,14 @@
if (headerChild != mExpandButton) {
headerChild.setVisibility(View.INVISIBLE);
} else {
- CrossFadeHelper.fadeOut(mExpandButton, endRunnable);
+ CrossFadeHelper.fadeOut(mExpandButton, transformationAmount);
}
}
return true;
}
@Override
- public void transformViewFrom(TransformState otherState) {
+ public void transformViewFrom(TransformState otherState, float transformationAmount) {
// if the transforming notification has a header, we have ensured that it looks the same
// but the expand button, so lets fade just that one and transform the work profile icon.
if (!(mTransformedView instanceof NotificationHeaderView)) {
@@ -85,12 +85,13 @@
continue;
}
if (headerChild == mExpandButton) {
- CrossFadeHelper.fadeIn(mExpandButton);
+ CrossFadeHelper.fadeIn(mExpandButton, transformationAmount);
} else {
headerChild.setVisibility(View.VISIBLE);
if (headerChild == mWorkProfileIcon) {
- mWorkProfileState.animateViewFrom(
- ((HeaderTransformState) otherState).mWorkProfileState);
+ mWorkProfileState.transformViewFullyFrom(
+ ((HeaderTransformState) otherState).mWorkProfileState,
+ transformationAmount);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationView.java
index 81144d5..c80cad8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationView.java
@@ -71,13 +71,13 @@
new ViewTransformationHelper.CustomTransformation() {
@Override
public boolean transformTo(TransformState ownState, TransformableView notification,
- Runnable endRunnable) {
+ float transformationAmount) {
// We want to transform to the same y location as the title
TransformState otherState = notification.getCurrentState(
TRANSFORMING_VIEW_TITLE);
- CrossFadeHelper.fadeOut(mTextView, endRunnable);
+ CrossFadeHelper.fadeOut(mTextView, transformationAmount);
if (otherState != null) {
- ownState.animateViewVerticalTo(otherState, endRunnable);
+ ownState.transformViewVerticalTo(otherState, transformationAmount);
otherState.recycle();
}
return true;
@@ -85,13 +85,13 @@
@Override
public boolean transformFrom(TransformState ownState,
- TransformableView notification) {
+ TransformableView notification, float transformationAmount) {
// We want to transform from the same y location as the title
TransformState otherState = notification.getCurrentState(
TRANSFORMING_VIEW_TITLE);
- CrossFadeHelper.fadeIn(mTextView);
+ CrossFadeHelper.fadeIn(mTextView, transformationAmount);
if (otherState != null) {
- ownState.animateViewVerticalFrom(otherState);
+ ownState.transformViewVerticalFrom(otherState, transformationAmount);
otherState.recycle();
}
return true;
@@ -133,11 +133,21 @@
}
@Override
+ public void transformTo(TransformableView notification, float transformationAmount) {
+ mTransformationHelper.transformTo(notification, transformationAmount);
+ }
+
+ @Override
public void transformFrom(TransformableView notification) {
mTransformationHelper.transformFrom(notification);
}
@Override
+ public void transformFrom(TransformableView notification, float transformationAmount) {
+ mTransformationHelper.transformFrom(notification, transformationAmount);
+ }
+
+ @Override
public void setVisible(boolean visible) {
setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
mTransformationHelper.setVisible(visible);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java
index e891a97..45027c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java
@@ -62,7 +62,7 @@
}
@Override
- protected boolean animateScale() {
+ protected boolean transformScale() {
return true;
}
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 aa001ed..7f8f20f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
@@ -35,7 +35,7 @@
@Override
public void setDark(boolean dark, boolean fade, long delay) {
- if (dark == mDark) {
+ if (dark == mDark && mDarkInitialized) {
return;
}
super.setDark(dark, fade, delay);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
index 5a71caf..842bd22 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
@@ -142,12 +142,13 @@
protected void updateTransformedTypes() {
mTransformationHelper.reset();
- mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_HEADER, mNotificationHeader);
+ mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_HEADER,
+ mNotificationHeader);
}
@Override
public void setDark(boolean dark, boolean fade, long delay) {
- if (dark == mDark) {
+ if (dark == mDark && mDarkInitialized) {
return;
}
super.setDark(dark, fade, delay);
@@ -299,11 +300,21 @@
}
@Override
+ public void transformTo(TransformableView notification, float transformationAmount) {
+ mTransformationHelper.transformTo(notification, transformationAmount);
+ }
+
+ @Override
public void transformFrom(TransformableView notification) {
mTransformationHelper.transformFrom(notification);
}
@Override
+ public void transformFrom(TransformableView notification, float transformationAmount) {
+ mTransformationHelper.transformFrom(notification, transformationAmount);
+ }
+
+ @Override
public void setVisible(boolean visible) {
super.setVisible(visible);
mTransformationHelper.setVisible(visible);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
new file mode 100644
index 0000000..30698e1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import android.content.Context;
+import android.service.notification.StatusBarNotification;
+import android.view.View;
+
+import com.android.systemui.statusbar.TransformableView;
+
+/**
+ * Wraps a notification containing a media template
+ */
+public class NotificationMediaTemplateViewWrapper extends NotificationTemplateViewWrapper {
+
+ protected NotificationMediaTemplateViewWrapper(Context ctx, View view) {
+ super(ctx, view);
+ }
+
+ View mActions;
+
+ private void resolveViews(StatusBarNotification notification) {
+ mActions = mView.findViewById(com.android.internal.R.id.media_actions);
+ }
+
+ @Override
+ public void notifyContentUpdated(StatusBarNotification notification) {
+ // Reinspect the notification. Before the super call, because the super call also updates
+ // the transformation types and we need to have our values set by then.
+ resolveViews(notification);
+ super.notifyContentUpdated(notification);
+ }
+
+ @Override
+ protected void updateTransformedTypes() {
+ // This also clears the existing types
+ super.updateTransformedTypes();
+ if (mActions != null) {
+ mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TEXT,
+ mActions);
+ }
+ }
+}
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 0c21f0b..78e23fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
@@ -49,76 +49,65 @@
new ViewTransformationHelper.CustomTransformation() {
@Override
public boolean transformTo(TransformState ownState,
- TransformableView notification, final Runnable endRunnable) {
+ TransformableView notification, final float transformationAmount) {
if (!(notification instanceof HybridNotificationView)) {
return false;
}
TransformState otherState = notification.getCurrentState(
TRANSFORMING_VIEW_TITLE);
final View text = ownState.getTransformedView();
- CrossFadeHelper.fadeOut(text, endRunnable);
+ CrossFadeHelper.fadeOut(text, transformationAmount);
if (otherState != null) {
- int[] otherStablePosition = otherState.getLaidOutLocationOnScreen();
- int[] ownPosition = ownState.getLaidOutLocationOnScreen();
- text.animate()
- .translationY((otherStablePosition[1]
- + otherState.getTransformedView().getHeight()
- - ownPosition[1]) * 0.33f)
- .setDuration(
- StackStateAnimator.ANIMATION_DURATION_STANDARD)
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- if (endRunnable != null) {
- endRunnable.run();
- }
- TransformState.setClippingDeactivated(text,
- false);
- }
- });
- TransformState.setClippingDeactivated(text, true);
+ ownState.transformViewVerticalTo(otherState, this,
+ transformationAmount);
otherState.recycle();
}
return true;
}
@Override
+ public boolean customTransformTarget(TransformState ownState,
+ TransformState otherState) {
+ float endY = getTransformationY(ownState, otherState);
+ ownState.setTransformationEndY(endY);
+ return true;
+ }
+
+ @Override
public boolean transformFrom(TransformState ownState,
- TransformableView notification) {
+ TransformableView notification, float transformationAmount) {
if (!(notification instanceof HybridNotificationView)) {
return false;
}
TransformState otherState = notification.getCurrentState(
TRANSFORMING_VIEW_TITLE);
final View text = ownState.getTransformedView();
- boolean isVisible = text.getVisibility() == View.VISIBLE;
- CrossFadeHelper.fadeIn(text);
+ CrossFadeHelper.fadeIn(text, transformationAmount);
if (otherState != null) {
- int[] otherStablePosition = otherState.getLaidOutLocationOnScreen();
- int[] ownStablePosition = ownState.getLaidOutLocationOnScreen();
- if (!isVisible) {
- text.setTranslationY((otherStablePosition[1]
- + otherState.getTransformedView().getHeight()
- - ownStablePosition[1]) * 0.33f);
- }
- text.animate()
- .translationY(0)
- .setDuration(
- StackStateAnimator.ANIMATION_DURATION_STANDARD)
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- TransformState.setClippingDeactivated(text,
- false);
- }
- });
- TransformState.setClippingDeactivated(text, true);
+ ownState.transformViewVerticalFrom(otherState, this,
+ transformationAmount);
otherState.recycle();
}
return true;
}
+
+ @Override
+ public boolean initTransformation(TransformState ownState,
+ TransformState otherState) {
+ float startY = getTransformationY(ownState, otherState);
+ ownState.setTransformationStartY(startY);
+ return true;
+ }
+
+ private float getTransformationY(TransformState ownState,
+ TransformState otherState) {
+ int[] otherStablePosition = otherState.getLaidOutLocationOnScreen();
+ int[] ownStablePosition = ownState.getLaidOutLocationOnScreen();
+ return (otherStablePosition[1]
+ + otherState.getTransformedView().getHeight()
+ - ownStablePosition[1]) * 0.33f;
+ }
+
}, TRANSFORMING_VIEW_TEXT);
}
@@ -174,7 +163,7 @@
@Override
public void setDark(boolean dark, boolean fade, long delay) {
- if (dark == mDark) {
+ if (dark == mDark && mDarkInitialized) {
return;
}
super.setDark(dark, fade, delay);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
index 7089b78..4738657 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
@@ -34,4 +34,8 @@
v.setTag(R.id.icon_is_grayscale, grayscale);
return grayscale;
}
+
+ public static float interpolate(float start, float end, float amount) {
+ return start * (1.0f - amount) + end * amount;
+ }
}
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 328f8b5..0df0d26 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
@@ -32,6 +32,7 @@
protected final View mView;
protected boolean mDark;
+ protected boolean mDarkInitialized = false;
public static NotificationViewWrapper wrap(Context ctx, View v) {
if (v.getId() == com.android.internal.R.id.status_bar_latest_event_content) {
@@ -39,6 +40,8 @@
return new NotificationBigPictureTemplateViewWrapper(ctx, v);
} else if ("bigText".equals(v.getTag())) {
return new NotificationBigTextTemplateViewWrapper(ctx, v);
+ } else if ("media".equals(v.getTag()) || "bigMediaNarrow".equals(v.getTag())) {
+ return new NotificationMediaTemplateViewWrapper(ctx, v);
}
return new NotificationTemplateViewWrapper(ctx, v);
} else if (v instanceof NotificationHeaderView) {
@@ -61,6 +64,7 @@
*/
public void setDark(boolean dark, boolean fade, long delay) {
mDark = dark;
+ mDarkInitialized = true;
}
/**
@@ -68,7 +72,7 @@
* @param notification
*/
public void notifyContentUpdated(StatusBarNotification notification) {
- mDark = false;
+ mDarkInitialized = false;
};
/**
@@ -98,12 +102,22 @@
}
@Override
+ public void transformTo(TransformableView notification, float transformationAmount) {
+ CrossFadeHelper.fadeOut(mView, transformationAmount);
+ }
+
+ @Override
public void transformFrom(TransformableView notification) {
// By default we are fading in completely
CrossFadeHelper.fadeIn(mView);
}
@Override
+ public void transformFrom(TransformableView notification, float transformationAmount) {
+ CrossFadeHelper.fadeIn(mView, transformationAmount);
+ }
+
+ @Override
public void setVisible(boolean visible) {
mView.animate().cancel();
mView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TextViewTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TextViewTransformState.java
index 5ab441d..d3393b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TextViewTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TextViewTransformState.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification;
+import android.text.Layout;
import android.text.TextUtils;
import android.util.Pools;
import android.view.View;
@@ -28,14 +29,13 @@
private static Pools.SimplePool<TextViewTransformState> sInstancePool
= new Pools.SimplePool<>(40);
- private CharSequence mText;
+ private TextView mText;
@Override
public void initFrom(View view) {
super.initFrom(view);
if (view instanceof TextView) {
- TextView txt = (TextView) view;
- mText = txt.getText();
+ mText = (TextView) view;
}
}
@@ -43,11 +43,27 @@
protected boolean sameAs(TransformState otherState) {
if (otherState instanceof TextViewTransformState) {
TextViewTransformState otherTvs = (TextViewTransformState) otherState;
- return TextUtils.equals(otherTvs.mText, mText);
+ if(TextUtils.equals(otherTvs.mText.getText(), mText.getText())) {
+ int ownEllipsized = getEllipsisCount();
+ int otherEllipsized = otherTvs.getEllipsisCount();
+ return ownEllipsized == otherEllipsized;
+ }
}
return super.sameAs(otherState);
}
+ private int getEllipsisCount() {
+ Layout l = mText.getLayout();
+ if (l != null) {
+ int lines = l.getLineCount();
+ if (lines > 0) {
+ // we only care about the first line
+ return l.getEllipsisCount(0);
+ }
+ }
+ return 0;
+ }
+
public static TextViewTransformState obtain() {
TextViewTransformState instance = sInstancePool.acquire();
if (instance != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
index 67d31be..f04fe5e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
@@ -30,23 +30,30 @@
import com.android.systemui.R;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.stack.StackStateAnimator;
+import com.android.systemui.statusbar.ViewTransformationHelper;
/**
* A transform state of a view.
*/
public class TransformState {
- private static final int ANIMATE_X = 0x1;
- private static final int ANIMATE_Y = 0x10;
- private static final int ANIMATE_ALL = ANIMATE_X | ANIMATE_Y;
+ private static final float UNDEFINED = -1f;
+ private static final int TRANSOFORM_X = 0x1;
+ private static final int TRANSOFORM_Y = 0x10;
+ private static final int TRANSOFORM_ALL = TRANSOFORM_X | TRANSOFORM_Y;
private static final int CLIP_CLIPPING_SET = R.id.clip_children_set_tag;
private static final int CLIP_CHILDREN_TAG = R.id.clip_children_tag;
private static final int CLIP_TO_PADDING = R.id.clip_to_padding_tag;
+ private static final int TRANSFORMATION_START_X = R.id.transformation_start_x_tag;
+ private static final int TRANSFORMATION_START_Y = R.id.transformation_start_y_tag;
+ private static final int TRANSFORMATION_START_SCLALE_X = R.id.transformation_start_scale_x_tag;
+ private static final int TRANSFORMATION_START_SCLALE_Y = R.id.transformation_start_scale_y_tag;
private static Pools.SimplePool<TransformState> sInstancePool = new Pools.SimplePool<>(40);
protected View mTransformedView;
private int[] mOwnPosition = new int[2];
+ private float mTransformationEndY = UNDEFINED;
+ private float mTransformationEndX = UNDEFINED;
public void initFrom(View view) {
mTransformedView = view;
@@ -55,129 +62,233 @@
/**
* Transforms the {@link #mTransformedView} from the given transformviewstate
* @param otherState the state to transform from
+ * @param transformationAmount how much to transform
*/
- public void transformViewFrom(TransformState otherState) {
+ public void transformViewFrom(TransformState otherState, float transformationAmount) {
mTransformedView.animate().cancel();
if (sameAs(otherState)) {
- // We have the same content, lets show ourselves
- mTransformedView.setAlpha(1.0f);
- mTransformedView.setVisibility(View.VISIBLE);
+ if (mTransformedView.getVisibility() == View.INVISIBLE) {
+ // We have the same content, lets show ourselves
+ mTransformedView.setAlpha(1.0f);
+ mTransformedView.setVisibility(View.VISIBLE);
+ }
} else {
- CrossFadeHelper.fadeIn(mTransformedView);
+ CrossFadeHelper.fadeIn(mTransformedView, transformationAmount);
}
- animateViewFrom(otherState);
+ transformViewFullyFrom(otherState, transformationAmount);
}
- public void animateViewFrom(TransformState otherState) {
- animateViewFrom(otherState, ANIMATE_ALL);
+ public void transformViewFullyFrom(TransformState otherState, float transformationAmount) {
+ transformViewFrom(otherState, TRANSOFORM_ALL, null, transformationAmount);
}
- public void animateViewVerticalFrom(TransformState otherState) {
- animateViewFrom(otherState, ANIMATE_Y);
+ public void transformViewVerticalFrom(TransformState otherState,
+ ViewTransformationHelper.CustomTransformation customTransformation,
+ float transformationAmount) {
+ transformViewFrom(otherState, TRANSOFORM_Y, customTransformation, transformationAmount);
}
- private void animateViewFrom(TransformState otherState, int animationFlags) {
+ public void transformViewVerticalFrom(TransformState otherState, float transformationAmount) {
+ transformViewFrom(otherState, TRANSOFORM_Y, null, transformationAmount);
+ }
+
+ private void transformViewFrom(TransformState otherState, int transformationFlags,
+ ViewTransformationHelper.CustomTransformation customTransformation,
+ float transformationAmount) {
final View transformedView = mTransformedView;
+ boolean transformX = (transformationFlags & TRANSOFORM_X) != 0;
+ boolean transformY = (transformationFlags & TRANSOFORM_Y) != 0;
+ boolean transformScale = transformScale();
// lets animate the positions correctly
- int[] otherPosition = otherState.getLocationOnScreen();
- int[] ownStablePosition = getLaidOutLocationOnScreen();
- if ((animationFlags & ANIMATE_X) != 0) {
- transformedView.setTranslationX(otherPosition[0] - ownStablePosition[0]);
- transformedView.animate().translationX(0);
- }
- if ((animationFlags & ANIMATE_Y) != 0) {
- transformedView.setTranslationY(otherPosition[1] - ownStablePosition[1]);
- transformedView.animate().translationY(0);
- }
- if (animateScale()) {
- // we also want to animate the scale if we're the same
- View otherView = otherState.getTransformedView();
- if (otherView.getWidth() != transformedView.getWidth()) {
- float scaleX = (otherView.getWidth() * otherView.getScaleX()
- / (float) transformedView.getWidth());
- transformedView.setScaleX(scaleX);
- transformedView.setPivotX(0);
- transformedView.animate().scaleX(1.0f);
+ if (transformationAmount == 0.0f) {
+ int[] otherPosition = otherState.getLocationOnScreen();
+ int[] ownStablePosition = getLaidOutLocationOnScreen();
+ if (customTransformation == null
+ || !customTransformation.initTransformation(this, otherState)) {
+ if (transformX) {
+ setTransformationStartX(otherPosition[0] - ownStablePosition[0]);
+ }
+ if (transformY) {
+ setTransformationStartY(otherPosition[1] - ownStablePosition[1]);
+ }
+ // we also want to animate the scale if we're the same
+ View otherView = otherState.getTransformedView();
+ if (transformScale && otherView.getWidth() != transformedView.getWidth()) {
+ setTransformationStartScaleX(otherView.getWidth() * otherView.getScaleX()
+ / (float) transformedView.getWidth());
+ transformedView.setPivotX(0);
+ } else {
+ setTransformationStartScaleX(UNDEFINED);
+ }
+ if (transformScale && otherView.getHeight() != transformedView.getHeight()) {
+ setTransformationStartScaleY(otherView.getHeight() * otherView.getScaleY()
+ / (float) transformedView.getHeight());
+ transformedView.setPivotY(0);
+ } else {
+ setTransformationStartScaleY(UNDEFINED);
+ }
}
- if (otherView.getHeight() != transformedView.getHeight()) {
- float scaleY = (otherView.getHeight() * otherView.getScaleY()
- / (float) transformedView.getHeight());
- transformedView.setScaleY(scaleY);
- transformedView.setPivotY(0);
- transformedView.animate().scaleY(1.0f);
+ if (!transformX) {
+ setTransformationStartX(UNDEFINED);
+ }
+ if (!transformY) {
+ setTransformationStartY(UNDEFINED);
+ }
+ if (!transformScale) {
+ setTransformationStartScaleX(UNDEFINED);
+ setTransformationStartScaleY(UNDEFINED);
+ }
+ setClippingDeactivated(transformedView, true);
+ }
+ float interpolatedValue = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(
+ transformationAmount);
+ if (transformX) {
+ transformedView.setTranslationX(NotificationUtils.interpolate(getTransformationStartX(),
+ 0.0f,
+ interpolatedValue));
+ }
+ if (transformY) {
+ transformedView.setTranslationY(NotificationUtils.interpolate(getTransformationStartY(),
+ 0.0f,
+ interpolatedValue));
+ }
+ if (transformScale) {
+ float transformationStartScaleX = getTransformationStartScaleX();
+ if (transformationStartScaleX != UNDEFINED) {
+ transformedView.setScaleX(
+ NotificationUtils.interpolate(transformationStartScaleX,
+ 1.0f,
+ interpolatedValue));
+ }
+ float transformationStartScaleY = getTransformationStartScaleY();
+ if (transformationStartScaleY != UNDEFINED) {
+ transformedView.setScaleY(
+ NotificationUtils.interpolate(transformationStartScaleY,
+ 1.0f,
+ interpolatedValue));
}
}
- transformedView.animate()
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD)
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- setClippingDeactivated(transformedView, false);
- }
- });
- setClippingDeactivated(transformedView, true);
}
- protected boolean animateScale() {
+ protected boolean transformScale() {
return false;
}
/**
* Transforms the {@link #mTransformedView} to the given transformviewstate
* @param otherState the state to transform from
- * @param endRunnable a runnable to run at the end of the animation
+ * @param transformationAmount how much to transform
* @return whether an animation was started
*/
- public boolean transformViewTo(TransformState otherState, final Runnable endRunnable) {
+ public boolean transformViewTo(TransformState otherState, float transformationAmount) {
mTransformedView.animate().cancel();
if (sameAs(otherState)) {
// We have the same text, lets show ourselfs
- mTransformedView.setAlpha(0.0f);
- mTransformedView.setVisibility(View.INVISIBLE);
+ if (mTransformedView.getVisibility() == View.VISIBLE) {
+ mTransformedView.setAlpha(0.0f);
+ mTransformedView.setVisibility(View.INVISIBLE);
+ }
return false;
} else {
- CrossFadeHelper.fadeOut(mTransformedView, endRunnable);
+ CrossFadeHelper.fadeOut(mTransformedView, transformationAmount);
}
- animateViewTo(otherState, endRunnable);
+ transformViewFullyTo(otherState, transformationAmount);
return true;
}
- public void animateViewTo(TransformState otherState, Runnable endRunnable) {
- animateViewTo(otherState, endRunnable, ANIMATE_ALL);
+ public void transformViewFullyTo(TransformState otherState, float transformationAmount) {
+ transformViewTo(otherState, TRANSOFORM_ALL, null, transformationAmount);
}
- public void animateViewVerticalTo(TransformState otherState, Runnable endRunnable) {
- animateViewTo(otherState, endRunnable, ANIMATE_Y);
+ public void transformViewVerticalTo(TransformState otherState,
+ ViewTransformationHelper.CustomTransformation customTransformation,
+ float transformationAmount) {
+ transformViewTo(otherState, TRANSOFORM_Y, customTransformation, transformationAmount);
}
- private void animateViewTo(TransformState otherState, final Runnable endRunnable,
- int animationFlags) {
+ public void transformViewVerticalTo(TransformState otherState, float transformationAmount) {
+ transformViewTo(otherState, TRANSOFORM_Y, null, transformationAmount);
+ }
+
+ private void transformViewTo(TransformState otherState, int transformationFlags,
+ ViewTransformationHelper.CustomTransformation customTransformation,
+ float transformationAmount) {
// lets animate the positions correctly
+
+ final View transformedView = mTransformedView;
+ boolean transformX = (transformationFlags & TRANSOFORM_X) != 0;
+ boolean transformY = (transformationFlags & TRANSOFORM_Y) != 0;
+ boolean transformScale = transformScale();
+ // lets animate the positions correctly
+ if (transformationAmount == 0.0f) {
+ if (transformX) {
+ float transformationStartX = getTransformationStartX();
+ float start = transformationStartX != UNDEFINED ? transformationStartX
+ : transformedView.getTranslationX();
+ setTransformationStartX(start);
+ }
+ if (transformY) {
+ float transformationStartY = getTransformationStartY();
+ float start = transformationStartY != UNDEFINED ? transformationStartY
+ : transformedView.getTranslationY();
+ setTransformationStartY(start);
+ }
+ View otherView = otherState.getTransformedView();
+ if (transformScale && otherView.getWidth() != transformedView.getWidth()) {
+ setTransformationStartScaleX(transformedView.getScaleX());
+ transformedView.setPivotX(0);
+ } else {
+ setTransformationStartScaleX(UNDEFINED);
+ }
+ if (transformScale && otherView.getHeight() != transformedView.getHeight()) {
+ setTransformationStartScaleY(transformedView.getScaleY());
+ transformedView.setPivotY(0);
+ } else {
+ setTransformationStartScaleY(UNDEFINED);
+ }
+ setClippingDeactivated(transformedView, true);
+ }
+ float interpolatedValue = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(
+ transformationAmount);
int[] otherStablePosition = otherState.getLaidOutLocationOnScreen();
int[] ownPosition = getLaidOutLocationOnScreen();
- final View transformedView = mTransformedView;
- if ((animationFlags & ANIMATE_X) != 0) {
- transformedView.animate()
- .translationX(otherStablePosition[0] - ownPosition[0]);
+ if (transformX) {
+ float endX = otherStablePosition[0] - ownPosition[0];
+ if (customTransformation != null
+ && customTransformation.customTransformTarget(this, otherState)) {
+ endX = mTransformationEndX;
+ }
+ transformedView.setTranslationX(NotificationUtils.interpolate(getTransformationStartX(),
+ endX,
+ interpolatedValue));
}
- if ((animationFlags & ANIMATE_Y) != 0) {
- transformedView.animate()
- .translationY(otherStablePosition[1] - ownPosition[1]);
+ if (transformY) {
+ float endY = otherStablePosition[1] - ownPosition[1];
+ if (customTransformation != null
+ && customTransformation.customTransformTarget(this, otherState)) {
+ endY = mTransformationEndY;
+ }
+ transformedView.setTranslationY(NotificationUtils.interpolate(getTransformationStartY(),
+ endY,
+ interpolatedValue));
}
- transformedView.animate()
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD)
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- if (endRunnable != null) {
- endRunnable.run();
- }
- setClippingDeactivated(transformedView, false);
- }
- });
- setClippingDeactivated(transformedView, true);
+ if (transformScale) {
+ View otherView = otherState.getTransformedView();
+ float transformationStartScaleX = getTransformationStartScaleX();
+ if (transformationStartScaleX != UNDEFINED) {
+ transformedView.setScaleX(
+ NotificationUtils.interpolate(transformationStartScaleX,
+ (otherView.getWidth() / (float) transformedView.getWidth()),
+ interpolatedValue));
+ }
+ float transformationStartScaleY = getTransformationStartScaleY();
+ if (transformationStartScaleY != UNDEFINED) {
+ transformedView.setScaleY(
+ NotificationUtils.interpolate(transformationStartScaleY,
+ (otherView.getHeight() / (float) transformedView.getHeight()),
+ interpolatedValue));
+ }
+ }
}
public static void setClippingDeactivated(final View transformedView, boolean deactivated) {
@@ -281,8 +392,54 @@
}
}
+ public void setTransformationEndY(float transformationEndY) {
+ mTransformationEndY = transformationEndY;
+ }
+
+ public void setTransformationEndX(float transformationEndX) {
+ mTransformationEndX = transformationEndX;
+ }
+
+ public float getTransformationStartX() {
+ Object tag = mTransformedView.getTag(TRANSFORMATION_START_X);
+ return tag == null ? UNDEFINED : (float) tag;
+ }
+
+ public float getTransformationStartY() {
+ Object tag = mTransformedView.getTag(TRANSFORMATION_START_Y);
+ return tag == null ? UNDEFINED : (float) tag;
+ }
+
+ public float getTransformationStartScaleX() {
+ Object tag = mTransformedView.getTag(TRANSFORMATION_START_SCLALE_X);
+ return tag == null ? UNDEFINED : (float) tag;
+ }
+
+ public float getTransformationStartScaleY() {
+ Object tag = mTransformedView.getTag(TRANSFORMATION_START_SCLALE_Y);
+ return tag == null ? UNDEFINED : (float) tag;
+ }
+
+ public void setTransformationStartX(float transformationStartX) {
+ mTransformedView.setTag(TRANSFORMATION_START_X, transformationStartX);
+ }
+
+ public void setTransformationStartY(float transformationStartY) {
+ mTransformedView.setTag(TRANSFORMATION_START_Y, transformationStartY);
+ }
+
+ private void setTransformationStartScaleX(float startScaleX) {
+ mTransformedView.setTag(TRANSFORMATION_START_SCLALE_X, startScaleX);
+ }
+
+ private void setTransformationStartScaleY(float startScaleY) {
+ mTransformedView.setTag(TRANSFORMATION_START_SCLALE_Y, startScaleY);
+ }
+
protected void reset() {
mTransformedView = null;
+ mTransformationEndX = UNDEFINED;
+ mTransformationEndY = UNDEFINED;
}
public void setVisible(boolean visible) {
@@ -306,6 +463,15 @@
mTransformedView.setTranslationY(0);
mTransformedView.setScaleX(1.0f);
mTransformedView.setScaleY(1.0f);
+ setClippingDeactivated(mTransformedView, false);
+ abortTransformation();
+ }
+
+ public void abortTransformation() {
+ mTransformedView.setTag(TRANSFORMATION_START_X, UNDEFINED);
+ mTransformedView.setTag(TRANSFORMATION_START_Y, UNDEFINED);
+ mTransformedView.setTag(TRANSFORMATION_START_SCLALE_X, UNDEFINED);
+ mTransformedView.setTag(TRANSFORMATION_START_SCLALE_Y, UNDEFINED);
}
public static TransformState obtain() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
index b742479..6d0fbb15 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -24,6 +24,7 @@
import com.android.systemui.statusbar.policy.DataSaverController.Listener;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.HotspotController.Callback;
+import com.android.systemui.statusbar.policy.NightModeController;
/**
* Manages which tiles should be automatically added to QS.
@@ -66,12 +67,33 @@
if (!Prefs.getBoolean(context, Key.QS_WORK_ADDED, false)) {
host.getManagedProfileController().addCallback(mProfileCallback);
}
+ if (!Prefs.getBoolean(context, Key.QS_NIGHT_ADDED, false)) {
+ host.getNightModeController().addListener(mNightModeListener);
+ }
}
public void destroy() {
// TODO: Remove any registered listeners.
}
+ private final NightModeController.Listener mNightModeListener =
+ new NightModeController.Listener() {
+ @Override
+ public void onNightModeChanged() {
+ mHost.addTile("night");
+ Prefs.putBoolean(mContext, Key.QS_NIGHT_ADDED, true);
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mHost.getNightModeController().removeListener(mNightModeListener);
+ }
+ });
+ }
+
+ @Override
+ public void onTwilightAutoChanged() { }
+ };
+
private final ManagedProfileController.Callback mProfileCallback =
new ManagedProfileController.Callback() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index 5796edb..ed71e57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -22,8 +22,12 @@
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
+import android.graphics.Paint;
import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
+import android.graphics.PorterDuff.Mode;
import android.graphics.drawable.Drawable;
import android.os.SystemClock;
import android.util.Log;
@@ -55,6 +59,7 @@
private final BarBackgroundDrawable mBarBackground;
private int mMode;
+ private boolean mAlwaysOpaque = false;
public BarTransitions(View view, int gradientResourceId) {
mTag = "BarTransitions." + view.getClass().getSimpleName();
@@ -69,13 +74,25 @@
return mMode;
}
+ /**
+ * @param alwaysOpaque if {@code true}, the bar's background will always be opaque, regardless
+ * of what mode it is currently set to.
+ */
+ public void setAlwaysOpaque(boolean alwaysOpaque) {
+ mAlwaysOpaque = alwaysOpaque;
+ }
+
+ public boolean isAlwaysOpaque() {
+ // Low-end devices do not support translucent modes, fallback to opaque
+ return !HIGH_END || mAlwaysOpaque;
+ }
+
public void transitionTo(int mode, boolean animate) {
- // low-end devices do not support translucent modes, fallback to opaque
- if (!HIGH_END && (mode == MODE_SEMI_TRANSPARENT || mode == MODE_TRANSLUCENT
+ if (isAlwaysOpaque() && (mode == MODE_SEMI_TRANSPARENT || mode == MODE_TRANSLUCENT
|| mode == MODE_TRANSPARENT)) {
mode = MODE_OPAQUE;
}
- if (!HIGH_END && (mode == MODE_LIGHTS_OUT_TRANSPARENT)) {
+ if (isAlwaysOpaque() && (mode == MODE_LIGHTS_OUT_TRANSPARENT)) {
mode = MODE_LIGHTS_OUT;
}
if (mMode == mode) return;
@@ -131,10 +148,13 @@
private int mGradientAlpha;
private int mColor;
+ private PorterDuffColorFilter mTintFilter;
+ private Paint mPaint = new Paint();
private int mGradientAlphaStart;
private int mColorStart;
+
public BarBackgroundDrawable(Context context, int gradientResourceId) {
final Resources res = context.getResources();
if (DEBUG_COLORS) {
@@ -163,6 +183,26 @@
}
@Override
+ public void setTint(int color) {
+ if (mTintFilter == null) {
+ mTintFilter = new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN);
+ } else {
+ mTintFilter.setColor(color);
+ }
+ invalidateSelf();
+ }
+
+ @Override
+ public void setTintMode(Mode tintMode) {
+ if (mTintFilter == null) {
+ mTintFilter = new PorterDuffColorFilter(0, tintMode);
+ } else {
+ mTintFilter.setMode(tintMode);
+ }
+ invalidateSelf();
+ }
+
+ @Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mGradient.setBounds(bounds);
@@ -208,6 +248,7 @@
} else {
targetColor = mOpaque;
}
+
if (!mAnimating) {
mColor = targetColor;
mGradientAlpha = targetGradientAlpha;
@@ -234,7 +275,11 @@
mGradient.draw(canvas);
}
if (Color.alpha(mColor) > 0) {
- canvas.drawColor(mColor);
+ mPaint.setColor(mColor);
+ if (mTintFilter != null) {
+ mPaint.setColorFilter(mTintFilter);
+ }
+ canvas.drawPaint(mPaint);
}
if (mAnimating) {
invalidateSelf(); // keep going
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BaseStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BaseStatusBarHeader.java
index eade2a8..6e1c862 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BaseStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BaseStatusBarHeader.java
@@ -19,7 +19,6 @@
import android.content.Context;
import android.util.AttributeSet;
import android.widget.RelativeLayout;
-
import com.android.systemui.qs.QSPanel;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.NetworkControllerImpl;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java
index 8c7c71f..04095e7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java
@@ -45,6 +45,7 @@
final AnimatedVectorDrawable avd = (AnimatedVectorDrawable) getContext()
.getDrawable(res).getConstantState().newDrawable();
setImageDrawable(avd);
+ avd.forceAnimationOnUI();
avd.start();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index b9e1ad2..ee88b00 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -16,7 +16,11 @@
package com.android.systemui.statusbar.phone;
+import android.app.ActivityManager;
import android.content.Context;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Slog;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
@@ -42,6 +46,8 @@
*/
public class KeyguardBouncer {
+ final static private String TAG = "KeyguardBouncer";
+
protected Context mContext;
protected ViewMediatorCallback mCallback;
protected LockPatternUtils mLockPatternUtils;
@@ -73,6 +79,11 @@
}
public void show(boolean resetSecuritySelection) {
+ final int keyguardUserId = KeyguardUpdateMonitor.getCurrentUser();
+ if (keyguardUserId == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser()) {
+ // In split system user mode, we never unlock system user.
+ return;
+ }
mFalsingManager.onBouncerShown();
ensureView();
if (resetSecuritySelection) {
@@ -84,14 +95,25 @@
return;
}
- // Try to dismiss the Keyguard. If no security pattern is set, this will dismiss the whole
- // Keyguard. If we need to authenticate, show the bouncer.
- if (!mKeyguardView.dismiss()) {
- mShowingSoon = true;
-
- // Split up the work over multiple frames.
- DejankUtils.postAfterTraversal(mShowRunnable);
+ final int activeUserId = ActivityManager.getCurrentUser();
+ final boolean allowDismissKeyguard =
+ !(UserManager.isSplitSystemUser() && activeUserId == UserHandle.USER_SYSTEM)
+ && activeUserId == keyguardUserId;
+ // If allowed, try to dismiss the Keyguard. If no security auth (password/pin/pattern) is
+ // set, this will dismiss the whole Keyguard. Otherwise, show the bouncer.
+ if (allowDismissKeyguard && mKeyguardView.dismiss()) {
+ return;
}
+
+ // This condition may indicate an error on Android, so log it.
+ if (!allowDismissKeyguard) {
+ Slog.w(TAG, "User can't dismiss keyguard: " + activeUserId + " != " + keyguardUserId);
+ }
+
+ mShowingSoon = true;
+
+ // Split up the work over multiple frames.
+ DejankUtils.postAfterTraversal(mShowRunnable);
}
private final Runnable mShowRunnable = new Runnable() {
@@ -258,19 +280,8 @@
return mKeyguardView == null || mKeyguardView.getSecurityMode() != SecurityMode.None;
}
- public boolean onMenuPressed() {
- ensureView();
- if (mKeyguardView.handleMenuKey()) {
-
- // We need to show it in case it is secure. If not, it will get dismissed in any case.
- mRoot.setVisibility(View.VISIBLE);
- mFalsingManager.onBouncerShown();
- mKeyguardView.requestFocus();
- mKeyguardView.onResume();
- return true;
- } else {
- return false;
- }
+ public boolean shouldDismissOnMenuPressed() {
+ return mKeyguardView.shouldEnableMenuKey();
}
public boolean interceptMediaKey(KeyEvent event) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
new file mode 100644
index 0000000..5b4a3f0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.app.ActivityManager;
+import android.app.IWallpaperManager;
+import android.app.IWallpaperManagerCallback;
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.util.Log;
+
+import libcore.io.IoUtils;
+
+import java.util.Objects;
+
+/**
+ * Manages the lockscreen wallpaper.
+ */
+public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implements Runnable {
+
+ private static final String TAG = "LockscreenWallpaper";
+
+ private final Context mContext;
+ private final PhoneStatusBar mBar;
+ private final IWallpaperManager mService;
+ private final WallpaperManager mWallpaperManager;
+ private final Handler mH;
+
+ private boolean mCached;
+ private Bitmap mCache;
+ private int mCurrentUserId;
+ // The user selected in the UI, or null if no user is selected or UI doesn't support selecting
+ // users.
+ private UserHandle mSelectedUser;
+
+ public LockscreenWallpaper(Context ctx, PhoneStatusBar bar, Handler h) {
+ mContext = ctx;
+ mBar = bar;
+ mH = h;
+ mService = IWallpaperManager.Stub.asInterface(
+ ServiceManager.getService(Context.WALLPAPER_SERVICE));
+ mWallpaperManager = (WallpaperManager) ctx.getSystemService(Context.WALLPAPER_SERVICE);
+ mCurrentUserId = ActivityManager.getCurrentUser();
+
+ try {
+ mService.setLockWallpaperCallback(this);
+ } catch (RemoteException e) {
+ Log.e(TAG, "System dead?" + e);
+ }
+ }
+
+ public Bitmap getBitmap() {
+ try {
+ if (mCached) {
+ return mCache;
+ }
+ if (!mService.isWallpaperSupported(mContext.getOpPackageName())) {
+ mCached = true;
+ mCache = null;
+ return null;
+ }
+ // Prefer the selected user (when specified) over the current user for the FLAG_SET_LOCK
+ // wallpaper.
+ final int lockWallpaperUserId =
+ mSelectedUser != null ? mSelectedUser.getIdentifier() : mCurrentUserId;
+ ParcelFileDescriptor fd = mService.getWallpaper(null, WallpaperManager.FLAG_SET_LOCK,
+ new Bundle(), lockWallpaperUserId);
+ if (fd != null) {
+ try {
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ mCache = BitmapFactory.decodeFileDescriptor(
+ fd.getFileDescriptor(), null, options);
+ mCached = true;
+ return mCache;
+ } catch (OutOfMemoryError e) {
+ Log.w(TAG, "Can't decode file", e);
+ return null;
+ } finally {
+ IoUtils.closeQuietly(fd);
+ }
+ } else {
+ mCached = true;
+ if (mSelectedUser != null && mSelectedUser.getIdentifier() != mCurrentUserId) {
+ // When selected user is different from the current user, show the selected
+ // user's static wallpaper.
+ mWallpaperManager.forgetLoadedWallpaper();
+ mCache = mWallpaperManager.getBitmapAsUser(mSelectedUser.getIdentifier());
+ } else {
+ // When there is no selected user, or it's same as the current user, show the
+ // system (possibly dynamic) wallpaper for the selected user.
+ mCache = null;
+ }
+ return mCache;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "System dead?" + e);
+ return null;
+ }
+ }
+
+ public void setCurrentUser(int user) {
+ if (user != mCurrentUserId) {
+ mCached = false;
+ mCurrentUserId = user;
+ }
+ }
+
+ public void setSelectedUser(UserHandle selectedUser) {
+ if (Objects.equals(selectedUser, mSelectedUser)) {
+ return;
+ }
+ mSelectedUser = selectedUser;
+
+ mH.removeCallbacks(this);
+ mH.post(this);
+ }
+
+ @Override
+ public void onWallpaperChanged() {
+ // Called on Binder thread.
+ mH.removeCallbacks(this);
+ mH.post(this);
+ }
+
+ @Override
+ public void run() {
+ // Called in response to onWallpaperChanged on the main thread.
+ mCached = false;
+ mCache = null;
+ getBitmap();
+ mBar.updateMediaMetaData(true /* metaDataChanged */, true /* allowEnterAnimation */);
+ }
+}
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 6698076..e53f044 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -512,6 +512,11 @@
}
});
}
+
+ @Override
+ public void onDockedStackMinimizedChanged(boolean minimized, long animDuration)
+ throws RemoteException {
+ }
});
} catch (RemoteException e) {
Log.e(TAG, "Failed registering docked stack exists listener", e);
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 1a0acbe..88b8afa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -42,6 +42,8 @@
import com.android.internal.logging.MetricsLogger;
import com.android.keyguard.KeyguardStatusView;
import com.android.systemui.DejankUtils;
+import com.android.systemui.DensityContainer;
+import com.android.systemui.DensityContainer.InflateListener;
import com.android.systemui.EventLogConstants;
import com.android.systemui.EventLogTags;
import com.android.systemui.Interpolators;
@@ -94,7 +96,7 @@
private TextView mClockView;
private View mReserveNotificationSpace;
private View mQsNavbarScrim;
- private NotificationsQuickSettingsContainer mNotificationContainerParent;
+ protected NotificationsQuickSettingsContainer mNotificationContainerParent;
protected NotificationStackScrollLayout mNotificationStackScroller;
private boolean mAnimateNextTopPaddingChange;
@@ -215,8 +217,14 @@
super.onFinishInflate();
mKeyguardStatusBar = (KeyguardStatusBarView) findViewById(R.id.keyguard_header);
mKeyguardStatusView = (KeyguardStatusView) findViewById(R.id.keyguard_status_view);
- mQsContainer = (QSContainer) findViewById(R.id.quick_settings_container);
- mQsContainer.getHeader().setOnClickListener(this);
+ DensityContainer container = (DensityContainer) findViewById(R.id.qs_density_container);
+ container.addInflateListener(new InflateListener() {
+ @Override
+ public void onInflated(View v) {
+ mQsContainer = (QSContainer) v.findViewById(R.id.quick_settings_container);
+ mQsContainer.getHeader().setOnClickListener(NotificationPanelView.this);
+ }
+ });
mClockView = (TextView) findViewById(R.id.clock_view);
mNotificationContainerParent = (NotificationsQuickSettingsContainer)
findViewById(R.id.notification_container_parent);
@@ -879,7 +887,11 @@
mQsTracking = false;
mTrackingPointer = -1;
trackMovement(event);
- flingQsWithCurrentVelocity(y, event.getActionMasked() == MotionEvent.ACTION_CANCEL);
+ float fraction = getQsExpansionFraction();
+ if (fraction != 0f || y >= mInitialTouchY) {
+ flingQsWithCurrentVelocity(y,
+ event.getActionMasked() == MotionEvent.ACTION_CANCEL);
+ }
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
@@ -1385,7 +1397,7 @@
// In Shade, interpolate linearly such that QS is closed whenever panel height is
// minimum QS expansion + minStackHeight
float panelHeightQsCollapsed = mNotificationStackScroller.getIntrinsicPadding()
- + mNotificationStackScroller.getMinStackHeight();
+ + mNotificationStackScroller.getLayoutMinHeight();
float panelHeightQsExpanded = calculatePanelHeightQsExpanded();
t = (expandedHeight - panelHeightQsCollapsed)
/ (panelHeightQsExpanded - panelHeightQsCollapsed);
@@ -1441,7 +1453,7 @@
&& mShadeEmpty) {
notificationHeight = mNotificationStackScroller.getEmptyShadeViewHeight()
+ mNotificationStackScroller.getBottomStackPeekSize()
- + mNotificationStackScroller.getCollapseSecondCardPadding();
+ + mNotificationStackScroller.getBottomStackSlowDownHeight();
}
int maxQsHeight = mQsMaxExpansionHeight;
@@ -1456,7 +1468,7 @@
+ notificationHeight;
if (totalHeight > mNotificationStackScroller.getHeight()) {
float fullyCollapsedHeight = maxQsHeight
- + mNotificationStackScroller.getMinStackHeight();
+ + mNotificationStackScroller.getLayoutMinHeight();
totalHeight = Math.max(fullyCollapsedHeight, mNotificationStackScroller.getHeight());
}
return (int) totalHeight;
@@ -1473,7 +1485,7 @@
private float getFadeoutAlpha() {
float alpha = (getNotificationsTopY() + mNotificationStackScroller.getFirstItemMinHeight())
/ (mQsMinExpansionHeight + mNotificationStackScroller.getBottomStackPeekSize()
- - mNotificationStackScroller.getCollapseSecondCardPadding());
+ - mNotificationStackScroller.getBottomStackSlowDownHeight());
alpha = Math.max(0, Math.min(alpha, 1));
alpha = (float) Math.pow(alpha, 0.75);
return alpha;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
index 7cc720d..6d90e5c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
@@ -47,7 +47,7 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mQsContainer = findViewById(R.id.quick_settings_container);
+ mQsContainer = findViewById(R.id.qs_density_container);
mStackScroller = findViewById(R.id.notification_stack_scroller);
mKeyguardStatusBar = findViewById(R.id.keyguard_header);
ViewStub userSwitcher = (ViewStub) findViewById(R.id.keyguard_user_switcher);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 401d405..073a848 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -26,7 +26,6 @@
import android.app.Notification;
import android.app.PendingIntent;
import android.app.StatusBarManager;
-import android.app.WallpaperManager;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
@@ -68,7 +67,6 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
-import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.Vibrator;
@@ -105,17 +103,20 @@
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.DemoMode;
+import com.android.systemui.DensityContainer;
+import com.android.systemui.DensityContainer.InflateListener;
import com.android.systemui.EventLogConstants;
import com.android.systemui.EventLogTags;
import com.android.systemui.Interpolators;
import com.android.systemui.Prefs;
import com.android.systemui.R;
+import com.android.systemui.SystemUIFactory;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.qs.QSDetail;
+import com.android.systemui.qs.QSContainer;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.recents.events.EventBus;
@@ -248,9 +249,7 @@
private static final boolean ONLY_CORE_APPS;
/** If true, the lockscreen will show a distinct wallpaper */
- private static final boolean ENABLE_LOCKSCREEN_WALLPAPER =
- !ActivityManager.isLowRamDeviceStatic()
- && SystemProperties.getBoolean("debug.lockscreen_wallpaper", false);
+ private static final boolean ENABLE_LOCKSCREEN_WALLPAPER = true;
/* If true, the device supports freeform window management.
* This affects the status bar UI. */
@@ -296,6 +295,7 @@
AccessibilityController mAccessibilityController;
FingerprintUnlockController mFingerprintUnlockController;
LightStatusBarController mLightStatusBarController;
+ protected LockscreenWallpaper mLockscreenWallpaper;
int mNaturalBarHeight = -1;
@@ -646,7 +646,7 @@
// Lastly, call to the icon policy to install/update all the icons.
mIconPolicy = new PhoneStatusBarPolicy(mContext, mIconController, mCastController,
mHotspotController, mUserInfoController, mBluetoothController,
- mRotationLockController);
+ mRotationLockController, mNetworkController.getDataSaverController());
mIconPolicy.setCurrentUserSetup(mUserSetup);
mSettingsObserver.onChange(false); // set up
@@ -746,6 +746,7 @@
mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
R.id.notification_stack_scroller);
mStackScroller.setLongPressListener(getNotificationLongClicker());
+ mStackScroller.setGearDisplayedListener(getGearDisplayedListener());
mStackScroller.setPhoneStatusBar(this);
mStackScroller.setGroupManager(mGroupManager);
mStackScroller.setHeadsUpManager(mHeadsUpManager);
@@ -770,16 +771,14 @@
ScrimView scrimBehind = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_behind);
ScrimView scrimInFront = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_in_front);
View headsUpScrim = mStatusBarWindow.findViewById(R.id.heads_up_scrim);
- mScrimController = new ScrimController(scrimBehind, scrimInFront, headsUpScrim,
- mScrimSrcModeEnabled);
+ mScrimController = SystemUIFactory.getInstance().createScrimController(
+ scrimBehind, scrimInFront, headsUpScrim, mScrimSrcModeEnabled);
mHeadsUpManager.addListener(mScrimController);
mStackScroller.setScrimController(mScrimController);
mScrimController.setBackDropView(mBackdrop);
mStatusBarView.setScrimController(mScrimController);
mDozeScrimController = new DozeScrimController(mScrimController, context);
- mHeader = (BaseStatusBarHeader) mStatusBarWindow.findViewById(R.id.header);
- mHeader.setActivityStarter(this);
mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header);
mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view);
mKeyguardBottomArea =
@@ -792,6 +791,10 @@
mKeyguardBottomArea.getLockIcon());
mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController);
+ if (ENABLE_LOCKSCREEN_WALLPAPER) {
+ mLockscreenWallpaper = new LockscreenWallpaper(mContext, this, mHandler);
+ }
+
// set the initial view visibility
setAreThereNotifications();
@@ -835,12 +838,6 @@
initSignalCluster(mStatusBarView);
initSignalCluster(mKeyguardStatusBar);
- initSignalCluster(mHeader);
-
- final boolean isAPhone = mNetworkController.hasVoiceCallingFeature();
- if (isAPhone) {
- mNetworkController.addEmergencyListener(mHeader);
- }
mFlashlightController = new FlashlightController(mContext);
mKeyguardBottomArea.setFlashlightController(mFlashlightController);
@@ -859,40 +856,40 @@
}
// Set up the quick settings tile panel
- mQSPanel = (QSPanel) mStatusBarWindow.findViewById(R.id.quick_settings_panel);
- if (mQSPanel != null) {
+ DensityContainer container = (DensityContainer) mStatusBarWindow.findViewById(
+ R.id.qs_density_container);
+ if (container != null) {
final QSTileHost qsh = new QSTileHost(mContext, this,
mBluetoothController, mLocationController, mRotationLockController,
mNetworkController, mZenModeController, mHotspotController,
mCastController, mFlashlightController,
mUserSwitcherController, mUserInfoController, mKeyguardMonitor,
- mSecurityController, mBatteryController, mIconController);
- mQSPanel.setHost(qsh);
- mQSPanel.setTiles(qsh.getTiles());
+ mSecurityController, mBatteryController, mIconController,
+ mNextAlarmController);
mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow);
- mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
- mHeader.setQSPanel(mQSPanel);
- QSDetail qsDetail = (QSDetail) mStatusBarWindow.findViewById(R.id.qs_detail);
- qsDetail.setHost(qsh);
- qsh.addCallback(new QSTileHost.Callback() {
+ container.addInflateListener(new InflateListener() {
@Override
- public void onTilesChanged() {
- mQSPanel.setTiles(qsh.getTiles());
+ public void onInflated(View v) {
+ QSContainer qsContainer = (QSContainer) v.findViewById(
+ R.id.quick_settings_container);
+ qsContainer.setHost(qsh);
+ mQSPanel = qsContainer.getQsPanel();
+ mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
+ mHeader = qsContainer.getHeader();
+ initSignalCluster(mHeader);
+ mHeader.setActivityStarter(PhoneStatusBar.this);
}
});
}
// User info. Trigger first load.
- mHeader.setUserInfoController(mUserInfoController);
mKeyguardStatusBar.setUserInfoController(mUserInfoController);
mKeyguardStatusBar.setUserSwitcherController(mUserSwitcherController);
mUserInfoController.reloadUserInfo();
- mHeader.setBatteryController(mBatteryController);
((BatteryMeterView) mStatusBarView.findViewById(R.id.battery)).setBatteryController(
mBatteryController);
mKeyguardStatusBar.setBatteryController(mBatteryController);
- mHeader.setNextAlarmController(mNextAlarmController);
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mBroadcastReceiver.onReceive(mContext,
@@ -998,7 +995,6 @@
SignalClusterView signalCluster =
(SignalClusterView) containerView.findViewById(R.id.signal_cluster);
if (signalCluster != null) {
- mNetworkController.addSignalCallback(signalCluster);
signalCluster.setSecurityController(mSecurityController);
signalCluster.setNetworkController(mNetworkController);
}
@@ -1141,31 +1137,42 @@
@Override
public boolean onLongClick(View v) {
- if (mRecents != null) {
- int dockSide = WindowManagerProxy.getInstance().getDockSide();
- if (dockSide == WindowManager.DOCKED_INVALID) {
- Point realSize = new Point();
- mContext.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY)
- .getRealSize(realSize);
- Rect initialBounds= new Rect(0, 0, realSize.x, realSize.y);
- boolean docked = mRecents.dockTopTask(NavigationBarGestureHelper.DRAG_MODE_NONE,
- ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT,
- initialBounds);
- if (docked) {
- MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_LONGPRESS);
- return true;
- }
- } else {
- EventBus.getDefault().send(new UndockingTaskEvent());
- MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_UNDOCK_LONGPRESS);
- return true;
- }
-
+ if (mRecents == null) {
+ return false;
+ }
+ boolean initiallyDocked = WindowManagerProxy.getInstance().getDockSide()
+ == WindowManager.DOCKED_INVALID;
+ boolean dockedAtEnd = toggleSplitScreenMode();
+ if (dockedAtEnd != initiallyDocked) {
+ int logAction = dockedAtEnd ? MetricsEvent.ACTION_WINDOW_DOCK_LONGPRESS
+ : MetricsEvent.ACTION_WINDOW_UNDOCK_LONGPRESS;
+ MetricsLogger.action(mContext, logAction);
+ return true;
}
return false;
}
};
+ @Override
+ protected boolean toggleSplitScreenMode() {
+ if (mRecents == null) {
+ return false;
+ }
+ int dockSide = WindowManagerProxy.getInstance().getDockSide();
+ if (dockSide == WindowManager.DOCKED_INVALID) {
+ Point realSize = new Point();
+ mContext.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY)
+ .getRealSize(realSize);
+ Rect initialBounds= new Rect(0, 0, realSize.x, realSize.y);
+ return mRecents.dockTopTask(NavigationBarGestureHelper.DRAG_MODE_NONE,
+ ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT,
+ initialBounds);
+ } else {
+ EventBus.getDefault().send(new UndockingTaskEvent());
+ return false;
+ }
+ }
+
private final View.OnLongClickListener mLongPressHomeListener
= new View.OnLongClickListener() {
@Override
@@ -1305,6 +1312,12 @@
if (DEBUG) {
Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + notification.getKey());
}
+ } else if (mNotificationData.getImportance(notification.getKey())
+ < NotificationListenerService.Ranking.IMPORTANCE_MAX) {
+ if (DEBUG) {
+ Log.d(TAG, "No Fullscreen intent: not important enough: "
+ + notification.getKey());
+ }
} else {
// Stop screensaver if the notification has a full-screen intent.
// (like an incoming phone call)
@@ -1411,7 +1424,7 @@
if (showingPublic) {
updatePublicContentView(ent, ent.notification);
}
- ent.row.setSensitive(sensitive);
+ ent.row.setSensitive(sensitive, hideSensitive);
if (ent.autoRedacted && ent.legacy) {
// TODO: Also fade this? Or, maybe easier (and better), provide a dark redacted form
// for legacy auto redacted notifications.
@@ -1583,8 +1596,7 @@
}
private boolean packageHasVisibilityOverride(String key) {
- return mNotificationData.getVisibilityOverride(key)
- != NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE;
+ return mNotificationData.getVisibilityOverride(key) == Notification.VISIBILITY_PRIVATE;
}
private void updateClearAll() {
@@ -1819,7 +1831,7 @@
};
/**
- * Refresh or remove lockscreen artwork from media metadata.
+ * Refresh or remove lockscreen artwork from media metadata or the lockscreen wallpaper.
*/
public void updateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation) {
if (!SHOW_LOCKSCREEN_MEDIA_ARTWORK) return;
@@ -1847,10 +1859,7 @@
}
}
if (ENABLE_LOCKSCREEN_WALLPAPER && artworkBitmap == null) {
- // TODO: use real lockscreen wallpaper.
- WallpaperManager wallpaperManager = mContext
- .getSystemService(WallpaperManager.class);
- artworkBitmap = wallpaperManager.getBitmap();
+ artworkBitmap = mLockscreenWallpaper.getBitmap();
}
final boolean hasArtwork = artworkBitmap != null;
@@ -3084,10 +3093,6 @@
else if (Intent.ACTION_SCREEN_ON.equals(action)) {
notifyNavigationBarScreenOn(true);
}
- else if (ENABLE_LOCKSCREEN_WALLPAPER
- && Intent.ACTION_WALLPAPER_CHANGED.equals(action)) {
- updateMediaMetaData(true, true);
- }
}
};
@@ -3173,6 +3178,7 @@
resetUserSetupObserver();
setControllerUsers();
clearCurrentMediaNotification();
+ mLockscreenWallpaper.setCurrentUser(newUserId);
updateMediaMetaData(true, false);
}
@@ -3548,7 +3554,7 @@
}
@Override
- protected boolean isPanelFullyCollapsed() {
+ public boolean isPanelFullyCollapsed() {
return mNotificationPanel.isFullyCollapsed();
}
@@ -3880,7 +3886,13 @@
}
public boolean onMenuPressed() {
- return mState == StatusBarState.KEYGUARD && mStatusBarKeyguardViewManager.onMenuPressed();
+ if (mDeviceInteractive && mState != StatusBarState.SHADE
+ && mStatusBarKeyguardViewManager.shouldDismissOnMenuPressed()) {
+ animateCollapsePanels(
+ CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL /* flags */, true /* force */);
+ return true;
+ }
+ return false;
}
public void endAffordanceLaunch() {
@@ -4086,7 +4098,7 @@
ExpandableNotificationRow row = null;
if (expandView instanceof ExpandableNotificationRow) {
row = (ExpandableNotificationRow) expandView;
- row.setUserExpanded(true);
+ row.setUserExpanded(true /* userExpanded */, true /* allowChildExpansion */);
}
boolean fullShadeNeedsBouncer = !userAllowsPrivateNotificationsInPublic(mCurrentUserId)
|| !mShowLockscreenNotifications || mFalsingManager.shouldEnforceBouncer();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index df5a622..c883cc9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -44,6 +44,7 @@
import com.android.systemui.statusbar.policy.BluetoothController.Callback;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.CastController.CastDevice;
+import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.RotationLockController;
import com.android.systemui.statusbar.policy.UserInfoController;
@@ -53,7 +54,7 @@
* bar at boot time. It goes through the normal API for icons, even though it probably
* strictly doesn't need to.
*/
-public class PhoneStatusBarPolicy implements Callback, RotationLockController.RotationLockControllerCallback {
+public class PhoneStatusBarPolicy implements Callback, RotationLockController.RotationLockControllerCallback, DataSaverController.Listener {
private static final String TAG = "PhoneStatusBarPolicy";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -67,6 +68,7 @@
private final String mSlotManagedProfile;
private final String mSlotRotate;
private final String mSlotHeadset;
+ private final String mSlotDataSaver;
private final Context mContext;
private final Handler mHandler = new Handler();
@@ -77,6 +79,7 @@
private final UserManager mUserManager;
private final StatusBarIconController mIconController;
private final RotationLockController mRotationLockController;
+ private final DataSaverController mDataSaver;
// Assume it's all good unless we hear otherwise. We don't always seem
// to get broadcasts that it *is* there.
@@ -97,7 +100,8 @@
public PhoneStatusBarPolicy(Context context, StatusBarIconController iconController,
CastController cast, HotspotController hotspot, UserInfoController userInfoController,
- BluetoothController bluetooth, RotationLockController rotationLockController) {
+ BluetoothController bluetooth, RotationLockController rotationLockController,
+ DataSaverController dataSaver) {
mContext = context;
mIconController = iconController;
mCast = cast;
@@ -108,6 +112,7 @@
mUserInfoController = userInfoController;
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mRotationLockController = rotationLockController;
+ mDataSaver = dataSaver;
mSlotCast = context.getString(com.android.internal.R.string.status_bar_cast);
mSlotHotspot = context.getString(com.android.internal.R.string.status_bar_hotspot);
@@ -120,6 +125,7 @@
com.android.internal.R.string.status_bar_managed_profile);
mSlotRotate = context.getString(com.android.internal.R.string.status_bar_rotate);
mSlotHeadset = context.getString(com.android.internal.R.string.status_bar_headset);
+ mSlotDataSaver = context.getString(com.android.internal.R.string.status_bar_data_saver);
mRotationLockController.addRotationLockControllerCallback(this);
@@ -176,6 +182,12 @@
mIconController.setIcon(mSlotManagedProfile, R.drawable.stat_sys_managed_profile_status,
mContext.getString(R.string.accessibility_managed_profile));
mIconController.setIconVisibility(mSlotManagedProfile, mManagedProfileIconVisible);
+
+ // data saver
+ mIconController.setIcon(mSlotDataSaver, R.drawable.stat_sys_data_saver,
+ context.getString(R.string.accessibility_data_saver_on));
+ mIconController.setIconVisibility(mSlotDataSaver, false);
+ mDataSaver.addListener(this);
}
public void setZenMode(int zen) {
@@ -456,11 +468,9 @@
mIconController.setIcon(mSlotRotate, R.drawable.stat_sys_rotate_landscape,
mContext.getString(R.string.accessibility_rotation_lock_on_landscape));
}
+ mIconController.setIconVisibility(mSlotRotate, true);
} else {
- mIconController.setIcon(mSlotRotate, portrait
- ? R.drawable.stat_sys_auto_rotate_portrait
- : R.drawable.stat_sys_auto_rotate_landscape,
- mContext.getString(R.string.accessibility_rotation_lock_off));
+ mIconController.setIconVisibility(mSlotRotate, false);
}
}
@@ -479,6 +489,11 @@
}
}
+ @Override
+ public void onDataSaverChanged(boolean isDataSaving) {
+ mIconController.setIconVisibility(mSlotDataSaver, isDataSaving);
+ }
+
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 2af2009..f894a22 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -57,7 +57,8 @@
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.CastController;
-import com.android.systemui.statusbar.policy.DisplayController;
+import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.NightModeController;
import com.android.systemui.statusbar.policy.FlashlightController;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
@@ -68,7 +69,7 @@
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.tuner.ColorMatrixTile;
+import com.android.systemui.tuner.NightModeTile;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -108,19 +109,21 @@
private final TileServices mServices;
private final List<Callback> mCallbacks = new ArrayList<>();
- private final DisplayController mDisplayController;
+ private final NightModeController mNightModeController;
private final AutoTileManager mAutoTiles;
private final ManagedProfileController mProfileController;
+ private final NextAlarmController mNextAlarmController;
private View mHeader;
public QSTileHost(Context context, PhoneStatusBar statusBar,
- BluetoothController bluetooth, LocationController location,
- RotationLockController rotation, NetworkController network,
- ZenModeController zen, HotspotController hotspot,
- CastController cast, FlashlightController flashlight,
- UserSwitcherController userSwitcher, UserInfoController userInfo,
- KeyguardMonitor keyguard, SecurityController security,
- BatteryController battery, StatusBarIconController iconController) {
+ BluetoothController bluetooth, LocationController location,
+ RotationLockController rotation, NetworkController network,
+ ZenModeController zen, HotspotController hotspot,
+ CastController cast, FlashlightController flashlight,
+ UserSwitcherController userSwitcher, UserInfoController userInfo,
+ KeyguardMonitor keyguard, SecurityController security,
+ BatteryController battery, StatusBarIconController iconController,
+ NextAlarmController nextAlarmController) {
mContext = context;
mStatusBar = statusBar;
mBluetooth = bluetooth;
@@ -137,7 +140,8 @@
mSecurity = security;
mBattery = battery;
mIconController = iconController;
- mDisplayController = new DisplayController(mContext);
+ mNextAlarmController = nextAlarmController;
+ mNightModeController = new NightModeController(mContext, true);
mProfileController = new ManagedProfileController(this);
final HandlerThread ht = new HandlerThread(QSTileHost.class.getSimpleName(),
@@ -152,6 +156,10 @@
mAutoTiles = new AutoTileManager(context, this);
}
+ public NextAlarmController getNextAlarmController() {
+ return mNextAlarmController;
+ }
+
public void setHeaderView(View view) {
mHeader = view;
}
@@ -171,6 +179,11 @@
}
@Override
+ public void removeCallback(Callback callback) {
+ mCallbacks.remove(callback);
+ }
+
+ @Override
public Collection<QSTile<?>> getTiles() {
return mTiles.values();
}
@@ -292,8 +305,8 @@
return mIconController;
}
- public DisplayController getDisplayController() {
- return mDisplayController;
+ public NightModeController getNightModeController() {
+ return mNightModeController;
}
public ManagedProfileController getManagedProfileController() {
@@ -422,8 +435,8 @@
else if (tileSpec.equals("user")) return new UserTile(this);
else if (tileSpec.equals("battery")) return new BatteryTile(this);
else if (tileSpec.equals("saver")) return new DataSaverTile(this);
- else if (tileSpec.equals(ColorMatrixTile.COLOR_MATRIX_SPEC))
- return new ColorMatrixTile(this);
+ else if (tileSpec.equals(NightModeTile.NIGHT_MODE_SPEC))
+ return new NightModeTile(this);
// Intent tiles.
else if (tileSpec.startsWith(IntentTile.PREFIX)) return IntentTile.create(this,tileSpec);
else if (tileSpec.startsWith(CustomTile.PREFIX)) return CustomTile.create(this,tileSpec);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
index bd5bac2..326ca2b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -21,7 +21,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
-import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.RippleDrawable;
import android.util.AttributeSet;
@@ -34,23 +33,23 @@
import com.android.keyguard.KeyguardStatusView;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
+import com.android.systemui.qs.QSAnimator;
import com.android.systemui.qs.QSPanel;
-import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.QuickQSPanel;
import com.android.systemui.qs.TouchAnimator;
-import com.android.systemui.qs.TouchAnimator.Listener;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
import com.android.systemui.tuner.TunerService;
public class QuickStatusBarHeader extends BaseStatusBarHeader implements
- NextAlarmChangeCallback, OnClickListener, Listener {
+ NextAlarmChangeCallback, OnClickListener {
private static final String TAG = "QuickStatusBarHeader";
- private static final float EXPAND_INDICATOR_THRESHOLD = .8f;
+ private static final float EXPAND_INDICATOR_THRESHOLD = .93f;
private ActivityStarter mActivityStarter;
private NextAlarmController mNextAlarmController;
@@ -89,7 +88,9 @@
private TouchAnimator mFirstHalfAnimator;
private TouchAnimator mDateSizeAnimator;
private TouchAnimator mAlarmTranslation;
+ private TouchAnimator mSettingsAlpha;
private float mExpansionAmount;
+ private QSTileHost mHost;
public QuickStatusBarHeader(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -127,14 +128,6 @@
((RippleDrawable) getBackground()).setForceSoftware(true);
((RippleDrawable) mSettingsButton.getBackground()).setForceSoftware(true);
- addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
- @Override
- public void onLayoutChange(View v, int left, int top, int right,
- int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
- setClipBounds(new Rect(getPaddingLeft(), 0, getWidth() - getPaddingRight(),
- getHeight()));
- }
- });
updateResources();
}
@@ -164,18 +157,15 @@
mAnimator = new TouchAnimator.Builder()
.addFloat(mSettingsContainer, "translationY", -mGearTranslation, 0)
.addFloat(mMultiUserSwitch, "translationY", -mGearTranslation, 0)
- .addFloat(mSettingsButton, "rotation", -90, 0)
- .setListener(this)
.build();
mSecondHalfAnimator = new TouchAnimator.Builder()
- .addFloat(mSettingsButton, "rotation", -90, 0)
+ .addFloat(mSettingsButton, "rotation", -180, 0)
.addFloat(mAlarmStatus, "alpha", 0, 1)
.addFloat(mEmergencyOnly, "alpha", 0, 1)
.setStartDelay(.5f)
.build();
mFirstHalfAnimator = new TouchAnimator.Builder()
.addFloat(mAlarmStatusCollapsed, "alpha", 1, 0)
- .addFloat(mHeaderQsPanel, "alpha", 1, 0)
.setEndDelay(.5f)
.build();
mDateSizeAnimator = new TouchAnimator.Builder()
@@ -183,6 +173,11 @@
.addFloat(mDateTimeGroup, "scaleY", 1, mDateScaleFactor)
.setStartDelay(.36f)
.build();
+ mSettingsAlpha = new TouchAnimator.Builder()
+ .addFloat(mSettingsContainer, "alpha", 0, 1)
+ .addFloat(mMultiUserSwitch, "alpha", 0, 1)
+ .setStartDelay(QSAnimator.EXPANDED_TILE_DELAY)
+ .build();
}
@Override
@@ -221,6 +216,7 @@
mFirstHalfAnimator.setPosition(headerExpansionFraction);
mDateSizeAnimator.setPosition(headerExpansionFraction);
mAlarmTranslation.setPosition(headerExpansionFraction);
+ mSettingsAlpha.setPosition(headerExpansionFraction);
updateAlarmVisibilities();
@@ -228,17 +224,11 @@
}
@Override
- public void onAnimationAtStart() {
- }
-
- @Override
- public void onAnimationAtEnd() {
- mHeaderQsPanel.setVisibility(View.INVISIBLE);
- }
-
- @Override
- public void onAnimationStarted() {
- mHeaderQsPanel.setVisibility(View.VISIBLE);
+ protected void onDetachedFromWindow() {
+ setListening(false);
+ mHost.getUserInfoController().remListener(mUserListener);
+ mHost.getNetworkController().removeEmergencyListener(this);
+ super.onDetachedFromWindow();
}
private void updateAlarmVisibilities() {
@@ -303,17 +293,18 @@
}
public void setupHost(final QSTileHost host) {
+ mHost = host;
host.setHeaderView(this);
mHeaderQsPanel.setQSPanelAndHeader(mQsPanel, this);
mHeaderQsPanel.setHost(host);
- mHeaderQsPanel.setMaxTiles(5);
- mHeaderQsPanel.setTiles(host.getTiles());
- host.addCallback(new QSTile.Host.Callback() {
- @Override
- public void onTilesChanged() {
- mHeaderQsPanel.setTiles(host.getTiles());
- }
- });
+ setUserInfoController(host.getUserInfoController());
+ setBatteryController(host.getBatteryController());
+ setNextAlarmController(host.getNextAlarmController());
+
+ final boolean isAPhone = mHost.getNetworkController().hasVoiceCallingFeature();
+ if (isAPhone) {
+ mHost.getNetworkController().addEmergencyListener(this);
+ }
}
@Override
@@ -359,12 +350,7 @@
@Override
public void setUserInfoController(UserInfoController userInfoController) {
- userInfoController.addListener(new UserInfoController.OnUserInfoChangedListener() {
- @Override
- public void onUserInfoChanged(String name, Drawable picture) {
- mMultiUserAvatar.setImageDrawable(picture);
- }
- });
+ userInfoController.addListener(mUserListener);
}
@Override
@@ -377,4 +363,11 @@
}
}
}
+
+ private final OnUserInfoChangedListener mUserListener = new OnUserInfoChangedListener() {
+ @Override
+ public void onUserInfoChanged(String name, Drawable picture) {
+ mMultiUserAvatar.setImageDrawable(picture);
+ }
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index f310c2c2..fe76ae7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -56,16 +56,16 @@
private static final int TAG_START_ALPHA = R.id.scrim_alpha_start;
private static final int TAG_END_ALPHA = R.id.scrim_alpha_end;
- private final ScrimView mScrimBehind;
+ protected final ScrimView mScrimBehind;
private final ScrimView mScrimInFront;
private final UnlockMethodCache mUnlockMethodCache;
private final View mHeadsUpScrim;
- private boolean mKeyguardShowing;
+ protected boolean mKeyguardShowing;
private float mFraction;
private boolean mDarkenWhileDragging;
- private boolean mBouncerShowing;
+ protected boolean mBouncerShowing;
private boolean mWakeAndUnlocking;
private boolean mAnimateChange;
private boolean mUpdatePending;
@@ -203,7 +203,7 @@
mUpdatePending = true;
}
- private void updateScrims() {
+ protected void updateScrims() {
if (mAnimateKeyguardFadingOut || mForceHideScrims) {
setScrimInFrontColor(0f);
setScrimBehindColor(0f);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index 3e3b169..a051973 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -39,7 +39,6 @@
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
-
import com.android.keyguard.KeyguardStatusView;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.FontSizeUtils;
@@ -48,7 +47,7 @@
import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.QSTile.DetailAdapter;
import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.NetworkControllerImpl.EmergencyListener;
+import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.tuner.TunerService;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 7a05b8f..0e84f733 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -509,8 +509,8 @@
return !(mLastShowing && !mLastOccluded) || mLastBouncerShowing || mLastRemoteInputActive;
}
- public boolean onMenuPressed() {
- return mBouncer.onMenuPressed();
+ public boolean shouldDismissOnMenuPressed() {
+ return mBouncer.shouldDismissOnMenuPressed();
}
public boolean interceptMediaKey(KeyEvent event) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
index 3bd68a9..ab34768 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
@@ -80,13 +80,13 @@
// Original is slightly larger than the mirror, so make sure to use the center for the
// positioning.
- int originalX = mInt2Cache[0] + original.getWidth()/2;
- int originalY = mInt2Cache[1];
+ int originalX = mInt2Cache[0] + original.getWidth() / 2;
+ int originalY = mInt2Cache[1] + original.getHeight() / 2;
mBrightnessMirror.setTranslationX(0);
mBrightnessMirror.setTranslationY(0);
mBrightnessMirror.getLocationInWindow(mInt2Cache);
- int mirrorX = mInt2Cache[0] + mBrightnessMirror.getWidth()/2;
- int mirrorY = mInt2Cache[1];
+ int mirrorX = mInt2Cache[0] + mBrightnessMirror.getWidth() / 2;
+ int mirrorY = mInt2Cache[1] + mBrightnessMirror.getHeight() / 2;
mBrightnessMirror.setTranslationX(originalX - mirrorX);
mBrightnessMirror.setTranslationY(originalY - mirrorY);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
index e618cb8..3142ddf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
@@ -19,11 +19,10 @@
import android.os.Looper;
import android.os.Message;
import android.telephony.SubscriptionInfo;
-
import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
-import com.android.systemui.statusbar.policy.NetworkControllerImpl.EmergencyListener;
import java.util.ArrayList;
import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java
index 186e8b5..6dd196b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java
@@ -60,6 +60,10 @@
public void setDataSaverEnabled(boolean enabled) {
mPolicyManager.setRestrictBackground(enabled);
+ try {
+ mPolicyListener.onRestrictBackgroundChanged(enabled);
+ } catch (RemoteException e) {
+ }
}
private final INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DisplayController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DisplayController.java
deleted file mode 100644
index d47050c..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DisplayController.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui.statusbar.policy;
-
-import libcore.util.Objects;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.res.Configuration;
-import android.provider.Settings;
-
-import com.android.systemui.R;
-import com.android.systemui.tuner.TunerService;
-
-import java.util.ArrayList;
-
-public class DisplayController implements TunerService.Tunable {
-
- public static final String COLOR_MATRIX_CUSTOM_ENABLED = "tuner_color_custom_enabled";
- public static final String COLOR_MATRIX_CUSTOM_VALUES = "tuner_color_custom_values";
-
- public static final String COLOR_STATE = "sysui_color_matrix_state";
-
- public static final int COLOR_STATE_DISABLED = 0;
- public static final int COLOR_STATE_ENABLED = 1;
- public static final int COLOR_STATE_AUTO = 2;
-
- public static final String AUTO_STRING = "auto_mode";
- public static final String NONE_STRING = "none";
-
- public static final int AUTO_INDEX = 2;
- public static final int CUSTOM_INDEX = 3;
-
- // Night mode ~= 3400 K
- private static final float[] NIGHT_VALUES = new float[] {
- 1, 0, 0, 0,
- 0, .754f, 0, 0,
- 0, 0, .516f, 0,
- 0, 0, 0, 1,
- };
- public static final float[] IDENTITY_MATRIX = new float[] {
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1,
- };
-
- private final ArrayList<Listener> mListeners = new ArrayList<>();
-
- private final Context mContext;
-
- private String mCurrentValue;
- private boolean mListening;
-
- public DisplayController(Context context) {
- mContext = context;
- TunerService.get(mContext).addTunable(this, COLOR_STATE,
- Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX);
- }
-
- public void addListener(Listener listener) {
- mListeners.add(listener);
- listener.onCurrentMatrixChanged();
- }
-
- public void removeListener(Listener listener) {
- mListeners.remove(listener);
- }
-
- public boolean isEnabled() {
- return TunerService.get(mContext).getValue(COLOR_STATE, COLOR_STATE_DISABLED)
- != COLOR_STATE_DISABLED;
- }
-
- public boolean isAuto() {
- return mListening;
- }
-
- public void setAuto(boolean auto) {
- TunerService.get(mContext).setValue(COLOR_STATE, auto ? COLOR_STATE_AUTO
- : COLOR_STATE_DISABLED);
- }
-
- public boolean isCustomSet() {
- return isCustomEnabled() && Objects.equal(getCurrentMatrix(), getCustomValues());
- }
-
- public String getCurrentMatrix() {
- return mCurrentValue;
- }
-
- public String getCustomValues() {
- return TunerService.get(mContext).getValue(COLOR_MATRIX_CUSTOM_VALUES);
- }
-
- public boolean isCustomEnabled() {
- return TunerService.get(mContext).getValue(COLOR_MATRIX_CUSTOM_ENABLED, 0) != 0;
- }
-
- @Override
- public void onTuningChanged(String key, String newValue) {
- if (Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX.equals(key)) {
- mCurrentValue = newValue;
- for (int i = 0; i < mListeners.size(); i++) {
- mListeners.get(i).onCurrentMatrixChanged();
- }
- } else if (COLOR_STATE.equals(key)) {
- final boolean listening = newValue != null
- && Integer.parseInt(newValue) == COLOR_STATE_AUTO;
- if (listening && !mListening) {
- mListening = true;
- mContext.registerReceiver(mReceiver,
- new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));
- updateNightMode();
- } else if (!listening && mListening) {
- mListening = false;
- mContext.unregisterReceiver(mReceiver);
- }
- for (int i = 0; i < mListeners.size(); i++) {
- mListeners.get(i).onCurrentMatrixChanged();
- }
- }
- }
-
- private void updateNightMode() {
- final int uiMode = mContext.getResources().getConfiguration().uiMode;
- final boolean isNightMode = (uiMode & Configuration.UI_MODE_NIGHT_MASK)
- == Configuration.UI_MODE_NIGHT_YES;
- String value = null;
- if (isNightMode) {
- value = toString(NIGHT_VALUES);
- }
- TunerService.get(mContext).setValue(Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX,
- value);
- }
-
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (Intent.ACTION_CONFIGURATION_CHANGED.equals(intent.getAction())) {
- updateNightMode();
- }
- }
- };
-
- public interface Listener {
- void onCurrentMatrixChanged();
- }
-
- public static String[] getColorTransforms(Context context) {
- return new String[] {
- NONE_STRING,
- toString(NIGHT_VALUES),
- AUTO_STRING, // Blank spot for auto values
- null, // Blank spot for custom values
- };
- }
-
- public static CharSequence[] getColorTitles(Context context) {
- // TODO: Move to string array resource.
- return new CharSequence[]{
- context.getString(R.string.color_matrix_none),
- context.getString(R.string.color_matrix_night),
- context.getString(R.string.color_matrix_auto),
- context.getString(R.string.color_matrix_custom),
- };
- }
-
- public static String toString(float[] values) {
- StringBuilder builder = new StringBuilder();
- for (int i = 0; i < values.length; i++) {
- if (builder.length() != 0) {
- builder.append(',');
- }
- builder.append(values[i]);
- }
- return builder.toString();
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java
index bd36462..159bd41 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java
@@ -19,6 +19,7 @@
import android.net.NetworkCapabilities;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import java.util.BitSet;
@@ -46,12 +47,12 @@
}
@Override
- public void notifyListeners() {
+ public void notifyListeners(SignalCallback callback) {
boolean ethernetVisible = mCurrentState.connected;
String contentDescription = getStringIfExists(getContentDescription());
// TODO: wire up data transfer using WifiSignalPoller.
- mCallbackHandler.setEthernetIndicators(new IconState(ethernetVisible, getCurrentIconId(),
+ callback.setEthernetIndicators(new IconState(ethernetVisible, getCurrentIconId(),
contentDescription));
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
index 29a8f67..9a21a1e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
@@ -93,6 +93,10 @@
}
}
+ public boolean hasFlashlight() {
+ return mCameraId != null;
+ }
+
public synchronized boolean isEnabled() {
return mFlashlightEnabled;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
index 500d603..047f14d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
@@ -21,7 +21,6 @@
void removeCallback(Callback callback);
boolean isHotspotEnabled();
void setHotspotEnabled(boolean enabled);
- boolean isTetheringAllowed();
public interface Callback {
void onHotspotChanged(boolean enabled);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
index 07b7409..f03d9e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -16,15 +16,12 @@
package com.android.systemui.statusbar.policy;
-import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
-import android.os.UserHandle;
-import android.os.UserManager;
import android.util.Log;
import java.io.FileDescriptor;
@@ -40,8 +37,6 @@
private final Receiver mReceiver = new Receiver();
private final ConnectivityManager mConnectivityManager;
private final Context mContext;
- private final UserManager mUserManager;
- private final int mCurrentUser;
private int mHotspotState;
@@ -49,8 +44,6 @@
mContext = context;
mConnectivityManager = (ConnectivityManager) context.getSystemService(
Context.CONNECTIVITY_SERVICE);
- mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
- mCurrentUser = ActivityManager.getCurrentUser();
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
@@ -95,12 +88,6 @@
return mHotspotState == WifiManager.WIFI_AP_STATE_ENABLED;
}
- @Override
- public boolean isTetheringAllowed() {
- return !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING,
- UserHandle.of(mCurrentUser));
- }
-
static final class OnStartTetheringCallback extends
ConnectivityManager.OnStartTetheringCallback {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
index 867a8a3..fb310a6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
@@ -21,6 +21,8 @@
import android.animation.ObjectAnimator;
import android.content.Context;
import android.database.DataSetObserver;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -242,7 +244,6 @@
@Override
public View getView(int position, View convertView, ViewGroup parent) {
UserSwitcherController.UserRecord item = getItem(position);
-
if (!(convertView instanceof UserDetailItemView)
|| !(convertView.getTag() instanceof UserSwitcherController.UserRecord)) {
convertView = LayoutInflater.from(mContext).inflate(
@@ -252,11 +253,17 @@
UserDetailItemView v = (UserDetailItemView) convertView;
String name = getName(mContext, item);
+ Drawable drawable;
if (item.picture == null) {
- v.bind(name, getDrawable(mContext, item));
+ drawable = getDrawable(mContext, item).mutate();
} else {
- v.bind(name, item.picture);
+ drawable = new BitmapDrawable(mContext.getResources(), item.picture);
}
+ // Disable the icon if switching is disabled
+ if (!item.isSwitchToEnabled) {
+ drawable.setTint(mContext.getColor(R.color.qs_tile_disabled_color));
+ }
+ v.bind(name, drawable);
convertView.setActivated(item.isCurrent);
convertView.setTag(item);
return convertView;
@@ -269,7 +276,7 @@
// Close the switcher if tapping the current user. Guest is excluded because
// tapping the guest user while it's current clears the session.
mKeyguardUserSwitcher.hideIfNotSimple(true /* animate */);
- } else {
+ } else if (user.isSwitchToEnabled) {
switchTo(user);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
index 401943e..29a8981 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
@@ -21,7 +21,6 @@
boolean setLocationEnabled(boolean enabled);
void addSettingsChangedCallback(LocationSettingsChangeCallback cb);
void removeSettingsChangedCallback(LocationSettingsChangeCallback cb);
- boolean isUserLocationRestricted();
/**
* A callback for change in location settings (the user has enabled/disabled location).
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
index 436a40d..8d84be4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
@@ -52,7 +52,6 @@
private AppOpsManager mAppOpsManager;
private StatusBarManager mStatusBarManager;
- private final int mCurrentUser;
private boolean mAreActiveLocationRequests;
@@ -74,7 +73,6 @@
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
mStatusBarManager
= (StatusBarManager) context.getSystemService(Context.STATUS_BAR_SERVICE);
- mCurrentUser = ActivityManager.getCurrentUser();
// Examine the current location state and initialize the status view.
updateActiveLocationRequests();
@@ -105,6 +103,10 @@
* @return true if attempt to change setting was successful.
*/
public boolean setLocationEnabled(boolean enabled) {
+ int currentUserId = ActivityManager.getCurrentUser();
+ if (isUserLocationRestricted(currentUserId)) {
+ return false;
+ }
final ContentResolver cr = mContext.getContentResolver();
// When enabling location, a user consent dialog will pop up, and the
// setting won't be fully enabled until the user accepts the agreement.
@@ -113,7 +115,7 @@
// QuickSettings always runs as the owner, so specifically set the settings
// for the current foreground user.
return Settings.Secure
- .putIntForUser(cr, Settings.Secure.LOCATION_MODE, mode, mCurrentUser);
+ .putIntForUser(cr, Settings.Secure.LOCATION_MODE, mode, currentUserId);
}
/**
@@ -131,10 +133,10 @@
/**
* Returns true if the current user is restricted from using location.
*/
- public boolean isUserLocationRestricted() {
+ private boolean isUserLocationRestricted(int userId) {
final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
return um.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION,
- UserHandle.of(mCurrentUser));
+ UserHandle.of(userId));
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 8fd4d9c..80dcfb6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -34,6 +34,7 @@
import com.android.internal.telephony.cdma.EriInfo;
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults;
@@ -198,7 +199,7 @@
}
@Override
- public void notifyListeners() {
+ public void notifyListeners(SignalCallback callback) {
MobileIconGroup icons = getIcons();
String contentDescription = getStringIfExists(getContentDescription());
@@ -231,7 +232,7 @@
|| mCurrentState.iconGroup == TelephonyIcons.ROAMING
|| mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED;
int typeIcon = showDataIcon ? icons.mDataType : 0;
- mCallbackHandler.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
+ callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
activityIn, activityOut, dataContentDescription, description, icons.mIsWide,
mSubscriptionInfo.getSubscriptionId());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 93c7322..348e0b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -19,7 +19,6 @@
import android.content.Context;
import android.content.Intent;
import android.telephony.SubscriptionInfo;
-
import com.android.settingslib.net.DataUsageController;
import com.android.settingslib.wifi.AccessPoint;
@@ -36,6 +35,11 @@
DataUsageController getMobileDataController();
DataSaverController getDataSaverController();
+ boolean hasVoiceCallingFeature();
+
+ void addEmergencyListener(EmergencyListener listener);
+ void removeEmergencyListener(EmergencyListener listener);
+
public interface SignalCallback {
void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
boolean activityIn, boolean activityOut, String description);
@@ -53,6 +57,10 @@
void setMobileDataEnabled(boolean enabled);
}
+ public interface EmergencyListener {
+ void setEmergencyCallsOnly(boolean emergencyOnly);
+ }
+
public static class IconState {
public final boolean visible;
public final int icon;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index eecf8c2..40eb71d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -252,6 +252,10 @@
mCallbackHandler.setEmergencyCallsOnly(isEmergencyOnly());
}
+ public void removeEmergencyListener(EmergencyListener listener) {
+ mCallbackHandler.setListening(listener, false);
+ }
+
public boolean hasMobileDataFeature() {
return mHasMobileDataFeature;
}
@@ -318,16 +322,16 @@
}
public void addSignalCallback(SignalCallback cb) {
- mCallbackHandler.setListening(cb, true);
- mCallbackHandler.setSubs(mCurrentSubscriptions);
- mCallbackHandler.setIsAirplaneMode(new IconState(mAirplaneMode,
+ cb.setSubs(mCurrentSubscriptions);
+ cb.setIsAirplaneMode(new IconState(mAirplaneMode,
TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext));
- mCallbackHandler.setNoSims(mHasNoSims);
- mWifiSignalController.notifyListeners();
- mEthernetSignalController.notifyListeners();
+ cb.setNoSims(mHasNoSims);
+ mWifiSignalController.notifyListeners(cb);
+ mEthernetSignalController.notifyListeners(cb);
for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
- mobileSignalController.notifyListeners();
+ mobileSignalController.notifyListeners(cb);
}
+ mCallbackHandler.setListening(cb, true);
}
@Override
@@ -812,10 +816,6 @@
}
};
- public interface EmergencyListener {
- void setEmergencyCallsOnly(boolean emergencyOnly);
- }
-
public static class SubscriptionDefaults {
public int getDefaultVoiceSubId() {
return SubscriptionManager.getDefaultVoiceSubscriptionId();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NightModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NightModeController.java
new file mode 100644
index 0000000..4611ef9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NightModeController.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.opengl.Matrix;
+import android.provider.Settings.Secure;
+import android.util.MathUtils;
+import com.android.systemui.tuner.TunerService;
+
+import java.util.ArrayList;
+
+/**
+ * Listens for changes to twilight from the TwilightService.
+ *
+ * Also pushes the current matrix to accessibility based on the current twilight
+ * and various tuner settings.
+ */
+public class NightModeController implements TunerService.Tunable {
+
+ public static final String NIGHT_MODE_ADJUST_TINT = "tuner_night_mode_adjust_tint";
+ private static final String COLOR_MATRIX_CUSTOM_VALUES = "tuner_color_custom_values";
+
+ private static final String ACTION_TWILIGHT_CHANGED = "android.intent.action.TWILIGHT_CHANGED";
+
+ private static final String EXTRA_IS_NIGHT = "isNight";
+ private static final String EXTRA_AMOUNT = "amount";
+
+ // Night mode ~= 3400 K
+ private static final float[] NIGHT_VALUES = new float[] {
+ 1, 0, 0, 0,
+ 0, .754f, 0, 0,
+ 0, 0, .516f, 0,
+ 0, 0, 0, 1,
+ };
+ public static final float[] IDENTITY_MATRIX = new float[] {
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1,
+ };
+
+ private final ArrayList<Listener> mListeners = new ArrayList<>();
+
+ private final Context mContext;
+
+ // This is whether or not this is the main NightMode controller in SysUI that should be
+ // updating relevant color matrixes or if its in the tuner process getting current state
+ // for UI.
+ private final boolean mUpdateMatrix;
+
+ private float[] mCustomMatrix;
+ private boolean mListening;
+ private boolean mAdjustTint;
+
+ private boolean mIsNight;
+ private float mAmount;
+ private boolean mIsAuto;
+
+ public NightModeController(Context context) {
+ this(context, false);
+ }
+
+ public NightModeController(Context context, boolean updateMatrix) {
+ mContext = context;
+ mUpdateMatrix = updateMatrix;
+ TunerService.get(mContext).addTunable(this, NIGHT_MODE_ADJUST_TINT,
+ COLOR_MATRIX_CUSTOM_VALUES, Secure.TWILIGHT_MODE);
+ }
+
+ public void setNightMode(boolean isNight) {
+ if (mIsAuto) {
+ if (mIsNight != isNight) {
+ TunerService.get(mContext).setValue(Secure.TWILIGHT_MODE, isNight
+ ? Secure.TWILIGHT_MODE_AUTO_OVERRIDE_ON
+ : Secure.TWILIGHT_MODE_AUTO_OVERRIDE_OFF);
+ } else {
+ TunerService.get(mContext).setValue(Secure.TWILIGHT_MODE,
+ Secure.TWILIGHT_MODE_AUTO);
+ }
+ } else {
+ TunerService.get(mContext).setValue(Secure.TWILIGHT_MODE, isNight
+ ? Secure.TWILIGHT_MODE_LOCKED_ON : Secure.TWILIGHT_MODE_LOCKED_OFF);
+ }
+ }
+
+ public void setAuto(boolean auto) {
+ mIsAuto = auto;
+ if (auto) {
+ TunerService.get(mContext).setValue(Secure.TWILIGHT_MODE, Secure.TWILIGHT_MODE_AUTO);
+ } else {
+ // Lock into the current state
+ TunerService.get(mContext).setValue(Secure.TWILIGHT_MODE, mIsNight
+ ? Secure.TWILIGHT_MODE_LOCKED_ON : Secure.TWILIGHT_MODE_LOCKED_OFF);
+ }
+ }
+
+ public boolean isAuto() {
+ return mIsAuto;
+ }
+
+ public void setAdjustTint(Boolean newValue) {
+ TunerService.get(mContext).setValue(NIGHT_MODE_ADJUST_TINT, ((Boolean) newValue) ? 1 : 0);
+ }
+
+ public void addListener(Listener listener) {
+ mListeners.add(listener);
+ listener.onNightModeChanged();
+ updateListening();
+ }
+
+ public void removeListener(Listener listener) {
+ mListeners.remove(listener);
+ updateListening();
+ }
+
+ private void updateListening() {
+ boolean shouldListen = mListeners.size() != 0 || (mUpdateMatrix && mAdjustTint);
+ if (shouldListen == mListening) return;
+ mListening = shouldListen;
+ if (mListening) {
+ mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_TWILIGHT_CHANGED));
+ } else {
+ mContext.unregisterReceiver(mReceiver);
+ }
+ }
+
+ public boolean isEnabled() {
+ if (!mListening) {
+ updateNightMode(mContext.registerReceiver(null,
+ new IntentFilter(ACTION_TWILIGHT_CHANGED)));
+ }
+ return mIsNight;
+ }
+
+ public String getCustomValues() {
+ return TunerService.get(mContext).getValue(COLOR_MATRIX_CUSTOM_VALUES);
+ }
+
+ public void setCustomValues(String values) {
+ TunerService.get(mContext).setValue(COLOR_MATRIX_CUSTOM_VALUES, values);
+ }
+
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ if (COLOR_MATRIX_CUSTOM_VALUES.equals(key)) {
+ mCustomMatrix = newValue != null ? toValues(newValue) : null;
+ updateCurrentMatrix();
+ } else if (NIGHT_MODE_ADJUST_TINT.equals(key)) {
+ mAdjustTint = newValue == null || Integer.parseInt(newValue) != 0;
+ updateListening();
+ updateCurrentMatrix();
+ } else if (Secure.TWILIGHT_MODE.equals(key)) {
+ mIsAuto = newValue != null && Integer.parseInt(newValue) >= Secure.TWILIGHT_MODE_AUTO;
+ }
+ }
+
+ private void updateCurrentMatrix() {
+ if (!mUpdateMatrix) return;
+ if ((!mAdjustTint || mAmount == 0) && mCustomMatrix == null) {
+ TunerService.get(mContext).setValue(Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, null);
+ return;
+ }
+ float[] values = scaleValues(IDENTITY_MATRIX, NIGHT_VALUES, mAdjustTint ? mAmount : 0);
+ if (mCustomMatrix != null) {
+ values = multiply(values, mCustomMatrix);
+ }
+ TunerService.get(mContext).setValue(Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX,
+ toString(values));
+ }
+
+ private void updateNightMode(Intent intent) {
+ mIsNight = intent != null && intent.getBooleanExtra(EXTRA_IS_NIGHT, false);
+ mAmount = intent != null ? intent.getFloatExtra(EXTRA_AMOUNT, 0) : 0;
+ }
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (ACTION_TWILIGHT_CHANGED.equals(intent.getAction())) {
+ updateNightMode(intent);
+ updateCurrentMatrix();
+ for (int i = 0; i < mListeners.size(); i++) {
+ mListeners.get(i).onNightModeChanged();
+ }
+ }
+ }
+ };
+
+ public interface Listener {
+ void onNightModeChanged();
+ void onTwilightAutoChanged();
+ }
+
+ private static float[] multiply(float[] matrix, float[] other) {
+ if (matrix == null) {
+ return other;
+ }
+ float[] result = new float[16];
+ Matrix.multiplyMM(result, 0, matrix, 0, other, 0);
+ return result;
+ }
+
+ private float[] scaleValues(float[] identityMatrix, float[] nightValues, float amount) {
+ float[] values = new float[identityMatrix.length];
+ for (int i = 0; i < values.length; i++) {
+ values[i] = MathUtils.lerp(identityMatrix[i], nightValues[i], amount);
+ }
+ return values;
+ }
+
+ public static String toString(float[] values) {
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < values.length; i++) {
+ if (builder.length() != 0) {
+ builder.append(',');
+ }
+ builder.append(values[i]);
+ }
+ return builder.toString();
+ }
+
+ public static float[] toValues(String customValues) {
+ String[] strValues = customValues.split(",");
+ float[] values = new float[strValues.length];
+ for (int i = 0; i < values.length; i++) {
+ values[i] = Float.parseFloat(strValues[i]);
+ }
+ return values;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
index c954d08..4cfd1c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.text.format.DateFormat;
import android.util.Log;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import java.io.PrintWriter;
import java.util.BitSet;
@@ -48,7 +49,7 @@
// is aware of current state.
protected final NetworkControllerImpl mNetworkController;
- protected final CallbackHandler mCallbackHandler;
+ private final CallbackHandler mCallbackHandler;
// Save the previous HISTORY_SIZE states for logging.
private final State[] mHistory;
@@ -198,12 +199,16 @@
}
}
+ public final void notifyListeners() {
+ notifyListeners(mCallbackHandler);
+ }
+
/**
* Trigger callbacks based on current state. The callbacks should be completely
* based on current state, and only need to be called in the scenario where
* mCurrentState != mLastState.
*/
- public abstract void notifyListeners();
+ public abstract void notifyListeners(SignalCallback callback);
/**
* Generate a blank T.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 6ca7dc8..cedc3c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -37,6 +37,8 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
+import android.telephony.PhoneStateListener;
+import android.telephony.TelephonyManager;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -115,6 +117,7 @@
filter.addAction(Intent.ACTION_USER_INFO_CHANGED);
filter.addAction(Intent.ACTION_USER_SWITCHED);
filter.addAction(Intent.ACTION_USER_STOPPING);
+ filter.addAction(Intent.ACTION_USER_UNLOCKED);
mContext.registerReceiverAsUser(mReceiver, UserHandle.SYSTEM, filter,
null /* permission */, null /* scheduler */);
@@ -130,10 +133,15 @@
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.ADD_USERS_WHEN_LOCKED), true,
mSettingsObserver);
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(
+ Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED),
+ true, mSettingsObserver);
// Fetch initial values.
mSettingsObserver.onChange(false);
keyguardMonitor.addCallback(mCallback);
+ listenForCallState();
refreshUsers(UserHandle.USER_NULL);
}
@@ -180,6 +188,7 @@
}
ArrayList<UserRecord> records = new ArrayList<>(infos.size());
int currentId = ActivityManager.getCurrentUser();
+ boolean canSwitchUsers = mUserManager.canSwitchUsers();
UserInfo currentUserInfo = null;
UserRecord guestRecord = null;
int avatarSize = mContext.getResources()
@@ -190,32 +199,42 @@
if (isCurrent) {
currentUserInfo = info;
}
- if (info.isGuest()) {
- guestRecord = new UserRecord(info, null /* picture */,
- true /* isGuest */, isCurrent, false /* isAddUser */,
- false /* isRestricted */);
- } else if (info.isEnabled() && info.supportsSwitchToByUser()) {
- Bitmap picture = bitmaps.get(info.id);
- if (picture == null) {
- picture = mUserManager.getUserIcon(info.id);
+ boolean switchToEnabled = canSwitchUsers || isCurrent;
+ if (info.isEnabled()) {
+ if (info.isGuest()) {
+ // Tapping guest icon triggers remove and a user switch therefore
+ // the icon shouldn't be enabled even if the user is current
+ guestRecord = new UserRecord(info, null /* picture */,
+ true /* isGuest */, isCurrent, false /* isAddUser */,
+ false /* isRestricted */, canSwitchUsers);
+ } else if (info.supportsSwitchToByUser()) {
+ Bitmap picture = bitmaps.get(info.id);
+ if (picture == null) {
+ picture = mUserManager.getUserIcon(info.id);
- if (picture != null) {
- picture = BitmapHelper.createCircularClip(
- picture, avatarSize, avatarSize);
+ if (picture != null) {
+ picture = BitmapHelper.createCircularClip(
+ picture, avatarSize, avatarSize);
+ }
}
+ int index = isCurrent ? 0 : records.size();
+ records.add(index, new UserRecord(info, picture, false /* isGuest */,
+ isCurrent, false /* isAddUser */, false /* isRestricted */,
+ switchToEnabled));
}
- int index = isCurrent ? 0 : records.size();
- records.add(index, new UserRecord(info, picture, false /* isGuest */,
- isCurrent, false /* isAddUser */, false /* isRestricted */));
}
}
+ boolean systemCanCreateUsers = !mUserManager.hasBaseUserRestriction(
+ UserManager.DISALLOW_ADD_USER, UserHandle.SYSTEM);
boolean currentUserCanCreateUsers = currentUserInfo != null
&& (currentUserInfo.isAdmin()
- || currentUserInfo.id == UserHandle.USER_SYSTEM);
- boolean canCreateGuest = (currentUserCanCreateUsers || addUsersWhenLocked)
+ || currentUserInfo.id == UserHandle.USER_SYSTEM)
+ && systemCanCreateUsers;
+ boolean anyoneCanCreateUsers = systemCanCreateUsers && addUsersWhenLocked;
+ boolean canCreateGuest = (currentUserCanCreateUsers || anyoneCanCreateUsers)
&& guestRecord == null;
- boolean canCreateUser = (currentUserCanCreateUsers || addUsersWhenLocked)
+ boolean canCreateUser = (currentUserCanCreateUsers || anyoneCanCreateUsers)
&& mUserManager.canAddMoreUsers();
boolean createIsRestricted = !addUsersWhenLocked;
@@ -224,8 +243,8 @@
if (canCreateGuest) {
guestRecord = new UserRecord(null /* info */, null /* picture */,
true /* isGuest */, false /* isCurrent */,
- false /* isAddUser */, createIsRestricted);
- checkIfAddUserDisallowed(guestRecord);
+ false /* isAddUser */, createIsRestricted, canSwitchUsers);
+ checkIfAddUserDisallowedByAdminOnly(guestRecord);
records.add(guestRecord);
}
} else {
@@ -237,8 +256,8 @@
if (!mSimpleUserSwitcher && canCreateUser) {
UserRecord addUserRecord = new UserRecord(null /* info */, null /* picture */,
false /* isGuest */, false /* isCurrent */, true /* isAddUser */,
- createIsRestricted);
- checkIfAddUserDisallowed(addUserRecord);
+ createIsRestricted, canSwitchUsers);
+ checkIfAddUserDisallowedByAdminOnly(addUserRecord);
records.add(addUserRecord);
}
@@ -401,6 +420,24 @@
mUserManager.removeUser(id);
}
+ private void listenForCallState() {
+ TelephonyManager.from(mContext).listen(new PhoneStateListener() {
+ private int mCallState;
+ @Override
+ public void onCallStateChanged(int state, String incomingNumber) {
+ if (mCallState == state) return;
+ if (DEBUG) Log.v(TAG, "Call state changed: " + state);
+ mCallState = state;
+ int currentUserId = ActivityManager.getCurrentUser();
+ UserInfo userInfo = mUserManager.getUserInfo(currentUserId);
+ if (userInfo != null && userInfo.isGuest()) {
+ showGuestNotification(currentUserId);
+ }
+ refreshUsers(UserHandle.USER_NULL);
+ }
+ }, PhoneStateListener.LISTEN_CALL_STATE);
+ }
+
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -459,6 +496,12 @@
} else if (Intent.ACTION_USER_INFO_CHANGED.equals(intent.getAction())) {
forcePictureLoadForId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
UserHandle.USER_NULL);
+ } else if (Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) {
+ // Unlocking the system user may require a refresh
+ int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+ if (userId != UserHandle.USER_SYSTEM) {
+ return;
+ }
}
refreshUsers(forcePictureLoadForId);
if (unpauseRefreshUsers) {
@@ -466,25 +509,6 @@
}
}
- private void showGuestNotification(int guestUserId) {
- PendingIntent removeGuestPI = PendingIntent.getBroadcastAsUser(mContext,
- 0, new Intent(ACTION_REMOVE_GUEST), 0, UserHandle.SYSTEM);
- Notification notification = new Notification.Builder(mContext)
- .setVisibility(Notification.VISIBILITY_SECRET)
- .setPriority(Notification.PRIORITY_MIN)
- .setSmallIcon(R.drawable.ic_person)
- .setContentTitle(mContext.getString(R.string.guest_notification_title))
- .setContentText(mContext.getString(R.string.guest_notification_text))
- .setContentIntent(removeGuestPI)
- .setShowWhen(false)
- .addAction(R.drawable.ic_delete,
- mContext.getString(R.string.guest_notification_remove_action),
- removeGuestPI)
- .build();
- NotificationManager.from(mContext).notifyAsUser(TAG_REMOVE_GUEST, ID_REMOVE_GUEST,
- notification, new UserHandle(guestUserId));
- }
-
private void showLogoutNotification(int userId) {
PendingIntent logoutPI = PendingIntent.getBroadcastAsUser(mContext,
0, new Intent(ACTION_LOGOUT_USER), 0, UserHandle.SYSTEM);
@@ -506,6 +530,28 @@
}
};
+ private void showGuestNotification(int guestUserId) {
+ boolean canSwitchUsers = mUserManager.canSwitchUsers();
+ // Disable 'Remove guest' action if cannot switch users right now
+ PendingIntent removeGuestPI = canSwitchUsers ? PendingIntent.getBroadcastAsUser(mContext,
+ 0, new Intent(ACTION_REMOVE_GUEST), 0, UserHandle.SYSTEM) : null;
+
+ Notification notification = new Notification.Builder(mContext)
+ .setVisibility(Notification.VISIBILITY_SECRET)
+ .setPriority(Notification.PRIORITY_MIN)
+ .setSmallIcon(R.drawable.ic_person)
+ .setContentTitle(mContext.getString(R.string.guest_notification_title))
+ .setContentText(mContext.getString(R.string.guest_notification_text))
+ .setContentIntent(removeGuestPI)
+ .setShowWhen(false)
+ .addAction(R.drawable.ic_delete,
+ mContext.getString(R.string.guest_notification_remove_action),
+ removeGuestPI)
+ .build();
+ NotificationManager.from(mContext).notifyAsUser(TAG_REMOVE_GUEST, ID_REMOVE_GUEST,
+ notification, new UserHandle(guestUserId));
+ }
+
private final Runnable mUnpauseRefreshUsers = new Runnable() {
@Override
public void run() {
@@ -615,10 +661,11 @@
}
}
- private void checkIfAddUserDisallowed(UserRecord record) {
+ private void checkIfAddUserDisallowedByAdminOnly(UserRecord record) {
EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(mContext,
UserManager.DISALLOW_ADD_USER, ActivityManager.getCurrentUser());
- if (admin != null) {
+ if (admin != null && !RestrictedLockUtils.hasBaseUserRestriction(mContext,
+ UserManager.DISALLOW_ADD_USER, ActivityManager.getCurrentUser())) {
record.isDisabledByAdmin = true;
record.enforcedAdmin = admin;
} else {
@@ -641,26 +688,29 @@
public final boolean isRestricted;
public boolean isDisabledByAdmin;
public EnforcedAdmin enforcedAdmin;
+ public boolean isSwitchToEnabled;
public UserRecord(UserInfo info, Bitmap picture, boolean isGuest, boolean isCurrent,
- boolean isAddUser, boolean isRestricted) {
+ boolean isAddUser, boolean isRestricted, boolean isSwitchToEnabled) {
this.info = info;
this.picture = picture;
this.isGuest = isGuest;
this.isCurrent = isCurrent;
this.isAddUser = isAddUser;
this.isRestricted = isRestricted;
+ this.isSwitchToEnabled = isSwitchToEnabled;
}
public UserRecord copyWithIsCurrent(boolean _isCurrent) {
- return new UserRecord(info, picture, isGuest, _isCurrent, isAddUser, isRestricted);
+ return new UserRecord(info, picture, isGuest, _isCurrent, isAddUser, isRestricted,
+ isSwitchToEnabled);
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("UserRecord(");
if (info != null) {
- sb.append("name=\"" + info.name + "\" id=" + info.id);
+ sb.append("name=\"").append(info.name).append("\" id=").append(info.id);
} else {
if (isGuest) {
sb.append("<add guest placeholder>");
@@ -675,7 +725,10 @@
if (isRestricted) sb.append(" <isRestricted>");
if (isDisabledByAdmin) {
sb.append(" <isDisabledByAdmin>");
- sb.append(" enforcedAdmin=" + enforcedAdmin);
+ sb.append(" enforcedAdmin=").append(enforcedAdmin);
+ }
+ if (isSwitchToEnabled) {
+ sb.append(" <isSwitchToEnabled>");
}
sb.append(')');
return sb.toString();
@@ -683,7 +736,7 @@
}
public final QSTile.DetailAdapter userDetailAdapter = new QSTile.DetailAdapter() {
- private final Intent USER_SETTINGS_INTENT = new Intent("android.settings.USER_SETTINGS");
+ private final Intent USER_SETTINGS_INTENT = new Intent(Settings.ACTION_USER_SETTINGS);
@Override
public CharSequence getTitle() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index cc98eb6..a6ed04f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -28,6 +28,7 @@
import com.android.internal.util.AsyncChannel;
import com.android.settingslib.wifi.WifiStatusTracker;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import java.util.Objects;
@@ -72,7 +73,7 @@
}
@Override
- public void notifyListeners() {
+ public void notifyListeners(SignalCallback callback) {
// only show wifi in the cluster if connected or if wifi-only
boolean wifiVisible = mCurrentState.enabled
&& (mCurrentState.connected || !mHasMobileData);
@@ -83,7 +84,7 @@
IconState statusIcon = new IconState(wifiVisible, getCurrentIconId(), contentDescription);
IconState qsIcon = new IconState(mCurrentState.connected, getQsCurrentIconId(),
contentDescription);
- mCallbackHandler.setWifiIndicators(mCurrentState.enabled, statusIcon, qsIcon,
+ callback.setWifiIndicators(mCurrentState.enabled, statusIcon, qsIcon,
ssidPresent && mCurrentState.activityIn, ssidPresent && mCurrentState.activityOut,
wifiDesc);
}
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 49aec42..7955733 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -29,6 +29,7 @@
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.HybridNotificationView;
import com.android.systemui.statusbar.notification.HybridNotificationViewManager;
+import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.phone.NotificationPanelView;
import java.util.ArrayList;
@@ -60,6 +61,8 @@
private ViewState mGroupOverFlowState;
private int mRealHeight;
private int mLayoutDirection = LAYOUT_DIRECTION_UNDEFINED;
+ private boolean mUserLocked;
+ private int mActualHeight;
public NotificationChildrenContainer(Context context) {
this(context, null);
@@ -164,6 +167,7 @@
int newIndex = childIndex < 0 ? mChildren.size() : childIndex;
mChildren.add(newIndex, row);
addView(row);
+ row.setUserLocked(mUserLocked);
View divider = inflateDivider();
addView(divider);
@@ -188,6 +192,7 @@
});
row.setSystemChildExpanded(false);
+ row.setUserLocked(false);
updateGroupOverflow();
}
@@ -259,10 +264,14 @@
}
private void updateExpansionStates() {
- // Let's make the first child expanded if the parent is
- for (int i = 0; i < mChildren.size(); i++) {
+ if (mChildrenExpanded || mUserLocked) {
+ // we don't modify it the group is expanded or if we are expanding it
+ return;
+ }
+ int size = mChildren.size();
+ for (int i = 0; i < size; i++) {
ExpandableNotificationRow child = mChildren.get(i);
- child.setSystemChildExpanded(false);
+ child.setSystemChildExpanded(i == 0 && size == 1);
}
}
@@ -281,27 +290,45 @@
*/
private int getIntrinsicHeight(float maxAllowedVisibleChildren) {
int intrinsicHeight = mNotificationHeaderHeight;
- if (mChildrenExpanded) {
- intrinsicHeight += mNotificatonTopPadding;
- }
int visibleChildren = 0;
int childCount = mChildren.size();
+ boolean firstChild = true;
+ float expandFactor = 0;
+ if (mUserLocked) {
+ expandFactor = getChildExpandFraction();
+ }
for (int i = 0; i < childCount; i++) {
if (visibleChildren >= maxAllowedVisibleChildren) {
break;
}
+ if (!firstChild) {
+ if (mUserLocked) {
+ intrinsicHeight += NotificationUtils.interpolate(mChildPadding, mDividerHeight,
+ expandFactor);
+ } else {
+ intrinsicHeight += mChildrenExpanded ? mDividerHeight : mChildPadding;
+ }
+ } else {
+ if (mUserLocked) {
+ intrinsicHeight += NotificationUtils.interpolate(
+ 0,
+ mNotificatonTopPadding + mDividerHeight,
+ expandFactor);
+ } else {
+ intrinsicHeight += mChildrenExpanded
+ ? mNotificatonTopPadding + mDividerHeight
+ : 0;
+ }
+ firstChild = false;
+ }
ExpandableNotificationRow child = mChildren.get(i);
intrinsicHeight += child.getIntrinsicHeight();
visibleChildren++;
}
- if (visibleChildren > 0) {
- if (mChildrenExpanded) {
- intrinsicHeight += visibleChildren * mDividerHeight;
- } else {
- intrinsicHeight += (visibleChildren - 1) * mChildPadding;
- }
- }
- if (!mChildrenExpanded) {
+ if (mUserLocked) {
+ intrinsicHeight += NotificationUtils.interpolate(mCollapsedBottompadding, 0.0f,
+ expandFactor);
+ } else if (!mChildrenExpanded) {
intrinsicHeight += mCollapsedBottompadding;
}
return intrinsicHeight;
@@ -323,12 +350,28 @@
int lastVisibleIndex = hasOverflow
? maxAllowedVisibleChildren - 2
: maxAllowedVisibleChildren - 1;
+ float expandFactor = 0;
+ if (mUserLocked) {
+ expandFactor = getChildExpandFraction();
+ }
for (int i = 0; i < childCount; i++) {
ExpandableNotificationRow child = mChildren.get(i);
if (!firstChild) {
- yPosition += mChildrenExpanded ? mDividerHeight : mChildPadding;
+ if (mUserLocked) {
+ yPosition += NotificationUtils.interpolate(mChildPadding, mDividerHeight,
+ expandFactor);
+ } else {
+ yPosition += mChildrenExpanded ? mDividerHeight : mChildPadding;
+ }
} else {
- yPosition += mChildrenExpanded ? mNotificatonTopPadding + mDividerHeight : 0;
+ if (mUserLocked) {
+ yPosition += NotificationUtils.interpolate(
+ 0,
+ mNotificatonTopPadding + mDividerHeight,
+ expandFactor);
+ } else {
+ yPosition += mChildrenExpanded ? mNotificatonTopPadding + mDividerHeight : 0;
+ }
firstChild = false;
}
StackViewState childState = resultState.getViewStateForView(child);
@@ -375,6 +418,7 @@
public void applyState(StackScrollState state) {
int childCount = mChildren.size();
ViewState tmpState = new ViewState();
+ float expandFraction = getChildExpandFraction();
for (int i = 0; i < childCount; i++) {
ExpandableNotificationRow child = mChildren.get(i);
StackViewState viewState = state.getViewStateForView(child);
@@ -384,7 +428,11 @@
View divider = mDividers.get(i);
tmpState.initFrom(divider);
tmpState.yTranslation = viewState.yTranslation - mDividerHeight;
- tmpState.alpha = mChildrenExpanded && viewState.alpha != 0 ? 0.5f : 0;
+ float alpha = mChildrenExpanded && viewState.alpha != 0 ? 0.5f : 0;
+ if (mUserLocked && viewState.alpha != 0) {
+ alpha = NotificationUtils.interpolate(0, 0.5f, expandFraction);
+ }
+ tmpState.alpha = alpha;
state.applyViewState(divider, tmpState);
}
if (mGroupOverflowContainer != null) {
@@ -407,6 +455,7 @@
long baseDelay, long duration) {
int childCount = mChildren.size();
ViewState tmpState = new ViewState();
+ float expandFraction = getChildExpandFraction();
for (int i = childCount - 1; i >= 0; i--) {
ExpandableNotificationRow child = mChildren.get(i);
StackViewState viewState = state.getViewStateForView(child);
@@ -416,7 +465,11 @@
View divider = mDividers.get(i);
tmpState.initFrom(divider);
tmpState.yTranslation = viewState.yTranslation - mDividerHeight;
- tmpState.alpha = mChildrenExpanded && viewState.alpha != 0 ? 0.5f : 0;
+ float alpha = mChildrenExpanded && viewState.alpha != 0 ? 0.5f : 0;
+ if (mUserLocked && viewState.alpha != 0) {
+ alpha = NotificationUtils.interpolate(0, 0.5f, expandFraction);
+ }
+ tmpState.alpha = alpha;
stateAnimator.startViewAnimations(divider, tmpState, baseDelay, duration);
}
if (mGroupOverflowContainer != null) {
@@ -442,6 +495,7 @@
public void setChildrenExpanded(boolean childrenExpanded) {
mChildrenExpanded = childrenExpanded;
+ updateExpansionStates();
}
public void setNotificationParent(ExpandableNotificationRow parent) {
@@ -449,15 +503,98 @@
}
public int getMaxContentHeight() {
- return getIntrinsicHeight(NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED);
+ int maxContentHeight = mNotificationHeaderHeight + mNotificatonTopPadding;
+ int visibleChildren = 0;
+ int childCount = mChildren.size();
+ for (int i = 0; i < childCount; i++) {
+ if (visibleChildren >= NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED) {
+ break;
+ }
+ ExpandableNotificationRow child = mChildren.get(i);
+ float childHeight = child.isExpanded()
+ ? child.getMaxExpandHeight()
+ : child.getShowingLayout().getMinHeight(true /* likeGroupExpanded */);
+ maxContentHeight += childHeight;
+ visibleChildren++;
+ }
+ if (visibleChildren > 0) {
+ maxContentHeight += visibleChildren * mDividerHeight;
+ }
+ return maxContentHeight;
+ }
+
+ public void setActualHeight(int actualHeight) {
+ if (!mUserLocked) {
+ return;
+ }
+ mActualHeight = actualHeight;
+ float fraction = getChildExpandFraction();
+ int childCount = mChildren.size();
+ for (int i = 0; i < childCount; i++) {
+ ExpandableNotificationRow child = mChildren.get(i);
+ float childHeight = child.isExpanded()
+ ? child.getMaxExpandHeight()
+ : child.getShowingLayout().getMinHeight(true /* likeGroupExpanded */);
+ float singleLineHeight = child.getShowingLayout().getMinHeight(
+ false /* likeGroupExpanded */);
+ child.setActualHeight((int) NotificationUtils.interpolate(singleLineHeight, childHeight,
+ fraction), false);
+ }
+ }
+
+ public float getChildExpandFraction() {
+ int allChildrenVisibleHeight = getChildrenExpandStartHeight();
+ int maxContentHeight = getMaxContentHeight();
+ float factor = (mActualHeight - allChildrenVisibleHeight)
+ / (float) (maxContentHeight - allChildrenVisibleHeight);
+ return Math.max(0.0f, Math.min(1.0f, factor));
+ }
+
+ private int getChildrenExpandStartHeight() {
+ int intrinsicHeight = mNotificationHeaderHeight;
+ int visibleChildren = 0;
+ int childCount = mChildren.size();
+ for (int i = 0; i < childCount; i++) {
+ if (visibleChildren >= NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED) {
+ break;
+ }
+ ExpandableNotificationRow child = mChildren.get(i);
+ intrinsicHeight += child.getMinHeight();
+ visibleChildren++;
+ }
+ if (visibleChildren > 0) {
+ intrinsicHeight += (visibleChildren - 1) * mChildPadding;
+ }
+ intrinsicHeight += mCollapsedBottompadding;
+ return intrinsicHeight;
}
public int getMinHeight() {
return getIntrinsicHeight(NUMBER_OF_CHILDREN_WHEN_COLLAPSED);
}
- public int getMinExpandHeight() {
- return getIntrinsicHeight(getMaxAllowedVisibleChildren(true /* forceCollapsed */));
+ public int getMinExpandHeight(boolean onKeyguard) {
+ int maxAllowedVisibleChildren = onKeyguard ? NUMBER_OF_CHILDREN_WHEN_COLLAPSED
+ : getMaxAllowedVisibleChildren(true /* forceCollapsed */);
+ int minExpandHeight = mNotificationHeaderHeight;
+ int visibleChildren = 0;
+ boolean firstChild = true;
+ int childCount = mChildren.size();
+ for (int i = 0; i < childCount; i++) {
+ if (visibleChildren >= maxAllowedVisibleChildren) {
+ break;
+ }
+ if (!firstChild) {
+ minExpandHeight += mChildPadding;
+ } else {
+ firstChild = false;
+ }
+ ExpandableNotificationRow child = mChildren.get(i);
+ minExpandHeight += child.getMinHeight();
+ visibleChildren++;
+ }
+ minExpandHeight += mCollapsedBottompadding;
+ return minExpandHeight;
}
public void setDark(boolean dark, boolean fade, long delay) {
@@ -477,4 +614,13 @@
mDividers.set(i, divider);
}
}
+
+ public void setUserLocked(boolean userLocked) {
+ mUserLocked = userLocked;
+ int childCount = mChildren.size();
+ for (int i = 0; i < childCount; i++) {
+ ExpandableNotificationRow child = mChildren.get(i);
+ child.setUserLocked(userLocked);
+ }
+ }
}
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 bf4245b..aa444f5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -18,10 +18,12 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.TimeAnimator;
import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
@@ -32,6 +34,7 @@
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
+import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Pair;
@@ -45,6 +48,8 @@
import android.view.animation.Interpolator;
import android.widget.OverScroller;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.ExpandHelper;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -56,8 +61,12 @@
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.ExpandableView;
import com.android.systemui.statusbar.NotificationOverflowContainer;
+import com.android.systemui.statusbar.NotificationSettingsIconRow;
+import com.android.systemui.statusbar.NotificationSettingsIconRow.SettingsIconRowListener;
import com.android.systemui.statusbar.StackScrollerDecorView;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.FakeShadowView;
+import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.statusbar.phone.ScrimController;
@@ -65,6 +74,8 @@
import com.android.systemui.statusbar.policy.ScrollAdapter;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.HashSet;
/**
@@ -72,7 +83,8 @@
*/
public class NotificationStackScrollLayout extends ViewGroup
implements SwipeHelper.Callback, ExpandHelper.Callback, ScrollAdapter,
- ExpandableView.OnHeightChangedListener, NotificationGroupManager.OnGroupChangeListener {
+ ExpandableView.OnHeightChangedListener, NotificationGroupManager.OnGroupChangeListener,
+ SettingsIconRowListener {
public static final float BACKGROUND_ALPHA_DIMMED = 0.7f;
private static final String TAG = "StackScroller";
@@ -87,7 +99,7 @@
private static final int INVALID_POINTER = -1;
private ExpandHelper mExpandHelper;
- private SwipeHelper mSwipeHelper;
+ private NotificationSwipeHelper mSwipeHelper;
private boolean mSwipingInProgress;
private int mCurrentStackHeight = Integer.MAX_VALUE;
private final Paint mBackgroundPaint = new Paint();
@@ -207,6 +219,11 @@
*/
private int mMaxScrollAfterExpand;
private SwipeHelper.LongPressListener mLongPressListener;
+ private GearDisplayedListener mGearDisplayedListener;
+
+ private NotificationSettingsIconRow mCurrIconRow;
+ private View mTranslatingParentView;
+ private View mGearExposedView;
/**
* Should in this touch motion only be scrolling allowed? It's true when the scroller was
@@ -266,6 +283,7 @@
private int mBgColor;
private float mDimAmount;
private ValueAnimator mDimAnimator;
+ private ArrayList<ExpandableView> mTmpSortedChildren = new ArrayList<>();
private Animator.AnimatorListener mDimEndListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -281,6 +299,31 @@
}
};
private ViewGroup mQsContainer;
+ private boolean mContinuousShadowUpdate;
+ private ViewTreeObserver.OnPreDrawListener mShadowUpdater
+ = new ViewTreeObserver.OnPreDrawListener() {
+
+ @Override
+ public boolean onPreDraw() {
+ updateViewShadows();
+ return true;
+ }
+ };
+ private Comparator<ExpandableView> mViewPositionComparator = new Comparator<ExpandableView>() {
+ @Override
+ public int compare(ExpandableView view, ExpandableView otherView) {
+ float endY = view.getTranslationY() + view.getActualHeight();
+ float otherEndY = otherView.getTranslationY() + otherView.getActualHeight();
+ if (endY < otherEndY) {
+ return -1;
+ } else if (endY > otherEndY) {
+ return 1;
+ } else {
+ // The two notifications end at the same location
+ return 0;
+ }
+ }
+ };
public NotificationStackScrollLayout(Context context) {
this(context, null);
@@ -304,8 +347,7 @@
minHeight, maxHeight);
mExpandHelper.setEventSource(this);
mExpandHelper.setScrollAdapter(this);
-
- mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, getContext());
+ mSwipeHelper = new NotificationSwipeHelper(SwipeHelper.X, this, getContext());
mSwipeHelper.setLongPressListener(mLongPressListener);
mStackScrollAlgorithm = new StackScrollAlgorithm(context);
initView(context);
@@ -321,6 +363,15 @@
}
@Override
+ public void onGearTouched(ExpandableNotificationRow row, int x, int y) {
+ if (mLongPressListener != null) {
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_TOUCH_GEAR,
+ row.getStatusBarNotification().getPackageName());
+ mLongPressListener.onLongPress(row, x, y);
+ }
+ }
+
+ @Override
protected void onDraw(Canvas canvas) {
canvas.drawRect(0, mCurrentBounds.top, getWidth(), mCurrentBounds.bottom, mBackgroundPaint);
if (DEBUG) {
@@ -371,12 +422,9 @@
.getDimensionPixelSize(R.dimen.notification_divider_height));
mIncreasedPaddingBetweenElements = context.getResources()
.getDimensionPixelSize(R.dimen.notification_divider_height_increased);
-
mBottomStackSlowDownHeight = mStackScrollAlgorithm.getBottomStackSlowDownLength();
mMinTopOverScrollToEscape = getResources().getDimensionPixelSize(
R.dimen.min_top_overscroll_to_qs);
- mCollapseSecondCardPadding = getResources().getDimensionPixelSize(
- R.dimen.notification_collapse_second_card_padding);
}
private void notifyHeightChangeListener(ExpandableView view) {
@@ -462,14 +510,6 @@
}
/**
- * @return whether the height of the layout needs to be adapted, in order to ensure that the
- * last child is not in the bottom stack.
- */
- private boolean needsHeightAdaption() {
- return getNotGoneChildCount() > 1;
- }
-
- /**
* Updates the children views according to the stack scroll algorithm. Call this whenever
* modifications to {@link #mOwnScrollY} are performed to reflect it in the view layout.
*/
@@ -492,7 +532,7 @@
ExpandableView child = (ExpandableView) getChildAt(i);
if (mChildrenToAddAnimated.contains(child)) {
int startingPosition = getPositionInLinearLayout(child);
- int padding = child.needsIncreasedPadding()
+ int padding = child.getIncreasedPaddingAmount() == 1.0f
? mIncreasedPaddingBetweenElements :
mPaddingBetweenElements;
int childHeight = getIntrinsicHeight(child) + padding;
@@ -552,7 +592,7 @@
mLastSetStackHeight = height;
setIsExpanded(height > 0.0f);
int newStackHeight = (int) height;
- int minStackHeight = getMinStackHeight();
+ int minStackHeight = getLayoutMinHeight();
int stackHeight;
float paddingOffset;
boolean trackingHeadsUp = mTrackingHeadsUp || mHeadsUpManager.hasPinnedHeadsUp();
@@ -565,20 +605,7 @@
stackHeight = newStackHeight;
} else {
int translationY;
- if (!trackingHeadsUp) {
- // We did not reach the position yet where we actually start growing,
- // so we translate the stack upwards.
- translationY = (newStackHeight - minStackHeight);
- // A slight parallax effect is introduced in order for the stack to catch up with
- // the top card.
- float partiallyThere = (newStackHeight - mTopPadding - mTopPaddingOverflow)
- / minStackHeight;
- partiallyThere = Math.max(0, partiallyThere);
- translationY += (1 - partiallyThere) * (mBottomStackPeekSize +
- mCollapseSecondCardPadding);
- } else {
- translationY = (int) (height - normalUnfoldPositionStart);
- }
+ translationY = newStackHeight - normalUnfoldPositionStart;
paddingOffset = translationY - mTopPadding;
stackHeight = (int) (height - (translationY - mTopPadding));
}
@@ -621,8 +648,8 @@
return mBottomStackPeekSize;
}
- public int getCollapseSecondCardPadding() {
- return mCollapseSecondCardPadding;
+ public int getBottomStackSlowDownHeight() {
+ return mBottomStackSlowDownHeight;
}
public void setLongPressListener(SwipeHelper.LongPressListener listener) {
@@ -630,6 +657,10 @@
mLongPressListener = listener;
}
+ public void setGearDisplayedListener(GearDisplayedListener listener) {
+ mGearDisplayedListener = listener;
+ }
+
public void setQsContainer(ViewGroup qsContainer) {
mQsContainer = qsContainer;
}
@@ -646,6 +677,7 @@
}
mSwipedOutViews.add(v);
mAmbientState.onDragFinished(v);
+ updateContinuousShadowDrawing();
if (v instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) v;
if (row.isHeadsUp()) {
@@ -666,8 +698,9 @@
}
@Override
- public void onChildSnappedBack(View animView) {
+ public void onChildSnappedBack(View animView, float targetLeft) {
mAmbientState.onDragFinished(animView);
+ updateContinuousShadowDrawing();
if (!mDragAnimPendingChildren.contains(animView)) {
if (mAnimationsEnabled) {
mSnappedBackChildren.add(animView);
@@ -678,6 +711,14 @@
// We start the swipe and snap back in the same frame, we don't want any animation
mDragAnimPendingChildren.remove(animView);
}
+
+ if (targetLeft == 0 && mCurrIconRow != null) {
+ mCurrIconRow.resetState();
+ mCurrIconRow = null;
+ if (mGearExposedView != null && mGearExposedView == mTranslatingParentView) {
+ mGearExposedView = null;
+ }
+ }
}
@Override
@@ -686,13 +727,14 @@
mScrimController.setTopHeadsUpDragAmount(animView,
Math.min(Math.abs(swipeProgress - 1.0f), 1.0f));
}
- return false;
+ return true; // Don't fade out the notification
}
public void onBeginDrag(View v) {
mFalsingManager.onNotificatonStartDismissing();
setSwipingInProgress(true);
mAmbientState.onBeginDrag(v);
+ updateContinuousShadowDrawing();
if (mAnimationsEnabled && (mIsExpanded || !isPinnedHeadsUp(v))) {
mDragAnimPendingChildren.add(v);
mNeedsAnimation = true;
@@ -726,8 +768,21 @@
return mPhoneStatusBar.isWakeUpComingFromTouch() ? 1.5f : 1.0f;
}
+ @Override
public View getChildAtPosition(MotionEvent ev) {
- return getChildAtPosition(ev.getX(), ev.getY());
+ View child = getChildAtPosition(ev.getX(), ev.getY());
+ if (child instanceof ExpandableNotificationRow) {
+ ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+ ExpandableNotificationRow parent = row.getNotificationParent();
+ if (mGearExposedView != null && parent != null
+ && parent.areChildrenExpanded() && mGearExposedView == parent) {
+ // In this case the group is expanded and showing the gear for the
+ // group, further interaction should apply to the group, not any
+ // child notifications so we use the parent of the child.
+ child = row.getNotificationParent();
+ }
+ }
+ return child;
}
public ExpandableView getClosestChildAtRawPosition(float touchX, float touchY) {
@@ -841,10 +896,6 @@
return mScrollingEnabled;
}
- public View getChildContentView(View v) {
- return v;
- }
-
public boolean canChildBeDismissed(View v) {
return StackScrollAlgorithm.canChildBeDismissed(v);
}
@@ -1462,18 +1513,18 @@
private void updateContentHeight() {
int height = 0;
- boolean previousNeedsIncreasedPaddings = false;
+ float previousIncreasedAmount = 0.0f;
for (int i = 0; i < getChildCount(); i++) {
ExpandableView expandableView = (ExpandableView) getChildAt(i);
if (expandableView.getVisibility() != View.GONE) {
- boolean needsIncreasedPaddings = expandableView.needsIncreasedPadding();
+ float increasedPaddingAmount = expandableView.getIncreasedPaddingAmount();
if (height != 0) {
- int padding = needsIncreasedPaddings || previousNeedsIncreasedPaddings
- ? mIncreasedPaddingBetweenElements
- : mPaddingBetweenElements;
- height += padding;
+ height += (int) NotificationUtils.interpolate(
+ mPaddingBetweenElements,
+ mIncreasedPaddingBetweenElements,
+ Math.max(previousIncreasedAmount, increasedPaddingAmount));
}
- previousNeedsIncreasedPaddings = needsIncreasedPaddings;
+ previousIncreasedAmount = increasedPaddingAmount;
height += expandableView.getIntrinsicHeight();
}
}
@@ -1744,8 +1795,12 @@
// it will be set once we reach the boundary
mMaxOverScroll = 0.0f;
}
+ int minScrollY = Math.max(0, scrollRange);
+ if (mExpandedInThisMotion) {
+ minScrollY = Math.min(minScrollY, mMaxScrollAfterExpand);
+ }
mScroller.fling(mScrollX, mOwnScrollY, 1, velocityY, 0, 0, 0,
- Math.max(0, scrollRange), 0, Integer.MAX_VALUE / 2);
+ minScrollY, 0, mExpandedInThisMotion && mOwnScrollY >= 0 ? 0 : Integer.MAX_VALUE / 2);
postInvalidateOnAnimation();
}
@@ -1776,7 +1831,7 @@
boolean ignoreIntrinsicPadding) {
float start = qsHeight;
float stackHeight = getHeight() - start;
- int minStackHeight = getMinStackHeight();
+ int minStackHeight = getLayoutMinHeight();
if (stackHeight <= minStackHeight) {
float overflow = minStackHeight - stackHeight;
stackHeight = minStackHeight;
@@ -1790,11 +1845,16 @@
setStackHeight(mLastSetStackHeight);
}
- public int getMinStackHeight() {
+ public int getLayoutMinHeight() {
final ExpandableView firstChild = getFirstChildNotGone();
- final int firstChildMinHeight = firstChild != null ? firstChild.getMinHeight()
+ int firstChildMinHeight = firstChild != null
+ ? firstChild.getIntrinsicHeight()
: mCollapsedSize;
- return firstChildMinHeight + mBottomStackPeekSize + mCollapseSecondCardPadding;
+ if (mOwnScrollY > 0) {
+ firstChildMinHeight = Math.max(firstChildMinHeight - mOwnScrollY, mCollapsedSize);
+ }
+ return Math.min(firstChildMinHeight + mBottomStackPeekSize + mBottomStackSlowDownHeight,
+ mMaxLayoutHeight - mTopPadding);
}
public float getTopPaddingOverflow() {
@@ -1806,7 +1866,7 @@
final int firstChildMinHeight = firstChild != null ? (int) firstChild.getMinHeight()
: mCollapsedSize;
return mIntrinsicPadding + firstChildMinHeight + mBottomStackPeekSize
- + mCollapseSecondCardPadding;
+ + mBottomStackSlowDownHeight;
}
private int clampPadding(int desiredPadding) {
@@ -1920,7 +1980,6 @@
}
private void onViewRemovedInternal(View child) {
- mStackScrollAlgorithm.notifyChildrenChanged(this);
if (mChangePositionInProgress) {
// This is only a position change, don't do anything special
return;
@@ -2028,9 +2087,10 @@
*/
private void updateScrollStateForRemovedChild(ExpandableView removedChild) {
int startingPosition = getPositionInLinearLayout(removedChild);
- int padding = removedChild.needsIncreasedPadding()
- ? mIncreasedPaddingBetweenElements :
- mPaddingBetweenElements;
+ int padding = (int) NotificationUtils.interpolate(
+ mPaddingBetweenElements,
+ mIncreasedPaddingBetweenElements,
+ removedChild.getIncreasedPaddingAmount());
int childHeight = getIntrinsicHeight(removedChild) + padding;
int endPosition = startingPosition + childHeight;
if (endPosition <= mOwnScrollY) {
@@ -2054,19 +2114,19 @@
private int getPositionInLinearLayout(View requestedChild) {
int position = 0;
- boolean previousNeedsIncreasedPaddings = false;
+ float previousIncreasedAmount = 0.0f;
for (int i = 0; i < getChildCount(); i++) {
ExpandableView child = (ExpandableView) getChildAt(i);
boolean notGone = child.getVisibility() != View.GONE;
if (notGone) {
- boolean needsIncreasedPaddings = child.needsIncreasedPadding();
+ float increasedPaddingAmount = child.getIncreasedPaddingAmount();
if (position != 0) {
- int padding = needsIncreasedPaddings || previousNeedsIncreasedPaddings
- ? mIncreasedPaddingBetweenElements :
- mPaddingBetweenElements;
- position += padding;
+ position += (int) NotificationUtils.interpolate(
+ mPaddingBetweenElements,
+ mIncreasedPaddingBetweenElements,
+ Math.max(previousIncreasedAmount, increasedPaddingAmount));
}
- previousNeedsIncreasedPaddings = needsIncreasedPaddings;
+ previousIncreasedAmount = increasedPaddingAmount;
}
if (child == requestedChild) {
return position;
@@ -2100,7 +2160,6 @@
private void onViewAddedInternal(View child) {
updateHideSensitiveForChild(child);
- mStackScrollAlgorithm.notifyChildrenChanged(this);
((ExpandableView) child).setOnHeightChangedListener(this);
generateAddAnimation(child, false /* fromMoreCard */);
updateAnimationState(child);
@@ -2205,6 +2264,7 @@
setAnimationRunning(true);
mAnimationEvents.clear();
updateBackground();
+ updateViewShadows();
} else {
applyCurrentState();
}
@@ -2567,12 +2627,8 @@
}
public int getEmptyBottomMargin() {
- int emptyMargin = mMaxLayoutHeight - mContentHeight - mBottomStackPeekSize;
- if (needsHeightAdaption()) {
- emptyMargin -= mBottomStackSlowDownHeight;
- } else {
- emptyMargin -= mCollapseSecondCardPadding;
- }
+ int emptyMargin = mMaxLayoutHeight - mContentHeight - mBottomStackPeekSize
+ - mBottomStackSlowDownHeight;
return Math.max(emptyMargin, 0);
}
@@ -2583,12 +2639,10 @@
public void onExpansionStarted() {
mIsExpansionChanging = true;
- mStackScrollAlgorithm.onExpansionStarted(mCurrentStackScrollState);
}
public void onExpansionStopped() {
mIsExpansionChanging = false;
- mStackScrollAlgorithm.onExpansionStopped();
if (!mIsExpanded) {
mOwnScrollY = 0;
@@ -2656,7 +2710,6 @@
if (mIsExpanded && mAnimationsEnabled) {
mRequestViewResizeAnimationOnLayout = true;
}
- mStackScrollAlgorithm.onReset(view);
updateAnimationState(view);
updateChronometerForChild(view);
}
@@ -2787,6 +2840,43 @@
}
runAnimationFinishedRunnables();
updateBackground();
+ updateViewShadows();
+ }
+
+ private void updateViewShadows() {
+ // we need to work around an issue where the shadow would not cast between siblings when
+ // their z difference is between 0 and 0.1
+
+ // Lefts first sort by Z difference
+ for (int i = 0; i < getChildCount(); i++) {
+ ExpandableView child = (ExpandableView) getChildAt(i);
+ if (child.getVisibility() != GONE) {
+ mTmpSortedChildren.add(child);
+ }
+ }
+ Collections.sort(mTmpSortedChildren, mViewPositionComparator);
+
+ // Now lets update the shadow for the views
+ ExpandableView previous = null;
+ for (int i = 0; i < mTmpSortedChildren.size(); i++) {
+ ExpandableView expandableView = mTmpSortedChildren.get(i);
+ float translationZ = expandableView.getTranslationZ();
+ float otherZ = previous == null ? translationZ : previous.getTranslationZ();
+ float diff = otherZ - translationZ;
+ if (diff <= 0.0f || diff >= FakeShadowView.SHADOW_SIBLING_TRESHOLD) {
+ // There is no fake shadow to be drawn
+ expandableView.setFakeShadowIntensity(0.0f, 0.0f, 0, 0);
+ } else {
+ float yLocation = previous.getTranslationY() + previous.getActualHeight() -
+ expandableView.getTranslationY();
+ expandableView.setFakeShadowIntensity(diff / FakeShadowView.SHADOW_SIBLING_TRESHOLD,
+ previous.getOutlineAlpha(), (int) yLocation,
+ previous.getOutlineTranslation());
+ }
+ previous = expandableView;
+ }
+
+ mTmpSortedChildren.clear();
}
public void goToFullShade(long delay) {
@@ -3008,6 +3098,9 @@
disableClipOptimization();
}
handleDismissAllClipping();
+ if (mCurrIconRow != null && mCurrIconRow.isVisible()) {
+ mCurrIconRow.getNotificationParent().animateTranslateNotification(0 /* left target */);
+ }
}
private void handleDismissAllClipping() {
@@ -3047,15 +3140,7 @@
}
public int getDismissViewHeight() {
- int height = mDismissView.getHeight() + mPaddingBetweenElements;
-
- // Hack: Accommodate for additional distance when we only have one notification and the
- // dismiss all button.
- if (getNotGoneChildCount() == 2 && getLastChildNotGone() == mDismissView
- && getFirstChildNotGone() instanceof ActivatableNotificationView) {
- height += mCollapseSecondCardPadding;
- }
- return height;
+ return mDismissView.getHeight() + mPaddingBetweenElements;
}
public int getEmptyShadeViewHeight() {
@@ -3222,6 +3307,7 @@
getViewTreeObserver().removeOnPreDrawListener(mBackgroundUpdater);
}
mAnimationRunning = animationRunning;
+ updateContinuousShadowDrawing();
}
}
@@ -3268,6 +3354,207 @@
public void flingTopOverscroll(float velocity, boolean open);
}
+ /**
+ * A listener that is notified when the gear is shown behind a notification.
+ */
+ public interface GearDisplayedListener {
+ void onGearDisplayed(ExpandableNotificationRow row);
+ }
+
+ private class NotificationSwipeHelper extends SwipeHelper {
+ private static final int MOVE_STATE_LEFT = -1;
+ private static final int MOVE_STATE_UNDEFINED = 0;
+ private static final int MOVE_STATE_RIGHT = 1;
+
+ private static final long GEAR_SHOW_DELAY = 60;
+
+ private CheckForDrag mCheckForDrag;
+ private Handler mHandler;
+ private int mMoveState = MOVE_STATE_UNDEFINED;
+
+ public NotificationSwipeHelper(int swipeDirection, Callback callback, Context context) {
+ super(swipeDirection, callback, context);
+ mHandler = new Handler();
+ }
+
+ @Override
+ public void onDownUpdate(View currView) {
+ // Set the active view
+ mTranslatingParentView = currView;
+
+ // Reset check for drag gesture
+ mCheckForDrag = null;
+ mCurrIconRow = null;
+
+ // Slide back any notifications that might be showing a gear
+ resetExposedGearView();
+
+ if (currView instanceof ExpandableNotificationRow) {
+ // Set the listener for the current row's gear
+ mCurrIconRow = ((ExpandableNotificationRow) currView).getSettingsRow();
+ mCurrIconRow.setGearListener(NotificationStackScrollLayout.this);
+ }
+ mMoveState = MOVE_STATE_UNDEFINED;
+ }
+
+ @Override
+ public void onMoveUpdate(View view, float translation, float delta) {
+ final int newMoveState = (delta < 0) ? MOVE_STATE_RIGHT : MOVE_STATE_LEFT;
+ if (mMoveState != MOVE_STATE_UNDEFINED && mMoveState != newMoveState) {
+ // Changed directions, make sure we check for drag again.
+ mCheckForDrag = null;
+ }
+ mMoveState = newMoveState;
+
+ final boolean gutsExposed = (view instanceof ExpandableNotificationRow)
+ && ((ExpandableNotificationRow) view).areGutsExposed();
+
+ if (!isPinnedHeadsUp(view) && !gutsExposed) {
+ // Only show the gear if we're not a heads up view and guts aren't exposed.
+ checkForDrag();
+ }
+ }
+
+ @Override
+ public void dismissChild(final View view, float velocity) {
+ cancelCheckForDrag();
+ super.dismissChild(view, velocity);
+ }
+
+ @Override
+ public void snapChild(final View animView, final float targetLeft, float velocity) {
+ final float snapBackThreshold = getSpaceForGear(animView);
+ final float translation = getTranslation(animView);
+ final boolean fromLeft = translation > 0;
+ final float absTrans = Math.abs(translation);
+ final float notiThreshold = getSize(mTranslatingParentView) * 0.4f;
+
+ boolean pastGear = (fromLeft && translation >= snapBackThreshold * 0.4f
+ && translation <= notiThreshold) ||
+ (!fromLeft && absTrans >= snapBackThreshold * 0.4f
+ && absTrans <= notiThreshold);
+
+ if (pastGear && !isPinnedHeadsUp(animView)
+ && (animView instanceof ExpandableNotificationRow)) {
+ // bouncity
+ final float target = fromLeft ? snapBackThreshold : -snapBackThreshold;
+ mGearExposedView = mTranslatingParentView;
+ if (mGearDisplayedListener != null) {
+ mGearDisplayedListener.onGearDisplayed((ExpandableNotificationRow) animView);
+ }
+ super.snapChild(animView, target, velocity);
+ } else {
+ super.snapChild(animView, 0, velocity);
+ }
+ }
+
+ @Override
+ public Animator getViewTranslationAnimator(View v, float target,
+ AnimatorUpdateListener listener) {
+ if (mDismissAllInProgress) {
+ // When dismissing all, we translate the entire view instead.
+ return super.getViewTranslationAnimator(v, target, listener);
+ } else if (v instanceof ExpandableNotificationRow) {
+ return ((ExpandableNotificationRow) v).getTranslateViewAnimator(target, listener);
+ } else {
+ return super.getViewTranslationAnimator(v, target, listener);
+ }
+ }
+
+ @Override
+ public void setTranslation(View v, float translate) {
+ if (mDismissAllInProgress) {
+ // When dismissing all, we translate the entire view instead.
+ super.setTranslation(v, translate);
+ } else {
+ ((ExpandableView) v).setTranslation(translate);
+ }
+ }
+
+ @Override
+ public float getTranslation(View v) {
+ if (mDismissAllInProgress) {
+ // When dismissing all, we translate the entire view instead.
+ return super.getTranslation(v);
+ } else {
+ return ((ExpandableView) v).getTranslation();
+ }
+ }
+
+ /**
+ * Returns the horizontal space in pixels required to display the gear behind a
+ * notification.
+ */
+ private float getSpaceForGear(View view) {
+ if (view instanceof ExpandableNotificationRow) {
+ return ((ExpandableNotificationRow) view).getSpaceForGear();
+ }
+ return 0;
+ }
+
+ private void checkForDrag() {
+ if (mCheckForDrag == null) {
+ mCheckForDrag = new CheckForDrag();
+ mHandler.postDelayed(mCheckForDrag, GEAR_SHOW_DELAY);
+ }
+ }
+
+ private void cancelCheckForDrag() {
+ if (mCurrIconRow != null) {
+ mCurrIconRow.cancelFadeAnimator();
+ }
+ mHandler.removeCallbacks(mCheckForDrag);
+ mCheckForDrag = null;
+ }
+
+ private final class CheckForDrag implements Runnable {
+ @Override
+ public void run() {
+ final float translation = getTranslation(mTranslatingParentView);
+ final float absTransX = Math.abs(translation);
+ final float bounceBackToGearWidth = getSpaceForGear(mTranslatingParentView);
+ final float notiThreshold = getSize(mTranslatingParentView) * 0.4f;
+ if (mCurrIconRow != null && absTransX >= bounceBackToGearWidth * 0.4
+ && absTransX < notiThreshold) {
+ // Show icon
+ mCurrIconRow.fadeInSettings(translation > 0 /* fromLeft */, translation,
+ notiThreshold);
+ } else {
+ // Allow more to be posted if this wasn't a drag.
+ mCheckForDrag = null;
+ }
+ }
+ }
+
+ private void resetExposedGearView() {
+ if (mGearExposedView == null || mGearExposedView == mTranslatingParentView) {
+ // If no gear is showing or it's showing for this view we do nothing.
+ return;
+ }
+
+ final View prevGearExposedView = mGearExposedView;
+ mGearExposedView = null;
+
+ Animator anim = getViewTranslationAnimator(prevGearExposedView,
+ 0 /* leftTarget */, null /* updateListener */);
+ if (anim != null) {
+ anim.start();
+ }
+ }
+ }
+
+ private void updateContinuousShadowDrawing() {
+ boolean continuousShadowUpdate = mAnimationRunning
+ || !mAmbientState.getDraggedViews().isEmpty();
+ if (continuousShadowUpdate != mContinuousShadowUpdate) {
+ if (continuousShadowUpdate) {
+ getViewTreeObserver().addOnPreDrawListener(mShadowUpdater);
+ } else {
+ getViewTreeObserver().removeOnPreDrawListener(mShadowUpdater);
+ }
+ }
+ }
+
static class AnimationEvent {
static AnimationFilter[] FILTERS = new AnimationFilter[] {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index e87b363..4c94fe9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -24,9 +24,11 @@
import com.android.systemui.R;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.ExpandableView;
+import com.android.systemui.statusbar.notification.FakeShadowView;
+import com.android.systemui.statusbar.notification.NotificationUtils;
import java.util.ArrayList;
-import java.util.HashSet;
+import java.util.HashMap;
import java.util.List;
/**
@@ -50,13 +52,8 @@
private StackIndentationFunctor mBottomStackIndentationFunctor;
private StackScrollAlgorithmState mTempAlgorithmState = new StackScrollAlgorithmState();
- private boolean mIsExpansionChanging;
- private int mFirstChildMaxHeight;
private boolean mIsExpanded;
- private ExpandableView mFirstChildWhileExpanding;
- private boolean mExpandedOnStart;
private int mBottomStackSlowDownLength;
- private int mCollapseSecondCardPadding;
public StackScrollAlgorithm(Context context) {
initView(context);
@@ -84,8 +81,6 @@
mZBasicHeight = (MAX_ITEMS_IN_BOTTOM_STACK + 1) * mZDistanceBetweenElements;
mBottomStackSlowDownLength = context.getResources()
.getDimensionPixelSize(R.dimen.bottom_stack_slow_down_length);
- mCollapseSecondCardPadding = context.getResources().getDimensionPixelSize(
- R.dimen.notification_collapse_second_card_padding);
mBottomStackIndentationFunctor = new PiecewiseLinearIndentationFunctor(
MAX_ITEMS_IN_BOTTOM_STACK,
mBottomStackPeekSize,
@@ -296,18 +291,22 @@
int childCount = hostView.getChildCount();
state.visibleChildren.clear();
state.visibleChildren.ensureCapacity(childCount);
- state.increasedPaddingSet.clear();
+ state.increasedPaddingMap.clear();
int notGoneIndex = 0;
ExpandableView lastView = null;
for (int i = 0; i < childCount; i++) {
ExpandableView v = (ExpandableView) hostView.getChildAt(i);
if (v.getVisibility() != View.GONE) {
notGoneIndex = updateNotGoneIndex(resultState, state, notGoneIndex, v);
- boolean needsIncreasedPadding = v.needsIncreasedPadding();
- if (needsIncreasedPadding) {
- state.increasedPaddingSet.add(v);
+ float increasedPadding = v.getIncreasedPaddingAmount();
+ if (increasedPadding != 0.0f) {
+ state.increasedPaddingMap.put(v, increasedPadding);
if (lastView != null) {
- state.increasedPaddingSet.add(lastView);
+ Float prevValue = state.increasedPaddingMap.get(lastView);
+ float newValue = prevValue != null
+ ? Math.max(prevValue, increasedPadding)
+ : increasedPadding;
+ state.increasedPaddingMap.put(lastView, newValue);
}
}
if (v instanceof ExpandableNotificationRow) {
@@ -422,9 +421,12 @@
private int getPaddingAfterChild(StackScrollAlgorithmState algorithmState,
ExpandableView child) {
- return algorithmState.increasedPaddingSet.contains(child)
- ? mIncreasedPaddingBetweenElements
- : mPaddingBetweenElements;
+ Float paddingValue = algorithmState.increasedPaddingMap.get(child);
+ return paddingValue == null
+ ? mPaddingBetweenElements
+ : (int) NotificationUtils.interpolate(mPaddingBetweenElements,
+ mIncreasedPaddingBetweenElements,
+ paddingValue);
}
private void updateHeadsUpStates(StackScrollState resultState,
@@ -499,7 +501,7 @@
int childHeight, int minHeight, AmbientState ambientState) {
int bottomStackStart = ambientState.getInnerHeight()
- - mBottomStackPeekSize - mCollapseSecondCardPadding;
+ - mBottomStackPeekSize - mBottomStackSlowDownLength;
int childStart = bottomStackStart - childHeight;
if (childStart < childViewState.yTranslation) {
float newHeight = bottomStackStart - childViewState.yTranslation;
@@ -586,12 +588,9 @@
// The starting position of the bottom stack peek
int bottomPeekStart = ambientState.getInnerHeight() - mBottomStackPeekSize -
- mCollapseSecondCardPadding + ambientState.getScrollY();
+ mBottomStackSlowDownLength + ambientState.getScrollY();
// Collapse and expand the first child while the shade is being expanded
- float maxHeight = mIsExpansionChanging && child == mFirstChildWhileExpanding
- ? mFirstChildMaxHeight
- : childHeight;
- childViewState.height = (int) Math.max(Math.min(bottomPeekStart, maxHeight),
+ childViewState.height = (int) Math.max(Math.min(bottomPeekStart, (float) childHeight),
child.getMinHeight());
}
@@ -605,20 +604,40 @@
private void updateZValuesForState(StackScrollState resultState,
StackScrollAlgorithmState algorithmState, AmbientState ambientState) {
int childCount = algorithmState.visibleChildren.size();
- int childrenOnTop = 0;
+ float childrenOnTop = 0.0f;
for (int i = childCount - 1; i >= 0; i--) {
ExpandableView child = algorithmState.visibleChildren.get(i);
StackViewState childViewState = resultState.getViewStateForView(child);
if (i > (childCount - 1 - algorithmState.itemsInBottomStack)) {
// We are in the bottom stack
float numItemsAbove = i - (childCount - 1 - algorithmState.itemsInBottomStack);
- childViewState.zTranslation = mZBasicHeight
- - numItemsAbove * mZDistanceBetweenElements;
+ float zSubtraction;
+ if (numItemsAbove <= 1.0f) {
+ float factor = 0.2f;
+ // Lets fade in slower to the threshold to make the shadow fade in look nicer
+ if (numItemsAbove <= factor) {
+ zSubtraction = FakeShadowView.SHADOW_SIBLING_TRESHOLD
+ * numItemsAbove * (1.0f / factor);
+ } else {
+ zSubtraction = FakeShadowView.SHADOW_SIBLING_TRESHOLD
+ + (numItemsAbove - factor) * (1.0f / (1.0f - factor))
+ * (mZDistanceBetweenElements
+ - FakeShadowView.SHADOW_SIBLING_TRESHOLD);
+ }
+ } else {
+ zSubtraction = numItemsAbove * mZDistanceBetweenElements;
+ }
+ childViewState.zTranslation = mZBasicHeight - zSubtraction;
} else if (child.mustStayOnScreen()
&& childViewState.yTranslation < ambientState.getTopPadding()
+ ambientState.getStackTranslation()) {
- // TODO; do this more cleanly
- childrenOnTop++;
+ if (childrenOnTop != 0.0f) {
+ childrenOnTop++;
+ } else {
+ float overlap = ambientState.getTopPadding()
+ + ambientState.getStackTranslation() - childViewState.yTranslation;
+ childrenOnTop += Math.min(1.0f, overlap / childViewState.height);
+ }
childViewState.zTranslation = mZBasicHeight
+ childrenOnTop * mZDistanceBetweenElements;
} else {
@@ -627,55 +646,6 @@
}
}
- public void onExpansionStarted(StackScrollState currentState) {
- mIsExpansionChanging = true;
- mExpandedOnStart = mIsExpanded;
- ViewGroup hostView = currentState.getHostView();
- updateFirstChildHeightWhileExpanding(hostView);
- }
-
- private void updateFirstChildHeightWhileExpanding(ViewGroup hostView) {
- mFirstChildWhileExpanding = (ExpandableView) findFirstVisibleChild(hostView);
- if (mFirstChildWhileExpanding != null) {
- if (mExpandedOnStart) {
-
- // We are collapsing the shade, so the first child can get as most as high as the
- // current height or the end value of the animation.
- mFirstChildMaxHeight = StackStateAnimator.getFinalActualHeight(
- mFirstChildWhileExpanding);
- } else {
- updateFirstChildMaxSizeToMaxHeight();
- }
- } else {
- mFirstChildMaxHeight = 0;
- }
- }
-
- private void updateFirstChildMaxSizeToMaxHeight() {
- // We are expanding the shade, expand it to its full height.
- if (!isMaxSizeInitialized(mFirstChildWhileExpanding)) {
-
- // This child was not layouted yet, wait for a layout pass
- mFirstChildWhileExpanding
- .addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
- @Override
- public void onLayoutChange(View v, int left, int top, int right,
- int bottom, int oldLeft, int oldTop, int oldRight,
- int oldBottom) {
- if (mFirstChildWhileExpanding != null) {
- mFirstChildMaxHeight = getMaxAllowedChildHeight(
- mFirstChildWhileExpanding);
- } else {
- mFirstChildMaxHeight = 0;
- }
- v.removeOnLayoutChangeListener(this);
- }
- });
- } else {
- mFirstChildMaxHeight = getMaxAllowedChildHeight(mFirstChildWhileExpanding);
- }
- }
-
private boolean isMaxSizeInitialized(ExpandableView child) {
if (child instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
@@ -695,32 +665,10 @@
return null;
}
- public void onExpansionStopped() {
- mIsExpansionChanging = false;
- mFirstChildWhileExpanding = null;
- }
-
public void setIsExpanded(boolean isExpanded) {
this.mIsExpanded = isExpanded;
}
- public void notifyChildrenChanged(final NotificationStackScrollLayout hostView) {
- if (mIsExpansionChanging) {
- hostView.post(new Runnable() {
- @Override
- public void run() {
- updateFirstChildHeightWhileExpanding(hostView);
- }
- });
- }
- }
-
- public void onReset(ExpandableView view) {
- if (view.equals(mFirstChildWhileExpanding)) {
- updateFirstChildMaxSizeToMaxHeight();
- }
- }
-
class StackScrollAlgorithmState {
/**
@@ -744,9 +692,10 @@
public final ArrayList<ExpandableView> visibleChildren = new ArrayList<ExpandableView>();
/**
- * The children from the host that need an increased padding after them.
+ * The children from the host that need an increased padding after them. A value of 0 means
+ * no increased padding, a value of 1 means full padding.
*/
- public final HashSet<ExpandableView> increasedPaddingSet = new HashSet<>();
+ public final HashMap<ExpandableView, Float> increasedPaddingMap = new HashMap<>();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 110258c..2524e1a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -116,11 +116,16 @@
}
@Override
+ protected boolean toggleSplitScreenMode() {
+ return false;
+ }
+
+ @Override
public void maybeEscalateHeadsUp() {
}
@Override
- protected boolean isPanelFullyCollapsed() {
+ public boolean isPanelFullyCollapsed() {
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java
new file mode 100644
index 0000000..8881c79
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.tuner;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.support.v7.preference.DropDownPreference;
+import android.text.TextUtils;
+import android.util.ArraySet;
+import android.util.AttributeSet;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+
+import static com.android.systemui.BatteryMeterDrawable.SHOW_PERCENT_SETTING;
+
+public class BatteryPreference extends DropDownPreference implements TunerService.Tunable {
+
+ private static final String PERCENT = "percent";
+ private static final String DEFAULT = "default";
+ private static final String DISABLED = "disabled";
+
+ private final String mBattery;
+ private boolean mBatteryEnabled;
+ private boolean mHasPercentage;
+ private ArraySet<String> mBlacklist;
+ private boolean mHasSetValue;
+
+ public BatteryPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mBattery = context.getString(com.android.internal.R.string.status_bar_battery);
+ setEntryValues(new CharSequence[] {PERCENT, DEFAULT, DISABLED });
+ }
+
+ @Override
+ public void onAttached() {
+ super.onAttached();
+ TunerService.get(getContext()).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
+ mHasPercentage = Settings.System.getInt(getContext().getContentResolver(),
+ SHOW_PERCENT_SETTING, 0) != 0;
+ }
+
+ @Override
+ public void onDetached() {
+ TunerService.get(getContext()).removeTunable(this);
+ super.onDetached();
+ }
+
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ if (StatusBarIconController.ICON_BLACKLIST.equals(key)) {
+ mBlacklist = StatusBarIconController.getIconBlacklist(newValue);
+ mBatteryEnabled = !mBlacklist.contains(mBattery);
+ }
+ if (!mHasSetValue) {
+ // Because of the complicated tri-state it can end up looping and setting state back to
+ // what the user didn't choose. To avoid this, just set the state once and rely on the
+ // preference to handle updates.
+ mHasSetValue = true;
+ if (mBatteryEnabled && mHasPercentage) {
+ setValue(PERCENT);
+ } else if (mBatteryEnabled) {
+ setValue(DEFAULT);
+ } else {
+ setValue(DISABLED);
+ }
+ }
+ }
+
+ @Override
+ protected boolean persistString(String value) {
+ final boolean v = PERCENT.equals(value);
+ MetricsLogger.action(getContext(), MetricsEvent.TUNER_BATTERY_PERCENTAGE, v);
+ Settings.System.putInt(getContext().getContentResolver(), SHOW_PERCENT_SETTING, v ? 1 : 0);
+ if (DISABLED.equals(value)) {
+ mBlacklist.add(mBattery);
+ } else {
+ mBlacklist.remove(mBattery);
+ }
+ TunerService.get(getContext()).setValue(StatusBarIconController.ICON_BLACKLIST,
+ TextUtils.join(",", mBlacklist));
+ return true;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/CalibratePreference.java b/packages/SystemUI/src/com/android/systemui/tuner/CalibratePreference.java
new file mode 100644
index 0000000..ff7be13
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/CalibratePreference.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.tuner;
+
+import android.content.Context;
+import android.support.v7.preference.DialogPreference;
+import android.util.AttributeSet;
+
+public class CalibratePreference extends DialogPreference {
+ public CalibratePreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java
new file mode 100644
index 0000000..ea92443
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+package com.android.systemui.tuner;
+
+import android.content.Context;
+import android.support.v7.preference.DropDownPreference;
+import android.text.TextUtils;
+import android.util.ArraySet;
+import android.util.AttributeSet;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.policy.Clock;
+
+public class ClockPreference extends DropDownPreference implements TunerService.Tunable {
+
+ private static final String SECONDS = "seconds";
+ private static final String DEFAULT = "default";
+ private static final String DISABLED = "disabled";
+
+ private final String mClock;
+ private boolean mClockEnabled;
+ private boolean mHasSeconds;
+ private ArraySet<String> mBlacklist;
+ private boolean mHasSetValue;
+
+ public ClockPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mClock = context.getString(com.android.internal.R.string.status_bar_clock);
+ setEntryValues(new CharSequence[] { SECONDS, DEFAULT, DISABLED });
+ }
+
+ @Override
+ public void onAttached() {
+ super.onAttached();
+ TunerService.get(getContext()).addTunable(this, StatusBarIconController.ICON_BLACKLIST,
+ Clock.CLOCK_SECONDS);
+ }
+
+ @Override
+ public void onDetached() {
+ TunerService.get(getContext()).removeTunable(this);
+ super.onDetached();
+ }
+
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ if (StatusBarIconController.ICON_BLACKLIST.equals(key)) {
+ mBlacklist = StatusBarIconController.getIconBlacklist(newValue);
+ mClockEnabled = !mBlacklist.contains(mClock);
+ } else if (Clock.CLOCK_SECONDS.equals(key)) {
+ mHasSeconds = newValue != null && Integer.parseInt(newValue) != 0;
+ }
+ if (!mHasSetValue) {
+ // Because of the complicated tri-state it can end up looping and setting state back to
+ // what the user didn't choose. To avoid this, just set the state once and rely on the
+ // preference to handle updates.
+ mHasSetValue = true;
+ if (mClockEnabled && mHasSeconds) {
+ setValue(SECONDS);
+ } else if (mClockEnabled) {
+ setValue(DEFAULT);
+ } else {
+ setValue(DISABLED);
+ }
+ }
+ }
+
+ @Override
+ protected boolean persistString(String value) {
+ TunerService.get(getContext()).setValue(Clock.CLOCK_SECONDS, SECONDS.equals(value) ? 1 : 0);
+ if (DISABLED.equals(value)) {
+ mBlacklist.add(mClock);
+ } else {
+ mBlacklist.remove(mClock);
+ }
+ TunerService.get(getContext()).setValue(StatusBarIconController.ICON_BLACKLIST,
+ TextUtils.join(",", mBlacklist));
+ return true;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ColorAndAppearanceFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/ColorAndAppearanceFragment.java
new file mode 100644
index 0000000..af95cf9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/ColorAndAppearanceFragment.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.tuner;
+
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.provider.Settings.Secure;
+import android.support.v14.preference.PreferenceFragment;
+import android.support.v7.preference.Preference;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.SeekBar;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.NightModeController;
+
+public class ColorAndAppearanceFragment extends PreferenceFragment {
+
+ private static final String KEY_CALIBRATE = "calibrate";
+
+ private static final long RESET_DELAY = 10000;
+ private static final CharSequence KEY_NIGHT_MODE = "night_mode";
+
+ private NightModeController mNightModeController;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mNightModeController = new NightModeController(getContext());
+ }
+
+ @Override
+ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+ addPreferencesFromResource(R.xml.color_and_appearance);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ MetricsLogger.visibility(getContext(), MetricsEvent.TUNER_COLOR_AND_APPEARANCE, true);
+ // TODO: Figure out better title model for Tuner, to avoid any more of this.
+ getActivity().setTitle(R.string.color_and_appearance);
+
+ Preference nightMode = findPreference(KEY_NIGHT_MODE);
+ nightMode.setSummary(mNightModeController.isEnabled()
+ ? R.string.night_mode_on : R.string.night_mode_off);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ MetricsLogger.visibility(getContext(), MetricsEvent.TUNER_COLOR_AND_APPEARANCE, false);
+ }
+
+ @Override
+ public void onDisplayPreferenceDialog(Preference preference) {
+ if (preference instanceof CalibratePreference) {
+ CalibrateDialog.show(this);
+ } else {
+ super.onDisplayPreferenceDialog(preference);
+ }
+ }
+
+ private void startRevertTimer() {
+ getView().postDelayed(mResetColorMatrix, RESET_DELAY);
+ }
+
+ private void onApply() {
+ MetricsLogger.action(getContext(), MetricsEvent.ACTION_TUNER_CALIBRATE_DISPLAY_CHANGED);
+ mNightModeController.setCustomValues(Settings.Secure.getString(
+ getContext().getContentResolver(), Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX));
+ getView().removeCallbacks(mResetColorMatrix);
+ }
+
+ private void onRevert() {
+ getView().removeCallbacks(mResetColorMatrix);
+ mResetColorMatrix.run();
+ }
+
+ private final Runnable mResetColorMatrix = new Runnable() {
+ @Override
+ public void run() {
+ ((DialogFragment) getFragmentManager().findFragmentByTag("RevertWarning")).dismiss();
+ Settings.Secure.putString(getContext().getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, null);
+ }
+ };
+
+ public static class CalibrateDialog extends DialogFragment implements
+ DialogInterface.OnClickListener {
+ private float[] mValues;
+ private NightModeController mNightModeController;
+
+ public static void show(ColorAndAppearanceFragment fragment) {
+ CalibrateDialog dialog = new CalibrateDialog();
+ dialog.setTargetFragment(fragment, 0);
+ dialog.show(fragment.getFragmentManager(), "Calibrate");
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mNightModeController = new NightModeController(getContext());
+ String customValues = mNightModeController.getCustomValues();
+ if (customValues == null) {
+ // Generate this as a string because its the easiest way to generate a copy of the
+ // identity.
+ customValues = NightModeController.toString(NightModeController.IDENTITY_MATRIX);
+ }
+ mValues = NightModeController.toValues(customValues);
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ View v = LayoutInflater.from(getContext()).inflate(R.layout.calibrate_sliders, null);
+ bindView(v.findViewById(R.id.r_group), 0);
+ bindView(v.findViewById(R.id.g_group), 5);
+ bindView(v.findViewById(R.id.b_group), 10);
+ MetricsLogger.visible(getContext(), MetricsEvent.TUNER_CALIBRATE_DISPLAY);
+ return new AlertDialog.Builder(getContext())
+ .setTitle(R.string.calibrate_display)
+ .setView(v)
+ .setPositiveButton(R.string.color_apply, this)
+ .setNegativeButton(android.R.string.cancel, null)
+ .create();
+ }
+
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ super.onDismiss(dialog);
+ MetricsLogger.hidden(getContext(), MetricsEvent.TUNER_CALIBRATE_DISPLAY);
+ }
+
+ private void bindView(View view, final int index) {
+ SeekBar seekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar);
+ seekBar.setMax(1000);
+ seekBar.setProgress((int) (1000 * mValues[index]));
+ seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ mValues[index] = progress / 1000f;
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ }
+ });
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (mValues[0] == 1 && mValues[5] == 1 && mValues[10] == 1) {
+ // Allow removal of matrix by all values set to highest.
+ mNightModeController.setCustomValues(null);
+ return;
+ }
+ ((ColorAndAppearanceFragment) getTargetFragment()).startRevertTimer();
+ Settings.Secure.putString(getContext().getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX,
+ NightModeController.toString(mValues));
+ RevertWarning.show((ColorAndAppearanceFragment) getTargetFragment());
+ }
+ }
+
+ public static class RevertWarning extends DialogFragment
+ implements DialogInterface.OnClickListener {
+
+ public static void show(ColorAndAppearanceFragment fragment) {
+ RevertWarning warning = new RevertWarning();
+ warning.setTargetFragment(fragment, 0);
+ warning.show(fragment.getFragmentManager(), "RevertWarning");
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ AlertDialog alertDialog = new AlertDialog.Builder(getContext())
+ .setTitle(R.string.color_revert_title)
+ .setMessage(R.string.color_revert_message)
+ .setPositiveButton(R.string.ok, this)
+ .create();
+ alertDialog.setCanceledOnTouchOutside(true);
+ return alertDialog;
+ }
+
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ super.onCancel(dialog);
+ ((ColorAndAppearanceFragment) getTargetFragment()).onRevert();
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ ((ColorAndAppearanceFragment) getTargetFragment()).onApply();
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixFragment.java
deleted file mode 100644
index dfacd03..0000000
--- a/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixFragment.java
+++ /dev/null
@@ -1,341 +0,0 @@
-/**
- * Copyright (c) 2015, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.tuner;
-
-import android.annotation.Nullable;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import android.provider.Settings;
-import android.support.v14.preference.PreferenceFragment;
-import android.support.v14.preference.SwitchPreference;
-import android.support.v7.preference.DropDownPreference;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceViewHolder;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.SeekBar;
-import android.widget.Switch;
-
-import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.QSTileHost;
-import com.android.systemui.statusbar.policy.DisplayController;
-
-import java.util.Objects;
-
-public class ColorMatrixFragment extends PreferenceFragment implements TunerService.Tunable {
-
- private static final String TAG = "ColorMatrixFragment";
-
- private static final long RESET_DELAY = 10000;
-
- private boolean mCustomEnabled;
- private DropDownPreference mSelectPreference;
- private String mCurrentValue;
- private String mCustomValues;
- private SwitchPreference mEnableCustomPreference;
- private MatrixPreference mCustomPreference;
- private int mState;
- private Switch mSwitch;
-
- @Override
- public void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- Context context = getContext();
- TunerService.get(context).addTunable(this, DisplayController.COLOR_MATRIX_CUSTOM_ENABLED,
- DisplayController.COLOR_MATRIX_CUSTOM_VALUES, DisplayController.COLOR_STATE,
- Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX);
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- final View view = LayoutInflater.from(getContext()).inflate(
- R.layout.color_matrix_settings, container, false);
- ((ViewGroup) view).addView(super.onCreateView(inflater, container, savedInstanceState));
- return view;
- }
-
- @Override
- public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
- final Context context = getPreferenceManager().getContext();
- setPreferenceScreen(getPreferenceManager().createPreferenceScreen(context));
-
- mSelectPreference = new DropDownPreference(context);
- mSelectPreference.setTitle(R.string.color_transform);
- mSelectPreference.setSummary("%s");
- mSelectPreference.setOnPreferenceChangeListener(
- new Preference.OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- if (Objects.equals(newValue, DisplayController.AUTO_STRING)) {
- Settings.Secure.putInt(context.getContentResolver(),
- DisplayController.COLOR_STATE,
- DisplayController.COLOR_STATE_AUTO);
- return true;
- }
- if (Objects.equals(newValue, DisplayController.NONE_STRING)) {
- Settings.Secure.putString(context.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, null);
- return true;
- }
- Settings.Secure.putInt(context.getContentResolver(),
- DisplayController.COLOR_STATE,
- DisplayController.COLOR_STATE_ENABLED);
- final String value = (String) newValue;
- Settings.Secure.putString(context.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX,
- value);
- return true;
- }
- });
- getPreferenceScreen().addPreference(mSelectPreference);
-
- mEnableCustomPreference = new SwitchPreference(context);
- mEnableCustomPreference.setTitle(R.string.color_enable_custom);
- mEnableCustomPreference.setOnPreferenceChangeListener(
- new Preference.OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- boolean enabled = (Boolean) newValue;
- if (!enabled && Objects.equals(mCurrentValue, mCustomValues)) {
- Settings.Secure.putString(context.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, null);
- }
- Settings.Secure.putInt(context.getContentResolver(),
- DisplayController.COLOR_MATRIX_CUSTOM_ENABLED, enabled ? 1 : 0);
- return true;
- }
- });
- getPreferenceScreen().addPreference(mEnableCustomPreference);
-
- mCustomPreference = new MatrixPreference(context);
- getPreferenceScreen().addPreference(mCustomPreference);
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- View switchBar = view.findViewById(R.id.switch_bar);
- mSwitch = (Switch) switchBar.findViewById(android.R.id.switch_widget);
- mSwitch.setChecked(mState != DisplayController.COLOR_STATE_DISABLED);
- switchBar.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- int newState = mState != DisplayController.COLOR_STATE_DISABLED
- ? DisplayController.COLOR_STATE_DISABLED
- : DisplayController.COLOR_STATE_ENABLED;
- ContentResolver contentResolver = getContext().getContentResolver();
- if (newState == DisplayController.COLOR_STATE_DISABLED) {
- String tiles = Settings.Secure.getString(contentResolver,
- QSTileHost.TILES_SETTING);
- if (tiles != null) {
- if (tiles.contains(",colors")) {
- tiles = tiles.replace(",colors", "");
- } else if (tiles.contains("colors,")) {
- tiles = tiles.replace("colors,", "");
- }
- Settings.Secure.putString(contentResolver, QSTileHost.TILES_SETTING,
- tiles);
- }
- }
- Settings.Secure.putInt(contentResolver,
- DisplayController.COLOR_STATE, newState);
- }
- });
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- TunerService.get(getContext()).removeTunable(this);
- }
-
- @Override
- public void onTuningChanged(String key, String newValue) {
- if (DisplayController.COLOR_MATRIX_CUSTOM_ENABLED.equals(key)) {
- mCustomEnabled = newValue != null && Integer.parseInt(newValue) != 0;
- mEnableCustomPreference.setChecked(mCustomEnabled);
- mCustomPreference.setEnabled(mCustomEnabled
- && mState != DisplayController.COLOR_STATE_DISABLED);
- updateSelectOptions();
- } else if (DisplayController.COLOR_MATRIX_CUSTOM_VALUES.equals(key)) {
- mCustomValues = newValue;
- if (mCustomValues == null) {
- mCustomValues = DisplayController.toString(DisplayController.IDENTITY_MATRIX);
- }
- mCustomPreference.setValues(mCustomValues);
- updateSelectOptions();
- } else if (DisplayController.COLOR_STATE.equals(key)) {
- mState = newValue != null ? Integer.parseInt(newValue) : 0;
- if (mSwitch != null) {
- mSwitch.setChecked(mState != DisplayController.COLOR_STATE_DISABLED);
- }
- mSelectPreference.setEnabled(mState != DisplayController.COLOR_STATE_DISABLED);
- mEnableCustomPreference.setEnabled(mState != DisplayController.COLOR_STATE_DISABLED);
- mCustomPreference.setEnabled(mCustomEnabled
- && mState != DisplayController.COLOR_STATE_DISABLED);
- } else {
- mCurrentValue = newValue;
- updateSelectOptions();
- }
- }
-
- private void updateSelectOptions() {
- final int N = DisplayController.CUSTOM_INDEX + (mCustomEnabled ? 1 : 0);
- String[] values = new String[N];
- CharSequence[] names = new CharSequence[N];
- CharSequence[] totalNames = DisplayController.getColorTitles(getContext());
- String[] entries = DisplayController.getColorTransforms(getContext());
- entries[DisplayController.CUSTOM_INDEX] = mCustomValues != null ? mCustomValues : "";
- for (int i = 0; i < N; i++) {
- values[i] = entries[i];
- names[i] = totalNames[i];
- }
- mSelectPreference.setEntries(names);
- mSelectPreference.setEntryValues(values);
- int index = 0;
- if (mState == DisplayController.COLOR_STATE_AUTO) {
- index = DisplayController.AUTO_INDEX;
- } else if (mCustomValues != null && Objects.equals(mCurrentValue, mCustomValues)) {
- index = DisplayController.CUSTOM_INDEX;
- } else if (Objects.equals(mCurrentValue, entries[1])) {
- index = 1;
- }
- mSelectPreference.setValueIndex(index);
- mSelectPreference.setSummary("%s");
- return;
- }
-
- private void startRevertTimer() {
- getView().postDelayed(mResetColorMatrix, RESET_DELAY);
- }
-
- private void onApply() {
- Settings.Secure.putString(getContext().getContentResolver(),
- DisplayController.COLOR_MATRIX_CUSTOM_VALUES, mCurrentValue);
- getView().removeCallbacks(mResetColorMatrix);
- }
-
- private void onRevert() {
- getView().removeCallbacks(mResetColorMatrix);
- mResetColorMatrix.run();
- }
-
- private final Runnable mResetColorMatrix = new Runnable() {
- @Override
- public void run() {
- ((DialogFragment) getFragmentManager().findFragmentByTag("RevertWarning")).dismiss();
- Settings.Secure.putString(getContext().getContentResolver(),
- Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, null);
- }
- };
-
- private class MatrixPreference extends Preference implements View.OnClickListener {
- private float[] mValues;
-
- public MatrixPreference(Context context) {
- super(context);
- setLayoutResource(R.layout.preference_matrix);
- }
-
- public void setValues(String customValues) {
- String[] strValues = customValues.split(",");
- mValues = new float[strValues.length];
- for (int i = 0; i < mValues.length; i++) {
- mValues[i] = Float.parseFloat(strValues[i]);
- }
- notifyChanged();
- }
-
- @Override
- public void onBindViewHolder(PreferenceViewHolder holder) {
- super.onBindViewHolder(holder);
- bindView(holder.findViewById(R.id.r_group), 0);
- bindView(holder.findViewById(R.id.g_group), 5);
- bindView(holder.findViewById(R.id.b_group), 10);
- holder.findViewById(R.id.apply).setOnClickListener(this);
- }
-
- private void bindView(View view, final int index) {
- SeekBar seekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar);
- seekBar.setMax(1000);
- seekBar.setProgress((int) (1000 * mValues[index]));
- seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- mValues[index] = progress / 1000f;
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- }
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- }
- });
- }
-
- @Override
- public void onClick(View v) {
- startRevertTimer();
- Settings.Secure.putString(getContext().getContentResolver(),
- Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX,
- DisplayController.toString(mValues));
- RevertWarning.show(ColorMatrixFragment.this);
- }
-
- }
-
- public static class RevertWarning extends DialogFragment
- implements DialogInterface.OnClickListener {
-
- public static void show(ColorMatrixFragment fragment) {
- RevertWarning warning = new RevertWarning();
- warning.setTargetFragment(fragment, 0);
- warning.show(fragment.getFragmentManager(), "RevertWarning");
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- AlertDialog alertDialog = new AlertDialog.Builder(getContext())
- .setTitle(R.string.color_revert_title)
- .setMessage(R.string.color_revert_message)
- .setPositiveButton(R.string.ok, this)
- .create();
- alertDialog.setCanceledOnTouchOutside(true);
- return alertDialog;
- }
-
- @Override
- public void onCancel(DialogInterface dialog) {
- super.onCancel(dialog);
- ((ColorMatrixFragment) getTargetFragment()).onRevert();
- }
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- ((ColorMatrixFragment) getTargetFragment()).onApply();
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixTile.java b/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixTile.java
deleted file mode 100644
index d8cf2e2..0000000
--- a/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixTile.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/**
- * Copyright (c) 2015, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.tuner;
-
-import android.app.ActivityManager;
-import android.provider.Settings;
-
-import com.android.internal.logging.MetricsProto.MetricsEvent;
-import com.android.systemui.R;
-import com.android.systemui.qs.QSTile;
-import com.android.systemui.statusbar.policy.DisplayController;
-
-import java.util.Objects;
-
-
-public class ColorMatrixTile extends QSTile<QSTile.State> implements DisplayController.Listener {
-
- public static final String COLOR_MATRIX_SPEC = "colors";
-
- private final DisplayController mDisplayController;
-
- private int mIndex;
- private String mCurrentValue;
-
- private boolean mCustomEnabled;
- private String[] mValues;
- private CharSequence[] mValueTitles;
-
- public ColorMatrixTile(Host host) {
- super(host);
- mDisplayController = host.getDisplayController();
- }
-
- @Override
- public void setListening(boolean listening) {
- if (listening) {
- mValues = DisplayController.getColorTransforms(mContext);
- mValueTitles = DisplayController.getColorTitles(mContext);
- mDisplayController.addListener(this);
- } else {
- mDisplayController.removeListener(this);
- }
- }
-
- @Override
- public State newTileState() {
- return new State();
- }
-
- @Override
- protected void handleClick() {
- mIndex++;
- if (mIndex == DisplayController.AUTO_INDEX) {
- mDisplayController.setAuto(true);
- } else {
- mDisplayController.setAuto(false);
- if (!mDisplayController.isCustomEnabled()
- && (mIndex == DisplayController.CUSTOM_INDEX)) {
- mIndex++;
- }
- if (mIndex == mValues.length - 1) {
- mIndex = 0;
- }
- Settings.Secure.putStringForUser(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, mValues[mIndex],
- ActivityManager.getCurrentUser());
- }
- refreshState();
- }
-
- @Override
- protected void handleUpdateState(State state, Object arg) {
- if (mDisplayController.isAuto()) {
- mIndex = DisplayController.AUTO_INDEX;
- } else if (mDisplayController.isCustomSet()) {
- mIndex = DisplayController.CUSTOM_INDEX;
- } else {
- mIndex = Objects.equals(mDisplayController.getCurrentMatrix(), mValues[1]) ? 1 : 0;
- }
- state.icon = ResourceIcon.get(R.drawable.ic_colorize);
- state.label = mValueTitles[mIndex];
- state.contentDescription = mValueTitles[mIndex];
- }
-
- @Override
- public void onCurrentMatrixChanged() {
- refreshState();
- }
-
- @Override
- public int getMetricsCategory() {
- return MetricsEvent.QS_COLOR_MATRIX;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/NightModeFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/NightModeFragment.java
new file mode 100644
index 0000000..8c945f9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/NightModeFragment.java
@@ -0,0 +1,203 @@
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.tuner;
+
+import android.annotation.Nullable;
+import android.app.UiModeManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.provider.Settings.Secure;
+import android.support.v14.preference.PreferenceFragment;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.Preference.OnPreferenceChangeListener;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Switch;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.NightModeController;
+import com.android.systemui.statusbar.policy.NightModeController.Listener;
+import com.android.systemui.tuner.TunerService.Tunable;
+
+public class NightModeFragment extends PreferenceFragment implements Tunable,
+ Listener, OnPreferenceChangeListener {
+
+ private static final String TAG = "NightModeFragment";
+
+ public static final String EXTRA_SHOW_NIGHT_MODE = "show_night_mode";
+
+ private static final CharSequence KEY_AUTO = "auto";
+ private static final CharSequence KEY_DARK_THEME = "dark_theme";
+ private static final CharSequence KEY_ADJUST_TINT = "adjust_tint";
+ private static final CharSequence KEY_ADJUST_BRIGHTNESS = "adjust_brightness";
+
+ private Switch mSwitch;
+
+ private NightModeController mNightModeController;
+ private SwitchPreference mAutoSwitch;
+ private SwitchPreference mDarkTheme;
+ private SwitchPreference mAdjustTint;
+ private SwitchPreference mAdjustBrightness;
+ private UiModeManager mUiModeManager;
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mNightModeController = new NightModeController(getContext());
+ mUiModeManager = getContext().getSystemService(UiModeManager.class);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ final View view = LayoutInflater.from(getContext()).inflate(
+ R.layout.night_mode_settings, container, false);
+ ((ViewGroup) view).addView(super.onCreateView(inflater, container, savedInstanceState));
+ return view;
+ }
+
+ @Override
+ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+ final Context context = getPreferenceManager().getContext();
+
+ addPreferencesFromResource(R.xml.night_mode);
+ mAutoSwitch = (SwitchPreference) findPreference(KEY_AUTO);
+ mAutoSwitch.setOnPreferenceChangeListener(this);
+ mDarkTheme = (SwitchPreference) findPreference(KEY_DARK_THEME);
+ mDarkTheme.setOnPreferenceChangeListener(this);
+ mAdjustTint = (SwitchPreference) findPreference(KEY_ADJUST_TINT);
+ mAdjustTint.setOnPreferenceChangeListener(this);
+ mAdjustBrightness = (SwitchPreference) findPreference(KEY_ADJUST_BRIGHTNESS);
+ mAdjustBrightness.setOnPreferenceChangeListener(this);
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ View switchBar = view.findViewById(R.id.switch_bar);
+ mSwitch = (Switch) switchBar.findViewById(android.R.id.switch_widget);
+ mSwitch.setChecked(mNightModeController.isEnabled());
+ switchBar.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ boolean newState = !mNightModeController.isEnabled();
+ MetricsLogger.action(getContext(), MetricsEvent.ACTION_TUNER_NIGHT_MODE, newState);
+ mNightModeController.setNightMode(newState);
+ mSwitch.setChecked(newState);
+ }
+ });
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ MetricsLogger.visibility(getContext(), MetricsEvent.TUNER_NIGHT_MODE, true);
+ mNightModeController.addListener(this);
+ TunerService.get(getContext()).addTunable(this, Secure.BRIGHTNESS_USE_TWILIGHT,
+ NightModeController.NIGHT_MODE_ADJUST_TINT);
+ mDarkTheme.setChecked(mUiModeManager.getNightMode() == UiModeManager.MODE_NIGHT_AUTO);
+ calculateDisabled();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ MetricsLogger.visibility(getContext(), MetricsEvent.TUNER_NIGHT_MODE, false);
+ mNightModeController.removeListener(this);
+ TunerService.get(getContext()).removeTunable(this);
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ final Boolean value = (Boolean) newValue;
+ if (mAutoSwitch == preference) {
+ MetricsLogger.action(getContext(), MetricsEvent.ACTION_TUNER_NIGHT_MODE_AUTO, value);
+ mNightModeController.setAuto(value);
+ } else if (mDarkTheme == preference) {
+ MetricsLogger.action(getContext(),
+ MetricsEvent.ACTION_TUNER_NIGHT_MODE_ADJUST_DARK_THEME, value);
+ mUiModeManager.setNightMode(value ? UiModeManager.MODE_NIGHT_AUTO
+ : UiModeManager.MODE_NIGHT_NO);
+ postCalculateDisabled();
+ } else if (mAdjustTint == preference) {
+ MetricsLogger.action(getContext(),
+ MetricsEvent.ACTION_TUNER_NIGHT_MODE_ADJUST_TINT, value);
+ mNightModeController.setAdjustTint(value);
+ postCalculateDisabled();
+ } else if (mAdjustBrightness == preference) {
+ MetricsLogger.action(getContext(),
+ MetricsEvent.ACTION_TUNER_NIGHT_MODE_ADJUST_BRIGHTNESS, value);
+ TunerService.get(getContext()).setValue(Secure.BRIGHTNESS_USE_TWILIGHT,
+ value ? 1 : 0);
+ postCalculateDisabled();
+ } else {
+ return false;
+ }
+ return true;
+ }
+
+ private void postCalculateDisabled() {
+ // Post this because its the easiest way to wait for all state to be calculated.
+ getView().post(new Runnable() {
+ @Override
+ public void run() {
+ calculateDisabled();
+ }
+ });
+ }
+
+ private void calculateDisabled() {
+ int enabledCount = (mDarkTheme.isChecked() ? 1 : 0)
+ + (mAdjustTint.isChecked() ? 1 : 0)
+ + (mAdjustBrightness.isChecked() ? 1 : 0);
+ if (enabledCount == 1) {
+ if (mDarkTheme.isChecked()) {
+ mDarkTheme.setEnabled(false);
+ } else if (mAdjustTint.isChecked()) {
+ mAdjustTint.setEnabled(false);
+ } else {
+ mAdjustBrightness.setEnabled(false);
+ }
+ } else {
+ mDarkTheme.setEnabled(true);
+ mAdjustTint.setEnabled(true);
+ mAdjustBrightness.setEnabled(true);
+ }
+ }
+
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ if (Secure.BRIGHTNESS_USE_TWILIGHT.equals(key)) {
+ mAdjustBrightness.setChecked(newValue != null && Integer.parseInt(newValue) != 0);
+ } else if (NightModeController.NIGHT_MODE_ADJUST_TINT.equals(key)) {
+ // Default on.
+ mAdjustTint.setChecked(newValue == null || Integer.parseInt(newValue) != 0);
+ }
+ }
+
+ @Override
+ public void onNightModeChanged() {
+ mSwitch.setChecked(mNightModeController.isEnabled());
+ }
+
+ @Override
+ public void onTwilightAutoChanged() {
+ mAutoSwitch.setChecked(mNightModeController.isAuto());
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/NightModeTile.java b/packages/SystemUI/src/com/android/systemui/tuner/NightModeTile.java
new file mode 100644
index 0000000..26e1d46
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/NightModeTile.java
@@ -0,0 +1,107 @@
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.tuner;
+
+import android.app.ActivityManager;
+import android.content.Intent;
+import android.provider.Settings;
+
+import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.systemui.Prefs;
+import com.android.systemui.Prefs.Key;
+import com.android.systemui.R;
+import com.android.systemui.qs.QSTile;
+import com.android.systemui.statusbar.policy.NightModeController;
+
+import java.util.Objects;
+
+
+public class NightModeTile extends QSTile<QSTile.State> implements NightModeController.Listener {
+
+ public static final String NIGHT_MODE_SPEC = "night";
+
+ private final NightModeController mNightModeController;
+
+ private int mIndex;
+ private String mCurrentValue;
+
+ private boolean mCustomEnabled;
+ private String[] mValues;
+ private CharSequence[] mValueTitles;
+
+ public NightModeTile(Host host) {
+ super(host);
+ mNightModeController = host.getNightModeController();
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return Prefs.getBoolean(mContext, Key.QS_NIGHT_ADDED, false)
+ && TunerService.isTunerEnabled(mContext);
+ }
+
+ @Override
+ public void setListening(boolean listening) {
+ if (listening) {
+ mNightModeController.addListener(this);
+ refreshState();
+ } else {
+ mNightModeController.removeListener(this);
+ }
+ }
+
+ @Override
+ public State newTileState() {
+ return new State();
+ }
+
+ @Override
+ public Intent getLongClickIntent() {
+ return new Intent(mContext, TunerActivity.class)
+ .putExtra(NightModeFragment.EXTRA_SHOW_NIGHT_MODE, true);
+ }
+
+ @Override
+ protected void handleClick() {
+ mNightModeController.setNightMode(!mNightModeController.isEnabled());
+ refreshState();
+ }
+
+ @Override
+ protected void handleUpdateState(State state, Object arg) {
+ // TODO: Right now this is just a dropper, needs an actual night icon.
+ boolean enabled = mNightModeController.isEnabled();
+ state.icon = ResourceIcon.get(enabled ? R.drawable.ic_night_mode
+ : R.drawable.ic_night_mode_disabled);
+ state.label = mContext.getString(R.string.night_mode);
+ state.contentDescription = mContext.getString(R.string.night_mode);
+ }
+
+ @Override
+ public void onNightModeChanged() {
+ refreshState();
+ }
+
+ @Override
+ public void onTwilightAutoChanged() {
+ // Don't care.
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsEvent.QS_COLOR_MATRIX;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
index 4225b48..748ee97 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
@@ -36,12 +36,22 @@
super.onCreate(savedInstanceState);
if (getFragmentManager().findFragmentByTag(TAG_TUNER) == null) {
- getFragmentManager().beginTransaction().replace(R.id.content_frame, new TunerFragment(),
+ boolean showNightMode = getIntent().getBooleanExtra(
+ NightModeFragment.EXTRA_SHOW_NIGHT_MODE, false);
+ getFragmentManager().beginTransaction().replace(R.id.content_frame,
+ showNightMode ? new NightModeFragment() : new TunerFragment(),
TAG_TUNER).commit();
}
}
@Override
+ public void onBackPressed() {
+ if (!getFragmentManager().popBackStackImmediate()) {
+ super.onBackPressed();
+ }
+ }
+
+ @Override
public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
try {
Class<?> cls = Class.forName(pref.getFragment());
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
index 9df5368..70f2fdc 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
@@ -37,8 +37,6 @@
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
-import static com.android.systemui.BatteryMeterDrawable.SHOW_PERCENT_SETTING;
-
public class TunerFragment extends PreferenceFragment {
private static final String TAG = "TunerFragment";
@@ -51,10 +49,6 @@
private static final int MENU_REMOVE = Menu.FIRST + 1;
- private final SettingObserver mSettingObserver = new SettingObserver();
-
- private SwitchPreference mBatteryPct;
-
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -72,7 +66,6 @@
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.tuner_prefs);
- mBatteryPct = (SwitchPreference) findPreference(KEY_BATTERY_PCT);
if (Settings.Secure.getInt(getContext().getContentResolver(), SETTING_SEEN_TUNER_WARNING,
0) == 0) {
if (getFragmentManager().findFragmentByTag(WARNING_TAG) == null) {
@@ -85,9 +78,6 @@
public void onResume() {
super.onResume();
getActivity().setTitle(R.string.system_ui_tuner);
- updateBatteryPct();
- getContext().getContentResolver().registerContentObserver(
- System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver);
MetricsLogger.visibility(getContext(), MetricsEvent.TUNER, true);
}
@@ -95,7 +85,6 @@
@Override
public void onPause() {
super.onPause();
- getContext().getContentResolver().unregisterContentObserver(mSettingObserver);
MetricsLogger.visibility(getContext(), MetricsEvent.TUNER, false);
}
@@ -123,35 +112,6 @@
return super.onOptionsItemSelected(item);
}
- private void updateBatteryPct() {
- mBatteryPct.setOnPreferenceChangeListener(null);
- mBatteryPct.setChecked(System.getInt(getContext().getContentResolver(),
- SHOW_PERCENT_SETTING, 0) != 0);
- mBatteryPct.setOnPreferenceChangeListener(mBatteryPctChange);
- }
-
- private final class SettingObserver extends ContentObserver {
- public SettingObserver() {
- super(new Handler());
- }
-
- @Override
- public void onChange(boolean selfChange, Uri uri, int userId) {
- super.onChange(selfChange, uri, userId);
- updateBatteryPct();
- }
- }
-
- private final OnPreferenceChangeListener mBatteryPctChange = new OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- final boolean v = (Boolean) newValue;
- MetricsLogger.action(getContext(), MetricsEvent.TUNER_BATTERY_PERCENTAGE, v);
- System.putInt(getContext().getContentResolver(), SHOW_PERCENT_SETTING, v ? 1 : 0);
- return true;
- }
- };
-
public static class TunerWarningFragment extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
index 7ad752e..5b9ebd7 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
@@ -6,24 +6,27 @@
import android.support.v14.preference.SwitchPreference;
import android.util.AttributeSet;
+import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
import com.android.systemui.tuner.TunerService.Tunable;
public class TunerSwitch extends SwitchPreference implements Tunable {
private final boolean mDefault;
+ private final int mAction;
public TunerSwitch(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TunerSwitch);
mDefault = a.getBoolean(R.styleable.TunerSwitch_defValue, false);
+ mAction = a.getInt(R.styleable.TunerSwitch_metricsAction, -1);
}
@Override
public void onAttached() {
super.onAttached();
- TunerService.get(getContext()).addTunable(this, getKey());
+ TunerService.get(getContext()).addTunable(this, getKey().split(","));
}
@Override
@@ -38,8 +41,18 @@
}
@Override
+ protected void onClick() {
+ super.onClick();
+ if (mAction != -1) {
+ MetricsLogger.action(getContext(), mAction, isChecked());
+ }
+ }
+
+ @Override
protected boolean persistBoolean(boolean value) {
- Settings.Secure.putString(getContext().getContentResolver(), getKey(), value ? "1" : "0");
+ for (String key : getKey().split(",")) {
+ Settings.Secure.putString(getContext().getContentResolver(), key, value ? "1" : "0");
+ }
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
index fac6338..123165e 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
@@ -23,11 +23,14 @@
import android.app.IActivityManager;
import android.app.ITaskStackListener;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.graphics.Rect;
+import android.media.session.MediaController;
+import android.media.session.MediaSessionManager;
import android.os.Debug;
import android.os.Handler;
import android.os.RemoteException;
@@ -65,17 +68,28 @@
public static final int SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_OVERLAY_ACTIVITY_FINISH = 0x2;
private int mSuspendPipResizingReason;
+ private static final float SCALE_FACTOR = 1.1f;
+
private Context mContext;
private IActivityManager mActivityManager;
+ private MediaSessionManager mMediaSessionManager;
private int mState = STATE_NO_PIP;
private final Handler mHandler = new Handler();
private List<Listener> mListeners = new ArrayList<>();
- private Rect mPipBound;
- private Rect mMenuModePipBound;
+ private Rect mCurrentPipBounds;
+ private Rect mPipBounds;
+ private Rect mMenuModePipBounds;
+ private Rect mRecentsPipBounds;
+ private Rect mRecentsFocusedPipBounds;
private boolean mInitialized;
private int mPipTaskId = TASK_ID_NO_PIP;
+ private ComponentName mPipComponentName;
+ private MediaController mPipMediaController;
private boolean mOnboardingShown;
+ private boolean mIsRecentsShown;
+ private boolean mIsPipFocusedInRecent;
+
private final Runnable mOnActivityPinnedRunnable = new Runnable() {
@Override
public void run() {
@@ -83,7 +97,7 @@
try {
stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
if (stackInfo == null) {
- Log.w(TAG, "There is no pinned stack");
+ Log.w(TAG, "Cannot find pinned stack");
return;
}
} catch (RemoteException e) {
@@ -92,16 +106,41 @@
}
if (DEBUG) Log.d(TAG, "PINNED_STACK:" + stackInfo);
mPipTaskId = stackInfo.taskIds[stackInfo.taskIds.length - 1];
+ mPipComponentName = ComponentName.unflattenFromString(
+ stackInfo.taskNames[stackInfo.taskNames.length - 1]);
// Set state to overlay so we show it when the pinned stack animation ends.
mState = STATE_PIP_OVERLAY;
+ mCurrentPipBounds = mPipBounds;
launchPipOnboardingActivityIfNeeded();
+ mMediaSessionManager.addOnActiveSessionsChangedListener(
+ mActiveMediaSessionListener, null);
+ updateMediaController(mMediaSessionManager.getActiveSessions(null));
}
};
private final Runnable mOnTaskStackChanged = new Runnable() {
@Override
public void run() {
if (mState != STATE_NO_PIP) {
- // TODO: check whether PIP task is closed.
+ StackInfo stackInfo = null;
+ try {
+ stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
+ if (stackInfo == null) {
+ Log.w(TAG, "There is no pinned stack");
+ closePipInternal(false);
+ return;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "getStackInfo failed", e);
+ return;
+ }
+ for (int i = stackInfo.taskIds.length - 1; i >= 0; --i) {
+ if (stackInfo.taskIds[i] == mPipTaskId) {
+ // PIP task is still alive.
+ return;
+ }
+ }
+ // PIP task doesn't exist anymore in PINNED_STACK.
+ closePipInternal(true);
}
}
};
@@ -114,10 +153,13 @@
private final Runnable mOnPinnedStackAnimationEnded = new Runnable() {
@Override
public void run() {
- if (mState == STATE_PIP_OVERLAY) {
- showPipOverlay();
- } else if (mState == STATE_PIP_MENU) {
- showPipMenu();
+ switch (mState) {
+ case STATE_PIP_OVERLAY:
+ showPipOverlay();
+ break;
+ case STATE_PIP_MENU:
+ showPipMenu();
+ break;
}
}
};
@@ -145,6 +187,13 @@
}
};
+ private final MediaSessionManager.OnActiveSessionsChangedListener mActiveMediaSessionListener =
+ new MediaSessionManager.OnActiveSessionsChangedListener() {
+ @Override
+ public void onActiveSessionsChanged(List<MediaController> controllers) {
+ updateMediaController(controllers);
+ }
+ };
private PipManager() { }
@@ -158,10 +207,18 @@
mInitialized = true;
mContext = context;
Resources res = context.getResources();
- mPipBound = Rect.unflattenFromString(res.getString(
+ mPipBounds = Rect.unflattenFromString(res.getString(
com.android.internal.R.string.config_defaultPictureInPictureBounds));
- mMenuModePipBound = Rect.unflattenFromString(res.getString(
+ mMenuModePipBounds = Rect.unflattenFromString(res.getString(
com.android.internal.R.string.config_centeredPictureInPictureBounds));
+ mRecentsPipBounds = Rect.unflattenFromString(res.getString(
+ com.android.internal.R.string.config_pictureInPictureBoundsInRecents));
+ float scaleBy = (SCALE_FACTOR - 1.0f) / 2;
+ mRecentsFocusedPipBounds = new Rect(
+ (int) (mRecentsPipBounds.left - scaleBy * mRecentsPipBounds.width()),
+ (int) (mRecentsPipBounds.top - scaleBy * mRecentsPipBounds.height()),
+ (int) (mRecentsPipBounds.right + scaleBy * mRecentsPipBounds.width()),
+ (int) (mRecentsPipBounds.bottom + scaleBy * mRecentsPipBounds.height()));
mActivityManager = ActivityManagerNative.getDefault();
TaskStackListener taskStackListener = new TaskStackListener();
@@ -176,6 +233,9 @@
mContext.registerReceiver(mBroadcastReceiver, intentFilter);
mOnboardingShown = Prefs.getBoolean(
mContext, TV_PICTURE_IN_PICTURE_ONBOARDING_SHOWN, false);
+
+ mMediaSessionManager =
+ (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
}
/**
@@ -184,7 +244,7 @@
*/
public void requestTvPictureInPicture() {
if (DEBUG) Log.d(TAG, "requestTvPictureInPicture()");
- if (!hasPipTasks()) {
+ if (!isPipShown()) {
startPip();
} else if (mState == STATE_PIP_OVERLAY) {
resizePinnedStack(STATE_PIP_MENU);
@@ -193,7 +253,7 @@
private void startPip() {
try {
- mActivityManager.moveTopActivityToPinnedStack(FULLSCREEN_WORKSPACE_STACK_ID, mPipBound);
+ mActivityManager.moveTopActivityToPinnedStack(FULLSCREEN_WORKSPACE_STACK_ID, mPipBounds);
} catch (RemoteException|IllegalArgumentException e) {
Log.e(TAG, "moveTopActivityToPinnedStack failed", e);
}
@@ -203,12 +263,23 @@
* Closes PIP (PIPed activity and PIP system UI).
*/
public void closePip() {
+ closePipInternal(true);
+ }
+
+ private void closePipInternal(boolean removePipStack) {
mState = STATE_NO_PIP;
mPipTaskId = TASK_ID_NO_PIP;
- try {
- mActivityManager.removeStack(PINNED_STACK_ID);
- } catch (RemoteException e) {
- Log.e(TAG, "removeStack failed", e);
+ mPipMediaController = null;
+ mMediaSessionManager.removeOnActiveSessionsChangedListener(mActiveMediaSessionListener);
+ if (removePipStack) {
+ try {
+ mActivityManager.removeStack(PINNED_STACK_ID);
+ } catch (RemoteException e) {
+ Log.e(TAG, "removeStack failed", e);
+ }
+ }
+ for (int i = mListeners.size() - 1; i >= 0; --i) {
+ mListeners.get(i).onPipActivityClosed();
}
}
@@ -270,37 +341,100 @@
public void resizePinnedStack(int state) {
if (DEBUG) Log.d(TAG, "resizePinnedStack() state=" + state);
mState = state;
- Rect bounds;
for (int i = mListeners.size() - 1; i >= 0; --i) {
mListeners.get(i).onPipResizeAboutToStart();
}
- switch (mState) {
- case STATE_PIP_MENU:
- bounds = mMenuModePipBound;
- break;
- case STATE_NO_PIP:
- bounds = null;
- break;
- default:
- bounds = mPipBound;
- break;
- }
-
if (mSuspendPipResizingReason != 0) {
if (DEBUG) Log.d(TAG,
"resizePinnedStack() deferring mSuspendPipResizingReason=" +
mSuspendPipResizingReason);
return;
}
-
+ switch (mState) {
+ case STATE_NO_PIP:
+ mCurrentPipBounds = null;
+ break;
+ case STATE_PIP_MENU:
+ mCurrentPipBounds = mMenuModePipBounds;
+ break;
+ case STATE_PIP_OVERLAY:
+ if (mIsRecentsShown) {
+ if (mIsPipFocusedInRecent) {
+ mCurrentPipBounds = mRecentsFocusedPipBounds;
+ } else {
+ mCurrentPipBounds = mRecentsPipBounds;
+ }
+ } else {
+ mCurrentPipBounds = mPipBounds;
+ }
+ break;
+ default:
+ mCurrentPipBounds = mPipBounds;
+ break;
+ }
try {
- mActivityManager.resizeStack(PINNED_STACK_ID, bounds, true, true, true);
+ mActivityManager.resizeStack(PINNED_STACK_ID, mCurrentPipBounds, true, true, true);
} catch (RemoteException e) {
Log.e(TAG, "showPipMenu failed", e);
}
}
/**
+ * Returns the current PIP bound for activities to sync their UI with PIP.
+ */
+ public Rect getPipBounds() {
+ return mCurrentPipBounds;
+ }
+
+ /**
+ * Called when Recents is started.
+ * PIPed activity will be resized accordingly and overlay will show available buttons.
+ */
+ public void onRecentsStarted() {
+ mIsRecentsShown = true;
+ mIsPipFocusedInRecent = false;
+ if (mState == STATE_NO_PIP) {
+ return;
+ }
+ resizePinnedStack(STATE_PIP_OVERLAY);
+ }
+
+ /**
+ * Called when Recents is stopped.
+ * PIPed activity will be resized accordingly and overlay will hide available buttons.
+ */
+ public void onRecentsStopped() {
+ mIsRecentsShown = false;
+ mIsPipFocusedInRecent = false;
+ if (mState == STATE_NO_PIP) {
+ return;
+ }
+ resizePinnedStack(STATE_PIP_OVERLAY);
+ }
+
+ /**
+ * Returns {@code true} if recents is shown.
+ */
+ boolean isRecentsShown() {
+ return mIsRecentsShown;
+ }
+
+ /**
+ * Called when the PIP view in {@link com.android.systemui.recents.tv.RecentsTvActivity}
+ * is focused.
+ * This only resizes pinned stack so it looks like it's in Recents.
+ * This should be called only by {@link com.android.systemui.recents.tv.RecentsTvActivity}.
+ */
+ public void onPipViewFocusChangedInRecents(boolean hasFocus) {
+ mIsPipFocusedInRecent = hasFocus;
+ if (mState != STATE_PIP_OVERLAY) {
+ Log.w(TAG, "There is no pinned stack to handle focus change.");
+ return;
+ }
+ resizePinnedStack(STATE_PIP_OVERLAY);
+ }
+
+ /**
* Shows PIP menu UI by launching {@link PipMenuActivity}. It also locates the pinned
* stack to the centered PIP bound {@link com.android.internal.R.string
* .config_centeredPictureInPictureBounds}.
@@ -313,9 +447,7 @@
}
Intent intent = new Intent(mContext, PipMenuActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- final ActivityOptions options = ActivityOptions.makeBasic();
- options.setLaunchStackId(PINNED_STACK_ID);
- mContext.startActivity(intent, options.toBundle());
+ mContext.startActivity(intent);
}
public void addListener(Listener listener) {
@@ -337,6 +469,13 @@
}
}
+ /**
+ * Returns {@code true} if PIP is shown.
+ */
+ public boolean isPipShown() {
+ return hasPipTasks();
+ }
+
private boolean hasPipTasks() {
try {
StackInfo stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
@@ -386,6 +525,34 @@
}
}
+ private void updateMediaController(List<MediaController> controllers) {
+ MediaController mediaController = null;
+ if (controllers != null && mState != STATE_NO_PIP && mPipComponentName != null) {
+ for (int i = controllers.size() - 1; i >= 0; i--) {
+ MediaController controller = controllers.get(i);
+ // We assumes that an app with PIPable activity
+ // keeps the single instance of media controller especially when PIP is on.
+ if (controller.getPackageName().equals(mPipComponentName.getPackageName())) {
+ mediaController = controller;
+ break;
+ }
+ }
+ }
+ if (mPipMediaController != mediaController) {
+ mPipMediaController = mediaController;
+ for (int i = mListeners.size() - 1; i >= 0; i--) {
+ mListeners.get(i).onMediaControllerChanged();
+ }
+ }
+ }
+
+ /**
+ * Gets the {@link android.media.session.MediaController} for the PIPed activity.
+ */
+ MediaController getMediaController() {
+ return mPipMediaController;
+ }
+
private class TaskStackListener extends ITaskStackListener.Stub {
@Override
public void onTaskStackChanged() throws RemoteException {
@@ -426,6 +593,8 @@
void onMoveToFullscreen();
/** Invoked when we are above to start resizing the Pip. */
void onPipResizeAboutToStart();
+ /** Invoked when the MediaController on PIPed activity is changed. */
+ void onMediaControllerChanged();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
index 7e229d4..285dfd1 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
@@ -18,51 +18,175 @@
import android.app.Activity;
import android.media.session.MediaController;
+import android.media.session.PlaybackState;
import android.os.Bundle;
import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
import com.android.systemui.R;
+import com.android.systemui.SystemUI;
+import com.android.systemui.SystemUIApplication;
+import com.android.systemui.recents.Recents;
+
+import static android.content.pm.PackageManager.FEATURE_LEANBACK;
+import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
+import static android.media.session.PlaybackState.ACTION_PAUSE;
+import static android.media.session.PlaybackState.ACTION_PLAY;
/**
* Activity to show the PIP menu to control PIP.
*/
public class PipMenuActivity extends Activity implements PipManager.Listener {
private static final String TAG = "PipMenuActivity";
- private static final boolean DEBUG = false;
private final PipManager mPipManager = PipManager.getInstance();
private MediaController mMediaController;
+ private View mFullButtonView;
+ private View mFullDescriptionView;
+ private View mPlayPauseView;
+ private ImageView mPlayPauseButtonImageView;
+ private TextView mPlayPauseDescriptionTextView;
+ private View mCloseButtonView;
+ private View mCloseDescriptionView;
+ private boolean mPipMovedToFullscreen;
+
+ private MediaController.Callback mMediaControllerCallback = new MediaController.Callback() {
+ @Override
+ public void onPlaybackStateChanged(PlaybackState state) {
+ updatePlayPauseView(state);
+ }
+ };
+
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.tv_pip_menu);
mPipManager.addListener(this);
- findViewById(R.id.full).setOnClickListener(new View.OnClickListener() {
+ mFullButtonView = findViewById(R.id.full_button);
+ mFullDescriptionView = findViewById(R.id.full_desc);
+ mFullButtonView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPipManager.movePipToFullscreen();
+ mPipMovedToFullscreen = true;
+ finish();
}
});
- findViewById(R.id.exit).setOnClickListener(new View.OnClickListener() {
+ mFullButtonView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ mFullDescriptionView.setVisibility(hasFocus ? View.VISIBLE : View.INVISIBLE);
+ }
+ });
+
+ mPlayPauseView = findViewById(R.id.play_pause);
+ mPlayPauseButtonImageView = (ImageView) findViewById(R.id.play_pause_button);
+ mPlayPauseDescriptionTextView = (TextView) findViewById(R.id.play_pause_desc);
+ mPlayPauseButtonImageView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mMediaController == null || mMediaController.getPlaybackState() == null) {
+ return;
+ }
+ long actions = mMediaController.getPlaybackState().getActions();
+ int state = mMediaController.getPlaybackState().getState();
+ if (((actions & ACTION_PLAY) != 0) && !isPlaying(state)) {
+ mMediaController.getTransportControls().play();
+ } else if ((actions & ACTION_PAUSE) != 0 && isPlaying(state)) {
+ mMediaController.getTransportControls().pause();
+ }
+ // View will be updated later in {@link mMediaControllerCallback}
+ }
+ });
+ mPlayPauseButtonImageView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ mPlayPauseDescriptionTextView.setVisibility(hasFocus ? View.VISIBLE : View.INVISIBLE);
+ }
+ });
+
+ mCloseButtonView = findViewById(R.id.close_button);
+ mCloseDescriptionView = findViewById(R.id.close_desc);
+ mCloseButtonView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPipManager.closePip();
finish();
}
});
- findViewById(R.id.cancel).setOnClickListener(new View.OnClickListener() {
+ mCloseButtonView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
- public void onClick(View v) {
- mPipManager.resizePinnedStack(PipManager.STATE_PIP_OVERLAY);
- finish();
+ public void onFocusChange(View v, boolean hasFocus) {
+ mCloseDescriptionView.setVisibility(hasFocus ? View.VISIBLE : View.INVISIBLE);
}
});
+ updateMediaController();
+ }
+
+ private void updateMediaController() {
+ MediaController newController = mPipManager.getMediaController();
+ if (mMediaController == newController) {
+ return;
+ }
+ if (mMediaController != null) {
+ mMediaController.unregisterCallback(mMediaControllerCallback);
+ }
+ mMediaController = newController;
+ if (mMediaController != null) {
+ mMediaController.registerCallback(mMediaControllerCallback);
+ updatePlayPauseView(mMediaController.getPlaybackState());
+ } else {
+ updatePlayPauseView(null);
+ }
+ }
+
+ private void updatePlayPauseView(PlaybackState playbackState) {
+ if (playbackState != null
+ && (playbackState.getActions() & (ACTION_PLAY | ACTION_PAUSE)) != 0) {
+ mPlayPauseView.setVisibility(View.VISIBLE);
+ if (isPlaying(playbackState.getState())) {
+ mPlayPauseButtonImageView.setImageResource(R.drawable.tv_pip_pause_button);
+ mPlayPauseDescriptionTextView.setText(R.string.pip_pause);
+ } else {
+ mPlayPauseButtonImageView.setImageResource(R.drawable.tv_pip_play_button);
+ mPlayPauseDescriptionTextView.setText(R.string.pip_play);
+ }
+ } else {
+ mPlayPauseView.setVisibility(View.GONE);
+ }
+ }
+
+ private boolean isPlaying(int state) {
+ return state == PlaybackState.STATE_BUFFERING
+ || state == PlaybackState.STATE_CONNECTING
+ || state == PlaybackState.STATE_PLAYING
+ || state == PlaybackState.STATE_FAST_FORWARDING
+ || state == PlaybackState.STATE_REWINDING
+ || state == PlaybackState.STATE_SKIPPING_TO_PREVIOUS
+ || state == PlaybackState.STATE_SKIPPING_TO_NEXT;
+ }
+
+ private void restorePipAndFinish() {
+ if (!mPipMovedToFullscreen) {
+ mPipManager.resizePinnedStack(PipManager.STATE_PIP_OVERLAY);
+ }
+ finish();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ restorePipAndFinish();
}
@Override
protected void onDestroy() {
super.onDestroy();
+ if (mMediaController != null) {
+ mMediaController.unregisterCallback(mMediaControllerCallback);
+ }
mPipManager.removeListener(this);
mPipManager.resumePipResizing(
PipManager.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_MENU_ACTIVITY_FINISH);
@@ -70,8 +194,7 @@
@Override
public void onBackPressed() {
- mPipManager.resizePinnedStack(PipManager.STATE_PIP_OVERLAY);
- finish();
+ restorePipAndFinish();
}
@Override
@@ -88,9 +211,28 @@
}
@Override
+ public void onMediaControllerChanged() {
+ updateMediaController();
+ }
+
+ @Override
public void onPipResizeAboutToStart() {
finish();
mPipManager.suspendPipResizing(
PipManager.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_MENU_ACTIVITY_FINISH);
}
+
+ @Override
+ public void finish() {
+ super.finish();
+ if (mPipManager.isRecentsShown() && !mPipMovedToFullscreen) {
+ SystemUI[] services = ((SystemUIApplication) getApplication()).getServices();
+ for (int i = services.length - 1; i >= 0; i--) {
+ if (services[i] instanceof Recents) {
+ ((Recents) services[i]).showRecents(false, null);
+ break;
+ }
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java
index 6f71c92..ad45625b 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java
@@ -17,9 +17,11 @@
package com.android.systemui.tv.pip;
import android.app.Activity;
+import android.graphics.Rect;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
+import android.view.ViewGroup.LayoutParams;
import com.android.systemui.R;
@@ -33,6 +35,8 @@
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.tv_pip_onboarding);
+ View pipOnboardingView = findViewById(R.id.pip_onboarding);
+ View pipOutlineView = findViewById(R.id.pip_outline);
mPipManager.addListener(this);
findViewById(R.id.close).setOnClickListener(new View.OnClickListener() {
@Override
@@ -40,6 +44,20 @@
finish();
}
});
+
+ int pipOutlineSpace = getResources().getDimensionPixelSize(R.dimen.tv_pip_bounds_space);
+ int screenWidth = getResources().getDisplayMetrics().widthPixels;
+ Rect pipBounds = mPipManager.getPipBounds();
+ pipOnboardingView.setPadding(
+ pipBounds.left - pipOutlineSpace,
+ pipBounds.top - pipOutlineSpace,
+ screenWidth - pipBounds.right - pipOutlineSpace, 0);
+
+ // Set width and height for outline view to enclose the PIP.
+ LayoutParams lp = pipOutlineView.getLayoutParams();
+ lp.width = pipBounds.width() + pipOutlineSpace * 2;
+ lp.height = pipBounds.height() + pipOutlineSpace * 2;
+ pipOutlineView.setLayoutParams(lp);
}
@Override
@@ -64,6 +82,8 @@
}
@Override
- public void onPipResizeAboutToStart() {
- }
+ public void onPipResizeAboutToStart() { }
+
+ @Override
+ public void onMediaControllerChanged() { }
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java
index 56a604d..95d655c 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java
@@ -19,8 +19,8 @@
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
-
import android.view.View;
+
import com.android.systemui.R;
/**
@@ -35,10 +35,10 @@
private final PipManager mPipManager = PipManager.getInstance();
private final Handler mHandler = new Handler();
private View mGuideOverlayView;
+ private View mGuideButtonsView;
private final Runnable mHideGuideOverlayRunnable = new Runnable() {
public void run() {
- // TODO: Uncomment this after the b/27224884 is fixed.
- //mGuideOverlayView.setVisibility(View.INVISIBLE);
+ mGuideOverlayView.setVisibility(View.INVISIBLE);
}
};
@@ -47,13 +47,21 @@
super.onCreate(bundle);
setContentView(R.layout.tv_pip_overlay);
mGuideOverlayView = findViewById(R.id.guide_overlay);
+ mGuideButtonsView = findViewById(R.id.guide_buttons);
mPipManager.addListener(this);
}
@Override
protected void onResume() {
super.onResume();
- mGuideOverlayView.setVisibility(View.VISIBLE);
+ // TODO: Implement animation for this
+ if (!mPipManager.isRecentsShown()) {
+ mGuideOverlayView.setVisibility(View.VISIBLE);
+ mGuideButtonsView.setVisibility(View.INVISIBLE);
+ } else {
+ mGuideOverlayView.setVisibility(View.INVISIBLE);
+ mGuideButtonsView.setVisibility(View.VISIBLE);
+ }
mHandler.removeCallbacks(mHideGuideOverlayRunnable);
mHandler.postDelayed(mHideGuideOverlayRunnable, SHOW_GUIDE_OVERLAY_VIEW_DURATION_MS);
}
@@ -95,4 +103,8 @@
mPipManager.suspendPipResizing(
PipManager.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_OVERLAY_ACTIVITY_FINISH);
}
+
+ @Override
+ public void onMediaControllerChanged() {
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index 1810c1c..1d5ca04 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -25,6 +25,7 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.ColorStateList;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.PixelFormat;
@@ -42,6 +43,7 @@
import android.provider.Settings.Global;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.util.Slog;
import android.util.SparseBooleanArray;
import android.view.Gravity;
import android.view.MotionEvent;
@@ -49,7 +51,6 @@
import android.view.View.AccessibilityDelegate;
import android.view.View.OnAttachStateChangeListener;
import android.view.View.OnClickListener;
-import android.view.View.OnLayoutChangeListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.ViewGroup.MarginLayoutParams;
@@ -91,39 +92,40 @@
public static final String SHOW_FULL_ZEN = "sysui_show_full_zen";
private static final long USER_ATTEMPT_GRACE_PERIOD = 1000;
- private static final int WAIT_FOR_RIPPLE = 200;
private final Context mContext;
private final H mHandler = new H();
private final VolumeDialogController mController;
- private final CustomDialog mDialog;
- private final ViewGroup mDialogView;
- private final ViewGroup mDialogContentView;
- private final ImageButton mExpandButton;
- private final View mSettingsButton;
- private final List<VolumeRow> mRows = new ArrayList<VolumeRow>();
+ private CustomDialog mDialog;
+ private ViewGroup mDialogView;
+ private ViewGroup mDialogContentView;
+ private ViewGroup mVolumeRowContainer;
+ private ImageButton mExpandButton;
+ private final List<VolumeRow> mRows = new ArrayList<>();
private final SpTexts mSpTexts;
private final SparseBooleanArray mDynamic = new SparseBooleanArray();
private final KeyguardManager mKeyguard;
private final AudioManager mAudioManager;
- private final int mExpandButtonAnimationDuration;
- private final ZenFooter mZenFooter;
+ private int mExpandButtonAnimationDuration;
+ private ZenFooter mZenFooter;
private final LayoutTransition mLayoutTransition;
private final Object mSafetyWarningLock = new Object();
private final Accessibility mAccessibility = new Accessibility();
private final ColorStateList mActiveSliderTint;
private final ColorStateList mInactiveSliderTint;
- private final VolumeDialogMotion mMotion;
+ private VolumeDialogMotion mMotion;
+ private final int mWindowType;
+ private final ZenModeController mZenModeController;
private boolean mShowing;
private boolean mExpanded;
+
private int mActiveStream;
private boolean mShowHeaders = VolumePrefs.DEFAULT_SHOW_HEADERS;
private boolean mAutomute = VolumePrefs.DEFAULT_ENABLE_AUTOMUTE;
private boolean mSilentMode = VolumePrefs.DEFAULT_ENABLE_SILENT_MODE;
private State mState;
- private int mExpandButtonRes;
private boolean mExpandButtonAnimationRunning;
private SafetyWarningDialog mSafetyWarning;
private Callback mCallback;
@@ -131,22 +133,43 @@
private boolean mPendingRecheckAll;
private long mCollapseTime;
private boolean mHovering = false;
- private int mLastActiveStream;
+ private int mDensity;
private boolean mShowFullZen;
- private final TunerZenModePanel mZenPanel;
+ private TunerZenModePanel mZenPanel;
public VolumeDialog(Context context, int windowType, VolumeDialogController controller,
ZenModeController zenModeController, Callback callback) {
mContext = context;
mController = controller;
mCallback = callback;
+ mWindowType = windowType;
+ mZenModeController = zenModeController;
mSpTexts = new SpTexts(mContext);
mKeyguard = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+ mActiveSliderTint = loadColorStateList(R.color.system_accent_color);
+ mInactiveSliderTint = loadColorStateList(R.color.volume_slider_inactive);
+ mLayoutTransition = new LayoutTransition();
+ mLayoutTransition.setDuration(new ValueAnimator().getDuration() / 2);
+ initDialog();
+
+ mAccessibility.init();
+
+ controller.addCallback(mControllerCallbackH, mHandler);
+ controller.getState();
+ TunerService.get(mContext).addTunable(this, SHOW_FULL_ZEN);
+
+ final Configuration currentConfig = mContext.getResources().getConfiguration();
+ mDensity = currentConfig.densityDpi;
+ }
+
+ private void initDialog() {
mDialog = new CustomDialog(mContext);
+ mHovering = false;
+ mShowing = false;
final Window window = mDialog.getWindow();
window.requestFeature(Window.FEATURE_NO_TITLE);
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
@@ -160,7 +183,7 @@
mDialog.setCanceledOnTouchOutside(true);
final Resources res = mContext.getResources();
final WindowManager.LayoutParams lp = window.getAttributes();
- lp.type = windowType;
+ lp.type = mWindowType;
lp.format = PixelFormat.TRANSLUCENT;
lp.setTitle(VolumeDialog.class.getSimpleName());
lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
@@ -170,8 +193,7 @@
window.setAttributes(lp);
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
- mActiveSliderTint = loadColorStateList(R.color.system_accent_color);
- mInactiveSliderTint = loadColorStateList(R.color.volume_slider_inactive);
+
mDialog.setContentView(R.layout.volume_dialog);
mDialogView = (ViewGroup) mDialog.findViewById(R.id.volume_dialog);
mDialogView.setOnHoverListener(new View.OnHoverListener() {
@@ -185,56 +207,53 @@
}
});
mDialogContentView = (ViewGroup) mDialog.findViewById(R.id.volume_dialog_content);
+ mVolumeRowContainer =
+ (ViewGroup) mDialogContentView.findViewById(R.id.volume_row_container);
+ mExpanded = false;
mExpandButton = (ImageButton) mDialogView.findViewById(R.id.volume_expand_button);
mExpandButton.setOnClickListener(mClickExpand);
updateWindowWidthH();
updateExpandButtonH();
- mLayoutTransition = new LayoutTransition();
- mLayoutTransition.setDuration(new ValueAnimator().getDuration() / 2);
+
mDialogContentView.setLayoutTransition(mLayoutTransition);
mMotion = new VolumeDialogMotion(mDialog, mDialogView, mDialogContentView, mExpandButton,
new VolumeDialogMotion.Callback() {
- @Override
- public void onAnimatingChanged(boolean animating) {
- if (animating) return;
- if (mPendingStateChanged) {
- mHandler.sendEmptyMessage(H.STATE_CHANGED);
- mPendingStateChanged = false;
- }
- if (mPendingRecheckAll) {
- mHandler.sendEmptyMessage(H.RECHECK_ALL);
- mPendingRecheckAll = false;
- }
- }
- });
+ @Override
+ public void onAnimatingChanged(boolean animating) {
+ if (animating) return;
+ if (mPendingStateChanged) {
+ mHandler.sendEmptyMessage(H.STATE_CHANGED);
+ mPendingStateChanged = false;
+ }
+ if (mPendingRecheckAll) {
+ mHandler.sendEmptyMessage(H.RECHECK_ALL);
+ mPendingRecheckAll = false;
+ }
+ }
+ });
- addRow(AudioManager.STREAM_RING,
- R.drawable.ic_volume_ringer, R.drawable.ic_volume_ringer_mute, true);
- addRow(AudioManager.STREAM_MUSIC,
- R.drawable.ic_volume_media, R.drawable.ic_volume_media_mute, true);
- addRow(AudioManager.STREAM_ALARM,
- R.drawable.ic_volume_alarm, R.drawable.ic_volume_alarm_mute, false);
- addRow(AudioManager.STREAM_VOICE_CALL,
- R.drawable.ic_volume_voice, R.drawable.ic_volume_voice, false);
- addRow(AudioManager.STREAM_BLUETOOTH_SCO,
- R.drawable.ic_volume_bt_sco, R.drawable.ic_volume_bt_sco, false);
- addRow(AudioManager.STREAM_SYSTEM,
- R.drawable.ic_volume_system, R.drawable.ic_volume_system_mute, false);
-
- mSettingsButton = mDialog.findViewById(R.id.volume_settings_button);
- mSettingsButton.setOnClickListener(mClickSettings);
+ if (mRows.isEmpty()) {
+ addRow(AudioManager.STREAM_RING,
+ R.drawable.ic_volume_ringer, R.drawable.ic_volume_ringer_mute, true);
+ addRow(AudioManager.STREAM_MUSIC,
+ R.drawable.ic_volume_media, R.drawable.ic_volume_media_mute, true);
+ addRow(AudioManager.STREAM_ALARM,
+ R.drawable.ic_volume_alarm, R.drawable.ic_volume_alarm_mute, false);
+ addRow(AudioManager.STREAM_VOICE_CALL,
+ R.drawable.ic_volume_voice, R.drawable.ic_volume_voice, false);
+ addRow(AudioManager.STREAM_BLUETOOTH_SCO,
+ R.drawable.ic_volume_bt_sco, R.drawable.ic_volume_bt_sco, false);
+ addRow(AudioManager.STREAM_SYSTEM,
+ R.drawable.ic_volume_system, R.drawable.ic_volume_system_mute, false);
+ } else {
+ addExistingRows();
+ }
mExpandButtonAnimationDuration = res.getInteger(R.integer.volume_expand_animation_duration);
mZenFooter = (ZenFooter) mDialog.findViewById(R.id.volume_zen_footer);
- mZenFooter.init(zenModeController);
+ mZenFooter.init(mZenModeController);
mZenPanel = (TunerZenModePanel) mDialog.findViewById(R.id.tuner_zen_mode_panel);
- mZenPanel.init(zenModeController);
+ mZenPanel.init(mZenModeController);
mZenPanel.setCallback(mZenPanelCallback);
-
- mAccessibility.init();
-
- controller.addCallback(mControllerCallbackH, mHandler);
- controller.getState();
- TunerService.get(mContext).addTunable(this, SHOW_FULL_ZEN);
}
@Override
@@ -285,46 +304,38 @@
}
private void addRow(int stream, int iconRes, int iconMuteRes, boolean important) {
- final VolumeRow row = initRow(stream, iconRes, iconMuteRes, important);
+ VolumeRow row = new VolumeRow();
+ initRow(row, stream, iconRes, iconMuteRes, important);
if (!mRows.isEmpty()) {
- final View v = new View(mContext);
- v.setId(android.R.id.background);
- final int h = mContext.getResources()
- .getDimensionPixelSize(R.dimen.volume_slider_interspacing);
- final LinearLayout.LayoutParams lp =
- new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, h);
- mDialogContentView.addView(v, mDialogContentView.getChildCount() - 2, lp);
- row.space = v;
+ addSpacer(row);
}
- row.settingsButton.addOnLayoutChangeListener(new OnLayoutChangeListener() {
- @Override
- public void onLayoutChange(View v, int left, int top, int right, int bottom,
- int oldLeft, int oldTop, int oldRight, int oldBottom) {
- final boolean moved = mLastActiveStream != mActiveStream ||
- oldLeft != left || oldTop != top;
- if (D.BUG) Log.d(TAG, "onLayoutChange moved=" + moved
- + " old=" + new Rect(oldLeft, oldTop, oldRight, oldBottom).toShortString()
- + "," + mLastActiveStream
- + " new=" + new Rect(left,top,right,bottom).toShortString()
- + "," + mActiveStream);
- mLastActiveStream = mActiveStream;
- if (moved) {
- for (int i = 0; i < mDialogContentView.getChildCount(); i++) {
- final View c = mDialogContentView.getChildAt(i);
- if (!c.isShown()) continue;
- if (c == row.view) {
- repositionExpandAnim(row);
- }
- return;
- }
- }
- }
- });
- // add new row just before the footer
- mDialogContentView.addView(row.view, mDialogContentView.getChildCount() - 2);
+ mVolumeRowContainer.addView(row.view);
mRows.add(row);
}
+ private void addExistingRows() {
+ int N = mRows.size();
+ for (int i = 0; i < N; i++) {
+ final VolumeRow row = mRows.get(i);
+ initRow(row, row.stream, row.iconRes, row.iconMuteRes, row.important);
+ if (i > 0) {
+ addSpacer(row);
+ }
+ mVolumeRowContainer.addView(row.view);
+ }
+ }
+
+ private void addSpacer(VolumeRow row) {
+ final View v = new View(mContext);
+ v.setId(android.R.id.background);
+ final int h = mContext.getResources()
+ .getDimensionPixelSize(R.dimen.volume_slider_interspacing);
+ final LinearLayout.LayoutParams lp =
+ new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, h);
+ mVolumeRowContainer.addView(v, lp);
+ row.space = v;
+ }
+
private boolean isAttached() {
return mDialogContentView != null && mDialogContentView.isAttachedToWindow();
}
@@ -345,18 +356,6 @@
return null;
}
- private void repositionExpandAnim(VolumeRow row) {
- final int[] loc = new int[2];
- row.settingsButton.getLocationInWindow(loc);
- final MarginLayoutParams mlp = (MarginLayoutParams) mDialogView.getLayoutParams();
- final int x = loc[0] - mlp.leftMargin;
- final int y = loc[1] - mlp.topMargin;
- if (D.BUG) Log.d(TAG, "repositionExpandAnim x=" + x + " y=" + y);
- mExpandButton.setTranslationX(x);
- mExpandButton.setTranslationY(y);
- mExpandButton.setTag((Integer) y);
- }
-
public void dump(PrintWriter writer) {
writer.println(VolumeDialog.class.getSimpleName() + " state:");
writer.print(" mShowing: "); writer.println(mShowing);
@@ -374,8 +373,8 @@
}
@SuppressLint("InflateParams")
- private VolumeRow initRow(final int stream, int iconRes, int iconMuteRes, boolean important) {
- final VolumeRow row = new VolumeRow();
+ private void initRow(final VolumeRow row, final int stream, int iconRes, int iconMuteRes,
+ boolean important) {
row.stream = stream;
row.iconRes = iconRes;
row.iconMuteRes = iconMuteRes;
@@ -442,9 +441,6 @@
row.userAttempt = 0; // reset the grace period, slider should update immediately
}
});
- row.settingsButton = (ImageButton) row.view.findViewById(R.id.volume_settings_button);
- row.settingsButton.setOnClickListener(mClickSettings);
- return row;
}
public void destroy() {
@@ -573,8 +569,6 @@
if (mExpandButtonAnimationRunning && isAttached()) return;
final int res = mExpanded ? R.drawable.ic_volume_collapse_animation
: R.drawable.ic_volume_expand_animation;
- if (res == mExpandButtonRes) return;
- mExpandButtonRes = res;
if (hasTouchFeature()) {
mExpandButton.setImageResource(res);
} else {
@@ -606,16 +600,6 @@
final boolean visible = isVisibleH(row, isActive);
Util.setVisOrGone(row.view, visible);
Util.setVisOrGone(row.space, visible && mExpanded);
- final int expandButtonRes = mExpanded ? R.drawable.ic_volume_settings : 0;
- if (expandButtonRes != row.cachedExpandButtonRes) {
- row.cachedExpandButtonRes = expandButtonRes;
- if (expandButtonRes == 0) {
- row.settingsButton.setImageDrawable(null);
- } else {
- row.settingsButton.setImageResource(expandButtonRes);
- }
- }
- Util.setVisOrInvis(row.settingsButton, false);
updateVolumeRowHeaderVisibleH(row);
row.header.setAlpha(mExpanded && isActive ? 1 : 0.5f);
updateVolumeRowSliderTintH(row, isActive);
@@ -629,8 +613,8 @@
if (row.ss == null || !row.ss.dynamic) continue;
if (!mDynamic.get(row.stream)) {
mRows.remove(i);
- mDialogContentView.removeView(row.view);
- mDialogContentView.removeView(row.space);
+ mVolumeRowContainer.removeView(row.view);
+ mVolumeRowContainer.removeView(row.space);
}
}
}
@@ -911,6 +895,12 @@
@Override
public void onConfigurationChanged() {
+ Configuration newConfig = mContext.getResources().getConfiguration();
+ final int density = newConfig.densityDpi;
+ if (density != mDensity) {
+ mDialog.dismiss();
+ initDialog();
+ }
updateWindowWidthH();
mSpTexts.update();
mZenFooter.onConfigurationChanged();
@@ -963,21 +953,6 @@
}
};
- private final OnClickListener mClickSettings = new OnClickListener() {
- @Override
- public void onClick(View v) {
- mSettingsButton.postDelayed(new Runnable() {
- @Override
- public void run() {
- Events.writeEvent(mContext, Events.EVENT_SETTINGS_CLICK);
- if (mCallback != null) {
- mCallback.onSettingsClicked();
- }
- }
- }, WAIT_FOR_RIPPLE);
- }
- };
-
private final class H extends Handler {
private static final int SHOW = 1;
private static final int DISMISS = 2;
@@ -1155,7 +1130,6 @@
private TextView header;
private ImageButton icon;
private SeekBar slider;
- private ImageButton settingsButton;
private int stream;
private StreamState ss;
private long userAttempt; // last user-driven slider change
@@ -1168,12 +1142,10 @@
private ColorStateList cachedSliderTint;
private int iconState; // from Events
private boolean cachedShowHeaders = VolumePrefs.DEFAULT_SHOW_HEADERS;
- private int cachedExpandButtonRes;
private int lastAudibleLevel = 1;
}
public interface Callback {
- void onSettingsClicked();
void onZenSettingsClicked();
void onZenPrioritySettingsClicked();
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
index d7635ad..3d33809 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
@@ -168,11 +168,6 @@
private final VolumeDialog.Callback mVolumeDialogCallback = new VolumeDialog.Callback() {
@Override
- public void onSettingsClicked() {
- startSettings(new Intent(Settings.ACTION_NOTIFICATION_SETTINGS));
- }
-
- @Override
public void onZenSettingsClicked() {
startSettings(ZenModePanel.ZEN_SETTINGS);
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePrefs.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePrefs.java
index 04339eb..bbb70ed 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePrefs.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePrefs.java
@@ -43,7 +43,7 @@
public static final String PREF_ADJUST_ALARMS = "pref_adjust_alarms";
public static final String PREF_ADJUST_NOTIFICATION = "pref_adjust_notification";
- public static final boolean DEFAULT_SHOW_HEADERS = true;
+ public static final boolean DEFAULT_SHOW_HEADERS = false;
public static final boolean DEFAULT_ENABLE_AUTOMUTE = true;
public static final boolean DEFAULT_ENABLE_SILENT_MODE = true;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
index a03e7f7..005767f 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
@@ -131,7 +131,7 @@
final boolean isForever = mConfig != null && mConfig.manualRule != null
&& mConfig.manualRule.conditionId == null;
- final String line2 =
+ final CharSequence line2 =
isForever ? mContext.getString(com.android.internal.R.string.zen_mode_forever_dnd)
: ZenModeConfig.getConditionSummary(mContext, mConfig, mController.getCurrentUser(),
true /*shortVersion*/);
@@ -139,9 +139,8 @@
}
public void onConfigurationChanged() {
- mEndNowButton.setText(mContext.getString(R.string.volume_zen_end_now));
- mSpTexts.update();
Util.setText(mEndNowButton, mContext.getString(R.string.volume_zen_end_now));
+ mSpTexts.update();
}
}
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index 964688b..c9c5805 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -29,9 +29,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src) \
$(call all-Iaidl-files-under, src) \
- $(call all-java-files-under, ../src) \
- $(call all-proto-files-under, ../src) \
- src/com/android/systemui/EventLogTags.logtags
+ $(call all-java-files-under, ../src)
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res \
frameworks/support/v7/preference/res \
@@ -53,7 +51,8 @@
android-support-v7-preference \
android-support-v7-appcompat \
android-support-v14-preference \
- android-support-v17-leanback
+ android-support-v17-leanback \
+ SystemUI-proto-tags
# sign this with platform cert, so this test is allowed to inject key events into
# UI it doesn't own. This is necessary to allow screenshots to be taken
diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index 2825601..5389c804 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -20,6 +20,8 @@
<uses-permission android:name="android.permission.INJECT_EVENTS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<uses-permission android:name="android.permission.MANAGE_USERS" />
<application>
diff --git a/packages/SystemUI/tests/src/com/android/systemui/EventLogTags.logtags b/packages/SystemUI/tests/src/com/android/systemui/EventLogTags.logtags
deleted file mode 120000
index 2f243d7..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/EventLogTags.logtags
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../src/com/android/systemui/EventLogTags.logtags
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/TouchAnimatorTests.java b/packages/SystemUI/tests/src/com/android/systemui/qs/TouchAnimatorTests.java
new file mode 100644
index 0000000..1d81fd4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/TouchAnimatorTests.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.qs;
+
+import android.view.View;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.qs.TouchAnimator.Listener;
+import org.mockito.Mockito;
+
+public class TouchAnimatorTests extends SysuiTestCase {
+
+ private Listener mTouchListener;
+ private View mTestView;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mTestView = new View(getContext());
+ mTouchListener = Mockito.mock(Listener.class);
+ }
+
+ public void testSetValueFloat() {
+ TouchAnimator animator = new TouchAnimator.Builder()
+ .addFloat(mTestView, "x", 0, 50)
+ .build();
+
+ animator.setPosition(0);
+ assertEquals(0f, mTestView.getX());
+
+ animator.setPosition(.5f);
+ assertEquals(25f, mTestView.getX());
+
+ animator.setPosition(1);
+ assertEquals(50f, mTestView.getX());
+ }
+
+ public void testSetValueInt() {
+ TouchAnimator animator = new TouchAnimator.Builder()
+ .addInt(mTestView, "top", 0, 50)
+ .build();
+
+ animator.setPosition(0);
+ assertEquals(0, mTestView.getTop());
+
+ animator.setPosition(.5f);
+ assertEquals(25, mTestView.getTop());
+
+ animator.setPosition(1);
+ assertEquals(50, mTestView.getTop());
+ }
+
+ public void testStartDelay() {
+ TouchAnimator animator = new TouchAnimator.Builder()
+ .addFloat(mTestView, "x", 0, 50)
+ .setStartDelay(.5f)
+ .build();
+
+ animator.setPosition(0);
+ assertEquals(0f, mTestView.getX());
+
+ animator.setPosition(.5f);
+ assertEquals(0f, mTestView.getX());
+
+ animator.setPosition(.75f);
+ assertEquals(25f, mTestView.getX());
+
+ animator.setPosition(1);
+ assertEquals(50f, mTestView.getX());
+ }
+
+ public void testEndDelay() {
+ TouchAnimator animator = new TouchAnimator.Builder()
+ .addFloat(mTestView, "x", 0, 50)
+ .setEndDelay(.5f)
+ .build();
+
+ animator.setPosition(0);
+ assertEquals(0f, mTestView.getX());
+
+ animator.setPosition(.25f);
+ assertEquals(25f, mTestView.getX());
+
+ animator.setPosition(.5f);
+ assertEquals(50f, mTestView.getX());
+
+ animator.setPosition(1);
+ assertEquals(50f, mTestView.getX());
+ }
+
+ public void testOnAnimationAtStartCallback() {
+ TouchAnimator animator = new TouchAnimator.Builder()
+ .setListener(mTouchListener)
+ .build();
+
+ // Called on init.
+ animator.setPosition(0);
+ verifyOnAnimationAtStart(1);
+
+ // Not called from same state.
+ animator.setPosition(0);
+ verifyOnAnimationAtStart(1);
+
+ // Called after starting and moving back to start.
+ animator.setPosition(.5f);
+ animator.setPosition(0);
+ verifyOnAnimationAtStart(2);
+
+ // Called when move from end to end.
+ animator.setPosition(1);
+ animator.setPosition(0);
+ verifyOnAnimationAtStart(3);
+ }
+
+ public void testOnAnimationAtEndCallback() {
+ TouchAnimator animator = new TouchAnimator.Builder()
+ .setListener(mTouchListener)
+ .build();
+
+ // Called on init.
+ animator.setPosition(1);
+ verifyOnAnimationAtEnd(1);
+
+ // Not called from same state.
+ animator.setPosition(1);
+ verifyOnAnimationAtEnd(1);
+
+ // Called after starting and moving back to end.
+ animator.setPosition(.5f);
+ animator.setPosition(1);
+ verifyOnAnimationAtEnd(2);
+
+ // Called when move from end to end.
+ animator.setPosition(0);
+ animator.setPosition(1);
+ verifyOnAnimationAtEnd(3);
+ }
+
+ public void testOnAnimationStartedCallback() {
+ TouchAnimator animator = new TouchAnimator.Builder()
+ .setListener(mTouchListener)
+ .build();
+
+ // Called on init.
+ animator.setPosition(.5f);
+ verifyOnAnimationStarted(1);
+
+ // Not called from same state.
+ animator.setPosition(.6f);
+ verifyOnAnimationStarted(1);
+
+ // Called after going to end then moving again.
+ animator.setPosition(1);
+ animator.setPosition(.5f);
+ verifyOnAnimationStarted(2);
+
+ // Called after moving to start then moving again.
+ animator.setPosition(0);
+ animator.setPosition(.5f);
+ verifyOnAnimationStarted(3);
+ }
+
+ // TODO: Add test for interpolator.
+
+ private void verifyOnAnimationAtStart(int times) {
+ Mockito.verify(mTouchListener, Mockito.times(times)).onAnimationAtStart();
+ }
+
+ private void verifyOnAnimationAtEnd(int times) {
+ Mockito.verify(mTouchListener, Mockito.times(times)).onAnimationAtEnd();
+ }
+
+ private void verifyOnAnimationStarted(int times) {
+ Mockito.verify(mTouchListener, Mockito.times(times)).onAnimationStarted();
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java
index c4ca039..01514646b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java
@@ -19,6 +19,9 @@
import android.os.Looper;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.statusbar.policy.DataSaverController;
+import com.android.systemui.statusbar.policy.HotspotController;
+import com.android.systemui.statusbar.policy.NetworkController;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
@@ -34,8 +37,13 @@
protected void setUp() throws Exception {
super.setUp();
mManagers = new ArrayList<>();
- QSTileHost host = new QSTileHost(mContext, null, null, null, null, null, null, null, null,
- null, null, null, null, null, null, null);
+ final NetworkController networkController = Mockito.mock(NetworkController.class);
+ Mockito.when(networkController.getDataSaverController()).thenReturn(
+ Mockito.mock(DataSaverController.class));
+ QSTileHost host = new QSTileHost(mContext, null, null, null, null,
+ networkController, null,
+ Mockito.mock(HotspotController.class), null,
+ null, null, null, null, null, null, null, null);
mTileService = new TestTileServices(host, Looper.myLooper());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
index 00b8de2..19cb243 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
@@ -19,12 +19,10 @@
import android.telephony.SubscriptionInfo;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
-
import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
-import com.android.systemui.statusbar.policy.NetworkControllerImpl.EmergencyListener;
-
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 5cf3767..60d33fa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -16,9 +16,6 @@
package com.android.systemui.statusbar.policy;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
@@ -31,14 +28,13 @@
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Log;
-
import com.android.internal.telephony.cdma.EriInfo;
import com.android.settingslib.net.DataUsageController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults;
-
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
@@ -47,6 +43,9 @@
import java.util.ArrayList;
import java.util.List;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
public class NetworkControllerBaseTest extends SysuiTestCase {
private static final String TAG = "NetworkControllerBaseTest";
protected static final int DEFAULT_LEVEL = 2;
@@ -102,13 +101,14 @@
// Trigger blank callbacks to always get the current state (some tests don't trigger
// changes from default state).
- mNetworkController.addSignalCallback(null);
+ mNetworkController.addSignalCallback(mock(SignalCallback.class));
mNetworkController.addEmergencyListener(null);
}
protected void setupNetworkController() {
// For now just pretend to be the data sim, so we can test that too.
mSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
+ when(mMockTm.getDataEnabled(mSubId)).thenReturn(true);
setDefaultSubId(mSubId);
setSubscriptions(mSubId);
mMobileSignalController = mNetworkController.mMobileSignalControllers.get(mSubId);
diff --git a/preloaded-classes b/preloaded-classes
index 2301c41..be645d2 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -1,4 +1,3 @@
-# Classes which are preloaded by com.android.internal.os.ZygoteInit.
[B
[C
[D
@@ -10,6 +9,7 @@
[Landroid.animation.Keyframe$FloatKeyframe;
[Landroid.animation.Keyframe$IntKeyframe;
[Landroid.animation.Keyframe$ObjectKeyframe;
+[Landroid.animation.Keyframe;
[Landroid.animation.PropertyValuesHolder;
[Landroid.app.LoaderManagerImpl;
[Landroid.content.ContentProviderResult;
@@ -26,12 +26,16 @@
[Landroid.content.pm.ProviderInfo;
[Landroid.content.pm.ServiceInfo;
[Landroid.content.pm.Signature;
+[Landroid.content.res.Configuration;
[Landroid.content.res.StringBlock;
[Landroid.content.res.XmlBlock;
+[Landroid.database.Cursor;
[Landroid.database.CursorWindow;
[Landroid.database.sqlite.SQLiteConnection$Operation;
[Landroid.database.sqlite.SQLiteConnectionPool$AcquiredConnectionStatus;
+[Landroid.graphics.Bitmap$CompressFormat;
[Landroid.graphics.Bitmap$Config;
+[Landroid.graphics.Bitmap;
[Landroid.graphics.Canvas$EdgeType;
[Landroid.graphics.FontFamily;
[Landroid.graphics.Interpolator$Result;
@@ -50,10 +54,12 @@
[Landroid.graphics.drawable.GradientDrawable$Orientation;
[Landroid.graphics.drawable.LayerDrawable$ChildDrawable;
[Landroid.graphics.drawable.RippleForeground;
+[Landroid.hardware.display.WifiDisplay;
[Landroid.hardware.soundtrigger.SoundTrigger$ConfidenceLevel;
[Landroid.hardware.soundtrigger.SoundTrigger$Keyphrase;
[Landroid.hardware.soundtrigger.SoundTrigger$KeyphraseRecognitionExtra;
[Landroid.icu.impl.ICUResourceBundle$OpenType;
+[Landroid.icu.impl.StandardPlural;
[Landroid.icu.impl.Trie2$ValueWidth;
[Landroid.icu.impl.UCharacterProperty$BinaryProperty;
[Landroid.icu.impl.UCharacterProperty$IntProperty;
@@ -67,17 +73,17 @@
[Landroid.icu.text.MessagePattern$ApostropheMode;
[Landroid.icu.text.MessagePattern$ArgType;
[Landroid.icu.text.MessagePattern$Part$Type;
+[Landroid.icu.text.PluralRules$Operand;
+[Landroid.icu.text.PluralRules$PluralType;
+[Landroid.icu.text.PluralRules$SampleType;
[Landroid.icu.text.UnicodeSet;
[Landroid.icu.util.BytesTrie$Result;
[Landroid.icu.util.Calendar$CalType;
+[Landroid.icu.util.Currency$CurrencyUsage;
[Landroid.icu.util.ULocale$Category;
[Landroid.icu.util.ULocale;
-[Landroid.media.AudioDeviceInfo;
[Landroid.media.AudioGain;
-[Landroid.media.AudioPatch;
-[Landroid.media.AudioPort;
-[Landroid.media.AudioPortConfig;
-[Landroid.media.MediaTimeProvider$OnMediaTimeListener;
+[Landroid.net.Network;
[Landroid.net.NetworkInfo$DetailedState;
[Landroid.net.NetworkInfo$State;
[Landroid.net.Uri;
@@ -85,6 +91,7 @@
[Landroid.os.AsyncTask$Status;
[Landroid.os.MessageQueue$IdleHandler;
[Landroid.os.Parcel;
+[Landroid.os.ParcelFileDescriptor;
[Landroid.os.Parcelable;
[Landroid.os.PatternMatcher;
[Landroid.os.storage.StorageVolume;
@@ -102,6 +109,7 @@
[Landroid.text.method.TextKeyListener;
[Landroid.text.style.AlignmentSpan;
[Landroid.text.style.CharacterStyle;
+[Landroid.text.style.ClickableSpan;
[Landroid.text.style.LeadingMarginSpan;
[Landroid.text.style.LineBackgroundSpan;
[Landroid.text.style.LineHeightSpan;
@@ -114,9 +122,13 @@
[Landroid.text.style.URLSpan;
[Landroid.text.style.WrapTogetherSpan;
[Landroid.util.LongSparseArray;
-[Landroid.util.PathParser$PathDataNode;
+[Landroid.util.Pair;
+[Landroid.util.Rational;
[Landroid.view.Choreographer$CallbackQueue;
+[Landroid.view.Display$ColorTransform;
[Landroid.view.Display$Mode;
+[Landroid.view.Display;
+[Landroid.view.HandlerActionQueue$HandlerAction;
[Landroid.view.MenuItem;
[Landroid.view.View;
[Landroid.widget.Editor$TextRenderNode;
@@ -130,17 +142,19 @@
[Lcom.android.internal.telephony.PhoneConstants$State;
[Lcom.android.okhttp.CipherSuite;
[Lcom.android.okhttp.ConnectionSpec;
+[Lcom.android.okhttp.HttpUrl$Builder$ParseResult;
[Lcom.android.okhttp.Protocol;
[Lcom.android.okhttp.TlsVersion;
[Lcom.android.org.bouncycastle.asn1.ASN1ObjectIdentifier;
-[Lcom.android.org.bouncycastle.asn1.x500.RDN;
-[Lcom.android.org.bouncycastle.asn1.x509.GeneralName;
[Lcom.android.org.conscrypt.OpenSSLX509CertPath$Encoding;
[Lcom.android.org.conscrypt.OpenSSLX509Certificate;
[Ldalvik.system.DexPathList$Element;
+[Ljava.beans.PropertyChangeListener;
+[Ljava.io.File$PathStatus;
[Ljava.io.File;
[Ljava.io.FileDescriptor;
[Ljava.io.IOException;
+[Ljava.io.ObjectInputStream$HandleTable$HandleList;
[Ljava.io.ObjectStreamField;
[Ljava.lang.Byte;
[Ljava.lang.CharSequence;
@@ -159,9 +173,11 @@
[Ljava.lang.Thread$State;
[Ljava.lang.Thread;
[Ljava.lang.ThreadGroup;
+[Ljava.lang.ThreadLocal$ThreadLocalMap$Entry;
[Ljava.lang.Throwable;
[Ljava.lang.Void;
[Ljava.lang.annotation.Annotation;
+[Ljava.lang.ref.WeakReference;
[Ljava.lang.reflect.AccessibleObject;
[Ljava.lang.reflect.Constructor;
[Ljava.lang.reflect.Field;
@@ -173,18 +189,24 @@
[Ljava.math.RoundingMode;
[Ljava.net.InetAddress;
[Ljava.net.Proxy$Type;
+[Ljava.nio.ByteBuffer;
+[Ljava.security.CryptoPrimitive;
+[Ljava.security.Principal;
[Ljava.security.Provider;
[Ljava.security.cert.Certificate;
[Ljava.security.cert.X509Certificate;
-[Ljava.text.Format$Field;
+[Ljava.text.DateFormat$Field;
+[Ljava.text.Normalizer$Form;
[Ljava.util.ArrayList;
+[Ljava.util.Enumeration;
+[Ljava.util.Formatter$Flags;
+[Ljava.util.Formatter$FormatString;
[Ljava.util.HashMap$HashMapEntry;
[Ljava.util.Hashtable$HashtableEntry;
+[Ljava.util.Locale$Category;
[Ljava.util.Locale;
[Ljava.util.Map$Entry;
[Ljava.util.TimerTask;
-[Ljava.util.TreeMap$Bound;
-[Ljava.util.TreeMap$Relation;
[Ljava.util.WeakHashMap$Entry;
[Ljava.util.concurrent.ConcurrentHashMap$Node;
[Ljava.util.concurrent.ConcurrentHashMap$Segment;
@@ -192,32 +214,40 @@
[Ljava.util.concurrent.TimeUnit;
[Ljava.util.logging.Handler;
[Ljava.util.regex.Pattern;
+[Ljavax.crypto.Cipher$InitType;
[Ljavax.crypto.Cipher$NeedToSet;
+[Ljavax.microedition.khronos.egl.EGLConfig;
[Ljavax.net.ssl.KeyManager;
+[Ljavax.net.ssl.SSLSession;
[Ljavax.net.ssl.TrustManager;
+[Ljavax.security.auth.x500.X500Principal;
[Ljavax.security.cert.X509Certificate;
+[Llibcore.io.ClassPathURLStreamHandler;
[Llibcore.reflect.AnnotationMember$DefaultValues;
[Llibcore.reflect.AnnotationMember;
-[Lorg.apache.harmony.security.asn1.ASN1Type;
-[Lorg.apache.harmony.security.utils.ObjectIdentifier;
[Lorg.apache.http.Header;
-[Lorg.apache.http.HeaderElement;
-[Lorg.apache.http.NameValuePair;
-[Lorg.apache.http.conn.routing.RouteInfo$LayerType;
-[Lorg.apache.http.conn.routing.RouteInfo$TunnelType;
[Lorg.json.JSONStringer$Scope;
[Lorg.kxml2.io.KXmlParser$ValueContext;
+[Lsun.misc.FormattedFloatingDecimal$Form;
+[Lsun.security.jca.ProviderConfig;
+[Lsun.security.jca.ServiceId;
+[Lsun.security.pkcs.SignerInfo;
+[Lsun.security.util.DerOutputStream;
+[Lsun.security.util.DerValue;
+[Lsun.security.util.DisabledAlgorithmConstraints$KeySizeConstraint$Operator;
+[Lsun.security.util.ObjectIdentifier;
+[Lsun.security.x509.AVA;
+[Lsun.security.x509.RDN;
+[Lsun.util.logging.PlatformLogger$Level;
[S
[Z
[[B
-[[C
[[I
-[[Lcom.android.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+[[Ljava.lang.Byte;
[[Ljava.lang.Class;
[[Ljava.lang.Object;
[[Ljava.lang.String;
[[Ljava.lang.annotation.Annotation;
-[[Lorg.apache.harmony.security.utils.ObjectIdentifier;
[[S
[[[I
android.R$styleable
@@ -240,17 +270,22 @@
android.accounts.IAccountManagerResponse$Stub
android.accounts.OnAccountsUpdateListener
android.accounts.OperationCanceledException
+android.animation.AnimationHandler
+android.animation.AnimationHandler$1
+android.animation.AnimationHandler$2
+android.animation.AnimationHandler$AnimationFrameCallback
+android.animation.AnimationHandler$AnimationFrameCallbackProvider
+android.animation.AnimationHandler$MyFrameCallbackProvider
android.animation.Animator
android.animation.Animator$AnimatorConstantState
android.animation.Animator$AnimatorListener
android.animation.Animator$AnimatorPauseListener
android.animation.AnimatorInflater
+android.animation.AnimatorInflater$PathDataEvaluator
android.animation.AnimatorListenerAdapter
android.animation.AnimatorSet
android.animation.AnimatorSet$AnimatorSetListener
android.animation.AnimatorSet$Builder
-android.animation.AnimatorSet$Dependency
-android.animation.AnimatorSet$DependencyListener
android.animation.AnimatorSet$Node
android.animation.ArgbEvaluator
android.animation.FloatEvaluator
@@ -272,10 +307,12 @@
android.animation.PathKeyframes$1
android.animation.PathKeyframes$2
android.animation.PathKeyframes$FloatKeyframesBase
+android.animation.PathKeyframes$IntKeyframesBase
android.animation.PathKeyframes$SimpleKeyframes
android.animation.PropertyValuesHolder
android.animation.PropertyValuesHolder$FloatPropertyValuesHolder
android.animation.PropertyValuesHolder$IntPropertyValuesHolder
+android.animation.PropertyValuesHolder$PropertyValues
android.animation.RectEvaluator
android.animation.StateListAnimator
android.animation.StateListAnimator$1
@@ -284,31 +321,34 @@
android.animation.TimeInterpolator
android.animation.TypeEvaluator
android.animation.ValueAnimator
-android.animation.ValueAnimator$AnimationHandler
-android.animation.ValueAnimator$AnimationHandler$1
-android.animation.ValueAnimator$AnimationHandler$2
android.animation.ValueAnimator$AnimatorUpdateListener
android.app.ActionBar
android.app.ActionBar$LayoutParams
android.app.Activity
android.app.Activity$HostCallbacks
android.app.ActivityManager
+android.app.ActivityManager$MemoryInfo
+android.app.ActivityManager$RecentTaskInfo
android.app.ActivityManager$RunningAppProcessInfo
android.app.ActivityManager$RunningAppProcessInfo$1
+android.app.ActivityManager$StackId
android.app.ActivityManager$TaskDescription
android.app.ActivityManager$TaskDescription$1
android.app.ActivityManagerNative
android.app.ActivityManagerNative$1
android.app.ActivityManagerProxy
+android.app.ActivityOptions
android.app.ActivityThread
android.app.ActivityThread$1
android.app.ActivityThread$2
android.app.ActivityThread$3
android.app.ActivityThread$ActivityClientRecord
+android.app.ActivityThread$ActivityConfigChangeData
android.app.ActivityThread$AppBindData
android.app.ActivityThread$ApplicationThread
android.app.ActivityThread$BindServiceData
android.app.ActivityThread$ContextCleanupInfo
+android.app.ActivityThread$CreateBackupAgentData
android.app.ActivityThread$CreateServiceData
android.app.ActivityThread$DropBoxReporter
android.app.ActivityThread$EventLoggingReporter
@@ -343,6 +383,7 @@
android.app.Dialog
android.app.Dialog$1
android.app.Dialog$ListenersHandler
+android.app.DialogFragment
android.app.DownloadManager
android.app.Fragment
android.app.Fragment$1
@@ -361,6 +402,8 @@
android.app.IAlarmManager$Stub
android.app.IAlarmManager$Stub$Proxy
android.app.IApplicationThread
+android.app.IBackupAgent
+android.app.IBackupAgent$Stub
android.app.IInstrumentationWatcher
android.app.IInstrumentationWatcher$Stub
android.app.INotificationManager
@@ -368,6 +411,8 @@
android.app.INotificationManager$Stub$Proxy
android.app.IServiceConnection
android.app.IServiceConnection$Stub
+android.app.ITransientNotification
+android.app.ITransientNotification$Stub
android.app.IUiAutomationConnection
android.app.IUiAutomationConnection$Stub
android.app.Instrumentation
@@ -391,10 +436,11 @@
android.app.NativeActivity
android.app.Notification
android.app.Notification$1
+android.app.Notification$Action
+android.app.Notification$BigTextStyle
android.app.Notification$Builder
-android.app.Notification$BuilderRemoteViews
+android.app.Notification$Style
android.app.NotificationManager
-android.app.OnActivityPausedListener
android.app.PendingIntent
android.app.PendingIntent$1
android.app.PendingIntent$CanceledException
@@ -481,11 +527,14 @@
android.app.SystemServiceRegistry$66
android.app.SystemServiceRegistry$67
android.app.SystemServiceRegistry$68
+android.app.SystemServiceRegistry$69
android.app.SystemServiceRegistry$7
+android.app.SystemServiceRegistry$70
android.app.SystemServiceRegistry$8
android.app.SystemServiceRegistry$9
android.app.SystemServiceRegistry$CachedServiceFetcher
android.app.SystemServiceRegistry$ServiceFetcher
+android.app.SystemServiceRegistry$StaticOuterContextServiceFetcher
android.app.SystemServiceRegistry$StaticServiceFetcher
android.app.UiModeManager
android.app.WallpaperManager
@@ -493,12 +542,15 @@
android.app.admin.IDevicePolicyManager
android.app.admin.IDevicePolicyManager$Stub
android.app.admin.IDevicePolicyManager$Stub$Proxy
+android.app.backup.BackupAgent
+android.app.backup.BackupAgent$BackupServiceBinder
+android.app.backup.BackupAgent$SharedPrefsSynchronizer
+android.app.backup.BackupAgentHelper
android.app.backup.BackupDataInput
android.app.backup.BackupDataInput$EntityHeader
android.app.backup.BackupDataOutput
android.app.backup.BackupHelperDispatcher
android.app.backup.BackupHelperDispatcher$Header
-android.app.backup.BackupManager
android.app.backup.FileBackupHelperBase
android.app.backup.FullBackup
android.app.backup.FullBackupDataOutput
@@ -514,12 +566,14 @@
android.app.usage.UsageStatsManager
android.appwidget.AppWidgetManager
android.appwidget.AppWidgetProvider
+android.auditing.SecurityLog
+android.auditing.SecurityLog$SecurityEvent
+android.auditing.SecurityLog$SecurityEvent$1
android.bluetooth.BluetoothAdapter
android.bluetooth.BluetoothAdapter$1
android.bluetooth.BluetoothManager
android.bluetooth.IBluetooth
android.bluetooth.IBluetooth$Stub
-android.bluetooth.IBluetooth$Stub$Proxy
android.bluetooth.IBluetoothManager
android.bluetooth.IBluetoothManager$Stub
android.bluetooth.IBluetoothManager$Stub$Proxy
@@ -531,8 +585,9 @@
android.content.ActivityNotFoundException
android.content.BroadcastReceiver
android.content.BroadcastReceiver$PendingResult
-android.content.BroadcastReceiver$PendingResult$1
android.content.ClipData
+android.content.ClipData$1
+android.content.ClipData$Item
android.content.ClipDescription
android.content.ClipDescription$1
android.content.ClipboardManager
@@ -545,10 +600,9 @@
android.content.ContentProviderClient
android.content.ContentProviderNative
android.content.ContentProviderOperation
-android.content.ContentProviderOperation$1
+android.content.ContentProviderOperation$Builder
android.content.ContentProviderProxy
android.content.ContentProviderResult
-android.content.ContentProviderResult$1
android.content.ContentResolver
android.content.ContentResolver$CursorWrapperInner
android.content.ContentResolver$ParcelFileDescriptorInner
@@ -583,6 +637,7 @@
android.content.IntentSender
android.content.IntentSender$SendIntentException
android.content.OperationApplicationException
+android.content.PeriodicSync
android.content.RestrictionsManager
android.content.ServiceConnection
android.content.SharedPreferences
@@ -620,6 +675,8 @@
android.content.pm.LauncherApps
android.content.pm.PackageInfo
android.content.pm.PackageInfo$1
+android.content.pm.PackageInstaller
+android.content.pm.PackageInstaller$SessionInfo
android.content.pm.PackageItemInfo
android.content.pm.PackageManager
android.content.pm.PackageManager$NameNotFoundException
@@ -646,14 +703,17 @@
android.content.res.AssetManager$AssetInputStream
android.content.res.ColorStateList
android.content.res.ColorStateList$1
+android.content.res.ColorStateList$ColorStateListFactory
android.content.res.CompatibilityInfo
android.content.res.CompatibilityInfo$1
android.content.res.CompatibilityInfo$2
+android.content.res.ComplexColor
android.content.res.Configuration
android.content.res.Configuration$1
android.content.res.ConfigurationBoundResourceCache
android.content.res.ConstantState
android.content.res.DrawableCache
+android.content.res.GradientColor
android.content.res.ObbInfo
android.content.res.ObbInfo$1
android.content.res.ObbScanner
@@ -685,6 +745,7 @@
android.database.CrossProcessCursor
android.database.CrossProcessCursorWrapper
android.database.Cursor
+android.database.CursorIndexOutOfBoundsException
android.database.CursorToBulkCursorAdaptor
android.database.CursorToBulkCursorAdaptor$ContentObserverProxy
android.database.CursorWindow
@@ -700,6 +761,8 @@
android.database.IContentObserver$Stub
android.database.IContentObserver$Stub$Proxy
android.database.MatrixCursor
+android.database.MatrixCursor$RowBuilder
+android.database.MergeCursor
android.database.Observable
android.database.SQLException
android.database.sqlite.DatabaseObjectNotClosedException
@@ -712,11 +775,13 @@
android.database.sqlite.SQLiteConnectionPool
android.database.sqlite.SQLiteConnectionPool$AcquiredConnectionStatus
android.database.sqlite.SQLiteConnectionPool$ConnectionWaiter
+android.database.sqlite.SQLiteConstraintException
android.database.sqlite.SQLiteCursor
android.database.sqlite.SQLiteCursorDriver
android.database.sqlite.SQLiteCustomFunction
android.database.sqlite.SQLiteDatabase
android.database.sqlite.SQLiteDatabase$1
+android.database.sqlite.SQLiteDatabase$CursorFactory
android.database.sqlite.SQLiteDatabaseConfiguration
android.database.sqlite.SQLiteDatabaseCorruptException
android.database.sqlite.SQLiteDatabaseLockedException
@@ -745,7 +810,7 @@
android.graphics.AvoidXfermode
android.graphics.Bitmap
android.graphics.Bitmap$1
-android.graphics.Bitmap$BitmapFinalizer
+android.graphics.Bitmap$CompressFormat
android.graphics.Bitmap$Config
android.graphics.BitmapFactory
android.graphics.BitmapFactory$Options
@@ -754,11 +819,11 @@
android.graphics.BlurMaskFilter
android.graphics.Camera
android.graphics.Canvas
-android.graphics.Canvas$CanvasFinalizer
android.graphics.Canvas$EdgeType
android.graphics.CanvasProperty
android.graphics.Color
android.graphics.ColorFilter
+android.graphics.ColorMatrix
android.graphics.ColorMatrixColorFilter
android.graphics.ComposePathEffect
android.graphics.ComposeShader
@@ -770,6 +835,7 @@
android.graphics.FontFamily
android.graphics.FontListParser
android.graphics.FontListParser$Alias
+android.graphics.FontListParser$Axis
android.graphics.FontListParser$Config
android.graphics.FontListParser$Family
android.graphics.FontListParser$Font
@@ -808,6 +874,7 @@
android.graphics.Point$1
android.graphics.PointF
android.graphics.PointF$1
+android.graphics.PorterDuff
android.graphics.PorterDuff$Mode
android.graphics.PorterDuffColorFilter
android.graphics.PorterDuffXfermode
@@ -836,11 +903,11 @@
android.graphics.drawable.Animatable2
android.graphics.drawable.AnimatedStateListDrawable
android.graphics.drawable.AnimatedStateListDrawable$AnimatedStateListState
-android.graphics.drawable.AnimatedStateListDrawable$Transition
android.graphics.drawable.AnimatedVectorDrawable
android.graphics.drawable.AnimatedVectorDrawable$1
android.graphics.drawable.AnimatedVectorDrawable$AnimatedVectorDrawableState
android.graphics.drawable.AnimatedVectorDrawable$AnimatedVectorDrawableState$PendingAnimator
+android.graphics.drawable.AnimatedVectorDrawable$VectorDrawableAnimatorRT
android.graphics.drawable.AnimationDrawable
android.graphics.drawable.AnimationDrawable$AnimationState
android.graphics.drawable.BitmapDrawable
@@ -852,7 +919,7 @@
android.graphics.drawable.Drawable$ConstantState
android.graphics.drawable.DrawableContainer
android.graphics.drawable.DrawableContainer$DrawableContainerState
-android.graphics.drawable.DrawableContainer$DrawableContainerState$ConstantStateFuture
+android.graphics.drawable.DrawableInflater
android.graphics.drawable.DrawableWrapper
android.graphics.drawable.DrawableWrapper$DrawableWrapperState
android.graphics.drawable.GradientDrawable
@@ -892,9 +959,11 @@
android.graphics.drawable.TransitionDrawable$TransitionState
android.graphics.drawable.VectorDrawable
android.graphics.drawable.VectorDrawable$VFullPath
+android.graphics.drawable.VectorDrawable$VFullPath$1
android.graphics.drawable.VectorDrawable$VGroup
+android.graphics.drawable.VectorDrawable$VGroup$1
+android.graphics.drawable.VectorDrawable$VObject
android.graphics.drawable.VectorDrawable$VPath
-android.graphics.drawable.VectorDrawable$VPathRenderer
android.graphics.drawable.VectorDrawable$VectorDrawableState
android.graphics.drawable.shapes.OvalShape
android.graphics.drawable.shapes.RectShape
@@ -913,7 +982,10 @@
android.hardware.SerialPort
android.hardware.SystemSensorManager
android.hardware.SystemSensorManager$BaseEventQueue
+android.hardware.camera2.CameraCharacteristics$Key
android.hardware.camera2.CameraManager
+android.hardware.camera2.CaptureRequest$Key
+android.hardware.camera2.CaptureResult$Key
android.hardware.camera2.DngCreator
android.hardware.camera2.impl.CameraMetadataNative
android.hardware.camera2.legacy.LegacyCameraDevice
@@ -928,6 +1000,12 @@
android.hardware.display.IDisplayManager$Stub$Proxy
android.hardware.display.IDisplayManagerCallback
android.hardware.display.IDisplayManagerCallback$Stub
+android.hardware.display.WifiDisplay
+android.hardware.display.WifiDisplay$1
+android.hardware.display.WifiDisplaySessionInfo
+android.hardware.display.WifiDisplaySessionInfo$1
+android.hardware.display.WifiDisplayStatus
+android.hardware.display.WifiDisplayStatus$1
android.hardware.fingerprint.FingerprintManager
android.hardware.hdmi.HdmiControlManager
android.hardware.input.IInputDevicesChangedListener
@@ -939,6 +1017,10 @@
android.hardware.input.InputDeviceIdentifier$1
android.hardware.input.InputManager
android.hardware.input.InputManager$InputDevicesChangedListener
+# These cannot be preloaded and need to be refactored into system server. b/17791590, b/21935130
+# android.hardware.location.ActivityRecognitionHardware
+# android.hardware.location.IActivityRecognitionHardware
+# android.hardware.location.IActivityRecognitionHardware$Stub
android.hardware.radio.RadioManager
android.hardware.radio.RadioManager$AmBandConfig
android.hardware.radio.RadioManager$AmBandConfig$1
@@ -963,6 +1045,8 @@
android.hardware.soundtrigger.SoundTrigger
android.hardware.soundtrigger.SoundTrigger$ConfidenceLevel
android.hardware.soundtrigger.SoundTrigger$ConfidenceLevel$1
+android.hardware.soundtrigger.SoundTrigger$GenericRecognitionEvent
+android.hardware.soundtrigger.SoundTrigger$GenericSoundModel
android.hardware.soundtrigger.SoundTrigger$Keyphrase
android.hardware.soundtrigger.SoundTrigger$Keyphrase$1
android.hardware.soundtrigger.SoundTrigger$KeyphraseRecognitionEvent
@@ -981,14 +1065,19 @@
android.hardware.soundtrigger.SoundTrigger$SoundModelEvent
android.hardware.soundtrigger.SoundTrigger$SoundModelEvent$1
android.hardware.soundtrigger.SoundTriggerModule
+android.hardware.usb.IUsbManager
+android.hardware.usb.IUsbManager$Stub
+android.hardware.usb.IUsbManager$Stub$Proxy
android.hardware.usb.UsbDevice
android.hardware.usb.UsbDeviceConnection
+android.hardware.usb.UsbInterface
android.hardware.usb.UsbManager
android.hardware.usb.UsbRequest
android.icu.impl.BMPSet
android.icu.impl.CacheBase
android.icu.impl.CalendarData
android.icu.impl.CalendarUtil
+android.icu.impl.CharTrie
android.icu.impl.ClassLoaderUtil
android.icu.impl.CurrencyData
android.icu.impl.CurrencyData$CurrencyDisplayInfo
@@ -1012,8 +1101,17 @@
android.icu.impl.ICUCurrencyMetaInfo$UniqueList
android.icu.impl.ICUData
android.icu.impl.ICUDebug
+android.icu.impl.ICULocaleService
+android.icu.impl.ICULocaleService$ICUResourceBundleFactory
+android.icu.impl.ICULocaleService$LocaleKey
+android.icu.impl.ICULocaleService$LocaleKeyFactory
+android.icu.impl.ICUNotifier
+android.icu.impl.ICURWLock
android.icu.impl.ICUResourceBundle
android.icu.impl.ICUResourceBundle$1
+android.icu.impl.ICUResourceBundle$2
+android.icu.impl.ICUResourceBundle$2$1
+android.icu.impl.ICUResourceBundle$AvailEntry
android.icu.impl.ICUResourceBundle$OpenType
android.icu.impl.ICUResourceBundle$WholeBundle
android.icu.impl.ICUResourceBundleImpl
@@ -1027,27 +1125,52 @@
android.icu.impl.ICUResourceBundleReader
android.icu.impl.ICUResourceBundleReader$Array
android.icu.impl.ICUResourceBundleReader$Array16
+android.icu.impl.ICUResourceBundleReader$Array32
android.icu.impl.ICUResourceBundleReader$Container
android.icu.impl.ICUResourceBundleReader$IsAcceptable
android.icu.impl.ICUResourceBundleReader$ReaderCache
-android.icu.impl.ICUResourceBundleReader$ReaderInfo
+android.icu.impl.ICUResourceBundleReader$ReaderCacheKey
android.icu.impl.ICUResourceBundleReader$ResourceCache
android.icu.impl.ICUResourceBundleReader$ResourceCache$Level
android.icu.impl.ICUResourceBundleReader$Table
android.icu.impl.ICUResourceBundleReader$Table16
android.icu.impl.ICUResourceBundleReader$Table1632
+android.icu.impl.ICUService
+android.icu.impl.ICUService$CacheEntry
+android.icu.impl.ICUService$Factory
+android.icu.impl.ICUService$Key
+android.icu.impl.IDNA2003
android.icu.impl.JavaTimeZone
android.icu.impl.LocaleIDParser
android.icu.impl.LocaleIDs
+android.icu.impl.Norm2AllModes
+android.icu.impl.Norm2AllModes$1
+android.icu.impl.Norm2AllModes$ComposeNormalizer2
+android.icu.impl.Norm2AllModes$DecomposeNormalizer2
+android.icu.impl.Norm2AllModes$FCDNormalizer2
+android.icu.impl.Norm2AllModes$NFCSingleton
+android.icu.impl.Norm2AllModes$NFKCSingleton
+android.icu.impl.Norm2AllModes$NoopNormalizer2
+android.icu.impl.Norm2AllModes$Norm2AllModesSingleton
+android.icu.impl.Norm2AllModes$Normalizer2WithImpl
+android.icu.impl.Normalizer2Impl
+android.icu.impl.Normalizer2Impl$1
+android.icu.impl.Normalizer2Impl$IsAcceptable
android.icu.impl.OlsonTimeZone
android.icu.impl.Pair
android.icu.impl.PatternProps
android.icu.impl.PatternTokenizer
+android.icu.impl.PluralRulesLoader
android.icu.impl.ReplaceableUCharacterIterator
android.icu.impl.RuleCharacterIterator
android.icu.impl.SimpleCache
android.icu.impl.SoftCache
android.icu.impl.SoftCache$SettableSoftReference
+android.icu.impl.StandardPlural
+android.icu.impl.StringPrepDataReader
+android.icu.impl.Trie
+android.icu.impl.Trie$DataManipulate
+android.icu.impl.Trie$DefaultGetFoldingOffset
android.icu.impl.Trie2
android.icu.impl.Trie2$1
android.icu.impl.Trie2$Range
@@ -1056,6 +1179,9 @@
android.icu.impl.Trie2$ValueMapper
android.icu.impl.Trie2$ValueWidth
android.icu.impl.Trie2_16
+android.icu.impl.Trie2_32
+android.icu.impl.UBiDiProps
+android.icu.impl.UBiDiProps$IsAcceptable
android.icu.impl.UCharacterProperty
android.icu.impl.UCharacterProperty$1
android.icu.impl.UCharacterProperty$10
@@ -1090,10 +1216,22 @@
android.icu.impl.UCharacterProperty$NormQuickCheckIntProperty
android.icu.impl.UPropertyAliases
android.icu.impl.UPropertyAliases$IsAcceptable
+android.icu.impl.URLHandler$URLVisitor
+android.icu.impl.USerializedSet
android.icu.impl.Utility
android.icu.impl.ZoneMeta
android.icu.impl.ZoneMeta$CustomTimeZoneCache
android.icu.impl.ZoneMeta$SystemTimeZoneCache
+android.icu.impl.coll.CollationData
+android.icu.impl.coll.CollationDataReader
+android.icu.impl.coll.CollationDataReader$IsAcceptable
+android.icu.impl.coll.CollationFastLatin
+android.icu.impl.coll.CollationLoader
+android.icu.impl.coll.CollationRoot
+android.icu.impl.coll.CollationSettings
+android.icu.impl.coll.CollationTailoring
+android.icu.impl.coll.SharedObject
+android.icu.impl.coll.SharedObject$Reference
android.icu.impl.locale.AsciiUtil
android.icu.impl.locale.BaseLocale
android.icu.impl.locale.BaseLocale$Cache
@@ -1106,6 +1244,13 @@
android.icu.lang.UCharacterEnums$ECharacterDirection
android.icu.lang.UScript
android.icu.lang.UScript$ScriptUsage
+android.icu.math.BigDecimal
+android.icu.math.MathContext
+android.icu.text.Collator
+android.icu.text.Collator$ServiceShim
+android.icu.text.CollatorServiceShim
+android.icu.text.CollatorServiceShim$CService
+android.icu.text.CollatorServiceShim$CService$1CollatorFactory
android.icu.text.CurrencyDisplayNames
android.icu.text.CurrencyMetaInfo
android.icu.text.CurrencyMetaInfo$CurrencyDigits
@@ -1129,9 +1274,12 @@
android.icu.text.DateTimePatternGenerator$PatternWithSkeletonFlag
android.icu.text.DateTimePatternGenerator$VariableField
android.icu.text.DecimalFormat
+android.icu.text.DecimalFormat$Unit
android.icu.text.DecimalFormatSymbols
+android.icu.text.DigitList
android.icu.text.DisplayContext
android.icu.text.DisplayContext$Type
+android.icu.text.IDNA
android.icu.text.MessageFormat
android.icu.text.MessageFormat$AppendableWrapper
android.icu.text.MessageFormat$Field
@@ -1140,13 +1288,48 @@
android.icu.text.MessagePattern$ArgType
android.icu.text.MessagePattern$Part
android.icu.text.MessagePattern$Part$Type
+android.icu.text.Normalizer
+android.icu.text.Normalizer$FCDMode
+android.icu.text.Normalizer$Mode
+android.icu.text.Normalizer$ModeImpl
+android.icu.text.Normalizer$NFCMode
+android.icu.text.Normalizer$NFDMode
+android.icu.text.Normalizer$NFKCMode
+android.icu.text.Normalizer$NFKDMode
+android.icu.text.Normalizer$NFKDModeImpl
+android.icu.text.Normalizer$NONEMode
+android.icu.text.Normalizer$QuickCheckResult
+android.icu.text.Normalizer2
android.icu.text.NumberFormat
+android.icu.text.NumberFormat$Field
android.icu.text.NumberingSystem
+android.icu.text.PluralRanges
+android.icu.text.PluralRanges$Matrix
+android.icu.text.PluralRules
+android.icu.text.PluralRules$1
+android.icu.text.PluralRules$AndConstraint
+android.icu.text.PluralRules$BinaryConstraint
+android.icu.text.PluralRules$Constraint
+android.icu.text.PluralRules$Factory
+android.icu.text.PluralRules$FixedDecimal
+android.icu.text.PluralRules$FixedDecimalRange
+android.icu.text.PluralRules$FixedDecimalSamples
+android.icu.text.PluralRules$Operand
+android.icu.text.PluralRules$PluralType
+android.icu.text.PluralRules$RangeConstraint
+android.icu.text.PluralRules$Rule
+android.icu.text.PluralRules$RuleList
+android.icu.text.PluralRules$SampleType
+android.icu.text.PluralRules$SimpleTokenizer
android.icu.text.Replaceable
android.icu.text.ReplaceableString
+android.icu.text.RuleBasedCollator
android.icu.text.SimpleDateFormat
android.icu.text.SimpleDateFormat$PatternItem
+android.icu.text.StringPrep
+android.icu.text.StringPrepParseException
android.icu.text.UCharacterIterator
+android.icu.text.UFieldPosition
android.icu.text.UFormat
android.icu.text.UForwardCharacterIterator
android.icu.text.UTF16
@@ -1166,6 +1349,7 @@
android.icu.util.Calendar$WeekData
android.icu.util.Calendar$WeekDataCache
android.icu.util.Currency
+android.icu.util.Currency$CurrencyUsage
android.icu.util.Currency$EquivalenceRelation
android.icu.util.Freezable
android.icu.util.GregorianCalendar
@@ -1174,6 +1358,7 @@
android.icu.util.MeasureUnit$2
android.icu.util.MeasureUnit$3
android.icu.util.MeasureUnit$Factory
+android.icu.util.Output
android.icu.util.SimpleTimeZone
android.icu.util.TimeUnit
android.icu.util.TimeZone
@@ -1187,16 +1372,27 @@
android.icu.util.UResourceBundleIterator
android.icu.util.UResourceTypeMismatchException
android.icu.util.VersionInfo
-android.inputmethodservice.ExtractEditText
android.location.CountryDetector
+android.location.GnssMeasurementCallbackTransport
+android.location.GnssMeasurementCallbackTransport$ListenerTransport
+android.location.GnssNavigationMessageCallbackTransport
+android.location.GnssNavigationMessageCallbackTransport$ListenerTransport
+android.location.IGnssMeasurementsListener
+android.location.IGnssMeasurementsListener$Stub
+android.location.IGnssNavigationMessageListener
+android.location.IGnssNavigationMessageListener$Stub
+android.location.ILocationManager
+android.location.ILocationManager$Stub
+android.location.ILocationManager$Stub$Proxy
+android.location.LocalListenerHelper
android.location.Location
android.location.Location$1
+android.location.Location$2
android.location.LocationManager
android.media.AmrInputStream
android.media.AudioAttributes
android.media.AudioAttributes$1
android.media.AudioAttributes$Builder
-android.media.AudioDeviceInfo
android.media.AudioDevicePort
android.media.AudioDevicePortConfig
android.media.AudioFormat
@@ -1205,31 +1401,45 @@
android.media.AudioHandle
android.media.AudioManager
android.media.AudioManager$1
-android.media.AudioManager$FocusEventHandlerDelegate
-android.media.AudioManager$FocusEventHandlerDelegate$1
-android.media.AudioManager$OnAmPortUpdateListener
-android.media.AudioManager$OnAudioPortUpdateListener
+android.media.AudioManager$2
+android.media.AudioManager$OnAudioFocusChangeListener
+android.media.AudioManager$ServiceEventHandlerDelegate
+android.media.AudioManager$ServiceEventHandlerDelegate$1
android.media.AudioMixPort
android.media.AudioMixPortConfig
android.media.AudioPatch
android.media.AudioPort
android.media.AudioPortConfig
android.media.AudioPortEventHandler
-android.media.AudioPortEventHandler$1
android.media.AudioRecord
+android.media.AudioRoutesInfo
+android.media.AudioRoutesInfo$1
+android.media.AudioRouting
android.media.AudioSystem
+android.media.AudioTimestamp
android.media.AudioTrack
android.media.CamcorderProfile
android.media.CameraProfile
android.media.DecoderCapabilities
android.media.EncoderCapabilities
+android.media.ExifInterface
android.media.IAudioFocusDispatcher
android.media.IAudioFocusDispatcher$Stub
+android.media.IAudioRoutesObserver
+android.media.IAudioRoutesObserver$Stub
android.media.IAudioService
android.media.IAudioService$Stub
android.media.IAudioService$Stub$Proxy
android.media.IMediaHTTPConnection
android.media.IMediaHTTPConnection$Stub
+android.media.IMediaRouterClient
+android.media.IMediaRouterClient$Stub
+android.media.IMediaRouterService
+android.media.IMediaRouterService$Stub
+android.media.IRecordingConfigDispatcher
+android.media.IRecordingConfigDispatcher$Stub
+android.media.IRemoteVolumeObserver
+android.media.IRemoteVolumeObserver$Stub
android.media.Image
android.media.ImageReader
android.media.ImageReader$SurfaceImage
@@ -1245,37 +1455,46 @@
android.media.MediaMetadataRetriever
android.media.MediaMuxer
android.media.MediaPlayer
-android.media.MediaPlayer$1
-android.media.MediaPlayer$EventHandler
android.media.MediaPlayer$OnCompletionListener
android.media.MediaPlayer$OnErrorListener
+android.media.MediaPlayer$OnPreparedListener
android.media.MediaPlayer$OnSeekCompleteListener
-android.media.MediaPlayer$OnSubtitleDataListener
-android.media.MediaPlayer$TimeProvider
-android.media.MediaPlayer$TimeProvider$EventHandler
android.media.MediaRecorder
android.media.MediaRouter
+android.media.MediaRouter$Callback
+android.media.MediaRouter$RouteCategory
+android.media.MediaRouter$RouteInfo
+android.media.MediaRouter$RouteInfo$1
+android.media.MediaRouter$Static
+android.media.MediaRouter$Static$1
+android.media.MediaRouter$Static$Client
+android.media.MediaRouter$VolumeChangeReceiver
+android.media.MediaRouter$WifiDisplayStatusChangedReceiver
+android.media.MediaRouterClientState
+android.media.MediaRouterClientState$1
android.media.MediaScanner
android.media.MediaSync
-android.media.MediaTimeProvider
-android.media.MediaTimeProvider$OnMediaTimeListener
android.media.PlaybackParams
android.media.PlaybackParams$1
android.media.RemoteDisplay
android.media.ResampleInputStream
android.media.SubtitleController$Listener
-android.media.SyncParams
+android.media.ThumbnailUtils
android.media.ToneGenerator
+android.media.audiofx.AcousticEchoCanceler
+android.media.audiofx.AudioEffect
android.media.audiopolicy.AudioMix
android.media.audiopolicy.AudioMixingRule
-android.media.audiopolicy.AudioMixingRule$AttributeMatchCriterion
+android.media.audiopolicy.AudioMixingRule$AudioMixMatchCriterion
android.media.midi.MidiManager
android.media.projection.MediaProjectionManager
android.media.session.MediaSessionManager
+android.media.soundtrigger.SoundTriggerManager
android.media.tv.TvInputManager
android.mtp.MtpDatabase
android.mtp.MtpDevice
android.mtp.MtpDeviceInfo
+android.mtp.MtpEvent
android.mtp.MtpObjectInfo
android.mtp.MtpPropertyGroup
android.mtp.MtpPropertyList
@@ -1283,6 +1502,8 @@
android.mtp.MtpStorage
android.mtp.MtpStorageInfo
android.net.ConnectivityManager
+android.net.ConnectivityManager$CallbackHandler
+android.net.ConnectivityManager$NetworkCallback
android.net.Credentials
android.net.DhcpResults
android.net.DhcpResults$1
@@ -1301,18 +1522,24 @@
android.net.LocalSocketImpl
android.net.LocalSocketImpl$SocketInputStream
android.net.LocalSocketImpl$SocketOutputStream
+android.net.Network
+android.net.Network$1
+android.net.NetworkCapabilities
+android.net.NetworkCapabilities$1
android.net.NetworkInfo
android.net.NetworkInfo$1
android.net.NetworkInfo$DetailedState
android.net.NetworkInfo$State
android.net.NetworkPolicyManager
+android.net.NetworkRequest
+android.net.NetworkRequest$1
+android.net.NetworkRequest$Builder
android.net.NetworkScoreManager
android.net.NetworkStats
android.net.NetworkStats$1
android.net.NetworkUtils
android.net.Proxy
android.net.ProxyInfo
-android.net.ProxyInfo$1
android.net.RouteInfo
android.net.RouteInfo$1
android.net.SSLCertificateSocketFactory
@@ -1334,8 +1561,6 @@
android.net.Uri$PathSegments
android.net.Uri$PathSegmentsBuilder
android.net.Uri$StringUri
-android.net.http.AndroidHttpClient
-android.net.http.AndroidHttpClient$1
android.net.nsd.NsdManager
android.net.wifi.IWifiManager
android.net.wifi.IWifiManager$Stub
@@ -1346,13 +1571,12 @@
android.net.wifi.WifiInfo
android.net.wifi.WifiInfo$1
android.net.wifi.WifiManager
-android.net.wifi.WifiManager$ServiceHandler
android.net.wifi.WifiManager$WifiLock
android.net.wifi.WifiScanner
android.net.wifi.WifiSsid
android.net.wifi.WifiSsid$1
+android.net.wifi.nan.WifiNanManager
android.net.wifi.p2p.WifiP2pManager
-android.net.wifi.passpoint.WifiPasspointManager
android.nfc.IAppCallback
android.nfc.IAppCallback$Stub
android.nfc.INfcAdapter
@@ -1360,13 +1584,10 @@
android.nfc.INfcAdapter$Stub$Proxy
android.nfc.INfcCardEmulation
android.nfc.INfcCardEmulation$Stub
-android.nfc.INfcCardEmulation$Stub$Proxy
+android.nfc.INfcFCardEmulation
+android.nfc.INfcFCardEmulation$Stub
android.nfc.INfcTag
android.nfc.INfcTag$Stub
-android.nfc.INfcTag$Stub$Proxy
-android.nfc.NfcActivityManager
-android.nfc.NfcAdapter
-android.nfc.NfcAdapter$1
android.nfc.NfcManager
android.opengl.EGL14
android.opengl.EGLConfig
@@ -1384,6 +1605,7 @@
android.opengl.GLES30
android.opengl.GLES31
android.opengl.GLES31Ext
+android.opengl.GLES32
android.opengl.GLUtils
android.opengl.Matrix
android.opengl.Visibility
@@ -1408,6 +1630,9 @@
android.os.CancellationSignal
android.os.CancellationSignal$OnCancelListener
android.os.CancellationSignal$Transport
+android.os.ConditionVariable
+android.os.CpuUsageInfo
+android.os.CpuUsageInfo$1
android.os.DeadObjectException
android.os.Debug
android.os.Debug$MemoryInfo
@@ -1421,6 +1646,7 @@
android.os.Handler$Callback
android.os.Handler$MessengerImpl
android.os.HandlerThread
+android.os.HardwarePropertiesManager
android.os.IBinder
android.os.IBinder$DeathRecipient
android.os.ICancellationSignal
@@ -1447,16 +1673,16 @@
android.os.MessageQueue$IdleHandler
android.os.Messenger
android.os.Messenger$1
+android.os.OperationCanceledException
android.os.Parcel
android.os.Parcel$1
android.os.ParcelFileDescriptor
android.os.ParcelFileDescriptor$1
android.os.ParcelFileDescriptor$AutoCloseInputStream
+android.os.ParcelUuid
android.os.Parcelable
android.os.Parcelable$ClassLoaderCreator
android.os.Parcelable$Creator
-android.os.ParcelableParcel
-android.os.ParcelableParcel$1
android.os.PatternMatcher
android.os.PatternMatcher$1
android.os.PersistableBundle
@@ -1466,6 +1692,7 @@
android.os.PowerManager$WakeLock$1
android.os.Process
android.os.RemoteException
+android.os.ResultReceiver
android.os.SELinux
android.os.ServiceManager
android.os.ServiceManagerNative
@@ -1492,6 +1719,7 @@
android.os.StrictMode$StrictModeDiskWriteViolation
android.os.StrictMode$StrictModeViolation
android.os.StrictMode$ThreadPolicy
+android.os.StrictMode$ThreadPolicy$Builder
android.os.StrictMode$ThreadSpanState
android.os.StrictMode$ViolationInfo
android.os.StrictMode$VmPolicy
@@ -1500,6 +1728,7 @@
android.os.SystemProperties
android.os.Trace
android.os.Trace$1
+android.os.TransactionTooLargeException
android.os.UEventObserver
android.os.UserHandle
android.os.UserHandle$1
@@ -1512,7 +1741,9 @@
android.os.storage.StorageManager
android.os.storage.StorageVolume
android.os.storage.StorageVolume$1
+android.preference.Preference$OnPreferenceChangeListener
android.preference.PreferenceActivity
+android.preference.PreferenceFragment
android.preference.PreferenceFragment$OnPreferenceStartFragmentCallback
android.preference.PreferenceManager
android.preference.PreferenceManager$OnPreferenceTreeClickListener
@@ -1556,17 +1787,33 @@
android.provider.Settings$System$InclusiveIntegerRangeValidator
android.provider.Settings$System$Validator
android.renderscript.RenderScriptCacheDir
-android.security.IKeystoreService
-android.security.IKeystoreService$Stub
-android.security.IKeystoreService$Stub$Proxy
-android.security.KeyStore
-android.security.KeyStoreException
+android.security.FrameworkNetworkSecurityPolicy
+android.security.KeyChain
android.security.NetworkSecurityPolicy
android.security.keystore.AndroidKeyStoreBCWorkaroundProvider
-android.security.keystore.AndroidKeyStoreKey
android.security.keystore.AndroidKeyStoreProvider
-android.security.keystore.KeyStoreCryptoOperation
+android.security.net.config.ApplicationConfig
+android.security.net.config.CertificateSource
+android.security.net.config.CertificatesEntryRef
+android.security.net.config.ConfigNetworkSecurityPolicy
+android.security.net.config.ConfigSource
+android.security.net.config.DirectoryCertificateSource
+android.security.net.config.DirectoryCertificateSource$1
+android.security.net.config.DirectoryCertificateSource$3
+android.security.net.config.DirectoryCertificateSource$CertSelector
+android.security.net.config.ManifestConfigSource
+android.security.net.config.ManifestConfigSource$DefaultConfigSource
+android.security.net.config.NetworkSecurityConfig
+android.security.net.config.NetworkSecurityConfig$1
+android.security.net.config.NetworkSecurityConfig$Builder
android.security.net.config.NetworkSecurityConfigProvider
+android.security.net.config.NetworkSecurityTrustManager
+android.security.net.config.PinSet
+android.security.net.config.RootTrustManager
+android.security.net.config.RootTrustManagerFactorySpi
+android.security.net.config.SystemCertificateSource
+android.security.net.config.TrustedCertificateStoreAdapter
+android.security.net.config.UserCertificateSource
android.service.persistentdata.PersistentDataBlockManager
android.system.ErrnoException
android.system.GaiException
@@ -1586,6 +1833,7 @@
android.system.StructTimeval
android.system.StructUcred
android.system.StructUtsname
+android.system.UnixSocketAddress
android.telecom.TelecomManager
android.telephony.CarrierConfigManager
android.telephony.PhoneNumberUtils
@@ -1604,15 +1852,12 @@
android.text.GetChars
android.text.GraphicsOperations
android.text.Html
-android.text.Html$HtmlParser
-android.text.HtmlToSpannedConverter
android.text.Hyphenator
android.text.InputFilter
android.text.InputType
android.text.Layout
android.text.Layout$Alignment
android.text.Layout$Directions
-android.text.Layout$Ellipsizer
android.text.MeasuredText
android.text.NoCopySpan
android.text.NoCopySpan$Concrete
@@ -1647,6 +1892,8 @@
android.text.TextUtils
android.text.TextUtils$1
android.text.TextUtils$EllipsizeCallback
+android.text.TextUtils$SimpleStringSplitter
+android.text.TextUtils$StringSplitter
android.text.TextUtils$TruncateAt
android.text.TextWatcher
android.text.format.DateFormat
@@ -1669,13 +1916,17 @@
android.text.method.SingleLineTransformationMethod
android.text.method.TextKeyListener
android.text.method.TextKeyListener$Capitalize
+android.text.method.Touch
android.text.method.TransformationMethod
android.text.method.TransformationMethod2
android.text.style.AlignmentSpan
+android.text.style.BackgroundColorSpan
android.text.style.CharacterStyle
android.text.style.ClickableSpan
+android.text.style.DynamicDrawableSpan
android.text.style.EasyEditSpan
android.text.style.ForegroundColorSpan
+android.text.style.ImageSpan
android.text.style.LeadingMarginSpan
android.text.style.LineBackgroundSpan
android.text.style.LineHeightSpan
@@ -1687,6 +1938,7 @@
android.text.style.SuggestionSpan
android.text.style.TabStopSpan
android.text.style.URLSpan
+android.text.style.UnderlineSpan
android.text.style.UpdateAppearance
android.text.style.UpdateLayout
android.text.style.WrapTogetherSpan
@@ -1710,6 +1962,7 @@
android.transition.Scene
android.transition.Transition
android.transition.Transition$1
+android.transition.Transition$EpicenterCallback
android.transition.TransitionInflater
android.transition.TransitionManager
android.transition.TransitionSet
@@ -1720,6 +1973,7 @@
android.util.ArrayMap
android.util.ArrayMap$1
android.util.ArraySet
+android.util.ArraySet$1
android.util.AttributeSet
android.util.Base64
android.util.Base64$Coder
@@ -1731,38 +1985,44 @@
android.util.EventLog$Event
android.util.FloatProperty
android.util.IntProperty
+android.util.JsonReader
+android.util.LocaleList
+android.util.LocaleList$1
android.util.Log
android.util.Log$1
+android.util.Log$ImmediateLogWriter
android.util.Log$TerribleFailureHandler
+android.util.LogPrinter
+android.util.LongArray
android.util.LongSparseArray
android.util.LongSparseLongArray
android.util.LruCache
android.util.MapCollections
android.util.MapCollections$ArrayIterator
android.util.MapCollections$KeySet
-android.util.MapCollections$ValuesCollection
android.util.MathUtils
android.util.MutableInt
android.util.MutableLong
android.util.Pair
android.util.PathParser
-android.util.PathParser$ExtractFloatResult
-android.util.PathParser$PathDataNode
+android.util.PathParser$PathData
android.util.Patterns
android.util.Pools$Pool
android.util.Pools$SimplePool
android.util.Pools$SynchronizedPool
android.util.Printer
android.util.Property
+android.util.Rational
android.util.Singleton
android.util.Size
-android.util.SizeF
android.util.Slog
android.util.SparseArray
android.util.SparseBooleanArray
android.util.SparseIntArray
+android.util.SparseLongArray
android.util.StateSet
android.util.SuperNotCalledException
+android.util.TimeFormatException
android.util.TypedValue
android.util.Xml
android.util.jar.StrictJarFile
@@ -1785,6 +2045,8 @@
android.view.ContextMenu$ContextMenuInfo
android.view.ContextThemeWrapper
android.view.Display
+android.view.Display$ColorTransform
+android.view.Display$ColorTransform$1
android.view.Display$Mode
android.view.Display$Mode$1
android.view.DisplayAdjustments
@@ -1792,11 +2054,14 @@
android.view.DisplayInfo
android.view.DisplayInfo$1
android.view.DisplayListCanvas
+android.view.DragEvent
android.view.FallbackEventHandler
android.view.FocusFinder
android.view.FocusFinder$1
android.view.FocusFinder$SequentialFocusComparator
android.view.FrameInfo
+android.view.FrameMetrics
+android.view.FrameMetricsObserver
android.view.FrameStats
android.view.GestureDetector
android.view.GestureDetector$GestureHandler
@@ -1807,9 +2072,9 @@
android.view.GraphicBuffer
android.view.GraphicBuffer$1
android.view.Gravity
+android.view.HandlerActionQueue
+android.view.HandlerActionQueue$HandlerAction
android.view.HardwareLayer
-android.view.HardwareRenderer
-android.view.HardwareRenderer$HardwareDrawCallbacks
android.view.IAssetAtlas
android.view.IAssetAtlas$Stub
android.view.IAssetAtlas$Stub$Proxy
@@ -1833,6 +2098,7 @@
android.view.InputChannel$1
android.view.InputDevice
android.view.InputDevice$1
+android.view.InputDevice$MotionRange
android.view.InputEvent
android.view.InputEvent$1
android.view.InputEventConsistencyVerifier
@@ -1844,6 +2110,7 @@
android.view.KeyCharacterMap
android.view.KeyCharacterMap$1
android.view.KeyCharacterMap$FallbackAction
+android.view.KeyCharacterMap$KeyData
android.view.KeyEvent
android.view.KeyEvent$1
android.view.KeyEvent$Callback
@@ -1868,7 +2135,9 @@
android.view.RenderNode
android.view.RenderNodeAnimator
android.view.RenderNodeAnimator$1
+android.view.RenderNodeAnimatorSetHelper
android.view.SearchEvent
+android.view.SoundEffectConstants
android.view.SubMenu
android.view.Surface
android.view.Surface$1
@@ -1876,11 +2145,14 @@
android.view.Surface$OutOfResourcesException
android.view.SurfaceControl
android.view.SurfaceControl$PhysicalDisplayInfo
+android.view.SurfaceHolder
android.view.SurfaceHolder$Callback
android.view.SurfaceHolder$Callback2
android.view.SurfaceSession
+android.view.SurfaceView
android.view.TextureView
android.view.ThreadedRenderer
+android.view.ThreadedRenderer$HardwareDrawCallbacks
android.view.ThreadedRenderer$ProcessInitializer
android.view.VelocityTracker
android.view.VelocityTracker$Estimator
@@ -1954,8 +2226,6 @@
android.view.ViewRootImpl$NativePostImeInputStage
android.view.ViewRootImpl$NativePreImeInputStage
android.view.ViewRootImpl$QueuedInputEvent
-android.view.ViewRootImpl$RunQueue
-android.view.ViewRootImpl$RunQueue$HandlerAction
android.view.ViewRootImpl$SyntheticInputStage
android.view.ViewRootImpl$SyntheticJoystickHandler
android.view.ViewRootImpl$SyntheticKeyboardHandler
@@ -1982,10 +2252,13 @@
android.view.Window
android.view.Window$Callback
android.view.Window$OnWindowDismissedCallback
+android.view.Window$WindowControllerCallback
android.view.WindowAnimationFrameStats
android.view.WindowAnimationFrameStats$1
+android.view.WindowCallbacks
android.view.WindowContentFrameStats
android.view.WindowContentFrameStats$1
+android.view.WindowId
android.view.WindowInsets
android.view.WindowLeaked
android.view.WindowManager
@@ -2006,6 +2279,9 @@
android.view.accessibility.AccessibilityNodeProvider
android.view.accessibility.AccessibilityRecord
android.view.accessibility.CaptioningManager
+android.view.accessibility.CaptioningManager$1
+android.view.accessibility.CaptioningManager$CaptioningChangeListener
+android.view.accessibility.CaptioningManager$MyContentObserver
android.view.accessibility.IAccessibilityManager
android.view.accessibility.IAccessibilityManager$Stub
android.view.accessibility.IAccessibilityManager$Stub$Proxy
@@ -2019,12 +2295,15 @@
android.view.animation.Animation$2
android.view.animation.Animation$3
android.view.animation.Animation$AnimationListener
+android.view.animation.AnimationSet
android.view.animation.AnimationUtils
android.view.animation.BaseInterpolator
android.view.animation.DecelerateInterpolator
android.view.animation.Interpolator
android.view.animation.LinearInterpolator
+android.view.animation.OvershootInterpolator
android.view.animation.PathInterpolator
+android.view.animation.ScaleAnimation
android.view.animation.Transformation
android.view.animation.TranslateAnimation
android.view.inputmethod.BaseInputConnection
@@ -2044,12 +2323,14 @@
android.view.inputmethod.InputMethodManager$H
android.view.inputmethod.InputMethodManager$ImeInputEventSender
android.view.inputmethod.InputMethodManager$PendingEvent
+android.view.inputmethod.InputMethodSubtype
android.view.textservice.SpellCheckerSession$SpellCheckerSessionListener
android.view.textservice.SpellCheckerSubtype
android.view.textservice.SpellCheckerSubtype$1
android.view.textservice.TextServicesManager
-android.webkit.IWebViewUpdateService
-android.webkit.IWebViewUpdateService$Stub
+android.webkit.MimeTypeMap
+android.webkit.URLUtil
+android.webkit.WebSettings
android.webkit.WebView
android.webkit.WebViewFactory
android.webkit.WebViewFactory$MissingWebViewPackageException
@@ -2065,8 +2346,8 @@
android.widget.AbsListView$SavedState$1
android.widget.AbsListView$SelectionBoundsAdjuster
android.widget.AbsListView$WindowRunnnable
+android.widget.AbsSeekBar
android.widget.AbsSpinner
-android.widget.AbsSpinner$RecycleBin
android.widget.AbsoluteLayout
android.widget.ActionMenuPresenter
android.widget.ActionMenuPresenter$1
@@ -2076,17 +2357,23 @@
android.widget.ActionMenuPresenter$PopupPresenterCallback
android.widget.ActionMenuView
android.widget.ActionMenuView$ActionMenuChildView
-android.widget.ActionMenuView$LayoutParams
android.widget.ActionMenuView$OnMenuItemClickListener
android.widget.Adapter
android.widget.AdapterView
android.widget.AdapterView$AdapterDataSetObserver
android.widget.AdapterView$OnItemClickListener
+android.widget.AdapterView$OnItemLongClickListener
android.widget.AdapterView$OnItemSelectedListener
android.widget.ArrayAdapter
+android.widget.AutoCompleteTextView
+android.widget.AutoCompleteTextView$DropDownItemClickListener
+android.widget.AutoCompleteTextView$MyWatcher
+android.widget.AutoCompleteTextView$PassThroughClickListener
android.widget.BaseAdapter
android.widget.Button
+android.widget.CheckBox
android.widget.Checkable
+android.widget.CheckedTextView
android.widget.CompoundButton
android.widget.CompoundButton$OnCheckedChangeListener
android.widget.EdgeEffect
@@ -2094,6 +2381,7 @@
android.widget.Editor
android.widget.Editor$1
android.widget.Editor$2
+android.widget.Editor$3
android.widget.Editor$Blink
android.widget.Editor$CursorAnchorInfoNotifier
android.widget.Editor$EditOperation
@@ -2101,17 +2389,23 @@
android.widget.Editor$InputContentType
android.widget.Editor$InputMethodState
android.widget.Editor$PositionListener
+android.widget.Editor$ProcessTextIntentActionsHandler
android.widget.Editor$SpanController
+android.widget.Editor$SuggestionHelper
+android.widget.Editor$SuggestionHelper$SuggestionSpanComparator
android.widget.Editor$TextRenderNode
android.widget.Editor$TextViewPositionListener
android.widget.Editor$UndoInputFilter
android.widget.Filter
android.widget.Filter$FilterListener
android.widget.Filterable
+android.widget.ForwardingListener
android.widget.FrameLayout
android.widget.FrameLayout$LayoutParams
android.widget.HeaderViewListAdapter
android.widget.HorizontalScrollView
+android.widget.HorizontalScrollView$SavedState
+android.widget.HorizontalScrollView$SavedState$1
android.widget.ImageButton
android.widget.ImageView
android.widget.ImageView$ScaleType
@@ -2119,7 +2413,6 @@
android.widget.LinearLayout$LayoutParams
android.widget.ListAdapter
android.widget.ListPopupWindow
-android.widget.ListPopupWindow$ForwardingListener
android.widget.ListPopupWindow$ListSelectorHider
android.widget.ListPopupWindow$PopupDataSetObserver
android.widget.ListPopupWindow$PopupScrollListener
@@ -2128,48 +2421,38 @@
android.widget.ListView
android.widget.ListView$ArrowScrollFocusResult
android.widget.ListView$FixedViewInfo
+android.widget.MultiAutoCompleteTextView
android.widget.OverScroller
android.widget.OverScroller$SplineOverScroller
android.widget.PopupWindow
android.widget.PopupWindow$1
+android.widget.PopupWindow$2
android.widget.PopupWindow$OnDismissListener
android.widget.ProgressBar
+android.widget.ProgressBar$1
android.widget.ProgressBar$SavedState
android.widget.ProgressBar$SavedState$1
+android.widget.RadioButton
+android.widget.RatingBar
android.widget.RelativeLayout
android.widget.RelativeLayout$DependencyGraph
android.widget.RelativeLayout$DependencyGraph$Node
android.widget.RelativeLayout$LayoutParams
android.widget.RemoteViews
-android.widget.RemoteViews$1
-android.widget.RemoteViews$2
-android.widget.RemoteViews$Action
-android.widget.RemoteViews$ActionException
-android.widget.RemoteViews$BitmapCache
-android.widget.RemoteViews$MemoryUsageCounter
-android.widget.RemoteViews$MutablePair
-android.widget.RemoteViews$OnClickHandler
-android.widget.RemoteViews$ReflectionAction
-android.widget.RemoteViews$SetDrawableParameters
-android.widget.RemoteViews$TextViewSizeAction
-android.widget.RemoteViews$ViewPaddingAction
android.widget.RemoteViewsAdapter$RemoteAdapterConnectionCallback
android.widget.RtlSpacingHelper
android.widget.ScrollBarDrawable
android.widget.ScrollView
-android.widget.ScrollView$SavedState
-android.widget.ScrollView$SavedState$1
android.widget.Scroller
android.widget.Scroller$ViscousFluidInterpolator
android.widget.SectionIndexer
+android.widget.SeekBar
android.widget.Space
android.widget.SpellChecker
android.widget.SpellChecker$SpellParser
android.widget.Spinner
-android.widget.Spinner$SpinnerPopup
android.widget.SpinnerAdapter
android.widget.TextView
-android.widget.TextView$2
android.widget.TextView$3
android.widget.TextView$BufferType
android.widget.TextView$ChangeWatcher
@@ -2177,13 +2460,17 @@
android.widget.TextView$Drawables
android.widget.TextView$OnEditorActionListener
android.widget.TextView$SavedState
-android.widget.TextView$SavedState$1
android.widget.ThemedSpinnerAdapter
+android.widget.Toast
+android.widget.Toast$TN
+android.widget.Toast$TN$1
+android.widget.Toast$TN$2
android.widget.Toolbar
android.widget.Toolbar$1
android.widget.Toolbar$2
android.widget.Toolbar$ExpandedActionViewMenuPresenter
android.widget.Toolbar$LayoutParams
+android.widget.ViewAnimator
android.widget.WrapperListAdapter
com.android.dex.Annotation
com.android.dex.ClassData
@@ -2216,19 +2503,10 @@
com.android.dex.util.ByteOutput
com.android.dex.util.ExceptionWithContext
com.android.dex.util.FileUtils
-com.android.i18n.phonenumbers.CountryCodeToRegionCodeMap
-com.android.i18n.phonenumbers.MetadataLoader
com.android.i18n.phonenumbers.NumberParseException
-com.android.i18n.phonenumbers.PhoneNumberUtil
-com.android.i18n.phonenumbers.PhoneNumberUtil$1
-com.android.i18n.phonenumbers.RegexCache
-com.android.i18n.phonenumbers.RegexCache$LRUCache
-com.android.i18n.phonenumbers.RegexCache$LRUCache$1
com.android.internal.R$styleable
com.android.internal.app.AlertController
com.android.internal.app.AlertController$1
-com.android.internal.app.AlertController$2
-com.android.internal.app.AlertController$AlertParams
com.android.internal.app.AlertController$ButtonHandler
com.android.internal.app.IAppOpsService
com.android.internal.app.IAppOpsService$Stub
@@ -2236,15 +2514,13 @@
com.android.internal.app.IVoiceInteractor
com.android.internal.app.IVoiceInteractor$Stub
com.android.internal.app.WindowDecorActionBar
-com.android.internal.app.WindowDecorActionBar$1
-com.android.internal.app.WindowDecorActionBar$2
-com.android.internal.app.WindowDecorActionBar$3
com.android.internal.appwidget.IAppWidgetService
com.android.internal.appwidget.IAppWidgetService$Stub
com.android.internal.appwidget.IAppWidgetService$Stub$Proxy
com.android.internal.content.NativeLibraryHelper
com.android.internal.content.ReferrerIntent
com.android.internal.content.ReferrerIntent$1
+com.android.internal.inputmethod.InputMethodUtils
com.android.internal.logging.AndroidConfig
com.android.internal.logging.AndroidHandler
com.android.internal.logging.AndroidHandler$1
@@ -2252,6 +2528,7 @@
com.android.internal.os.AndroidPrintStream
com.android.internal.os.BinderInternal
com.android.internal.os.BinderInternal$GcWatcher
+com.android.internal.os.InstallerConnection$InstallerException
com.android.internal.os.LoggingPrintStream
com.android.internal.os.LoggingPrintStream$1
com.android.internal.os.RuntimeInit
@@ -2266,17 +2543,15 @@
com.android.internal.os.ZygoteInit
com.android.internal.os.ZygoteInit$MethodAndArgsCaller
com.android.internal.os.ZygoteSecurityException
+com.android.internal.policy.DecorContext
+com.android.internal.policy.DecorView
+com.android.internal.policy.DecorView$ColorViewState
com.android.internal.policy.PhoneFallbackEventHandler
com.android.internal.policy.PhoneLayoutInflater
com.android.internal.policy.PhoneWindow
com.android.internal.policy.PhoneWindow$1
-com.android.internal.policy.PhoneWindow$ActionMenuPresenterCallback
-com.android.internal.policy.PhoneWindow$ColorViewState
-com.android.internal.policy.PhoneWindow$DecorView
-com.android.internal.policy.PhoneWindow$DialogMenuCallback
com.android.internal.policy.PhoneWindow$PanelFeatureState
-com.android.internal.policy.PhoneWindow$PanelFeatureState$SavedState
-com.android.internal.policy.PhoneWindow$PanelFeatureState$SavedState$1
+com.android.internal.policy.PhoneWindow$PhoneWindowMenuCallback
com.android.internal.policy.PhoneWindow$RotationWatcher
com.android.internal.policy.PhoneWindow$RotationWatcher$1
com.android.internal.telephony.ISub
@@ -2295,13 +2570,11 @@
com.android.internal.transition.EpicenterTranslateClipReveal
com.android.internal.transition.TransitionConstants
com.android.internal.util.ArrayUtils
-com.android.internal.util.AsyncChannel
-com.android.internal.util.AsyncChannel$DeathMonitor
-com.android.internal.util.FastMath
com.android.internal.util.FastPrintWriter
com.android.internal.util.FastPrintWriter$DummyWriter
com.android.internal.util.FastXmlSerializer
com.android.internal.util.GrowingArrayUtils
+com.android.internal.util.LineBreakBufferedWriter
com.android.internal.util.Preconditions
com.android.internal.util.VirtualRefBasePtr
com.android.internal.util.XmlUtils
@@ -2339,25 +2612,16 @@
com.android.internal.view.menu.MenuPresenter
com.android.internal.view.menu.MenuPresenter$Callback
com.android.internal.view.menu.MenuView
-com.android.internal.widget.AbsActionBarView
-com.android.internal.widget.AbsActionBarView$VisibilityAnimListener
-com.android.internal.widget.ActionBarContainer
-com.android.internal.widget.ActionBarContainer$ActionBarBackgroundDrawable
-com.android.internal.widget.ActionBarContextView
-com.android.internal.widget.ActionBarOverlayLayout
-com.android.internal.widget.ActionBarOverlayLayout$1
-com.android.internal.widget.ActionBarOverlayLayout$2
-com.android.internal.widget.ActionBarOverlayLayout$3
-com.android.internal.widget.ActionBarOverlayLayout$4
-com.android.internal.widget.ActionBarOverlayLayout$5
+com.android.internal.view.menu.ShowableListMenu
com.android.internal.widget.ActionBarOverlayLayout$ActionBarVisibilityCallback
-com.android.internal.widget.ActionBarOverlayLayout$LayoutParams
+com.android.internal.widget.AlertDialogLayout
com.android.internal.widget.BackgroundFallback
com.android.internal.widget.ButtonBarLayout
com.android.internal.widget.DecorContentParent
com.android.internal.widget.DecorToolbar
com.android.internal.widget.DialogTitle
com.android.internal.widget.EditableInputConnection
+com.android.internal.widget.ScrollBarUtils
com.android.internal.widget.ToolbarWidgetWrapper
com.android.internal.widget.ToolbarWidgetWrapper$1
com.android.okhttp.Address
@@ -2379,6 +2643,10 @@
com.android.okhttp.Headers
com.android.okhttp.Headers$Builder
com.android.okhttp.HttpHandler
+com.android.okhttp.HttpHandler$CleartextURLFilter
+com.android.okhttp.HttpUrl
+com.android.okhttp.HttpUrl$Builder
+com.android.okhttp.HttpUrl$Builder$ParseResult
com.android.okhttp.HttpsHandler
com.android.okhttp.OkHttpClient
com.android.okhttp.OkHttpClient$1
@@ -2400,6 +2668,7 @@
com.android.okhttp.internal.OptionalMethod
com.android.okhttp.internal.Platform
com.android.okhttp.internal.RouteDatabase
+com.android.okhttp.internal.URLFilter
com.android.okhttp.internal.Util
com.android.okhttp.internal.Util$1
com.android.okhttp.internal.http.AuthenticatorAdapter
@@ -2421,8 +2690,6 @@
com.android.okhttp.internal.http.RetryableSink
com.android.okhttp.internal.http.RouteException
com.android.okhttp.internal.http.RouteSelector
-com.android.okhttp.internal.http.SocketConnector
-com.android.okhttp.internal.http.SocketConnector$ConnectedSocket
com.android.okhttp.internal.http.StatusLine
com.android.okhttp.internal.http.Transport
com.android.okhttp.internal.huc.DelegatingHttpsURLConnection
@@ -2436,6 +2703,7 @@
com.android.okhttp.okio.Buffer
com.android.okhttp.okio.BufferedSink
com.android.okhttp.okio.BufferedSource
+com.android.okhttp.okio.ForwardingTimeout
com.android.okhttp.okio.Okio
com.android.okhttp.okio.Okio$1
com.android.okhttp.okio.Okio$2
@@ -2451,75 +2719,20 @@
com.android.okhttp.okio.Timeout
com.android.okhttp.okio.Timeout$1
com.android.okhttp.okio.Util
-com.android.org.bouncycastle.asn1.ASN1Boolean
-com.android.org.bouncycastle.asn1.ASN1Choice
com.android.org.bouncycastle.asn1.ASN1Encodable
-com.android.org.bouncycastle.asn1.ASN1EncodableVector
-com.android.org.bouncycastle.asn1.ASN1InputStream
-com.android.org.bouncycastle.asn1.ASN1Integer
-com.android.org.bouncycastle.asn1.ASN1Null
com.android.org.bouncycastle.asn1.ASN1Object
com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier
-com.android.org.bouncycastle.asn1.ASN1OctetString
-com.android.org.bouncycastle.asn1.ASN1OctetStringParser
-com.android.org.bouncycastle.asn1.ASN1OutputStream
+com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier$OidHandle
com.android.org.bouncycastle.asn1.ASN1Primitive
-com.android.org.bouncycastle.asn1.ASN1Sequence
-com.android.org.bouncycastle.asn1.ASN1SequenceParser
-com.android.org.bouncycastle.asn1.ASN1Set
-com.android.org.bouncycastle.asn1.ASN1StreamParser
-com.android.org.bouncycastle.asn1.ASN1String
-com.android.org.bouncycastle.asn1.ASN1TaggedObject
-com.android.org.bouncycastle.asn1.ASN1TaggedObjectParser
-com.android.org.bouncycastle.asn1.BERTags
-com.android.org.bouncycastle.asn1.DERBitString
-com.android.org.bouncycastle.asn1.DERFactory
-com.android.org.bouncycastle.asn1.DERIA5String
-com.android.org.bouncycastle.asn1.DERNull
-com.android.org.bouncycastle.asn1.DEROctetString
-com.android.org.bouncycastle.asn1.DEROutputStream
-com.android.org.bouncycastle.asn1.DERPrintableString
-com.android.org.bouncycastle.asn1.DERSequence
-com.android.org.bouncycastle.asn1.DERSet
-com.android.org.bouncycastle.asn1.DERTaggedObject
-com.android.org.bouncycastle.asn1.DERUTF8String
-com.android.org.bouncycastle.asn1.DLSequence
-com.android.org.bouncycastle.asn1.DLSet
-com.android.org.bouncycastle.asn1.DefiniteLengthInputStream
-com.android.org.bouncycastle.asn1.InMemoryRepresentable
-com.android.org.bouncycastle.asn1.IndefiniteLengthInputStream
-com.android.org.bouncycastle.asn1.LimitedInputStream
-com.android.org.bouncycastle.asn1.StreamUtil
+com.android.org.bouncycastle.asn1.OIDTokenizer
com.android.org.bouncycastle.asn1.bc.BCObjectIdentifiers
com.android.org.bouncycastle.asn1.iana.IANAObjectIdentifiers
+com.android.org.bouncycastle.asn1.misc.MiscObjectIdentifiers
com.android.org.bouncycastle.asn1.nist.NISTObjectIdentifiers
com.android.org.bouncycastle.asn1.oiw.OIWObjectIdentifiers
com.android.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers
-com.android.org.bouncycastle.asn1.x500.AttributeTypeAndValue
-com.android.org.bouncycastle.asn1.x500.RDN
-com.android.org.bouncycastle.asn1.x500.X500Name
-com.android.org.bouncycastle.asn1.x500.X500NameStyle
-com.android.org.bouncycastle.asn1.x500.style.AbstractX500NameStyle
-com.android.org.bouncycastle.asn1.x500.style.BCStyle
-com.android.org.bouncycastle.asn1.x509.AlgorithmIdentifier
-com.android.org.bouncycastle.asn1.x509.BasicConstraints
-com.android.org.bouncycastle.asn1.x509.Extension
-com.android.org.bouncycastle.asn1.x509.GeneralName
-com.android.org.bouncycastle.asn1.x509.GeneralNames
-com.android.org.bouncycastle.asn1.x509.PolicyInformation
-com.android.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo
-com.android.org.bouncycastle.asn1.x509.X509Extension
com.android.org.bouncycastle.asn1.x509.X509ObjectIdentifiers
com.android.org.bouncycastle.asn1.x9.X9ObjectIdentifiers
-com.android.org.bouncycastle.crypto.Digest
-com.android.org.bouncycastle.crypto.ExtendedDigest
-com.android.org.bouncycastle.crypto.digests.AndroidDigestFactory
-com.android.org.bouncycastle.crypto.digests.AndroidDigestFactoryInterface
-com.android.org.bouncycastle.crypto.digests.AndroidDigestFactoryOpenSSL
-com.android.org.bouncycastle.crypto.digests.OpenSSLDigest
-com.android.org.bouncycastle.crypto.digests.OpenSSLDigest$SHA1
-com.android.org.bouncycastle.jcajce.PKIXExtendedParameters
-com.android.org.bouncycastle.jcajce.PKIXExtendedParameters$Builder
com.android.org.bouncycastle.jcajce.provider.asymmetric.DH$Mappings
com.android.org.bouncycastle.jcajce.provider.asymmetric.DSA$Mappings
com.android.org.bouncycastle.jcajce.provider.asymmetric.EC$Mappings
@@ -2575,40 +2788,27 @@
com.android.org.bouncycastle.jcajce.util.BCJcaJceHelper
com.android.org.bouncycastle.jcajce.util.JcaJceHelper
com.android.org.bouncycastle.jcajce.util.ProviderJcaJceHelper
-com.android.org.bouncycastle.jce.exception.ExtException
com.android.org.bouncycastle.jce.interfaces.BCKeyStore
-com.android.org.bouncycastle.jce.provider.AnnotatedException
com.android.org.bouncycastle.jce.provider.BouncyCastleProvider
com.android.org.bouncycastle.jce.provider.BouncyCastleProvider$1
com.android.org.bouncycastle.jce.provider.BouncyCastleProviderConfiguration
-com.android.org.bouncycastle.jce.provider.CertBlacklist
-com.android.org.bouncycastle.jce.provider.CertPathValidatorUtilities
-com.android.org.bouncycastle.jce.provider.PKIXCRLUtil
-com.android.org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi
-com.android.org.bouncycastle.jce.provider.PKIXNameConstraintValidator
-com.android.org.bouncycastle.jce.provider.PKIXNameConstraintValidatorException
-com.android.org.bouncycastle.jce.provider.PKIXPolicyNode
-com.android.org.bouncycastle.jce.provider.PrincipalUtils
-com.android.org.bouncycastle.jce.provider.RFC3280CertPathUtilities
com.android.org.bouncycastle.util.Arrays
com.android.org.bouncycastle.util.Encodable
com.android.org.bouncycastle.util.Strings
-com.android.org.bouncycastle.util.encoders.Encoder
-com.android.org.bouncycastle.util.encoders.Hex
-com.android.org.bouncycastle.util.encoders.HexEncoder
-com.android.org.bouncycastle.util.io.Streams
-com.android.org.bouncycastle.x509.ExtendedPKIXParameters
+com.android.org.bouncycastle.util.Strings$1
com.android.org.conscrypt.AbstractSessionContext
com.android.org.conscrypt.AbstractSessionContext$1
com.android.org.conscrypt.AddressUtils
com.android.org.conscrypt.ByteArray
com.android.org.conscrypt.CertPinManager
+com.android.org.conscrypt.CertificatePriorityComparator
com.android.org.conscrypt.ChainStrengthAnalyzer
com.android.org.conscrypt.ClientSessionContext
com.android.org.conscrypt.ClientSessionContext$HostAndPort
com.android.org.conscrypt.CryptoUpcalls
com.android.org.conscrypt.FileClientSessionCache
com.android.org.conscrypt.FileClientSessionCache$Impl
+com.android.org.conscrypt.Hex
com.android.org.conscrypt.JSSEProvider
com.android.org.conscrypt.KeyManagerFactoryImpl
com.android.org.conscrypt.KeyManagerImpl
@@ -2624,14 +2824,17 @@
com.android.org.conscrypt.OpenSSLContextImpl
com.android.org.conscrypt.OpenSSLContextImpl$TLSv12
com.android.org.conscrypt.OpenSSLECGroupContext
+com.android.org.conscrypt.OpenSSLECKeyFactory
com.android.org.conscrypt.OpenSSLECPointContext
com.android.org.conscrypt.OpenSSLECPublicKey
+com.android.org.conscrypt.OpenSSLExtendedSessionImpl
com.android.org.conscrypt.OpenSSLKey
com.android.org.conscrypt.OpenSSLKeyHolder
com.android.org.conscrypt.OpenSSLMessageDigestJDK
com.android.org.conscrypt.OpenSSLMessageDigestJDK$MD5
com.android.org.conscrypt.OpenSSLMessageDigestJDK$SHA1
com.android.org.conscrypt.OpenSSLProvider
+com.android.org.conscrypt.OpenSSLRSAKeyFactory
com.android.org.conscrypt.OpenSSLRSAPublicKey
com.android.org.conscrypt.OpenSSLRandom
com.android.org.conscrypt.OpenSSLSessionImpl
@@ -2651,7 +2854,6 @@
com.android.org.conscrypt.PinEntryException
com.android.org.conscrypt.PinManagerException
com.android.org.conscrypt.Platform
-com.android.org.conscrypt.Platform$OpenSSLMapper
com.android.org.conscrypt.SSLClientSessionCache
com.android.org.conscrypt.SSLParametersImpl
com.android.org.conscrypt.SSLParametersImpl$AliasChooser
@@ -2660,12 +2862,10 @@
com.android.org.conscrypt.TrustManagerFactoryImpl
com.android.org.conscrypt.TrustManagerImpl
com.android.org.conscrypt.TrustManagerImpl$ExtendedKeyUsagePKIXCertPathChecker
+com.android.org.conscrypt.TrustManagerImpl$TrustAnchorComparator
com.android.org.conscrypt.TrustedCertificateIndex
com.android.org.conscrypt.TrustedCertificateKeyStoreSpi
com.android.org.conscrypt.TrustedCertificateStore
-com.android.org.conscrypt.TrustedCertificateStore$1
-com.android.org.conscrypt.TrustedCertificateStore$2
-com.android.org.conscrypt.TrustedCertificateStore$CertSelector
com.android.org.conscrypt.util.ArrayUtils
com.android.server.NetworkManagementSocketTagger
com.android.server.NetworkManagementSocketTagger$1
@@ -2685,6 +2885,7 @@
dalvik.system.CloseGuard$Reporter
dalvik.system.DalvikLogHandler
dalvik.system.DalvikLogging
+dalvik.system.DexClassLoader
dalvik.system.DexFile
dalvik.system.DexFile$DFEnum
dalvik.system.DexPathList
@@ -2696,28 +2897,41 @@
dalvik.system.VMRuntime
dalvik.system.VMStack
dalvik.system.ZygoteHooks
+java.beans.ChangeListenerMap
java.beans.PropertyChangeEvent
+java.beans.PropertyChangeListener
java.beans.PropertyChangeSupport
+java.beans.PropertyChangeSupport$PropertyChangeListenerMap
+java.io.Bits
java.io.BufferedInputStream
java.io.BufferedOutputStream
java.io.BufferedReader
java.io.BufferedWriter
java.io.ByteArrayInputStream
java.io.ByteArrayOutputStream
+java.io.CharArrayWriter
java.io.Closeable
java.io.DataInput
java.io.DataInputStream
java.io.DataOutput
java.io.DataOutputStream
java.io.EOFException
+java.io.ExpiringCache
+java.io.ExpiringCache$1
+java.io.ExpiringCache$Entry
java.io.Externalizable
java.io.File
+java.io.File$PathStatus
+java.io.File$TempDirectory
java.io.FileDescriptor
-java.io.FileFilter
java.io.FileInputStream
+java.io.FileInputStream$UseManualSkipException
java.io.FileNotFoundException
java.io.FileOutputStream
java.io.FileReader
+java.io.FileSystem
+java.io.FileWriter
+java.io.FilenameFilter
java.io.FilterInputStream
java.io.FilterOutputStream
java.io.FilterReader
@@ -2727,13 +2941,17 @@
java.io.InputStreamReader
java.io.InterruptedIOException
java.io.InvalidObjectException
+java.io.NotSerializableException
java.io.ObjectInput
java.io.ObjectInputStream
+java.io.ObjectInputStream$BlockDataInputStream
+java.io.ObjectInputStream$HandleTable
+java.io.ObjectInputStream$HandleTable$HandleList
+java.io.ObjectInputStream$PeekInputStream
+java.io.ObjectInputStream$ValidationList
java.io.ObjectOutput
java.io.ObjectOutputStream
-java.io.ObjectOutputStream$PutField
java.io.ObjectStreamClass
-java.io.ObjectStreamClass$5
java.io.ObjectStreamConstants
java.io.ObjectStreamException
java.io.ObjectStreamField
@@ -2745,27 +2963,32 @@
java.io.PushbackReader
java.io.RandomAccessFile
java.io.Reader
+java.io.SequenceInputStream
java.io.Serializable
java.io.SerializablePermission
-java.io.SerializationHandleMap
+java.io.StreamCorruptedException
java.io.StringReader
java.io.StringWriter
java.io.UTFDataFormatException
+java.io.UnixFileSystem
java.io.UnsupportedEncodingException
java.io.Writer
java.lang.AbstractMethodError
java.lang.AbstractStringBuilder
java.lang.Appendable
java.lang.ArrayIndexOutOfBoundsException
+java.lang.ArrayStoreException
java.lang.AssertionError
java.lang.AutoCloseable
java.lang.Boolean
java.lang.BootClassLoader
java.lang.Byte
+java.lang.Byte$ByteCache
java.lang.CaseMapper
java.lang.CaseMapper$1
java.lang.CharSequence
java.lang.Character
+java.lang.Character$CharacterCache
java.lang.Character$Subset
java.lang.Character$UnicodeBlock
java.lang.Class
@@ -2787,24 +3010,30 @@
java.lang.Double
java.lang.Enum
java.lang.Enum$1
+java.lang.EnumConstantNotPresentException
java.lang.Error
java.lang.Exception
java.lang.Float
+java.lang.FloatingDecimal
+java.lang.FloatingDecimal$1
+java.lang.FloatingDecimal$2
java.lang.IllegalAccessException
java.lang.IllegalArgumentException
java.lang.IllegalStateException
java.lang.IllegalThreadStateException
java.lang.IncompatibleClassChangeError
java.lang.IndexOutOfBoundsException
+java.lang.InheritableThreadLocal
java.lang.InstantiationException
java.lang.Integer
-java.lang.IntegralToString
-java.lang.IntegralToString$1
+java.lang.Integer$IntegerCache
java.lang.InternalError
java.lang.InterruptedException
java.lang.Iterable
+java.lang.JavaLangAccess
java.lang.LinkageError
java.lang.Long
+java.lang.Long$LongCache
java.lang.Math
java.lang.Math$NoImagePreloadHolder
java.lang.NoClassDefFoundError
@@ -2818,16 +3047,19 @@
java.lang.Object
java.lang.OutOfMemoryError
java.lang.Package
+java.lang.Process
+java.lang.ProcessEnvironment
java.lang.Readable
-java.lang.RealToString
-java.lang.RealToString$1
java.lang.ReflectiveOperationException
java.lang.Runnable
java.lang.Runtime
java.lang.RuntimeException
java.lang.RuntimePermission
java.lang.SecurityException
+java.lang.SecurityManager
java.lang.Short
+java.lang.Short$ShortCache
+java.lang.Shutdown
java.lang.StackOverflowError
java.lang.StackTraceElement
java.lang.StrictMath
@@ -2835,28 +3067,40 @@
java.lang.String$CaseInsensitiveComparator
java.lang.StringBuffer
java.lang.StringBuilder
+java.lang.StringCoding
java.lang.StringFactory
java.lang.StringIndexOutOfBoundsException
-java.lang.StringToReal
-java.lang.StringToReal$StringExponentPair
java.lang.System
java.lang.System$PropertiesWithNonOverrideableDefaults
java.lang.Thread
+java.lang.Thread$1
+java.lang.Thread$Caches
java.lang.Thread$State
java.lang.Thread$UncaughtExceptionHandler
+java.lang.Thread$WeakClassKey
java.lang.ThreadDeath
java.lang.ThreadGroup
java.lang.ThreadLocal
-java.lang.ThreadLocal$Values
+java.lang.ThreadLocal$ThreadLocalMap
+java.lang.ThreadLocal$ThreadLocalMap$Entry
java.lang.Throwable
-java.lang.TwoEnumerationsInOne
+java.lang.Throwable$PrintStreamOrWriter
+java.lang.Throwable$SentinelHolder
+java.lang.Throwable$WrappedPrintStream
+java.lang.Throwable$WrappedPrintWriter
+java.lang.TypeNotPresentException
+java.lang.UNIXProcess
java.lang.UnsatisfiedLinkError
java.lang.UnsupportedOperationException
java.lang.VMClassLoader
java.lang.VirtualMachineError
java.lang.Void
java.lang.annotation.Annotation
+java.lang.annotation.AnnotationTypeMismatchException
+java.lang.annotation.IncompleteAnnotationException
java.lang.annotation.Inherited
+java.lang.annotation.Retention
+java.lang.annotation.Target
java.lang.ref.FinalizerReference
java.lang.ref.FinalizerReference$Sentinel
java.lang.ref.PhantomReference
@@ -2871,7 +3115,6 @@
java.lang.reflect.Array
java.lang.reflect.Constructor
java.lang.reflect.Field
-java.lang.reflect.Field$1
java.lang.reflect.GenericArrayType
java.lang.reflect.GenericDeclaration
java.lang.reflect.InvocationHandler
@@ -2889,52 +3132,67 @@
java.math.BigDecimal
java.math.BigInt
java.math.BigInteger
+java.math.BitLevel
+java.math.Multiplication
java.math.NativeBN
java.math.RoundingMode
+java.net.AbstractPlainDatagramSocketImpl
+java.net.AbstractPlainSocketImpl
java.net.AddressCache
java.net.AddressCache$AddressCacheEntry
java.net.AddressCache$AddressCacheKey
java.net.ConnectException
-java.net.ContentHandler
java.net.CookieHandler
+java.net.DatagramPacket
+java.net.DatagramSocketImpl
java.net.HttpURLConnection
+java.net.IDN
java.net.Inet4Address
java.net.Inet6Address
+java.net.Inet6AddressImpl
java.net.InetAddress
+java.net.InetAddress$1
+java.net.InetAddress$InetAddressHolder
+java.net.InetAddressImpl
java.net.InetSocketAddress
-java.net.InetUnixAddress
+java.net.InetSocketAddress$InetSocketAddressHolder
java.net.JarURLConnection
java.net.MalformedURLException
+java.net.NetworkInterface
+java.net.Parts
+java.net.PlainDatagramSocketImpl
java.net.PlainSocketImpl
java.net.ProtocolException
java.net.Proxy
java.net.Proxy$Type
java.net.ProxySelector
-java.net.ProxySelectorImpl
java.net.ResponseCache
java.net.ServerSocket
java.net.Socket
java.net.SocketAddress
java.net.SocketException
java.net.SocketImpl
+java.net.SocketInputStream
java.net.SocketOptions
+java.net.SocketOutputStream
java.net.SocketTimeoutException
+java.net.SocksConsts
+java.net.SocksSocketImpl
+java.net.SocksSocketImpl$3
java.net.URI
-java.net.URI$1
-java.net.URI$PartEncoder
+java.net.URI$Parser
java.net.URISyntaxException
java.net.URL
java.net.URLConnection
-java.net.URLConnection$DefaultContentHandler
+java.net.URLDecoder
java.net.URLEncoder
-java.net.URLEncoder$1
java.net.URLStreamHandler
java.net.URLStreamHandlerFactory
java.net.UnknownHostException
+java.nio.Bits
java.nio.Buffer
java.nio.BufferOverflowException
java.nio.BufferUnderflowException
-java.nio.ByteArrayBuffer
java.nio.ByteBuffer
java.nio.ByteBufferAsCharBuffer
java.nio.ByteBufferAsDoubleBuffer
@@ -2943,42 +3201,43 @@
java.nio.ByteBufferAsLongBuffer
java.nio.ByteBufferAsShortBuffer
java.nio.ByteOrder
-java.nio.CharArrayBuffer
java.nio.CharBuffer
-java.nio.CharSequenceAdapter
java.nio.DirectByteBuffer
+java.nio.DirectByteBuffer$MemoryRef
java.nio.DoubleBuffer
-java.nio.FileChannelImpl
-java.nio.FileChannelImpl$1
-java.nio.FileChannelImpl$FileLockImpl
java.nio.FloatBuffer
+java.nio.HeapByteBuffer
+java.nio.HeapCharBuffer
java.nio.IntBuffer
java.nio.InvalidMarkException
java.nio.LongBuffer
java.nio.MappedByteBuffer
-java.nio.MemoryBlock
-java.nio.MemoryBlock$MemoryMappedBlock
-java.nio.MemoryBlock$NonMovableHeapBlock
-java.nio.MemoryBlock$UnmanagedBlock
java.nio.NIOAccess
-java.nio.NioUtils
java.nio.ReadOnlyBufferException
java.nio.ShortBuffer
+java.nio.StringCharBuffer
java.nio.channels.AsynchronousCloseException
java.nio.channels.ByteChannel
java.nio.channels.Channel
java.nio.channels.ClosedByInterruptException
java.nio.channels.ClosedChannelException
+java.nio.channels.DatagramChannel
java.nio.channels.FileChannel
java.nio.channels.FileChannel$MapMode
java.nio.channels.FileLock
java.nio.channels.GatheringByteChannel
java.nio.channels.InterruptibleChannel
+java.nio.channels.NetworkChannel
java.nio.channels.ReadableByteChannel
java.nio.channels.ScatteringByteChannel
+java.nio.channels.SeekableByteChannel
+java.nio.channels.SelectableChannel
+java.nio.channels.ServerSocketChannel
+java.nio.channels.SocketChannel
java.nio.channels.WritableByteChannel
java.nio.channels.spi.AbstractInterruptibleChannel
java.nio.channels.spi.AbstractInterruptibleChannel$1
+java.nio.channels.spi.AbstractSelectableChannel
java.nio.charset.CharacterCodingException
java.nio.charset.Charset
java.nio.charset.CharsetDecoder
@@ -2987,45 +3246,62 @@
java.nio.charset.CharsetEncoderICU
java.nio.charset.CharsetICU
java.nio.charset.CoderResult
+java.nio.charset.CoderResult$1
+java.nio.charset.CoderResult$2
+java.nio.charset.CoderResult$Cache
java.nio.charset.CodingErrorAction
java.nio.charset.IllegalCharsetNameException
-java.nio.charset.ModifiedUtf8
java.nio.charset.StandardCharsets
java.nio.charset.UnsupportedCharsetException
+java.security.AccessControlContext
java.security.AccessControlException
java.security.AccessController
+java.security.AlgorithmConstraints
+java.security.AlgorithmParameters
+java.security.AlgorithmParametersSpi
java.security.BasicPermission
-java.security.DigestException
+java.security.BasicPermissionCollection
+java.security.CryptoPrimitive
java.security.GeneralSecurityException
java.security.Guard
java.security.InvalidAlgorithmParameterException
java.security.InvalidKeyException
+java.security.InvalidParameterException
java.security.Key
java.security.KeyException
+java.security.KeyFactory
java.security.KeyFactorySpi
java.security.KeyManagementException
+java.security.KeyPair
java.security.KeyStore
+java.security.KeyStore$1
+java.security.KeyStore$LoadStoreParameter
java.security.KeyStoreException
java.security.KeyStoreSpi
java.security.MessageDigest
-java.security.MessageDigest$MessageDigestImpl
+java.security.MessageDigest$Delegate
java.security.MessageDigestSpi
java.security.NoSuchAlgorithmException
java.security.NoSuchProviderException
java.security.Permission
+java.security.PermissionCollection
java.security.Principal
java.security.PrivateKey
java.security.PrivilegedAction
+java.security.PrivilegedActionException
+java.security.PrivilegedExceptionAction
java.security.ProtectionDomain
java.security.Provider
+java.security.Provider$EngineDescription
java.security.Provider$Service
+java.security.Provider$ServiceKey
+java.security.Provider$UString
java.security.PublicKey
java.security.SecureRandom
java.security.SecureRandomSpi
java.security.Security
-java.security.Security$SecurityDoor
java.security.Signature
-java.security.Signature$SignatureImpl
+java.security.Signature$Delegate
java.security.SignatureException
java.security.SignatureSpi
java.security.UnrecoverableEntryException
@@ -3033,15 +3309,14 @@
java.security.cert.CRL
java.security.cert.CRLException
java.security.cert.CertPath
-java.security.cert.CertPathBuilderException
+java.security.cert.CertPathChecker
+java.security.cert.CertPathHelperImpl
java.security.cert.CertPathParameters
java.security.cert.CertPathValidator
java.security.cert.CertPathValidatorException
java.security.cert.CertPathValidatorResult
java.security.cert.CertPathValidatorSpi
java.security.cert.CertSelector
-java.security.cert.CertStoreException
-java.security.cert.CertStoreParameters
java.security.cert.Certificate
java.security.cert.CertificateEncodingException
java.security.cert.CertificateException
@@ -3050,11 +3325,14 @@
java.security.cert.CertificateFactorySpi
java.security.cert.CertificateNotYetValidException
java.security.cert.CertificateParsingException
+java.security.cert.Extension
java.security.cert.PKIXCertPathChecker
java.security.cert.PKIXCertPathValidatorResult
java.security.cert.PKIXParameters
+java.security.cert.PKIXRevocationChecker
java.security.cert.PolicyNode
java.security.cert.TrustAnchor
+java.security.cert.X509CRL
java.security.cert.X509CertSelector
java.security.cert.X509Certificate
java.security.cert.X509Extension
@@ -3064,51 +3342,70 @@
java.security.interfaces.ECPrivateKey
java.security.interfaces.ECPublicKey
java.security.interfaces.RSAKey
+java.security.interfaces.RSAPrivateCrtKey
java.security.interfaces.RSAPrivateKey
java.security.interfaces.RSAPublicKey
java.security.spec.AlgorithmParameterSpec
java.security.spec.ECField
+java.security.spec.ECFieldF2m
java.security.spec.ECFieldFp
java.security.spec.ECParameterSpec
java.security.spec.ECPoint
+java.security.spec.ECPrivateKeySpec
+java.security.spec.ECPublicKeySpec
java.security.spec.EllipticCurve
+java.security.spec.EncodedKeySpec
java.security.spec.InvalidKeySpecException
java.security.spec.InvalidParameterSpecException
java.security.spec.KeySpec
+java.security.spec.PKCS8EncodedKeySpec
+java.security.spec.RSAPrivateCrtKeySpec
+java.security.spec.RSAPrivateKeySpec
+java.security.spec.RSAPublicKeySpec
+java.security.spec.X509EncodedKeySpec
+java.sql.Timestamp
java.text.AttributedCharacterIterator$Attribute
-java.text.Bidi
-java.text.Bidi$Run
+java.text.CalendarBuilder
java.text.Collator
java.text.DateFormat
java.text.DateFormat$Field
java.text.DateFormatSymbols
java.text.DecimalFormat
java.text.DecimalFormatSymbols
+java.text.DontCareFieldPosition
+java.text.DontCareFieldPosition$1
java.text.FieldPosition
java.text.Format
java.text.Format$Field
+java.text.Format$FieldDelegate
+java.text.Normalizer
+java.text.Normalizer$Form
java.text.NumberFormat
-java.text.NumberFormat$Field
java.text.ParseException
java.text.ParsePosition
java.text.RuleBasedCollator
java.text.SimpleDateFormat
+java.text.spi.DateFormatProvider
+java.text.spi.DateFormatSymbolsProvider
+java.text.spi.DecimalFormatSymbolsProvider
+java.text.spi.NumberFormatProvider
java.util.AbstractCollection
java.util.AbstractList
-java.util.AbstractList$FullListIterator
-java.util.AbstractList$SimpleListIterator
-java.util.AbstractList$SubAbstractList
-java.util.AbstractList$SubAbstractListRandomAccess
+java.util.AbstractList$Itr
+java.util.AbstractList$ListItr
java.util.AbstractMap
java.util.AbstractMap$1
java.util.AbstractMap$2
-java.util.AbstractMap$2$1
+java.util.AbstractMap$SimpleImmutableEntry
java.util.AbstractQueue
java.util.AbstractSequentialList
java.util.AbstractSet
java.util.ArrayDeque
java.util.ArrayList
-java.util.ArrayList$ArrayListIterator
+java.util.ArrayList$Itr
+java.util.ArrayList$ListItr
+java.util.ArrayList$SubList
+java.util.ArrayList$SubList$1
java.util.Arrays
java.util.Arrays$ArrayList
java.util.BitSet
@@ -3117,7 +3414,6 @@
java.util.Collections
java.util.Collections$1
java.util.Collections$2
-java.util.Collections$3
java.util.Collections$AsLIFOQueue
java.util.Collections$CheckedCollection
java.util.Collections$CheckedList
@@ -3127,7 +3423,10 @@
java.util.Collections$CheckedSortedMap
java.util.Collections$CheckedSortedSet
java.util.Collections$CopiesList
+java.util.Collections$EmptyEnumeration
+java.util.Collections$EmptyIterator
java.util.Collections$EmptyList
+java.util.Collections$EmptyListIterator
java.util.Collections$EmptyMap
java.util.Collections$EmptySet
java.util.Collections$ReverseComparator
@@ -3136,7 +3435,6 @@
java.util.Collections$SingletonList
java.util.Collections$SingletonMap
java.util.Collections$SingletonSet
-java.util.Collections$SingletonSet$1
java.util.Collections$SynchronizedCollection
java.util.Collections$SynchronizedList
java.util.Collections$SynchronizedMap
@@ -3147,10 +3445,11 @@
java.util.Collections$UnmodifiableCollection
java.util.Collections$UnmodifiableCollection$1
java.util.Collections$UnmodifiableList
+java.util.Collections$UnmodifiableList$1
java.util.Collections$UnmodifiableMap
java.util.Collections$UnmodifiableMap$UnmodifiableEntrySet
java.util.Collections$UnmodifiableMap$UnmodifiableEntrySet$1
-java.util.Collections$UnmodifiableMap$UnmodifiableEntrySet$UnmodifiableMapEntry
+java.util.Collections$UnmodifiableMap$UnmodifiableEntrySet$UnmodifiableEntry
java.util.Collections$UnmodifiableRandomAccessList
java.util.Collections$UnmodifiableSet
java.util.Collections$UnmodifiableSortedMap
@@ -3164,110 +3463,139 @@
java.util.Dictionary
java.util.DualPivotQuicksort
java.util.EnumMap
+java.util.EnumMap$1
+java.util.EnumMap$EnumMapIterator
java.util.EnumSet
java.util.Enumeration
java.util.EventListener
java.util.EventObject
java.util.Formattable
java.util.Formatter
-java.util.Formatter$1
-java.util.Formatter$CachedDecimalFormat
+java.util.Formatter$Conversion
+java.util.Formatter$FixedString
+java.util.Formatter$Flags
+java.util.Formatter$FormatSpecifier
java.util.Formatter$FormatSpecifierParser
-java.util.Formatter$FormatToken
+java.util.Formatter$FormatString
java.util.GregorianCalendar
java.util.HashMap
java.util.HashMap$EntryIterator
java.util.HashMap$EntrySet
java.util.HashMap$HashIterator
java.util.HashMap$HashMapEntry
+java.util.HashMap$Holder
java.util.HashMap$KeyIterator
java.util.HashMap$KeySet
java.util.HashMap$ValueIterator
java.util.HashMap$Values
java.util.HashSet
java.util.Hashtable
-java.util.Hashtable$HashIterator
+java.util.Hashtable$EntrySet
+java.util.Hashtable$Enumerator
java.util.Hashtable$HashtableEntry
-java.util.Hashtable$KeyEnumeration
-java.util.Hashtable$ValueIterator
-java.util.Hashtable$Values
+java.util.Hashtable$Holder
+java.util.Hashtable$KeySet
+java.util.Hashtable$ValueCollection
java.util.IdentityHashMap
+java.util.IdentityHashMap$EntryIterator
+java.util.IdentityHashMap$EntrySet
java.util.IdentityHashMap$IdentityHashMapIterator
+java.util.IdentityHashMap$KeySet
java.util.IllegalFormatException
java.util.IllformedLocaleException
java.util.Iterator
java.util.LinkedHashMap
java.util.LinkedHashMap$EntryIterator
java.util.LinkedHashMap$KeyIterator
-java.util.LinkedHashMap$LinkedEntry
java.util.LinkedHashMap$LinkedHashIterator
+java.util.LinkedHashMap$LinkedHashMapEntry
java.util.LinkedHashMap$ValueIterator
java.util.LinkedHashSet
java.util.LinkedList
-java.util.LinkedList$Link
-java.util.LinkedList$LinkIterator
+java.util.LinkedList$ListItr
+java.util.LinkedList$Node
java.util.List
java.util.ListIterator
java.util.Locale
java.util.Locale$Builder
-java.util.Locale$NoImagePreloadHolder
+java.util.Locale$Cache
+java.util.Locale$Category
+java.util.Locale$LocaleKey
java.util.Map
java.util.Map$Entry
-java.util.MapEntry
-java.util.MapEntry$Type
-java.util.MiniEnumSet
-java.util.MiniEnumSet$MiniEnumSetIterator
java.util.MissingResourceException
java.util.NavigableMap
java.util.NavigableSet
java.util.NoSuchElementException
java.util.Objects
java.util.PriorityQueue
+java.util.PriorityQueue$Itr
java.util.Properties
+java.util.Properties$LineReader
+java.util.PropertyResourceBundle
java.util.Queue
java.util.Random
java.util.RandomAccess
+java.util.RandomAccessSubList
+java.util.RegularEnumSet
+java.util.RegularEnumSet$EnumSetIterator
java.util.ResourceBundle
-java.util.ResourceBundle$MissingBundle
+java.util.ResourceBundle$1
+java.util.ResourceBundle$BundleReference
+java.util.ResourceBundle$CacheKey
+java.util.ResourceBundle$CacheKeyReference
+java.util.ResourceBundle$Control
+java.util.ResourceBundle$Control$1
+java.util.ResourceBundle$Control$CandidateListCache
+java.util.ResourceBundle$LoaderReference
+java.util.ResourceBundle$RBClassLoader
+java.util.ResourceBundle$RBClassLoader$1
+java.util.Scanner
+java.util.ServiceLoader
+java.util.ServiceLoader$1
+java.util.ServiceLoader$LazyIterator
java.util.Set
java.util.SimpleTimeZone
java.util.SortedMap
java.util.SortedSet
java.util.Stack
java.util.StringTokenizer
+java.util.SubList
+java.util.TaskQueue
java.util.TimSort
java.util.TimeZone
java.util.Timer
-java.util.Timer$FinalizerHelper
-java.util.Timer$TimerImpl
-java.util.Timer$TimerImpl$TimerHeap
+java.util.Timer$1
java.util.TimerTask
+java.util.TimerThread
java.util.TreeMap
-java.util.TreeMap$1
-java.util.TreeMap$Bound
-java.util.TreeMap$Bound$1
-java.util.TreeMap$Bound$2
-java.util.TreeMap$Bound$3
-java.util.TreeMap$BoundedMap
-java.util.TreeMap$BoundedMap$BoundedIterator
+java.util.TreeMap$AscendingSubMap
+java.util.TreeMap$EntryIterator
java.util.TreeMap$EntrySet
-java.util.TreeMap$EntrySet$1
+java.util.TreeMap$KeyIterator
java.util.TreeMap$KeySet
-java.util.TreeMap$KeySet$1
-java.util.TreeMap$MapIterator
-java.util.TreeMap$Node
-java.util.TreeMap$Relation
+java.util.TreeMap$NavigableSubMap
+java.util.TreeMap$PrivateEntryIterator
+java.util.TreeMap$TreeMapEntry
+java.util.TreeMap$ValueIterator
+java.util.TreeMap$Values
java.util.TreeSet
java.util.UUID
+java.util.UUID$Holder
java.util.Vector
java.util.Vector$1
+java.util.Vector$Itr
java.util.WeakHashMap
-java.util.WeakHashMap$2
-java.util.WeakHashMap$2$1
java.util.WeakHashMap$Entry
-java.util.WeakHashMap$Entry$Type
+java.util.WeakHashMap$EntrySet
java.util.WeakHashMap$HashIterator
+java.util.WeakHashMap$Holder
+java.util.WeakHashMap$KeyIterator
+java.util.WeakHashMap$KeySet
+java.util.WeakHashMap$Values
+java.util.XMLUtils
java.util.concurrent.AbstractExecutorService
+java.util.concurrent.ArrayBlockingQueue
java.util.concurrent.BlockingQueue
java.util.concurrent.Callable
java.util.concurrent.CancellationException
@@ -3283,6 +3611,8 @@
java.util.concurrent.ConcurrentHashMap$Traverser
java.util.concurrent.ConcurrentHashMap$TreeBin
java.util.concurrent.ConcurrentHashMap$TreeNode
+java.util.concurrent.ConcurrentHashMap$ValueIterator
+java.util.concurrent.ConcurrentHashMap$ValuesView
java.util.concurrent.ConcurrentLinkedQueue
java.util.concurrent.ConcurrentLinkedQueue$Node
java.util.concurrent.ConcurrentMap
@@ -3340,6 +3670,8 @@
java.util.concurrent.atomic.AtomicInteger
java.util.concurrent.atomic.AtomicLong
java.util.concurrent.atomic.AtomicReference
+java.util.concurrent.atomic.AtomicReferenceFieldUpdater
+java.util.concurrent.atomic.AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl
java.util.concurrent.locks.AbstractOwnableSynchronizer
java.util.concurrent.locks.AbstractQueuedSynchronizer
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject
@@ -3357,31 +3689,38 @@
java.util.concurrent.locks.ReentrantReadWriteLock$Sync
java.util.concurrent.locks.ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter
java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock
-java.util.jar.Attributes
-java.util.jar.Attributes$Name
java.util.jar.JarEntry
java.util.jar.JarFile
-java.util.jar.JarFile$JarFileEnumerator
-java.util.logging.ConsoleHandler
+java.util.jar.JarFile$1
+java.util.jar.JarFile$JarFileEntry
java.util.logging.ErrorManager
-java.util.logging.Filter
java.util.logging.Formatter
java.util.logging.Handler
java.util.logging.Level
+java.util.logging.Level$KnownLevel
java.util.logging.LogManager
java.util.logging.LogManager$1
+java.util.logging.LogManager$2
+java.util.logging.LogManager$4
+java.util.logging.LogManager$Cleaner
+java.util.logging.LogManager$LogNode
+java.util.logging.LogManager$LoggerContext
+java.util.logging.LogManager$LoggerContext$1
+java.util.logging.LogManager$LoggerWeakRef
+java.util.logging.LogManager$RootLogger
+java.util.logging.LogManager$SystemLoggerContext
+java.util.logging.LogRecord
java.util.logging.Logger
-java.util.logging.Logger$1
java.util.logging.LoggingPermission
-java.util.logging.SimpleFormatter
-java.util.logging.StreamHandler
+java.util.logging.LoggingProxyImpl
java.util.regex.MatchResult
java.util.regex.Matcher
java.util.regex.Pattern
java.util.regex.PatternSyntaxException
-java.util.regex.Splitter
+java.util.spi.LocaleServiceProvider
java.util.zip.Adler32
java.util.zip.CRC32
+java.util.zip.CheckedInputStream
java.util.zip.Checksum
java.util.zip.DataFormatException
java.util.zip.Deflater
@@ -3390,26 +3729,38 @@
java.util.zip.GZIPOutputStream
java.util.zip.Inflater
java.util.zip.InflaterInputStream
-java.util.zip.Zip64
+java.util.zip.ZStreamRef
+java.util.zip.ZipCoder
java.util.zip.ZipConstants
java.util.zip.ZipEntry
java.util.zip.ZipFile
java.util.zip.ZipFile$1
-java.util.zip.ZipFile$EocdRecord
-java.util.zip.ZipFile$RAFStream
-java.util.zip.ZipFile$ZipInflaterInputStream
+java.util.zip.ZipFile$ZipFileInflaterInputStream
+java.util.zip.ZipFile$ZipFileInputStream
javax.crypto.BadPaddingException
javax.crypto.Cipher
+javax.crypto.Cipher$CipherSpiAndProvider
+javax.crypto.Cipher$InitParams
+javax.crypto.Cipher$InitType
javax.crypto.Cipher$NeedToSet
+javax.crypto.Cipher$SpiAndProviderUpdater
+javax.crypto.Cipher$Transform
javax.crypto.CipherSpi
javax.crypto.IllegalBlockSizeException
+javax.crypto.JceSecurity
+javax.crypto.Mac
javax.crypto.NoSuchPaddingException
+javax.crypto.NullCipher
javax.crypto.SecretKey
javax.crypto.ShortBufferException
javax.crypto.spec.IvParameterSpec
javax.crypto.spec.SecretKeySpec
javax.microedition.khronos.egl.EGL
javax.microedition.khronos.egl.EGL10
+javax.microedition.khronos.egl.EGLConfig
+javax.microedition.khronos.egl.EGLContext
+javax.microedition.khronos.egl.EGLDisplay
+javax.microedition.khronos.egl.EGLSurface
javax.microedition.khronos.opengles.GL
javax.microedition.khronos.opengles.GL10
javax.microedition.khronos.opengles.GL10Ext
@@ -3419,56 +3770,61 @@
javax.net.DefaultSocketFactory
javax.net.ServerSocketFactory
javax.net.SocketFactory
-javax.net.ssl.DistinguishedNameParser
+javax.net.ssl.ExtendedSSLSession
+javax.net.ssl.HandshakeCompletedEvent
javax.net.ssl.HandshakeCompletedListener
javax.net.ssl.HostnameVerifier
javax.net.ssl.HttpsURLConnection
javax.net.ssl.KeyManager
javax.net.ssl.KeyManagerFactory
+javax.net.ssl.KeyManagerFactory$1
javax.net.ssl.KeyManagerFactorySpi
javax.net.ssl.SSLContext
javax.net.ssl.SSLContextSpi
javax.net.ssl.SSLEngine
javax.net.ssl.SSLException
+javax.net.ssl.SSLHandshakeException
+javax.net.ssl.SSLParameters
javax.net.ssl.SSLPeerUnverifiedException
javax.net.ssl.SSLProtocolException
+javax.net.ssl.SSLServerSocket
javax.net.ssl.SSLServerSocketFactory
javax.net.ssl.SSLSession
+javax.net.ssl.SSLSessionBindingEvent
+javax.net.ssl.SSLSessionBindingListener
javax.net.ssl.SSLSessionContext
javax.net.ssl.SSLSocket
javax.net.ssl.SSLSocketFactory
+javax.net.ssl.SSLSocketFactory$1
javax.net.ssl.TrustManager
javax.net.ssl.TrustManagerFactory
+javax.net.ssl.TrustManagerFactory$1
javax.net.ssl.TrustManagerFactorySpi
javax.net.ssl.X509ExtendedKeyManager
+javax.net.ssl.X509ExtendedTrustManager
javax.net.ssl.X509KeyManager
javax.net.ssl.X509TrustManager
+javax.security.auth.callback.UnsupportedCallbackException
javax.security.auth.x500.X500Principal
javax.security.cert.Certificate
javax.security.cert.CertificateException
javax.security.cert.X509Certificate
javax.xml.parsers.ParserConfigurationException
-libcore.icu.AlphabeticIndex
-libcore.icu.AlphabeticIndex$ImmutableIndex
+javax.xml.transform.TransformerConfigurationException
+javax.xml.transform.TransformerException
libcore.icu.DateIntervalFormat
-libcore.icu.DateIntervalFormat$FormatterCache
libcore.icu.DateUtilsBridge
libcore.icu.ICU
libcore.icu.LocaleData
-libcore.icu.NativeCollation
libcore.icu.NativeConverter
-libcore.icu.NativeDecimalFormat
-libcore.icu.NativeDecimalFormat$FieldPositionIterator
-libcore.icu.NativeIDN
-libcore.icu.NativeNormalizer
-libcore.icu.NativePluralRules
-libcore.icu.RuleBasedCollatorICU
libcore.icu.TimeZoneNames
-libcore.icu.Transliterator
libcore.internal.StringPool
libcore.io.AsynchronousCloseMonitor
libcore.io.BlockGuardOs
libcore.io.BufferIterator
+libcore.io.ClassPathURLStreamHandler
+libcore.io.ClassPathURLStreamHandler$ClassPathURLConnection
+libcore.io.ClassPathURLStreamHandler$ClassPathURLConnection$1
libcore.io.DropBox
libcore.io.DropBox$DefaultReporter
libcore.io.DropBox$Reporter
@@ -3476,7 +3832,6 @@
libcore.io.EventLogger$DefaultReporter
libcore.io.EventLogger$Reporter
libcore.io.ForwardingOs
-libcore.io.HeapBufferIterator
libcore.io.IoBridge
libcore.io.IoUtils
libcore.io.IoUtils$FileReader
@@ -3486,19 +3841,13 @@
libcore.io.NioBufferIterator
libcore.io.Os
libcore.io.Posix
-libcore.io.Streams
libcore.math.MathUtils
libcore.net.NetworkSecurityPolicy
+libcore.net.NetworkSecurityPolicy$DefaultNetworkSecurityPolicy
libcore.net.UriCodec
libcore.net.event.NetworkEventDispatcher
libcore.net.event.NetworkEventListener
-libcore.net.url.FileHandler
-libcore.net.url.FileURLConnection
-libcore.net.url.FileURLConnection$1
-libcore.net.url.JarHandler
-libcore.net.url.JarURLConnectionImpl
-libcore.net.url.JarURLConnectionImpl$JarURLConnectionInputStream
-libcore.net.url.UrlUtils
+libcore.reflect.AnnotatedElements
libcore.reflect.AnnotationAccess
libcore.reflect.AnnotationFactory
libcore.reflect.AnnotationMember
@@ -3508,13 +3857,15 @@
libcore.reflect.ListOfTypes
libcore.reflect.ListOfVariables
libcore.reflect.ParameterizedTypeImpl
+libcore.reflect.TypeVariableImpl
libcore.reflect.Types
libcore.util.BasicLruCache
libcore.util.CharsetUtils
libcore.util.CollectionUtils
-libcore.util.CollectionUtils$1
-libcore.util.CollectionUtils$1$1
libcore.util.EmptyArray
+libcore.util.NativeAllocationRegistry
+libcore.util.NativeAllocationRegistry$CleanerRunner
+libcore.util.NativeAllocationRegistry$CleanerThunk
libcore.util.Objects
libcore.util.ZoneInfo
libcore.util.ZoneInfo$CheckedArithmeticException
@@ -3522,280 +3873,66 @@
libcore.util.ZoneInfoDB
libcore.util.ZoneInfoDB$TzData
libcore.util.ZoneInfoDB$TzData$1
-org.apache.commons.logging.Log
-org.apache.commons.logging.LogFactory
-org.apache.commons.logging.impl.Jdk14Logger
-org.apache.commons.logging.impl.WeakHashtable
org.apache.harmony.dalvik.NativeTestTarget
org.apache.harmony.dalvik.ddmc.Chunk
org.apache.harmony.dalvik.ddmc.ChunkHandler
org.apache.harmony.dalvik.ddmc.DdmServer
org.apache.harmony.dalvik.ddmc.DdmVmInternal
org.apache.harmony.luni.internal.util.TimezoneGetter
-org.apache.harmony.security.asn1.ASN1Any
-org.apache.harmony.security.asn1.ASN1Choice
-org.apache.harmony.security.asn1.ASN1Constants
-org.apache.harmony.security.asn1.ASN1Constructed
-org.apache.harmony.security.asn1.ASN1Oid
-org.apache.harmony.security.asn1.ASN1Oid$1
-org.apache.harmony.security.asn1.ASN1Primitive
-org.apache.harmony.security.asn1.ASN1Sequence
-org.apache.harmony.security.asn1.ASN1SequenceOf
-org.apache.harmony.security.asn1.ASN1SetOf
-org.apache.harmony.security.asn1.ASN1StringType
-org.apache.harmony.security.asn1.ASN1StringType$1
-org.apache.harmony.security.asn1.ASN1StringType$2
-org.apache.harmony.security.asn1.ASN1StringType$3
-org.apache.harmony.security.asn1.ASN1StringType$4
-org.apache.harmony.security.asn1.ASN1StringType$5
-org.apache.harmony.security.asn1.ASN1StringType$6
-org.apache.harmony.security.asn1.ASN1StringType$7
-org.apache.harmony.security.asn1.ASN1StringType$ASN1StringUTF8Type
-org.apache.harmony.security.asn1.ASN1Type
-org.apache.harmony.security.asn1.ASN1TypeCollection
-org.apache.harmony.security.asn1.ASN1ValueCollection
-org.apache.harmony.security.asn1.BerInputStream
-org.apache.harmony.security.asn1.BerOutputStream
-org.apache.harmony.security.asn1.DerInputStream
-org.apache.harmony.security.asn1.DerOutputStream
-org.apache.harmony.security.provider.crypto.CryptoProvider
-org.apache.harmony.security.utils.AlgNameMapper
-org.apache.harmony.security.utils.AlgNameMapperSource
-org.apache.harmony.security.utils.ObjectIdentifier
-org.apache.harmony.security.x501.AttributeTypeAndValue
-org.apache.harmony.security.x501.AttributeTypeAndValue$1
-org.apache.harmony.security.x501.AttributeTypeAndValue$2
-org.apache.harmony.security.x501.AttributeTypeAndValueComparator
-org.apache.harmony.security.x501.AttributeValue
-org.apache.harmony.security.x501.DirectoryString
-org.apache.harmony.security.x501.DirectoryString$1
-org.apache.harmony.security.x501.Name
-org.apache.harmony.security.x501.Name$1
org.apache.harmony.xml.ExpatAttributes
org.apache.harmony.xml.ExpatParser
-org.apache.http.ConnectionReuseStrategy
-org.apache.http.FormattedHeader
org.apache.http.Header
-org.apache.http.HeaderElement
-org.apache.http.HeaderElementIterator
org.apache.http.HeaderIterator
-org.apache.http.HttpClientConnection
-org.apache.http.HttpConnection
-org.apache.http.HttpConnectionMetrics
org.apache.http.HttpEntity
org.apache.http.HttpEntityEnclosingRequest
org.apache.http.HttpException
org.apache.http.HttpHost
-org.apache.http.HttpInetConnection
org.apache.http.HttpMessage
org.apache.http.HttpRequest
-org.apache.http.HttpRequestInterceptor
org.apache.http.HttpResponse
-org.apache.http.HttpResponseFactory
-org.apache.http.HttpResponseInterceptor
org.apache.http.HttpVersion
org.apache.http.NameValuePair
-org.apache.http.ParseException
org.apache.http.ProtocolException
org.apache.http.ProtocolVersion
org.apache.http.ReasonPhraseCatalog
-org.apache.http.RequestLine
org.apache.http.StatusLine
-org.apache.http.auth.AuthSchemeFactory
-org.apache.http.auth.AuthSchemeRegistry
-org.apache.http.auth.AuthState
-org.apache.http.auth.AuthenticationException
-org.apache.http.client.AuthenticationHandler
-org.apache.http.client.CookieStore
-org.apache.http.client.CredentialsProvider
+org.apache.http.client.ClientProtocolException
org.apache.http.client.HttpClient
-org.apache.http.client.HttpRequestRetryHandler
-org.apache.http.client.RedirectHandler
-org.apache.http.client.RequestDirector
org.apache.http.client.ResponseHandler
-org.apache.http.client.UserTokenHandler
org.apache.http.client.methods.AbortableHttpRequest
org.apache.http.client.methods.HttpEntityEnclosingRequestBase
org.apache.http.client.methods.HttpGet
org.apache.http.client.methods.HttpPost
org.apache.http.client.methods.HttpRequestBase
org.apache.http.client.methods.HttpUriRequest
-org.apache.http.client.params.HttpClientParams
-org.apache.http.client.protocol.RequestAddCookies
-org.apache.http.client.protocol.RequestDefaultHeaders
-org.apache.http.client.protocol.RequestProxyAuthentication
-org.apache.http.client.protocol.RequestTargetAuthentication
-org.apache.http.client.protocol.ResponseProcessCookies
-org.apache.http.client.utils.URIUtils
-org.apache.http.conn.BasicManagedEntity
+org.apache.http.client.utils.URLEncodedUtils
org.apache.http.conn.ClientConnectionManager
-org.apache.http.conn.ClientConnectionOperator
-org.apache.http.conn.ClientConnectionRequest
org.apache.http.conn.ConnectTimeoutException
-org.apache.http.conn.ConnectionKeepAliveStrategy
-org.apache.http.conn.ConnectionReleaseTrigger
-org.apache.http.conn.EofSensorInputStream
-org.apache.http.conn.EofSensorWatcher
-org.apache.http.conn.ManagedClientConnection
-org.apache.http.conn.OperatedClientConnection
org.apache.http.conn.params.ConnManagerPNames
org.apache.http.conn.params.ConnManagerParams
org.apache.http.conn.params.ConnManagerParams$1
org.apache.http.conn.params.ConnPerRoute
-org.apache.http.conn.params.ConnPerRouteBean
-org.apache.http.conn.params.ConnRoutePNames
-org.apache.http.conn.params.ConnRouteParams
-org.apache.http.conn.routing.BasicRouteDirector
-org.apache.http.conn.routing.HttpRoute
-org.apache.http.conn.routing.HttpRouteDirector
-org.apache.http.conn.routing.HttpRoutePlanner
-org.apache.http.conn.routing.RouteInfo
-org.apache.http.conn.routing.RouteInfo$LayerType
-org.apache.http.conn.routing.RouteInfo$TunnelType
-org.apache.http.conn.routing.RouteTracker
org.apache.http.conn.scheme.LayeredSocketFactory
-org.apache.http.conn.scheme.PlainSocketFactory
-org.apache.http.conn.scheme.Scheme
-org.apache.http.conn.scheme.SchemeRegistry
org.apache.http.conn.scheme.SocketFactory
-org.apache.http.conn.ssl.AbstractVerifier
-org.apache.http.conn.ssl.AllowAllHostnameVerifier
-org.apache.http.conn.ssl.BrowserCompatHostnameVerifier
-org.apache.http.conn.ssl.SSLSocketFactory
-org.apache.http.conn.ssl.StrictHostnameVerifier
-org.apache.http.conn.ssl.X509HostnameVerifier
-org.apache.http.cookie.CookieSpecFactory
-org.apache.http.cookie.CookieSpecRegistry
-org.apache.http.cookie.MalformedCookieException
org.apache.http.entity.AbstractHttpEntity
org.apache.http.entity.BasicHttpEntity
org.apache.http.entity.ByteArrayEntity
-org.apache.http.entity.ContentLengthStrategy
-org.apache.http.entity.HttpEntityWrapper
-org.apache.http.impl.AbstractHttpClientConnection
-org.apache.http.impl.DefaultConnectionReuseStrategy
-org.apache.http.impl.DefaultHttpResponseFactory
-org.apache.http.impl.EnglishReasonPhraseCatalog
-org.apache.http.impl.HttpConnectionMetricsImpl
-org.apache.http.impl.SocketHttpClientConnection
-org.apache.http.impl.auth.BasicSchemeFactory
-org.apache.http.impl.auth.DigestSchemeFactory
-org.apache.http.impl.client.AbstractAuthenticationHandler
-org.apache.http.impl.client.AbstractHttpClient
-org.apache.http.impl.client.BasicCredentialsProvider
-org.apache.http.impl.client.ClientParamsStack
-org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy
-org.apache.http.impl.client.DefaultHttpClient
-org.apache.http.impl.client.DefaultHttpRequestRetryHandler
-org.apache.http.impl.client.DefaultProxyAuthenticationHandler
-org.apache.http.impl.client.DefaultRedirectHandler
-org.apache.http.impl.client.DefaultRequestDirector
-org.apache.http.impl.client.DefaultTargetAuthenticationHandler
-org.apache.http.impl.client.DefaultUserTokenHandler
org.apache.http.impl.client.EntityEnclosingRequestWrapper
org.apache.http.impl.client.RequestWrapper
-org.apache.http.impl.client.RoutedRequest
-org.apache.http.impl.client.TunnelRefusedException
-org.apache.http.impl.conn.AbstractClientConnAdapter
-org.apache.http.impl.conn.AbstractPoolEntry
-org.apache.http.impl.conn.AbstractPooledConnAdapter
-org.apache.http.impl.conn.DefaultClientConnection
-org.apache.http.impl.conn.DefaultClientConnectionOperator
-org.apache.http.impl.conn.DefaultResponseParser
-org.apache.http.impl.conn.IdleConnectionHandler
-org.apache.http.impl.conn.IdleConnectionHandler$TimeValues
-org.apache.http.impl.conn.ProxySelectorRoutePlanner
-org.apache.http.impl.conn.tsccm.AbstractConnPool
-org.apache.http.impl.conn.tsccm.BasicPoolEntry
-org.apache.http.impl.conn.tsccm.BasicPoolEntryRef
-org.apache.http.impl.conn.tsccm.BasicPooledConnAdapter
-org.apache.http.impl.conn.tsccm.ConnPoolByRoute
-org.apache.http.impl.conn.tsccm.ConnPoolByRoute$1
-org.apache.http.impl.conn.tsccm.PoolEntryRequest
-org.apache.http.impl.conn.tsccm.RefQueueHandler
-org.apache.http.impl.conn.tsccm.RefQueueWorker
-org.apache.http.impl.conn.tsccm.RouteSpecificPool
-org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager
-org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager$1
-org.apache.http.impl.conn.tsccm.WaitingThreadAborter
-org.apache.http.impl.cookie.BestMatchSpecFactory
-org.apache.http.impl.cookie.BrowserCompatSpecFactory
org.apache.http.impl.cookie.DateParseException
-org.apache.http.impl.cookie.NetscapeDraftSpecFactory
-org.apache.http.impl.cookie.RFC2109SpecFactory
-org.apache.http.impl.cookie.RFC2965SpecFactory
-org.apache.http.impl.entity.EntityDeserializer
-org.apache.http.impl.entity.EntitySerializer
-org.apache.http.impl.entity.LaxContentLengthStrategy
-org.apache.http.impl.entity.StrictContentLengthStrategy
-org.apache.http.impl.io.AbstractMessageParser
-org.apache.http.impl.io.AbstractMessageWriter
-org.apache.http.impl.io.AbstractSessionInputBuffer
-org.apache.http.impl.io.AbstractSessionOutputBuffer
-org.apache.http.impl.io.ChunkedInputStream
-org.apache.http.impl.io.ContentLengthOutputStream
-org.apache.http.impl.io.HttpRequestWriter
-org.apache.http.impl.io.HttpTransportMetricsImpl
-org.apache.http.impl.io.SocketInputBuffer
-org.apache.http.impl.io.SocketOutputBuffer
-org.apache.http.io.HttpMessageParser
-org.apache.http.io.HttpMessageWriter
-org.apache.http.io.HttpTransportMetrics
-org.apache.http.io.SessionInputBuffer
-org.apache.http.io.SessionOutputBuffer
+org.apache.http.impl.cookie.DateUtils
org.apache.http.message.AbstractHttpMessage
org.apache.http.message.BasicHeader
-org.apache.http.message.BasicHeaderElement
-org.apache.http.message.BasicHeaderElementIterator
-org.apache.http.message.BasicHeaderValueParser
org.apache.http.message.BasicHttpResponse
-org.apache.http.message.BasicLineFormatter
-org.apache.http.message.BasicLineParser
-org.apache.http.message.BasicListHeaderIterator
org.apache.http.message.BasicNameValuePair
-org.apache.http.message.BasicRequestLine
org.apache.http.message.BasicStatusLine
-org.apache.http.message.BufferedHeader
org.apache.http.message.HeaderGroup
-org.apache.http.message.HeaderValueParser
-org.apache.http.message.LineFormatter
-org.apache.http.message.LineParser
-org.apache.http.message.ParserCursor
org.apache.http.params.AbstractHttpParams
org.apache.http.params.BasicHttpParams
org.apache.http.params.CoreConnectionPNames
-org.apache.http.params.CoreProtocolPNames
org.apache.http.params.HttpConnectionParams
org.apache.http.params.HttpParams
-org.apache.http.params.HttpProtocolParams
-org.apache.http.protocol.BasicHttpContext
-org.apache.http.protocol.BasicHttpProcessor
-org.apache.http.protocol.HTTP
org.apache.http.protocol.HttpContext
-org.apache.http.protocol.HttpProcessor
-org.apache.http.protocol.HttpRequestExecutor
-org.apache.http.protocol.HttpRequestInterceptorList
-org.apache.http.protocol.HttpResponseInterceptorList
-org.apache.http.protocol.RequestConnControl
-org.apache.http.protocol.RequestContent
-org.apache.http.protocol.RequestExpectContinue
-org.apache.http.protocol.RequestTargetHost
-org.apache.http.protocol.RequestUserAgent
-org.apache.http.util.ByteArrayBuffer
-org.apache.http.util.CharArrayBuffer
-org.apache.http.util.LangUtils
-org.ccil.cowan.tagsoup.AttributesImpl
-org.ccil.cowan.tagsoup.AutoDetector
-org.ccil.cowan.tagsoup.Element
-org.ccil.cowan.tagsoup.ElementType
-org.ccil.cowan.tagsoup.HTMLModels
-org.ccil.cowan.tagsoup.HTMLScanner
-org.ccil.cowan.tagsoup.HTMLSchema
-org.ccil.cowan.tagsoup.Parser
-org.ccil.cowan.tagsoup.Parser$1
-org.ccil.cowan.tagsoup.ScanHandler
-org.ccil.cowan.tagsoup.Scanner
-org.ccil.cowan.tagsoup.Schema
org.json.JSON
org.json.JSONArray
org.json.JSONException
@@ -3817,9 +3954,218 @@
org.xml.sax.SAXNotRecognizedException
org.xml.sax.SAXNotSupportedException
org.xml.sax.XMLReader
-org.xml.sax.ext.LexicalHandler
org.xml.sax.helpers.DefaultHandler
org.xmlpull.v1.XmlPullParser
org.xmlpull.v1.XmlPullParserException
org.xmlpull.v1.XmlSerializer
+sun.misc.Cleaner
+sun.misc.CompoundEnumeration
+sun.misc.FormattedFloatingDecimal
+sun.misc.FormattedFloatingDecimal$1
+sun.misc.FormattedFloatingDecimal$Form
+sun.misc.FpUtils
+sun.misc.Hashing
+sun.misc.IOUtils
+sun.misc.IoTrace
+sun.misc.REException
sun.misc.Unsafe
+sun.misc.VM
+sun.misc.Version
+sun.net.ConnectionResetException
+sun.net.NetHooks
+sun.net.NetProperties
+sun.net.NetProperties$1
+sun.net.spi.DefaultProxySelector
+sun.net.spi.DefaultProxySelector$1
+sun.net.spi.DefaultProxySelector$2
+sun.net.spi.DefaultProxySelector$NonProxyInfo
+sun.net.spi.nameservice.NameService
+sun.net.util.IPAddressUtil
+sun.net.www.ParseUtil
+sun.net.www.protocol.file.Handler
+sun.net.www.protocol.jar.Handler
+sun.nio.ch.DatagramChannelImpl
+sun.nio.ch.DatagramDispatcher
+sun.nio.ch.DirectBuffer
+sun.nio.ch.EPollArrayWrapper
+sun.nio.ch.FileChannelImpl
+sun.nio.ch.FileChannelImpl$Unmapper
+sun.nio.ch.FileDispatcher
+sun.nio.ch.FileDispatcherImpl
+sun.nio.ch.FileKey
+sun.nio.ch.FileLockImpl
+sun.nio.ch.FileLockTable
+sun.nio.ch.IOStatus
+sun.nio.ch.IOUtil
+sun.nio.ch.InheritedChannel
+sun.nio.ch.Interruptible
+sun.nio.ch.NativeDispatcher
+sun.nio.ch.NativeThread
+sun.nio.ch.NativeThreadSet
+sun.nio.ch.Net
+sun.nio.ch.SelChImpl
+sun.nio.ch.ServerSocketChannelImpl
+sun.nio.ch.SharedFileLockTable
+sun.nio.ch.SharedFileLockTable$FileLockReference
+sun.nio.ch.SocketChannelImpl
+sun.nio.ch.Util
+sun.nio.ch.Util$1
+sun.nio.cs.ArrayDecoder
+sun.nio.cs.ArrayEncoder
+sun.nio.cs.StreamDecoder
+sun.nio.cs.StreamEncoder
+sun.nio.cs.ThreadLocalCoders
+sun.nio.cs.ThreadLocalCoders$1
+sun.nio.cs.ThreadLocalCoders$2
+sun.nio.cs.ThreadLocalCoders$Cache
+sun.reflect.annotation.AnnotationType
+sun.security.action.GetBooleanAction
+sun.security.action.GetPropertyAction
+sun.security.ec.ECKeyFactory
+sun.security.ec.ECKeyFactory$1
+sun.security.ec.ECKeyFactory$2
+sun.security.ec.ECParameters
+sun.security.ec.NamedCurve
+sun.security.jca.GetInstance
+sun.security.jca.GetInstance$Instance
+sun.security.jca.ProviderConfig
+sun.security.jca.ProviderConfig$2
+sun.security.jca.ProviderList
+sun.security.jca.ProviderList$1
+sun.security.jca.ProviderList$2
+sun.security.jca.ProviderList$3
+sun.security.jca.ProviderList$ServiceList
+sun.security.jca.ProviderList$ServiceList$1
+sun.security.jca.Providers
+sun.security.jca.ServiceId
+sun.security.pkcs.PKCS9Attribute
+sun.security.pkcs.ParsingException
+sun.security.pkcs.SignerInfo
+sun.security.provider.CertPathProvider
+sun.security.provider.X509Factory
+sun.security.provider.certpath.AdaptableX509CertSelector
+sun.security.provider.certpath.AlgorithmChecker
+sun.security.provider.certpath.BasicChecker
+sun.security.provider.certpath.CertPathHelper
+sun.security.provider.certpath.ConstraintsChecker
+sun.security.provider.certpath.KeyChecker
+sun.security.provider.certpath.PKIX
+sun.security.provider.certpath.PKIX$ValidatorParams
+sun.security.provider.certpath.PKIXCertPathValidator
+sun.security.provider.certpath.PKIXMasterCertPathValidator
+sun.security.provider.certpath.PolicyChecker
+sun.security.provider.certpath.PolicyNodeImpl
+sun.security.provider.certpath.UntrustedChecker
+sun.security.util.BitArray
+sun.security.util.ByteArrayLexOrder
+sun.security.util.ByteArrayTagOrder
+sun.security.util.Cache
+sun.security.util.Cache$EqualByteArray
+sun.security.util.Debug
+sun.security.util.DerEncoder
+sun.security.util.DerIndefLenConverter
+sun.security.util.DerInputBuffer
+sun.security.util.DerInputStream
+sun.security.util.DerOutputStream
+sun.security.util.DerValue
+sun.security.util.DisabledAlgorithmConstraints
+sun.security.util.DisabledAlgorithmConstraints$1
+sun.security.util.DisabledAlgorithmConstraints$KeySizeConstraint
+sun.security.util.DisabledAlgorithmConstraints$KeySizeConstraint$Operator
+sun.security.util.DisabledAlgorithmConstraints$KeySizeConstraints
+sun.security.util.KeyUtil
+sun.security.util.Length
+sun.security.util.MemoryCache
+sun.security.util.MemoryCache$CacheEntry
+sun.security.util.MemoryCache$SoftCacheEntry
+sun.security.util.ObjectIdentifier
+sun.security.util.UntrustedCertificates
+sun.security.x509.AVA
+sun.security.x509.AVAKeyword
+sun.security.x509.AccessDescription
+sun.security.x509.AlgorithmId
+sun.security.x509.AuthorityInfoAccessExtension
+sun.security.x509.AuthorityKeyIdentifierExtension
+sun.security.x509.BasicConstraintsExtension
+sun.security.x509.CRLDistributionPointsExtension
+sun.security.x509.CRLNumberExtension
+sun.security.x509.CRLReasonCodeExtension
+sun.security.x509.CertAttrSet
+sun.security.x509.CertificateAlgorithmId
+sun.security.x509.CertificateExtensions
+sun.security.x509.CertificateIssuerExtension
+sun.security.x509.CertificatePoliciesExtension
+sun.security.x509.CertificatePolicyId
+sun.security.x509.CertificateSerialNumber
+sun.security.x509.CertificateValidity
+sun.security.x509.CertificateVersion
+sun.security.x509.CertificateX509Key
+sun.security.x509.DNSName
+sun.security.x509.DeltaCRLIndicatorExtension
+sun.security.x509.DistributionPoint
+sun.security.x509.ExtendedKeyUsageExtension
+sun.security.x509.Extension
+sun.security.x509.FreshestCRLExtension
+sun.security.x509.GeneralName
+sun.security.x509.GeneralNameInterface
+sun.security.x509.GeneralNames
+sun.security.x509.InhibitAnyPolicyExtension
+sun.security.x509.IssuerAlternativeNameExtension
+sun.security.x509.IssuingDistributionPointExtension
+sun.security.x509.KeyIdentifier
+sun.security.x509.KeyUsageExtension
+sun.security.x509.NameConstraintsExtension
+sun.security.x509.NetscapeCertTypeExtension
+sun.security.x509.OCSPNoCheckExtension
+sun.security.x509.OIDMap
+sun.security.x509.OIDMap$OIDInfo
+sun.security.x509.PKIXExtensions
+sun.security.x509.PolicyConstraintsExtension
+sun.security.x509.PolicyInformation
+sun.security.x509.PolicyMappingsExtension
+sun.security.x509.PrivateKeyUsageExtension
+sun.security.x509.RDN
+sun.security.x509.SerialNumber
+sun.security.x509.SubjectAlternativeNameExtension
+sun.security.x509.SubjectInfoAccessExtension
+sun.security.x509.SubjectKeyIdentifierExtension
+sun.security.x509.URIName
+sun.security.x509.X500Name
+sun.security.x509.X500Name$1
+sun.security.x509.X509AttributeName
+sun.security.x509.X509CertImpl
+sun.security.x509.X509CertInfo
+sun.security.x509.X509Key
+sun.util.LocaleServiceProviderPool
+sun.util.LocaleServiceProviderPool$1
+sun.util.calendar.AbstractCalendar
+sun.util.calendar.BaseCalendar
+sun.util.calendar.BaseCalendar$Date
+sun.util.calendar.CalendarDate
+sun.util.calendar.CalendarSystem
+sun.util.calendar.CalendarUtils
+sun.util.calendar.Gregorian
+sun.util.calendar.Gregorian$Date
+sun.util.calendar.JulianCalendar
+sun.util.calendar.LocalGregorianCalendar
+sun.util.locale.BaseLocale
+sun.util.locale.BaseLocale$Cache
+sun.util.locale.BaseLocale$Key
+sun.util.locale.Extension
+sun.util.locale.InternalLocaleBuilder
+sun.util.locale.InternalLocaleBuilder$CaseInsensitiveChar
+sun.util.locale.LanguageTag
+sun.util.locale.LocaleExtensions
+sun.util.locale.LocaleObjectCache
+sun.util.locale.LocaleObjectCache$CacheEntry
+sun.util.locale.LocaleSyntaxException
+sun.util.locale.LocaleUtils
+sun.util.locale.ParseStatus
+sun.util.locale.StringTokenIterator
+sun.util.locale.UnicodeLocaleExtension
+sun.util.logging.LoggingProxy
+sun.util.logging.LoggingSupport
+sun.util.logging.LoggingSupport$1
+sun.util.logging.PlatformLogger
+sun.util.logging.PlatformLogger$1
+sun.util.logging.PlatformLogger$Level
diff --git a/proto/jarjar-rules.txt b/proto/jarjar-rules.txt
index 0c77c2a..50220b4 100644
--- a/proto/jarjar-rules.txt
+++ b/proto/jarjar-rules.txt
@@ -1 +1,2 @@
-rule com.google.** com.android.@1
+rule com.google.protobuf.nano.** com.android.framework.protobuf.nano.@1
+
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 3f3f851..f3140d2 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -24,334 +24,1734 @@
// Known visual elements: views or controls.
enum View {
+ // Unknown view
VIEW_UNKNOWN = 0;
+
+ // OBSOLETE
MAIN_SETTINGS = 1;
+
+ // OPEN: Settings > Accessibility
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACCESSIBILITY = 2;
+
+ // OPEN: Settings > Accessibility > Captions
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACCESSIBILITY_CAPTION_PROPERTIES = 3;
+
+ // OPEN: Settings > Accessibility > [Service]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACCESSIBILITY_SERVICE = 4;
+
+ // OPEN: Settings > Accessibility > Color correction
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACCESSIBILITY_TOGGLE_DALTONIZER = 5;
+
+ // OPEN: Settings > Accessibility > Accessibility shortcut
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE = 6;
+
+ // OPEN: Settings > Accessibility > Magnification gestures
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFICATION = 7;
+
+ // OPEN: Settings > Accounts
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACCOUNT = 8;
+
+ // OPEN: Settings > Accounts > [Single Account Sync Settings]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACCOUNTS_ACCOUNT_SYNC = 9;
+
+ // OPEN: Settings > Accounts > Add an account
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACCOUNTS_CHOOSE_ACCOUNT_ACTIVITY = 10;
+
+ // OPEN: Settings > Accounts > [List of accounts when more than one]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACCOUNTS_MANAGE_ACCOUNTS = 11;
+
+ // OPEN: Settings > Cellular network settings > APNs
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APN = 12;
+
+ // OPEN: Settings > More > Cellular network settings > APNs > [Edit APN]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APN_EDITOR = 13;
+
+ // OBSOLETE
APP_OPS_DETAILS = 14;
+
+ // OBSOLETE
APP_OPS_SUMMARY = 15;
+
+ // OBSOLETE
APPLICATION = 16;
+
+ // OPEN: Settings > Apps > Configure apps > App links > [App]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APPLICATIONS_APP_LAUNCH = 17;
+
+ // OBSOLETE
APPLICATIONS_APP_PERMISSION = 18;
+
+ // OPEN: Settings > Internal storage > Apps storage > [App]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APPLICATIONS_APP_STORAGE = 19;
+
+ // OPEN: Settings > Apps > [App info]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APPLICATIONS_INSTALLED_APP_DETAILS = 20;
+
+ // OPEN: Settings > Memory > App usage > [App Memory usage]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APPLICATIONS_PROCESS_STATS_DETAIL = 21;
+
+ // OBSOLETE
APPLICATIONS_PROCESS_STATS_MEM_DETAIL = 22;
+
+ // OPEN: Settings > Memory > App usage
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APPLICATIONS_PROCESS_STATS_UI = 23;
+
+ // OPEN: Settings > Bluetooth
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
BLUETOOTH = 24;
+
+ // OPEN: Choose Bluetooth device (ex: when sharing)
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
BLUETOOTH_DEVICE_PICKER = 25;
+
+ // OBSOLETE
BLUETOOTH_DEVICE_PROFILES = 26;
+
+ // OPEN: Settings > Security > Choose screen lock
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
CHOOSE_LOCK_GENERIC = 27;
+
+ // OPEN: Settings > Security > Choose screen lock > Choose your password
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
CHOOSE_LOCK_PASSWORD = 28;
+
+ // OPEN: Settings > Security > Choose screen lock > Choose your pattern
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
CHOOSE_LOCK_PATTERN = 29;
+
+ // OPEN: Settings > Security > Choose screen lock > Confirm your password
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
CONFIRM_LOCK_PASSWORD = 30;
+
+ // OPEN: Settings > Security > Choose screen lock > Confirm your pattern
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
CONFIRM_LOCK_PATTERN = 31;
+
+ // OPEN: Settings > Security > Encrypt phone
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
CRYPT_KEEPER = 32;
+
+ // OPEN: Settings > Security > Encrypt phone > Confirm
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
CRYPT_KEEPER_CONFIRM = 33;
+
+ // OPEN: Settings > Search results
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
DASHBOARD_SEARCH_RESULTS = 34;
+
+ // OPEN: Settings (Root page)
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
DASHBOARD_SUMMARY = 35;
+
+ // OBSOLETE
DATA_USAGE = 36;
+
+ // OPEN: Settings > Data usage
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
DATA_USAGE_SUMMARY = 37;
+
+ // OPEN: Settings > Date & time
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
DATE_TIME = 38;
+
+ // OPEN: Settings > Developer options
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
DEVELOPMENT = 39;
+
+ // OPEN: Settings > About phone
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
DEVICEINFO = 40;
+
+ // OPEN: Settings > About phone > Status > IMEI information
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
DEVICEINFO_IMEI_INFORMATION = 41;
+
+ // OPEN: Settings > Internal storage
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
DEVICEINFO_STORAGE = 42;
+
+ // OPEN: Settings > About phone > Status > SIM status
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
DEVICEINFO_SIM_STATUS = 43;
+
+ // OPEN: Settings > About phone > Status
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
DEVICEINFO_STATUS = 44;
+
+ // OBSOLETE
DEVICEINFO_USB = 45;
+
+ // OPEN: Settings > Display
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
DISPLAY = 46;
+
+ // OPEN: Settings > Display > Daydream
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
DREAM = 47;
+
+ // OPEN: Settings > Security > Screen lock > Secure start-up
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ENCRYPTION = 48;
+
+ // OPEN: Settings > Security > Nexus Imprint
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
FINGERPRINT = 49;
+
+ // OBSOLETE
FINGERPRINT_ENROLL = 50;
+
+ // OPEN: Settings > Battery > History details
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
FUELGAUGE_BATTERY_HISTORY_DETAIL = 51;
+
+ // OPEN: Settings > Battery > Battery saver
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
FUELGAUGE_BATTERY_SAVER = 52;
+
+ // OPEN: Settings > Battery > [App Use details]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
FUELGAUGE_POWER_USAGE_DETAIL = 53;
+
+ // OPEN: Settings > Battery
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
FUELGAUGE_POWER_USAGE_SUMMARY = 54;
+
+ // OPEN: Settings > Home
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
HOME = 55;
+
+ // OPEN: Settings > Security > SIM card lock settings
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ICC_LOCK = 56;
+
+ // OPEN: Settings > Language & input
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
INPUTMETHOD_LANGUAGE = 57;
+
+ // OPEN: Settings > Language & input > Physical keyboard
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
INPUTMETHOD_KEYBOARD = 58;
+
+ // OPEN: Settings > Language & input > Spell checker
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
INPUTMETHOD_SPELL_CHECKERS = 59;
+
+ // OBSOLETE
INPUTMETHOD_SUBTYPE_ENABLER = 60;
+
+ // OPEN: Settings > Language & input > Personal dictionary
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
INPUTMETHOD_USER_DICTIONARY = 61;
+
+ // OPEN: Settings > Language & input > Add word
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
INPUTMETHOD_USER_DICTIONARY_ADD_WORD = 62;
+
+ // OPEN: Settings > Location
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
LOCATION = 63;
+
+ // OPEN: Settings > Location > Location mode
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
LOCATION_MODE = 64;
+
+ // OPEN: Settings > Apps
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
MANAGE_APPLICATIONS = 65;
+
+ // OPEN: Settings > Backup & reset > Factory data reset
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
MASTER_CLEAR = 66;
+
+ // OPEN: Settings > Backup & reset > Factory data reset > Confirm
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
MASTER_CLEAR_CONFIRM = 67;
+
+ // OPEN: Settings > Data usage > Network restrictions
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NET_DATA_USAGE_METERED = 68;
+
+ // OPEN: Settings > More > Android Beam
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NFC_BEAM = 69;
+
+ // OPEN: Settings > Tap & pay
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NFC_PAYMENT = 70;
+
+ // OPEN: Settings > Sound & notification
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NOTIFICATION = 71;
+
+ // OPEN: Settings > Sound & notification > App notifications > [App]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NOTIFICATION_APP_NOTIFICATION = 72;
+
+ // OPEN: Settings > Sound & notification > Other sounds
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NOTIFICATION_OTHER_SOUND = 73;
+
+ // OBSOLETE
NOTIFICATION_REDACTION = 74;
+
+ // OPEN: Settings Widget > Notification log
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NOTIFICATION_STATION = 75;
+
+ // OPEN: Settings > Sound & notification > Do not disturb
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NOTIFICATION_ZEN_MODE = 76;
+
+ // OPEN: OBSOLETE
OWNER_INFO = 77;
+
+ // OPEN: Print job notification > Print job settings
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
PRINT_JOB_SETTINGS = 78;
+
+ // OPEN: Settings > Printing > [Print Service]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
PRINT_SERVICE_SETTINGS = 79;
+
+ // OPEN: Settings > Printing
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
PRINT_SETTINGS = 80;
+
+ // OPEN: Settings > Backup & reset
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
PRIVACY = 81;
+
+ //OBSOLETE
PROXY_SELECTOR = 82;
+
+ // OPEN: Settings > Backup & reset > Network settings reset
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
RESET_NETWORK = 83;
+
+ // OPEN: Settings > Backup & reset > Network settings reset > Confirm
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
RESET_NETWORK_CONFIRM = 84;
+
+ // OPEN: Settings > Developer Options > Running Services
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
RUNNING_SERVICE_DETAILS = 85;
+
+ // OPEN: Settings > Security > Screen pinning
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
SCREEN_PINNING = 86;
+
+ // OPEN: Settings > Security
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
SECURITY = 87;
+
+ // OPEN: Settings > SIM cards
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
SIM = 88;
+
+ // OBSOLETE
TESTING = 89;
+
+ // OPEN: Settings > More > Tethering & portable hotspot
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TETHER = 90;
+
+ // OPEN: Settings > Security > Trust agents
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TRUST_AGENT = 91;
+
+ // OPEN: Settings > Security > Trusted credentials
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TRUSTED_CREDENTIALS = 92;
+
+ // OPEN: Settings > Language & input > TTS output > [Engine] > Settings
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TTS_ENGINE_SETTINGS = 93;
+
+ // OPEN: Settings > Language & input > Text-to-speech output
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TTS_TEXT_TO_SPEECH = 94;
+
+ // OPEN: Settings > Security > Apps with usage access
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
USAGE_ACCESS = 95;
+
+ // OPEN: Settings > Users
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
USER = 96;
+
+ // OPEN: Settings > Users > [Restricted profile app & content access]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
USERS_APP_RESTRICTIONS = 97;
+
+ // OPEN: Settings > Users > [User settings]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
USER_DETAILS = 98;
+
+ // OBSOLETE
VOICE_INPUT = 99;
+
+ // OPEN: Settings > More > VPN
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
VPN = 100;
+
+ // OPEN: Settings > Display > Choose wallpaper from
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
WALLPAPER_TYPE = 101;
+
+ // OPEN: Settings > Display > Cast
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
WFD_WIFI_DISPLAY = 102;
+
+ // OPEN: Settings > Wi-Fi
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
WIFI = 103;
+
+ // OPEN: Settings > Wi-Fi > Advanced Wi-Fi
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
WIFI_ADVANCED = 104;
+
+ // OPEN: Settings > More > Wi-Fi Calling
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
WIFI_CALLING = 105;
+
+ // OPEN: Settings > Wi-Fi > Saved networks
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
WIFI_SAVED_ACCESS_POINTS = 106;
+
+ // OBSOLETE
WIFI_APITEST = 107;
+
+ // OBSOLETE
WIFI_INFO = 108;
+
+ // OPEN: Settings > Wi-Fi > Advanced Wi-Fi > Wi-Fi Direct
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
WIFI_P2P = 109;
+
+ // OPEN: Settings > More
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
WIRELESS = 110;
+
+ // OPEN: Quick Settings Panel
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_PANEL = 111;
+
+ // OPEN: QS Airplane mode tile shown
+ // ACTION: QS Airplane mode tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_AIRPLANEMODE = 112;
+
+ // OPEN: QS Bluetooth tile shown
+ // ACTION: QS Bluetooth tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_BLUETOOTH = 113;
+
+ // OPEN: QS Cast tile shown
+ // ACTION: QS Cast tile tapped
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_CAST = 114;
+
+ // OPEN: QS Cellular tile shown
+ // ACTION: QS Cellular tile tapped
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_CELLULAR = 115;
+
+ // OPEN: QS Color inversion tile shown
+ // ACTION: QS Color inversion tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_COLORINVERSION = 116;
+
+ // OPEN: QS Cellular tile > Cellular detail panel
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_DATAUSAGEDETAIL = 117;
+
+ // OPEN: QS Do not disturb tile shown
+ // ACTION: QS Do not disturb tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_DND = 118;
+
+ // OPEN: QS Flashlight tile shown
+ // ACTION: QS Flashlight tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_FLASHLIGHT = 119;
+
+ // OPEN: QS Hotspot tile shown
+ // ACTION: QS Hotspot tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_HOTSPOT = 120;
+
+ // OPEN: QS 3P tile shown
+ // ACTION: QS 3P tile tapped
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_INTENT = 121;
+
+ // OPEN: QS Location tile shown
+ // ACTION: QS Location tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_LOCATION = 122;
+
+ // OPEN: QS Rotation tile shown
+ // ACTION: QS Rotation tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_ROTATIONLOCK = 123;
+
+ // OBSOLETE
QS_USERDETAILITE = 124;
+
+ // OPEN: QS User list panel
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_USERDETAIL = 125;
+
+ // OPEN: QS WiFi tile shown
+ // ACTION: QS WiFi tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_WIFI = 126;
+
+ // OPEN: Notification Panel (including lockscreen)
+ // CATEGORY: NOTIFICATION
+ // OS: 5.1.1
+ // GMS: 7.5.26
NOTIFICATION_PANEL = 127;
+
+ // OPEN: Notification in panel became visible.
+ // PACKAGE: App that posted the notification.
+ // ACTION: Notification is tapped.
+ // PACKAGE: App that posted the notification
+ // DETAIL: Notification is expanded by user.
+ // PACKAGE: App that posted the notification
+ // DISMISS: Notification is dismissed.
+ // PACKAGE: App that posted the notification
+ // SUBTYPE: Dismiss reason from NotificationManagerService.java
+ // CATEGORY: NOTIFICATION
+ // OS: 5.1.1
+ // GMS: 7.5.26
NOTIFICATION_ITEM = 128;
+
+ // ACTION: User tapped notification action
+ // PACKAGE: App that posted the notification
+ // SUBTYPE: Index of action on notification
+ // CATEGORY: NOTIFICATION
+ // OS: 5.0
+ // GMS: 7.5.26
NOTIFICATION_ITEM_ACTION = 129;
+
+ // OPEN: Settings > Apps > Configure apps > App permissions
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APPLICATIONS_ADVANCED = 130;
+
+ // OPEN: Settings > Location > Scanning
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
LOCATION_SCANNING = 131;
+
+ // OBSOLETE
MANAGE_APPLICATIONS_ALL = 132;
+
+ // OPEN: Settings > Sound & notification > App notifications
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
MANAGE_APPLICATIONS_NOTIFICATIONS = 133;
+
+ // ACTION: Settings > Wi-Fi > Overflow > Add Network
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_WIFI_ADD_NETWORK = 134;
+
+ // ACTION: Settings > Wi-Fi > [Long press network] > Connect to network
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_WIFI_CONNECT = 135;
+
+ // ACTION: Settings > Wi-Fi > Overflow > Refresh
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_WIFI_FORCE_SCAN = 136;
+
+ // ACTION: Settings > Wi-Fi > [Long press network] > Forget network
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_WIFI_FORGET = 137;
+
+ // ACTION: Settings > Wi-Fi > Toggle off
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_WIFI_OFF = 138;
+
+ // ACTION: Settings > Wi-Fi > Toggle on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_WIFI_ON = 139;
+
+ // OBSOLETE
MANAGE_PERMISSIONS = 140;
+
+ // OPEN: Settings > Sound & notification > DND > Priority only allows
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NOTIFICATION_ZEN_MODE_PRIORITY = 141;
+
+ // OPEN: Settings > Sound & notification > DND > Automatic rules
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NOTIFICATION_ZEN_MODE_AUTOMATION = 142;
+
+ // OPEN: Settings > Apps > Configure apps > App links
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
MANAGE_DOMAIN_URLS = 143;
+
+ // OPEN: Settings > Sound & notification > DND > [Time based rule]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NOTIFICATION_ZEN_MODE_SCHEDULE_RULE = 144;
+
+ // OPEN: Settings > Sound & notification > DND > [External rule]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NOTIFICATION_ZEN_MODE_EXTERNAL_RULE = 145;
+
+ // OPEN: Settings > Sound & notification > DND > [Event rule]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NOTIFICATION_ZEN_MODE_EVENT_RULE = 146;
+
+ // ACTION: App notification settings > Block Notifications
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_BAN_APP_NOTES = 147;
+
+ // ACTION: Notification shade > Dismiss all button
+ // CATEGORY: NOTIFICATION
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_DISMISS_ALL_NOTES = 148;
+
+ // OPEN: QS Do Not Disturb detail panel
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_DND_DETAILS = 149;
+
+ // OPEN: QS Bluetooth detail panel
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_BLUETOOTH_DETAILS = 150;
+
+ // OPEN: QS Cast detail panel
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_CAST_DETAILS = 151;
+
+ // OPEN: QS Wi-Fi detail panel
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_WIFI_DETAILS = 152;
+
+ // ACTION: QS Wi-Fi detail panel > Wi-Fi toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_WIFI_TOGGLE = 153;
+
+ // ACTION: QS Bluetooth detail panel > Bluetooth toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_BLUETOOTH_TOGGLE = 154;
+
+ // ACTION: QS Cellular detail panel > Cellular toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_CELLULAR_TOGGLE = 155;
+
+ // ACTION: QS User list panel > Select different user
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_SWITCH_USER = 156;
+
+ // ACTION: QS Cast detail panel > Select cast device
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_CAST_SELECT = 157;
+
+ // ACTION: QS Cast detail panel > Disconnect cast device
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_CAST_DISCONNECT = 158;
+
+ // ACTION: Settings > Bluetooth > Toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_BLUETOOTH_TOGGLE = 159;
+
+ // ACTION: Settings > Bluetooth > Overflow > Refresh
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_BLUETOOTH_SCAN = 160;
+
+ // ACTION: Settings > Bluetooth > Overflow > Rename this device
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_BLUETOOTH_RENAME = 161;
+
+ // ACTION: Settings > Bluetooth > Overflow > Show received files
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_BLUETOOTH_FILES = 162;
+
+ // ACTION: QS DND details panel > Increase / Decrease exit time
+ // SUBTYPE: true is increase, false is decrease
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_DND_TIME = 163;
+
+ // ACTION: QS DND details panel > [Exit condition]
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_DND_CONDITION_SELECT = 164;
+
+ // ACTION: QS DND details panel > [DND mode]
+ // SUBTYPE: 1 is priority, 2 is silence, 3 is alarms only
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_DND_ZEN_SELECT = 165;
+
+ // ACTION: QS DND detail panel > DND toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_DND_TOGGLE = 166;
+
+ // ACTION: DND Settings > Priority only allows > Reminder toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ZEN_ALLOW_REMINDERS = 167;
+
+ // ACTION: DND Settings > Priority only allows > Event toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ZEN_ALLOW_EVENTS = 168;
+
+ // ACTION: DND Settings > Priority only allows > Messages
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ZEN_ALLOW_MESSAGES = 169;
+
+ // ACTION: DND Settings > Priority only allows > Calls
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ZEN_ALLOW_CALLS = 170;
+
+ // ACTION: DND Settings > Priority only allows > Repeat callers toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ZEN_ALLOW_REPEAT_CALLS = 171;
+
+ // ACTION: DND Settings > Automatic rules > Add rule
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ZEN_ADD_RULE = 172;
+
+ // ACTION: DND Settings > Automatic rules > Add rule > OK
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ZEN_ADD_RULE_OK = 173;
+
+ // ACTION: DND Settings > Automatic rules > [Rule] > Delete rule
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ZEN_DELETE_RULE = 174;
+
+ // ACTION: DND Settings > Automatic rules > [Rule] > Delete rule > Delete
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ZEN_DELETE_RULE_OK = 175;
+
+ // ACTION: DND Settings > Automatic rules > [Rule] > Toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ZEN_ENABLE_RULE = 176;
+
+ // ACTION: Settings > More > Airplane mode toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_AIRPLANE_TOGGLE = 177;
+
+ // ACTION: Settings > Data usage > Cellular data toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_CELL_DATA_TOGGLE = 178;
+
+ // OPEN: Settings > Sound & notification > Notification access
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NOTIFICATION_ACCESS = 179;
+
+ // OPEN: Settings > Sound & notification > Do Not Disturb access
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NOTIFICATION_ZEN_MODE_ACCESS = 180;
+
+ // OPEN: Settings > Apps > Configure apps > Default Apps
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APPLICATIONS_DEFAULT_APPS = 181;
+
+ // OPEN: Settings > Internal storage > Apps storage
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APPLICATIONS_STORAGE_APPS = 182;
+
+ // OPEN: Settings > Security > Usage access
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APPLICATIONS_USAGE_ACCESS_DETAIL = 183;
+
+ // OPEN: Settings > Battery > Battery optimization
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APPLICATIONS_HIGH_POWER_APPS = 184;
+
+ // OBSOLETE
FUELGAUGE_HIGH_POWER_DETAILS = 185;
+
+ // ACTION: Lockscreen > Unlock gesture
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 5.1.1
+ // GMS: 7.8.22
ACTION_LS_UNLOCK = 186;
+
+ // ACTION: Lockscreen > Pull shade open
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 5.1.1
+ // GMS: 7.8.22
ACTION_LS_SHADE = 187;
+
+ // ACTION: Lockscreen > Tap on lock, shows hint
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 5.1.1
+ // GMS: 7.8.22
ACTION_LS_HINT = 188;
+
+ // ACTION: Lockscreen > Camera
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 5.1.1
+ // GMS: 7.8.22
ACTION_LS_CAMERA = 189;
+
+ // ACTION: Lockscreen > Dialer
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 5.1.1
+ // GMS: 7.8.22
ACTION_LS_DIALER = 190;
+
+ // ACTION: Lockscreen > Tap on lock, locks phone
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 5.1.1
+ // GMS: 7.8.22
ACTION_LS_LOCK = 191;
+
+ // ACTION: Lockscreen > Tap on notification, false touch rejection
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 5.1.1
+ // GMS: 7.8.22
ACTION_LS_NOTE = 192;
+
+ // ACTION: Lockscreen > Swipe down to open quick settings
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.8.22
ACTION_LS_QS = 193;
+
+ // ACTION: Swipe down to open quick settings when unlocked
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.8.22
ACTION_SHADE_QS_PULL = 194;
+
+ // ACTION: Notification shade > Tap to open quick settings
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.8.22
ACTION_SHADE_QS_TAP = 195;
+
+ // OPEN: Lockscreen
+ // SUBTYPE: 0 is unsecure, 1 is secured by password / pattern / PIN
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 5.1.1
+ // GMS: 7.8.22
LOCKSCREEN = 196;
+
+ // OPEN: Lockscreen > Screen to enter password / pattern / PIN
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 5.1.1
+ // GMS: 7.8.22
BOUNCER = 197;
+
+ // OPEN: Screen turned on
+ // SUBTYPE: 2 is user action
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 5.1.1
+ // GMS: 7.8.22
SCREEN = 198;
+
+ // OPEN: Notification caused sound, vibration, and/or LED blink
+ // SUBTYPE: 1 is buzz, 2 is beep, blink is 4, or'd together
+ // CATEGORY: NOTIFICATION
+ // OS: 5.1.1
+ // GMS: 7.8.53
NOTIFICATION_ALERT = 199;
+
+ // ACTION: Lockscreen > Emergency Call button
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 5.1.1
+ // GMS: 7.5.26
ACTION_EMERGENCY_CALL = 200;
+
+ // OPEN: Settings > Apps > Configure > Default apps > Assist & voice input
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APPLICATIONS_MANAGE_ASSIST = 201;
+
+ // OPEN: Settings > Memory
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
PROCESS_STATS_SUMMARY = 202;
+
+ // ACTION: Settings > Display > When device is rotated
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ROTATION_LOCK = 203;
+
+ // ACTION: Long press on notification to view controls
+ // CATEGORY: NOTIFICATION
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_NOTE_CONTROLS = 204;
+
+ // ACTION: Notificatoin controls > Info button
+ // CATEGORY: NOTIFICATION
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_NOTE_INFO = 205;
+
+ // ACTION: Notification controls > Settings button
+ // CATEGORY: NOTIFICATION
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_APP_NOTE_SETTINGS = 206;
+
+ // OPEN: Volume Dialog (with hardware buttons)
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
VOLUME_DIALOG = 207;
+
+ // OPEN: Volume dialog > Expanded volume dialog (multiple sliders)
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
VOLUME_DIALOG_DETAILS = 208;
+
+ // ACTION: Volume dialog > Adjust volume slider
+ // SUBTYPE: volume level (0-7)
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_VOLUME_SLIDER = 209;
+
+ // ACTION: Volume dialog > Select non-active stream
+ // SUBTYPE: stream (defined in AudioSystem.java)
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_VOLUME_STREAM = 210;
+
+ // ACTION: Adjust volume with hardware key
+ // SUBTYPE: volume level (0-7)
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_VOLUME_KEY = 211;
+
+ // ACTION: Volume dialog > Mute a stream by tapping icon
+ // SUBTYPE: mute is 1, audible is 2
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_VOLUME_ICON = 212;
+
+ // ACTION: Volume dialog > Change ringer mode by tapping icon
+ // SUBTYPE: 2 is audible, 3 is vibrate
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_RINGER_MODE = 213;
+
+ // ACTION: Chooser shown (share target, file open, etc.)
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ACTIVITY_CHOOSER_SHOWN = 214;
+
+ // ACTION: Chooser > User taps an app target
+ // SUBTYPE: Index of target
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ACTIVITY_CHOOSER_PICKED_APP_TARGET = 215;
+
+ // ACTION: Chooser > User taps a service target
+ // SUBTYPE: Index of target
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET = 216;
+
+ // ACTION: Chooser > User taps a standard target
+ // SUBTYPE: Index of target
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ACTIVITY_CHOOSER_PICKED_STANDARD_TARGET = 217;
+
+ // ACTION: QS Brightness Slider (with auto brightness disabled)
+ // SUBTYPE: slider value
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_BRIGHTNESS = 218;
+
+ // ACTION: QS Brightness Slider (with auto brightness enabled)
+ // SUBTYPE: slider value
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_BRIGHTNESS_AUTO = 219;
+
+ // OPEN: Settings > Display > Brightness Slider
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
BRIGHTNESS_DIALOG = 220;
+
+ // OPEN: Settings > Apps > Configure Apps > Draw over other apps
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
SYSTEM_ALERT_WINDOW_APPS = 221;
+
+ // OPEN: Display has entered dream mode
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
DREAMING = 222;
+
+ // OPEN: Display has entered ambient notification mode
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
DOZING = 223;
+
+ // OPEN: Overview
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
OVERVIEW_ACTIVITY = 224;
+
+ // OPEN: Settings > About phone > Legal information
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ABOUT_LEGAL_SETTINGS = 225;
+
+ // OPEN: Settings > Search > Perform search
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_SEARCH_RESULTS = 226;
+
+ // OPEN: Settings > System UI Tuner
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TUNER = 227;
+
+ // OPEN: Settings > System UI Tuner > Quick Settings
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TUNER_QS = 228;
+
+ // OPEN: Settings > System UI Tuner > Demo mode
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TUNER_DEMO_MODE = 229;
+
+ // ACTION: Settings > System UI Tuner > Quick Settings > Move tile
+ // PACKAGE: Tile
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TUNER_QS_REORDER = 230;
+
+ // ACTION: Settings > System UI Tuner > Quick Settings > Add tile
+ // PACKAGE: Tile
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TUNER_QS_ADD = 231;
+
+ // ACTION: Settings > System UI Tuner > Quick Settings > Remove tile
+ // PACKAGE: Tile
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TUNER_QS_REMOVE = 232;
+
+ // ACTION: Settings > System UI Tuner > Status bar > Enable icon
+ // PACKAGE: Icon
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TUNER_STATUS_BAR_ENABLE = 233;
+
+ // ACTION: Settings > System UI Tuner > Status bar > Disable icon
+ // PACKAGE: Icon
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TUNER_STATUS_BAR_DISABLE = 234;
+
+ // ACTION: Settings > System UI Tuner > Demo mode > Enable demo mode
+ // SUBTYPE: false is disabled, true is enabled
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TUNER_DEMO_MODE_ENABLED = 235;
+
+ // ACTION: Settings > System UI Tuner > Demo mode > Show demo mode
+ // SUBTYPE: false is disabled, true is enabled
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TUNER_DEMO_MODE_ON = 236;
+
+ // ACTION: Settings > System UI Tuner > Show embedded battery percentage
+ // SUBTYPE: 0 is disabled, 1 is enabled
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TUNER_BATTERY_PERCENTAGE = 237;
+
+ // OPEN: Settings > Developer options > Inactive apps
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
FUELGAUGE_INACTIVE_APPS = 238;
+
+ // ACTION: Long press home to bring up assistant
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ASSIST_LONG_PRESS = 239;
+
+ // OPEN: Settings > Security > Nexus Imprint > Add Fingerprint
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
FINGERPRINT_ENROLLING = 240;
+
+ // OPEN: Fingerprint Enroll > Find Sensor
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
FINGERPRINT_FIND_SENSOR = 241;
+
+ // OPEN: Fingerprint Enroll > Fingerprint Enrolled!
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
FINGERPRINT_ENROLL_FINISH = 242;
+
+ // OPEN: Fingerprint Enroll introduction
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
FINGERPRINT_ENROLL_INTRO = 243;
+
+ // OPEN: Fingerprint Enroll onboarding
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
FINGERPRINT_ENROLL_ONBOARD = 244;
+
+ // OPEN: Fingerprint Enroll > Let's Start!
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
FINGERPRINT_ENROLL_SIDECAR = 245;
+
+ // OPEN: Fingerprint Enroll SUW > Let's Start!
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
FINGERPRINT_ENROLLING_SETUP = 246;
+
+ // OPEN: Fingerprint Enroll SUW > Find Sensor
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
FINGERPRINT_FIND_SENSOR_SETUP = 247;
+
+ // OPEN: Fingerprint Enroll SUW > Fingerprint Enrolled!
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
FINGERPRINT_ENROLL_FINISH_SETUP = 248;
+
+ // OPEN: Fingerprint Enroll SUW introduction
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
FINGERPRINT_ENROLL_INTRO_SETUP = 249;
+
+ // OPEN: Fingerprint Enroll SUW onboarding
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
FINGERPRINT_ENROLL_ONBOARD_SETUP = 250;
+
+ // ACTION: Add fingerprint > Enroll fingerprint
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
ACTION_FINGERPRINT_ENROLL = 251;
+
+ // ACTION: Authenticate using fingerprint
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
ACTION_FINGERPRINT_AUTH = 252;
+
+ // ACTION: Settings > Security > Nexus Imprint > [Fingerprint] > Delete
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
ACTION_FINGERPRINT_DELETE = 253;
+
+ // ACTION: Settings > Security > Nexus Imprint > [Fingerprint] > Rename
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
ACTION_FINGERPRINT_RENAME = 254;
+
+ // ACTION: Double tap camera shortcut
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.8.99
ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE = 255;
+
+ // ACTION: Double twist camera shortcut
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.8.99
ACTION_WIGGLE_CAMERA_GESTURE = 256;
+
+ // OPEN: QS Work Mode tile shown
+ // ACTION: QS Work Mode tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: N
+ // GMS: 7.8.99
QS_WORKMODE = 257;
+
+ // OPEN: Settings > Developer Options > Background Check
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
BACKGROUND_CHECK_SUMMARY = 258;
+
+ // OPEN: QS Lock tile shown
+ // ACTION: QS Lock tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: N
+ // GMS: 7.8.99
QS_LOCK_TILE = 259;
+
+ // OPEN: QS User Tile shown
+ // CATEGORY: QUICK_SETTINGS
+ // OS: N
+ // GMS: 7.8.99
QS_USER_TILE = 260;
+
+ // OPEN: QS Battery tile shown
+ // CATEGORY: QUICK_SETTINGS
+ // OS: N
+ // GMS: 7.8.99
QS_BATTERY_TILE = 261;
+
+ // OPEN: Settings > Sound > Do not disturb > Visual interruptions
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
NOTIFICATION_ZEN_MODE_VISUAL_INTERRUPTIONS = 262;
+
+ // ACTION: Visual interruptions > No screen interuptions toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
ACTION_ZEN_ALLOW_WHEN_SCREEN_OFF = 263;
- // Dead
+
+ // ACTION: Visual interruptions > No notification light toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
ACTION_ZEN_ALLOW_LIGHTS = 264;
+
+ // OPEN: Settings > Notifications > [App] > Topic Notifications
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
NOTIFICATION_TOPIC_NOTIFICATION = 265;
+
+ // ACTION: Settings > Apps > Default Apps > Select different SMS app
+ // PACKAGE: Selected SMS app
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
ACTION_DEFAULT_SMS_APP_CHANGED = 266;
+
+ // OPEN: QS Color modification tile shown
+ // ACTION: QS Color modification tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: N
+ // GMS: 7.8.99
QS_COLOR_MATRIX = 267;
+
+ // OPEN: QS Custom tile shown
+ // ACTION: QS Work Mode tile tapped
+ // CATEGORY: QUICK_SETTINGS
+ // OS: N
+ // GMS: 7.8.99
QS_CUSTOM = 268;
+
+ // ACTION: Visual interruptions > Never turn off the screen toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
ACTION_ZEN_ALLOW_WHEN_SCREEN_ON = 269;
- // Logged when the user docks a window from recents by
- // longpressing a task and dragging it to the dock area.
+ // ACTION: Overview > Long-press task, drag to enter split-screen
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
ACTION_WINDOW_DOCK_DRAG_DROP = 270;
- // Logged when the user docks a fullscreen window by long pressing
- // recents which also opens recents on the lower/right side.
+ // ACTION: In App > Long-press Overview button to enter split-screen
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
ACTION_WINDOW_DOCK_LONGPRESS = 271;
- // Logged when the user docks a window by dragging from the navbar
- // which also opens recents on the lower/right side.
+ // ACTION: In App > Swipe Overview button to enter split-screen
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
ACTION_WINDOW_DOCK_SWIPE = 272;
- // Logged when the user launches a profile-specific app and we
- // intercept it with the confirm credentials UI.
+ // ACTION: Launch profile-specific app > Confirm credentials
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
PROFILE_CHALLENGE = 273;
+ // OPEN: QS Battery detail panel
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
QS_BATTERY_DETAIL = 274;
- // Logged when the user goes into the overview history.
+ // OPEN: Overview > History
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
OVERVIEW_HISTORY = 275;
- // Logged when the user pages through overview.
- OVERVIEW_PAGE = 276;
+ // ACTION: Overview > Page by tapping Overview button
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
+ ACTION_OVERVIEW_PAGE = 276;
- // Logged when the user launches a task from overview.
- OVERVIEW_SELECT = 277;
+ // ACTION: Overview > Select app
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
+ ACTION_OVERVIEW_SELECT = 277;
- // Logged when the user views the emergency info.
+ // ACTION: View emergency info
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
ACTION_VIEW_EMERGENCY_INFO = 278;
- // Logged when the user views the edit emergency info activity.
+ // ACTION: Edit emergency info activity
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
ACTION_EDIT_EMERGENCY_INFO = 279;
- // Logged when the user edits an emergency info field.
+ // ACTION: Edit emergency info field
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
ACTION_EDIT_EMERGENCY_INFO_FIELD = 280;
- // Logged when the user adds a new emergency contact.
+ // ACTION: Add emergency contact
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
ACTION_ADD_EMERGENCY_CONTACT = 281;
- // Logged when the user deletes an emergency contact.
+ // ACTION: Delete emergency contact
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
ACTION_DELETE_EMERGENCY_CONTACT = 282;
- // Logged when the user calls an emergency contact.
+ // ACTION: Call emergency contact
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
ACTION_CALL_EMERGENCY_CONTACT = 283;
- // QS Tile for Data Saver.
+ // OPEN: QS Data Saver tile shown
+ // ACTION: QS Data Saver tile tapped
+ // CATEGORY: QUICK_SETTINGS
QS_DATA_SAVER = 284;
// OPEN: Settings > Security > User credentials
// CATEGORY: Settings
- // OS: 6.1
+ // OS: N
// GMS: 7.8.99
USER_CREDENTIALS = 285;
- // Logged when the user undocks a previously docked window by long pressing recents while in
- // docked mode.
+ // ACTION: In App (splitscreen) > Long-press Overview to exit split-screen
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
ACTION_WINDOW_UNDOCK_LONGPRESS = 286;
// Logged when the user scrolls through overview manually
@@ -369,5 +1769,192 @@
// Logged when the user saves a modification to notification importance. Negative numbers
// indicate the user lowered the importance; positive means they increased it.
ACTION_SAVE_IMPORTANCE = 291;
+
+ // ACTION: Long-press power button, then tap "Take bug report" option.
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
+ ACTION_BUGREPORT_FROM_POWER_MENU_INTERACTIVE = 292;
+
+ // ACTION: Long-press power button, then long-press "Take bug report" option.
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
+ ACTION_BUGREPORT_FROM_POWER_MENU_FULL = 293;
+
+ // ACTION: Settings -> Developer Options -> Take bug report -> Interactive report
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
+ // Interactive bug report initiated from Settings.
+ ACTION_BUGREPORT_FROM_SETTINGS_INTERACTIVE = 294;
+
+ // ACTION: Settings -> Developer Options -> Take bug report -> Full report
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
+ // Interactive bug report initiated from Settings.
+ ACTION_BUGREPORT_FROM_SETTINGS_FULL = 295;
+
+ // ACTION: User tapped notification action to cancel a bug report
+ // CATEGORY: NOTIFICATION
+ // OS: N
+ // GMS: 7.8.99
+ ACTION_BUGREPORT_NOTIFICATION_ACTION_CANCEL = 296;
+
+ // ACTION: User tapped notification action to launch bug report details screen
+ // CATEGORY: NOTIFICATION
+ // OS: N
+ // GMS: 7.8.99
+ ACTION_BUGREPORT_NOTIFICATION_ACTION_DETAILS = 297;
+
+ // ACTION: User tapped notification action to take adition screenshot on bug report
+ // CATEGORY: NOTIFICATION
+ // OS: N
+ // GMS: 7.8.99
+ ACTION_BUGREPORT_NOTIFICATION_ACTION_SCREENSHOT = 298;
+
+ // ACTION: User tapped notification to share bug report
+ // CATEGORY: NOTIFICATION
+ // OS: N
+ // GMS: 7.8.99
+ ACTION_BUGREPORT_NOTIFICATION_ACTION_SHARE = 299;
+
+ // ACTION: User changed bug report name using the details screen
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
+ ACTION_BUGREPORT_DETAILS_NAME_CHANGED = 300;
+
+ // ACTION: User changed bug report title using the details screen
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
+ ACTION_BUGREPORT_DETAILS_TITLE_CHANGED = 301;
+
+ // ACTION: User changed bug report description using the details screen
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
+ ACTION_BUGREPORT_DETAILS_DESCRIPTION_CHANGED = 302;
+
+ // ACTION: User tapped Save in the bug report details screen.
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
+ ACTION_BUGREPORT_DETAILS_SAVED = 303;
+
+ // ACTION: User tapped Cancel in the bug report details screen.
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
+ ACTION_BUGREPORT_DETAILS_CANCELED = 304;
+
+ // Tuner: Open/close calibrate dialog.
+ TUNER_CALIBRATE_DISPLAY = 305;
+
+ // Tuner: Open/close color and appearance.
+ TUNER_COLOR_AND_APPEARANCE = 306;
+
+ // Tuner: Apply calibrate dialog.
+ ACTION_TUNER_CALIBRATE_DISPLAY_CHANGED = 307;
+
+ // Tuner: Open/close night mode.
+ TUNER_NIGHT_MODE = 308;
+
+ // Tuner: Change night mode.
+ ACTION_TUNER_NIGHT_MODE = 309;
+
+ // Tuner: Change night mode auto.
+ ACTION_TUNER_NIGHT_MODE_AUTO = 310;
+
+ // Tuner: Change night mode adjust dark theme.
+ ACTION_TUNER_NIGHT_MODE_ADJUST_DARK_THEME = 311;
+
+ // Tuner: Change night mode adjust tint.
+ ACTION_TUNER_NIGHT_MODE_ADJUST_TINT = 312;
+
+ // Tuner: Change night mode adjust brightness.
+ ACTION_TUNER_NIGHT_MODE_ADJUST_BRIGHTNESS = 313;
+
+ // Tuner: Change do not disturb in volume panel.
+ ACTION_TUNER_DO_NOT_DISTURB_VOLUME_PANEL = 314;
+
+ // Tuner: Change do not disturb volume buttons shortcut.
+ ACTION_TUNER_DO_NOT_DISTURB_VOLUME_SHORTCUT = 315;
+
+ // Logs the action the user takes when an app crashed.
+ ACTION_APP_CRASH = 316;
+
+ // Logs the action the user takes when an app ANR'd.
+ ACTION_APP_ANR = 317;
+
+ // Logged when a user double taps the overview button to launch the previous task
+ OVERVIEW_LAUNCH_PREVIOUS_TASK = 318;
+
+ // Logged when we execute an app transition. This indicates the total delay from startActivity
+ // until the app transition is starting to animate, in milliseconds.
+ APP_TRANSITION_DELAY_MS = 319;
+
+ // Logged when we execute an app transition. This indicates the reason why the transition
+ // started. Must be one of ActivityManagerInternal.APP_TRANSITION_* reasons.
+ APP_TRANSITION_REASON = 320;
+
+ // Logged when we execute an app transition and we drew a starting window. This indicates the
+ // delay from startActivity until the starting window was drawn.
+ APP_TRANSITION_STARTING_WINDOW_DELAY_MS = 321;
+
+ // Logged when we execute an app transition and all windows of the app got drawn. This indicates
+ // the delay from startActivity until all windows have been drawn.
+ APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS = 322;
+
+ // Logged when we execute an app transition. This indicates the component name of the current
+ // transition.
+ APP_TRANSITION_COMPONENT_NAME = 323;
+
+ // Logged when we execute an app transition. This indicates whether the process was already
+ // running.
+ APP_TRANSITION_PROCESS_RUNNING = 324;
+
+ // Logged when we execute an app transition. This indicates the device uptime in seconds when
+ // the transition was executed.
+ APP_TRANSITION_DEVICE_UPTIME_SECONDS = 325;
+
+ // User granted access to the request folder; action takes an integer
+ // representing the folder's index on Environment.STANDARD_DIRECTORIES
+ ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_FOLDER = 326;
+
+ // User denied access to the request folder; action takes an integer
+ // representing the folder's index on Environment.STANDARD_DIRECTORIES
+ ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_FOLDER = 327;
+
+ // User granted access to the request folder; action pass package name
+ // of calling package.
+ ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_PACKAGE = 328;
+
+ // User denied access to the request folder; action pass package name
+ // of calling package.
+ ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_PACKAGE = 329;
+
+ // App requested access to a directory it has already been granted
+ // access before; action takes an integer representing the folder's
+ // index on Environment.STANDARD_DIRECTORIES
+ ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_FOLDER = 330;
+
+ // App requested access to a directory it has already been granted
+ // access before; action pass package name of calling package.
+ ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_PACKAGE = 331;
+
+ // Logged when the user slides a notification and
+ // reveals the gear beneath it.
+ ACTION_REVEAL_GEAR = 332;
+
+ // Logged when the user taps on the gear beneath
+ // a notification.
+ ACTION_TOUCH_GEAR = 333;
+
+ // Add new aosp constants above this line.
+ // END OF AOSP CONSTANTS
+
}
}
diff --git a/rs/java/android/renderscript/Allocation.java b/rs/java/android/renderscript/Allocation.java
index 8c78a3a..fc92966 100644
--- a/rs/java/android/renderscript/Allocation.java
+++ b/rs/java/android/renderscript/Allocation.java
@@ -115,7 +115,7 @@
if (cmp == Short.TYPE) {
if (checkType) {
- validateIsInt16();
+ validateIsInt16OrFloat16();
return mType.mElement.mType;
}
return Element.DataType.SIGNED_16;
@@ -402,9 +402,10 @@
"32 bit integer source does not match allocation type " + mType.mElement.mType);
}
- private void validateIsInt16() {
+ private void validateIsInt16OrFloat16() {
if ((mType.mElement.mType == Element.DataType.SIGNED_16) ||
- (mType.mElement.mType == Element.DataType.UNSIGNED_16)) {
+ (mType.mElement.mType == Element.DataType.UNSIGNED_16) ||
+ (mType.mElement.mType == Element.DataType.FLOAT_16)) {
return;
}
throw new RSIllegalArgumentException(
@@ -751,7 +752,7 @@
* @param d the source data array
*/
public void copyFrom(short[] d) {
- validateIsInt16();
+ validateIsInt16OrFloat16();
copyFromUnchecked(d, Element.DataType.SIGNED_16, d.length);
}
@@ -1060,7 +1061,7 @@
* @param d the source data array
*/
public void copy1DRangeFrom(int off, int count, short[] d) {
- validateIsInt16();
+ validateIsInt16OrFloat16();
copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_16, d.length);
}
@@ -1204,7 +1205,7 @@
* @param data to be placed into the Allocation
*/
public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) {
- validateIsInt16();
+ validateIsInt16OrFloat16();
copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
Element.DataType.SIGNED_16, data.length);
}
@@ -1473,7 +1474,7 @@
* @param d The array to be set from the Allocation.
*/
public void copyTo(short[] d) {
- validateIsInt16();
+ validateIsInt16OrFloat16();
copyTo(d, Element.DataType.SIGNED_16, d.length);
}
@@ -1693,7 +1694,7 @@
* @param d the source data array
*/
public void copy1DRangeTo(int off, int count, short[] d) {
- validateIsInt16();
+ validateIsInt16OrFloat16();
copy1DRangeToUnchecked(off, count, d, Element.DataType.SIGNED_16, d.length);
}
@@ -1794,7 +1795,7 @@
* @param data Dest Array to be copied into
*/
public void copy2DRangeTo(int xoff, int yoff, int w, int h, short[] data) {
- validateIsInt16();
+ validateIsInt16OrFloat16();
copy2DRangeToUnchecked(xoff, yoff, w, h, data,
Element.DataType.SIGNED_16, data.length);
}
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 3bef19e..4877a378 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -151,6 +151,7 @@
return; \
case RS_TYPE_SIGNED_16: \
case RS_TYPE_UNSIGNED_16: \
+ case RS_TYPE_FLOAT_16: \
len = _env->GetArrayLength((jshortArray)data); \
ptr = _env->GetShortArrayElements((jshortArray)data, flag); \
if (ptr == nullptr) { \
@@ -1061,7 +1062,7 @@
type, kind, norm, size);
}
return (jlong)(uintptr_t)rsElementCreate((RsContext)con, (RsDataType)type, (RsDataKind)kind,
- norm, size);
+ norm, size, true);
}
static jlong
@@ -1100,7 +1101,7 @@
jlong id = (jlong)(uintptr_t)rsElementCreate2((RsContext)con,
(const RsElement *)ids, fieldCount,
nameArray, fieldCount * sizeof(size_t), sizeArray,
- (const uint32_t *)arraySizes, fieldCount);
+ (const uint32_t *)arraySizes, fieldCount, true);
free(ids);
free(arraySizes);
@@ -1174,7 +1175,7 @@
}
return (jlong)(uintptr_t)rsTypeCreate((RsContext)con, (RsElement)eid, dimx, dimy, dimz, mips,
- faces, yuv);
+ faces, yuv, true);
}
static void
@@ -1210,7 +1211,7 @@
}
return (jlong)(uintptr_t) rsAllocationCreateTyped((RsContext)con, (RsType)type,
(RsAllocationMipmapControl)mips,
- (uint32_t)usage, (uintptr_t)pointer);
+ (uint32_t)usage, (uintptr_t)pointer, true);
}
static void
@@ -1315,7 +1316,7 @@
const void* ptr = bitmap.getPixels();
jlong id = (jlong)(uintptr_t)rsAllocationCreateFromBitmap((RsContext)con,
(RsType)type, (RsAllocationMipmapControl)mip,
- ptr, bitmap.getSize(), usage);
+ ptr, bitmap.getSize(), usage, true);
bitmap.unlockPixels();
return id;
}
@@ -1331,7 +1332,7 @@
const void* ptr = bitmap.getPixels();
jlong id = (jlong)(uintptr_t)rsAllocationCreateTyped((RsContext)con,
(RsType)type, (RsAllocationMipmapControl)mip,
- (uint32_t)usage, (uintptr_t)ptr);
+ (uint32_t)usage, (uintptr_t)ptr, true);
bitmap.unlockPixels();
return id;
}
@@ -1347,7 +1348,7 @@
const void* ptr = bitmap.getPixels();
jlong id = (jlong)(uintptr_t)rsAllocationCubeCreateFromBitmap((RsContext)con,
(RsType)type, (RsAllocationMipmapControl)mip,
- ptr, bitmap.getSize(), usage);
+ ptr, bitmap.getSize(), usage, true);
bitmap.unlockPixels();
return id;
}
diff --git a/services/accessibility/Android.mk b/services/accessibility/Android.mk
index d98fc28..ce89aa7 100644
--- a/services/accessibility/Android.mk
+++ b/services/accessibility/Android.mk
@@ -7,4 +7,6 @@
LOCAL_SRC_FILES += \
$(call all-java-files-under,java)
+LOCAL_JAVA_LIBRARIES := services.core
+
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 4be6833..9e6c21c 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -94,6 +94,7 @@
import com.android.internal.statusbar.IStatusBarService;
import com.android.server.LocalServices;
+import com.android.server.statusbar.StatusBarManagerInternal;
import org.xmlpull.v1.XmlPullParserException;
import java.io.FileDescriptor;
@@ -351,6 +352,7 @@
// user change and unlock
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
+ intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
intentFilter.addAction(Intent.ACTION_USER_REMOVED);
intentFilter.addAction(Intent.ACTION_USER_PRESENT);
intentFilter.addAction(Intent.ACTION_SETTING_RESTORED);
@@ -361,6 +363,8 @@
String action = intent.getAction();
if (Intent.ACTION_USER_SWITCHED.equals(action)) {
switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
+ } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
+ unlockUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
} else if (Intent.ACTION_USER_REMOVED.equals(action)) {
removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
} else if (Intent.ACTION_USER_PRESENT.equals(action)) {
@@ -651,10 +655,9 @@
userState.mUiAutomationServiceOwner = owner;
userState.mUiAutomationServiceClient = serviceClient;
userState.mUiAutomationFlags = flags;
- userState.mIsAccessibilityEnabled = true;
userState.mInstalledServices.add(accessibilityServiceInfo);
if ((flags & UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES) == 0) {
- // Set the temporary state.
+ // Set the temporary state, and use it instead of settings
userState.mIsTouchExplorationEnabled = false;
userState.mIsEnhancedWebAccessibilityEnabled = false;
userState.mIsDisplayMagnificationEnabled = false;
@@ -705,7 +708,6 @@
return;
}
- userState.mIsAccessibilityEnabled = true;
userState.mIsTouchExplorationEnabled = touchExplorationEnabled;
userState.mIsEnhancedWebAccessibilityEnabled = false;
userState.mIsDisplayMagnificationEnabled = false;
@@ -900,6 +902,13 @@
}
}
+ private void unlockUser(int userId) {
+ synchronized (mLock) {
+ UserState userState = getUserStateLocked(userId);
+ onUserStateChangedLocked(userState);
+ }
+ }
+
private void removeUser(int userId) {
synchronized (mLock) {
mUserStates.remove(userId);
@@ -1002,8 +1011,9 @@
List<ResolveInfo> installedServices = mPackageManager.queryIntentServicesAsUser(
new Intent(AccessibilityService.SERVICE_INTERFACE),
PackageManager.GET_SERVICES
- | PackageManager.GET_META_DATA
- | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
+ | PackageManager.GET_META_DATA
+ | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ | PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE,
mCurrentUserId);
for (int i = 0, count = installedServices.size(); i < count; i++) {
@@ -1233,56 +1243,44 @@
}
}
- private void manageServicesLocked(UserState userState) {
+ private void updateServicesLocked(UserState userState) {
Map<ComponentName, Service> componentNameToServiceMap =
userState.mComponentNameToServiceMap;
- boolean isEnabled = userState.mIsAccessibilityEnabled;
+ boolean isUnlocked = mContext.getSystemService(UserManager.class)
+ .isUserUnlocked(userState.mUserId);
for (int i = 0, count = userState.mInstalledServices.size(); i < count; i++) {
AccessibilityServiceInfo installedService = userState.mInstalledServices.get(i);
ComponentName componentName = ComponentName.unflattenFromString(
installedService.getId());
+
Service service = componentNameToServiceMap.get(componentName);
- if (isEnabled) {
- // Wait for the binding if it is in process.
- if (userState.mBindingServices.contains(componentName)) {
+ // Ignore non-encryption-aware services until user is unlocked
+ if (!isUnlocked && !installedService.isEncryptionAware()) {
+ Slog.d(LOG_TAG, "Ignoring non-encryption-aware service " + componentName);
+ continue;
+ }
+
+ // Wait for the binding if it is in process.
+ if (userState.mBindingServices.contains(componentName)) {
+ continue;
+ }
+ if (userState.mEnabledServices.contains(componentName)) {
+ if (service == null) {
+ service = new Service(userState.mUserId, componentName, installedService);
+ } else if (userState.mBoundServices.contains(service)) {
continue;
}
- if (userState.mEnabledServices.contains(componentName)) {
- if (service == null) {
- service = new Service(userState.mUserId, componentName, installedService);
- } else if (userState.mBoundServices.contains(service)) {
- continue;
- }
- service.bindLocked();
- } else {
- if (service != null) {
- service.unbindLocked();
- }
- }
+ service.bindLocked();
} else {
if (service != null) {
service.unbindLocked();
- } else {
- userState.mBindingServices.remove(componentName);
}
}
}
- // No enabled installed services => disable accessibility to avoid
- // sending accessibility events with no recipient across processes.
- if (isEnabled && userState.mBoundServices.isEmpty()
- && userState.mBindingServices.isEmpty()) {
- userState.mIsAccessibilityEnabled = false;
- final long identity = Binder.clearCallingIdentity();
- try {
- Settings.Secure.putIntForUser(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
+ updateAccessibilityEnabledSetting(userState);
}
private void scheduleUpdateClientsIfNeededLocked(UserState userState) {
@@ -1309,7 +1307,8 @@
flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER;
}
// Touch exploration without accessibility makes no sense.
- if (userState.mIsAccessibilityEnabled && userState.mIsTouchExplorationEnabled) {
+ if (userState.isHandlingAccessibilityEvents()
+ && userState.mIsTouchExplorationEnabled) {
flags |= AccessibilityInputFilter.FLAG_FEATURE_TOUCH_EXPLORATION;
}
if (userState.mIsFilterKeyEventsEnabled) {
@@ -1448,25 +1447,17 @@
}
private void updateWindowsForAccessibilityCallbackLocked(UserState userState) {
- if (userState.mIsAccessibilityEnabled) {
- // We observe windows for accessibility only if there is at least
- // one bound service that can retrieve window content that specified
- // it is interested in accessing such windows. For services that are
- // binding we do an update pass after each bind event, so we run this
- // code and register the callback if needed.
- boolean boundServiceCanRetrieveInteractiveWindows = false;
+ // We observe windows for accessibility only if there is at least
+ // one bound service that can retrieve window content that specified
+ // it is interested in accessing such windows. For services that are
+ // binding we do an update pass after each bind event, so we run this
+ // code and register the callback if needed.
- List<Service> boundServices = userState.mBoundServices;
- final int boundServiceCount = boundServices.size();
- for (int i = 0; i < boundServiceCount; i++) {
- Service boundService = boundServices.get(i);
- if (boundService.canRetrieveInteractiveWindowsLocked()) {
- boundServiceCanRetrieveInteractiveWindows = true;
- break;
- }
- }
-
- if (boundServiceCanRetrieveInteractiveWindows) {
+ List<Service> boundServices = userState.mBoundServices;
+ final int boundServiceCount = boundServices.size();
+ for (int i = 0; i < boundServiceCount; i++) {
+ Service boundService = boundServices.get(i);
+ if (boundService.canRetrieveInteractiveWindowsLocked()) {
if (mWindowsForAccessibilityCallback == null) {
mWindowsForAccessibilityCallback = new WindowsForAccessibilityCallback();
mWindowManagerService.setWindowsForAccessibilityCallback(
@@ -1534,37 +1525,30 @@
userState.mIsFilterKeyEventsEnabled = false;
}
- private void updateServicesLocked(UserState userState) {
- if (userState.mIsAccessibilityEnabled) {
- manageServicesLocked(userState);
- } else {
- unbindAllServicesLocked(userState);
- }
- }
-
private boolean readConfigurationForUserStateLocked(UserState userState) {
- boolean somthingChanged = readAccessibilityEnabledSettingLocked(userState);
- somthingChanged |= readInstalledAccessibilityServiceLocked(userState);
- somthingChanged |= readEnabledAccessibilityServicesLocked(userState);
- somthingChanged |= readTouchExplorationGrantedAccessibilityServicesLocked(userState);
- somthingChanged |= readTouchExplorationEnabledSettingLocked(userState);
- somthingChanged |= readHighTextContrastEnabledSettingLocked(userState);
- somthingChanged |= readEnhancedWebAccessibilityEnabledChangedLocked(userState);
- somthingChanged |= readDisplayMagnificationEnabledSettingLocked(userState);
- somthingChanged |= readAutoclickEnabledSettingLocked(userState);
- somthingChanged |= readDisplayColorAdjustmentSettingsLocked(userState);
- return somthingChanged;
+ boolean somethingChanged = readInstalledAccessibilityServiceLocked(userState);
+ somethingChanged |= readEnabledAccessibilityServicesLocked(userState);
+ somethingChanged |= readTouchExplorationGrantedAccessibilityServicesLocked(userState);
+ somethingChanged |= readTouchExplorationEnabledSettingLocked(userState);
+ somethingChanged |= readHighTextContrastEnabledSettingLocked(userState);
+ somethingChanged |= readEnhancedWebAccessibilityEnabledChangedLocked(userState);
+ somethingChanged |= readDisplayMagnificationEnabledSettingLocked(userState);
+ somethingChanged |= readAutoclickEnabledSettingLocked(userState);
+ somethingChanged |= readDisplayColorAdjustmentSettingsLocked(userState);
+
+ return somethingChanged;
}
- private boolean readAccessibilityEnabledSettingLocked(UserState userState) {
- final boolean accessibilityEnabled = Settings.Secure.getIntForUser(
- mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId) == 1;
- if (accessibilityEnabled != userState.mIsAccessibilityEnabled) {
- userState.mIsAccessibilityEnabled = accessibilityEnabled;
- return true;
+ private void updateAccessibilityEnabledSetting(UserState userState) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_ENABLED,
+ userState.isHandlingAccessibilityEvents() ? 0 : 1,
+ userState.mUserId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
- return false;
}
private boolean readTouchExplorationEnabledSettingLocked(UserState userState) {
@@ -1748,14 +1732,14 @@
private void updateMagnificationLocked(UserState userState) {
final int userId = userState.mUserId;
if (userId == mCurrentUserId && mMagnificationController != null) {
- if (userHasMagnificationServicesLocked(userState)) {
+ if (userState.mIsDisplayMagnificationEnabled ||
+ userHasMagnificationServicesLocked(userState)) {
mMagnificationController.setUserId(userState.mUserId);
} else {
// If the user no longer has any magnification-controlling
// services and is not using magnification gestures, then
// reset the state to normal.
- if (!userState.mIsDisplayMagnificationEnabled
- && mMagnificationController.resetIfNeeded(true)) {
+ if (mMagnificationController.resetIfNeeded(true)) {
// Animations are still running, so wait until we receive a
// callback verifying that we've reset magnification.
mUnregisterMagnificationOnReset = true;
@@ -1789,7 +1773,7 @@
// Check whether any Accessibility Services are still enabled and, if not, remove flag
// requesting no soft keyboard
final boolean accessibilityRequestingNoIme = userState.mSoftKeyboardShowMode == 1;
- if (accessibilityRequestingNoIme && !userState.mIsAccessibilityEnabled) {
+ if (accessibilityRequestingNoIme && !userState.isHandlingAccessibilityEvents()) {
// No active Accessibility Services can be requesting the soft keyboard to be hidden
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
@@ -1833,7 +1817,6 @@
UserState userState = mUserStates.valueAt(i);
pw.append("User state[attributes:{id=" + userState.mUserId);
pw.append(", currentUser=" + (userState.mUserId == mCurrentUserId));
- pw.append(", accessibilityEnabled=" + userState.mIsAccessibilityEnabled);
pw.append(", touchExplorationEnabled=" + userState.mIsTouchExplorationEnabled);
pw.append(", displayMagnificationEnabled="
+ userState.mIsDisplayMagnificationEnabled);
@@ -1983,7 +1966,7 @@
private void announceNewUserIfNeeded() {
synchronized (mLock) {
UserState userState = getCurrentUserStateLocked();
- if (userState.mIsAccessibilityEnabled) {
+ if (userState.isHandlingAccessibilityEvents()) {
UserManager userManager = (UserManager) mContext.getSystemService(
Context.USER_SERVICE);
String message = mContext.getString(R.string.user_switched,
@@ -2162,8 +2145,13 @@
mIntent = new Intent().setComponent(mComponentName);
mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
com.android.internal.R.string.accessibility_binding_label);
- mIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
- mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0));
+ final long idendtity = Binder.clearCallingIdentity();
+ try {
+ mIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
+ mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0));
+ } finally {
+ Binder.restoreCallingIdentity(idendtity);
+ }
}
setDynamicallyConfigurableProperties(accessibilityServiceInfo);
}
@@ -2754,6 +2742,9 @@
case AccessibilityService.GLOBAL_ACTION_POWER_DIALOG: {
showGlobalActions();
} return true;
+ case AccessibilityService.GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN: {
+ toggleSplitScreen();
+ } return true;
}
return false;
} finally {
@@ -3225,6 +3216,10 @@
mWindowManagerService.showGlobalActions();
}
+ private void toggleSplitScreen() {
+ LocalServices.getService(StatusBarManagerInternal.class).toggleSplitScreen();
+ }
+
private IAccessibilityInteractionConnection getConnectionLocked(int windowId) {
if (DEBUG) {
Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId);
@@ -3441,11 +3436,14 @@
case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG:
case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR:
- case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY:
- case WindowManager.LayoutParams.TYPE_DOCK_DIVIDER: {
+ case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY: {
return AccessibilityWindowInfo.TYPE_SYSTEM;
}
+ case WindowManager.LayoutParams.TYPE_DOCK_DIVIDER: {
+ return AccessibilityWindowInfo.TYPE_SPLIT_SCREEN_DIVIDER;
+ }
+
case WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY: {
return AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY;
}
@@ -4026,7 +4024,6 @@
public int mSoftKeyboardShowMode = 0;
- public boolean mIsAccessibilityEnabled;
public boolean mIsTouchExplorationEnabled;
public boolean mIsTextHighContrastEnabled;
public boolean mIsEnhancedWebAccessibilityEnabled;
@@ -4061,11 +4058,11 @@
public int getClientState() {
int clientState = 0;
- if (mIsAccessibilityEnabled) {
+ if (isHandlingAccessibilityEvents()) {
clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
}
// Touch exploration relies on enabled accessibility.
- if (mIsAccessibilityEnabled && mIsTouchExplorationEnabled) {
+ if (isHandlingAccessibilityEvents() && mIsTouchExplorationEnabled) {
clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
}
if (mIsTextHighContrastEnabled) {
@@ -4074,6 +4071,10 @@
return clientState;
}
+ public boolean isHandlingAccessibilityEvents() {
+ return !mBoundServices.isEmpty() || !mBoundServices.isEmpty();
+ }
+
public void onSwitchToAnotherUser() {
// Clear UI test automation state.
if (mUiAutomationService != null) {
@@ -4093,7 +4094,6 @@
// Clear state persisted in settings.
mEnabledServices.clear();
mTouchExplorationGrantedServices.clear();
- mIsAccessibilityEnabled = false;
mIsTouchExplorationEnabled = false;
mIsEnhancedWebAccessibilityEnabled = false;
mIsDisplayMagnificationEnabled = false;
@@ -4120,9 +4120,6 @@
private final class AccessibilityContentObserver extends ContentObserver {
- private final Uri mAccessibilityEnabledUri = Settings.Secure.getUriFor(
- Settings.Secure.ACCESSIBILITY_ENABLED);
-
private final Uri mTouchExplorationEnabledUri = Settings.Secure.getUriFor(
Settings.Secure.TOUCH_EXPLORATION_ENABLED);
@@ -4164,8 +4161,6 @@
}
public void register(ContentResolver contentResolver) {
- contentResolver.registerContentObserver(mAccessibilityEnabledUri,
- false, this, UserHandle.USER_ALL);
contentResolver.registerContentObserver(mTouchExplorationEnabledUri,
false, this, UserHandle.USER_ALL);
contentResolver.registerContentObserver(mDisplayMagnificationEnabledUri,
@@ -4205,11 +4200,7 @@
return;
}
- if (mAccessibilityEnabledUri.equals(uri)) {
- if (readAccessibilityEnabledSettingLocked(userState)) {
- onUserStateChangedLocked(userState);
- }
- } else if (mTouchExplorationEnabledUri.equals(uri)) {
+ if (mTouchExplorationEnabledUri.equals(uri)) {
if (readTouchExplorationEnabledSettingLocked(userState)) {
onUserStateChangedLocked(userState);
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 4646f3c..3659a40 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -16,9 +16,14 @@
package com.android.server.appwidget;
+import static android.content.Context.KEYGUARD_SERVICE;
+import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
import android.app.AlarmManager;
import android.app.AppGlobals;
import android.app.AppOpsManager;
+import android.app.KeyguardManager;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManagerInternal;
import android.app.admin.DevicePolicyManagerInternal.OnCrossProfileWidgetProvidersChangeListener;
@@ -72,10 +77,12 @@
import android.util.TypedValue;
import android.util.Xml;
import android.view.Display;
+import android.view.View;
import android.view.WindowManager;
import android.widget.RemoteViews;
import com.android.internal.R;
+import com.android.internal.app.UnlaunchableAppActivity;
import com.android.internal.appwidget.IAppWidgetHost;
import com.android.internal.appwidget.IAppWidgetService;
import com.android.internal.os.BackgroundThread;
@@ -146,7 +153,7 @@
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
if (DEBUG) {
- Slog.i(TAG, "Received broadcast: " + action);
+ Slog.i(TAG, "Received broadcast: " + action + " on user " + userId);
}
if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
@@ -156,10 +163,10 @@
} else if (Intent.ACTION_USER_STOPPED.equals(action)) {
onUserStopped(userId);
} else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
- reloadWidgetsMaskedStateForUser(userId);
+ reloadWidgetsMaskedStateForGroup(userId);
} else if (Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED.equals(action)) {
synchronized (mLock) {
- reloadWidgetQuietModeMaskedStateLocked(userId);
+ reloadWidgetsMaskedState(userId);
}
} else if (Intent.ACTION_PACKAGES_SUSPENDED.equals(action)) {
String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
@@ -202,6 +209,7 @@
private final AlarmManager mAlarmManager;
private final UserManager mUserManager;
private final AppOpsManager mAppOpsManager;
+ private final KeyguardManager mKeyguardManager;
private final SecurityPolicy mSecurityPolicy;
@@ -223,6 +231,7 @@
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
+ mKeyguardManager = (KeyguardManager) mContext.getSystemService(KEYGUARD_SERVICE);
mSaveStateHandler = BackgroundThread.getHandler();
mCallbackHandler = new CallbackHandler(mContext.getMainLooper());
mBackupRestoreController = new BackupRestoreController();
@@ -353,7 +362,10 @@
}
private void onPackageBroadcastReceived(Intent intent, int userId) {
- if (!mUserManager.isUserUnlocked(userId)) return;
+ if (!mUserManager.isUserUnlocked(userId) ||
+ isProfileWithLockedParent(userId)) {
+ return;
+ }
final String action = intent.getAction();
boolean added = false;
@@ -432,45 +444,52 @@
/**
* Reload all widgets' masked state for the given user and its associated profiles, including
- * due to quiet mode and package suspension.
+ * due to user not being available and package suspension.
+ * userId must be the group parent.
*/
- private void reloadWidgetsMaskedStateForUser(int userId) {
- if (!mUserManager.isUserUnlocked(userId)) return;
+ private void reloadWidgetsMaskedStateForGroup(int userId) {
+ if (!mUserManager.isUserUnlocked(userId)) {
+ return;
+ }
synchronized (mLock) {
- reloadWidgetPackageSuspensionMaskedStateLocked(userId);
+ reloadWidgetsMaskedState(userId);
List<UserInfo> profiles = mUserManager.getEnabledProfiles(userId);
if (profiles != null) {
for (int i = 0; i < profiles.size(); i++) {
UserInfo user = profiles.get(i);
- reloadWidgetQuietModeMaskedStateLocked(user.id);
- reloadWidgetPackageSuspensionMaskedStateLocked(user.id);
+ reloadWidgetsMaskedState(user.id);
}
}
}
}
- /**
- * Mask/unmask widgets in the given profile, depending on the quiet state of the profile.
- */
- private void reloadWidgetQuietModeMaskedStateLocked(int profileId) {
- if (!mUserManager.isUserUnlocked(profileId)) return;
+ private void reloadWidgetsMaskedState(int userId) {
final long identity = Binder.clearCallingIdentity();
try {
- UserInfo user = mUserManager.getUserInfo(profileId);
- if (!user.isManagedProfile()) {
- return;
- }
- boolean shouldMask = user.isQuietModeEnabled();
+ UserInfo user = mUserManager.getUserInfo(userId);
+
+ boolean lockedProfile = !mUserManager.isUserUnlocked(userId);
+ boolean quietProfile = user.isQuietModeEnabled();
final int N = mProviders.size();
for (int i = 0; i < N; i++) {
Provider provider = mProviders.get(i);
int providerUserId = provider.getUserId();
- if (providerUserId != profileId) {
+ if (providerUserId != userId) {
continue;
}
- if (provider.setMaskedByQuietProfileLocked(shouldMask)) {
+
+ boolean changed = provider.setMaskedByLockedProfileLocked(lockedProfile);
+ changed |= provider.setMaskedByQuietProfileLocked(quietProfile);
+ try {
+ boolean suspended = mPackageManager.isPackageSuspendedForUser(
+ provider.info.provider.getPackageName(), provider.getUserId());
+ changed |= provider.setMaskedBySuspendedPackageLocked(suspended);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to query application info", e);
+ }
+ if (changed) {
if (provider.isMaskedLocked()) {
- maskWidgetsViewsLocked(provider);
+ maskWidgetsViewsLocked(provider, null);
} else {
unmaskWidgetsViewsLocked(provider);
}
@@ -482,33 +501,6 @@
}
/**
- * Reload widget's masked state due to package suspension state.
- */
- private void reloadWidgetPackageSuspensionMaskedStateLocked(int profileId) {
- final int N = mProviders.size();
- for (int i = 0; i < N; i++) {
- Provider provider = mProviders.get(i);
- int providerUserId = provider.getUserId();
- if (providerUserId != profileId) {
- continue;
- }
- try {
- boolean suspended = mPackageManager.isPackageSuspendedForUser(
- provider.info.provider.getPackageName(), provider.getUserId());
- if (provider.setMaskedBySuspendedPackageLocked(suspended)) {
- if (provider.isMaskedLocked()) {
- maskWidgetsViewsLocked(provider);
- } else {
- unmaskWidgetsViewsLocked(provider);
- }
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to query application info", e);
- }
- }
- }
-
- /**
* Incrementally update the masked state due to package suspension state.
*/
private void updateWidgetPackageSuspensionMaskedState(String[] packagesArray, boolean suspended,
@@ -528,7 +520,7 @@
}
if (provider.setMaskedBySuspendedPackageLocked(suspended)) {
if (provider.isMaskedLocked()) {
- maskWidgetsViewsLocked(provider);
+ maskWidgetsViewsLocked(provider, null);
} else {
unmaskWidgetsViewsLocked(provider);
}
@@ -537,31 +529,94 @@
}
}
- private void maskWidgetsViewsLocked(Provider provider) {
- Bitmap iconBitmap = null;
+ private Bitmap createMaskedWidgetBitmap(String providerPackage, int providerUserId) {
+ final long identity = Binder.clearCallingIdentity();
try {
// Load the unbadged application icon and pass it to the widget to appear on
// the masked view.
- final String providerPackage = provider.info.provider.getPackageName();
Context userContext = mContext.createPackageContextAsUser(providerPackage, 0,
- UserHandle.of(provider.getUserId()));
+ UserHandle.of(providerUserId));
PackageManager pm = userContext.getPackageManager();
Drawable icon = pm.getApplicationInfo(providerPackage, 0).loadUnbadgedIcon(pm);
// Create a bitmap of the icon which is what the widget's remoteview requires.
- iconBitmap = mIconUtilities.createIconBitmap(icon);
+ return mIconUtilities.createIconBitmap(icon);
} catch (NameNotFoundException e) {
Slog.e(TAG, "Fail to get application icon", e);
// Provider package removed, no need to mask its views as its state will be
// purged very soon.
+ return null;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ private RemoteViews createMaskedWidgetRemoteViews(Bitmap icon, boolean showBadge,
+ PendingIntent onClickIntent) {
+ RemoteViews views = new RemoteViews(mContext.getPackageName(),
+ R.layout.work_widget_mask_view);
+ if (icon != null) {
+ views.setImageViewBitmap(R.id.work_widget_app_icon, icon);
+ }
+ if (!showBadge) {
+ views.setViewVisibility(R.id.work_widget_badge_icon, View.INVISIBLE);
+ }
+ if (onClickIntent != null) {
+ views.setOnClickPendingIntent(R.id.work_widget_mask_frame, onClickIntent);
+ }
+ return views;
+ }
+
+ /**
+ * Mask the target widget belonging to the specified provider, or all active widgets
+ * of the provider if target widget == null.
+ */
+ private void maskWidgetsViewsLocked(Provider provider, Widget targetWidget) {
+ final int widgetCount = provider.widgets.size();
+ if (widgetCount == 0) {
return;
}
+ final String providerPackage = provider.info.provider.getPackageName();
+ final int providerUserId = provider.getUserId();
+ Bitmap iconBitmap = createMaskedWidgetBitmap(providerPackage, providerUserId);
+ if (iconBitmap == null) {
+ return;
+ }
+ final boolean showBadge;
+ final Intent onClickIntent;
+ if (provider.maskedBySuspendedPackage) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ UserInfo userInfo = mUserManager.getUserInfo(providerUserId);
+ showBadge = userInfo.isManagedProfile();
+ onClickIntent = UnlaunchableAppActivity.createPackageSuspendedDialogIntent(
+ providerPackage, providerUserId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ } else if (provider.maskedByQuietProfile) {
+ showBadge = true;
+ onClickIntent = UnlaunchableAppActivity.createInQuietModeDialogIntent(
+ providerUserId);
+ } else /* provider.maskedByLockedProfile */ {
+ showBadge = true;
+ onClickIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null, null,
+ providerUserId);
+ if (onClickIntent != null) {
+ onClickIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ }
+ }
- final int widgetCount = provider.widgets.size();
for (int j = 0; j < widgetCount; j++) {
Widget widget = provider.widgets.get(j);
- if (widget.replaceWithMaskedViewsLocked(mContext, iconBitmap)) {
- scheduleNotifyUpdateAppWidgetLocked(widget,
- widget.getEffectiveViewsLocked());
+ if (targetWidget != null && targetWidget != widget) continue;
+ PendingIntent intent = null;
+ if (onClickIntent != null) {
+ intent = PendingIntent.getActivity(mContext, widget.appWidgetId,
+ onClickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ }
+ RemoteViews views = createMaskedWidgetRemoteViews(iconBitmap, showBadge, intent);
+ if (widget.replaceWithMaskedViewsLocked(views)) {
+ scheduleNotifyUpdateAppWidgetLocked(widget, widget.getEffectiveViewsLocked());
}
}
}
@@ -571,8 +626,7 @@
for (int j = 0; j < widgetCount; j++) {
Widget widget = provider.widgets.get(j);
if (widget.clearMaskedViewsLocked()) {
- scheduleNotifyUpdateAppWidgetLocked(widget,
- widget.getEffectiveViewsLocked());
+ scheduleNotifyUpdateAppWidgetLocked(widget, widget.getEffectiveViewsLocked());
}
}
}
@@ -596,7 +650,10 @@
throw new IllegalStateException(
"User " + userId + " must be unlocked for widgets to be available");
}
-
+ if (isProfileWithLockedParent(userId)) {
+ throw new IllegalStateException(
+ "Profile " + userId + " must have unlocked parent");
+ }
final int[] profileIds = mSecurityPolicy.getEnabledGroupProfileIds(userId);
// Careful lad, we may have already loaded the state for some
@@ -2320,7 +2377,7 @@
final PackageManager pm = mContext.getPackageManager();
final int userId = UserHandle.getUserId(providerId.uid);
final ApplicationInfo app = pm.getApplicationInfoAsUser(activityInfo.packageName,
- PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userId);
+ 0, userId);
resources = pm.getResourcesForApplication(app);
} finally {
Binder.restoreCallingIdentity(identity);
@@ -2423,16 +2480,23 @@
int flags = PackageManager.GET_META_DATA;
// We really need packages to be around and parsed to know if they
- // provide widgets, and we only load widgets after user is unlocked.
+ // provide widgets.
flags |= PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
+ // Widget hosts that are non-crypto aware may be hosting widgets
+ // from a profile that is still locked, so let them see those
+ // widgets.
+ if (isProfileWithUnlockedParent(userId)) {
+ flags |= PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
+ }
+
// Widgets referencing shared libraries need to have their
// dependencies loaded.
flags |= PackageManager.GET_SHARED_LIBRARY_FILES;
return mPackageManager.queryIntentReceivers(intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
- flags, userId);
+ flags, userId).getList();
} catch (RemoteException re) {
return Collections.emptyList();
} finally {
@@ -2441,8 +2505,12 @@
}
private void onUserUnlocked(int userId) {
+ if (isProfileWithLockedParent(userId)) {
+ return;
+ }
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
+ reloadWidgetsMaskedStateForGroup(mSecurityPolicy.getGroupParent(userId));
final int N = mProviders.size();
for (int i = 0; i < N; i++) {
@@ -2580,6 +2648,14 @@
mWidgetPackages.put(userId, packages = new ArraySet<String>());
}
packages.add(widget.provider.info.provider.getPackageName());
+
+ // If we are adding a widget it might be for a provider that
+ // is currently masked, if so mask the widget.
+ if (widget.provider.isMaskedLocked()) {
+ maskWidgetsViewsLocked(widget.provider, widget);
+ } else {
+ widget.clearMaskedViewsLocked();
+ }
}
/**
@@ -2973,7 +3049,6 @@
private void onUserStopped(int userId) {
synchronized (mLock) {
- boolean providersChanged = false;
boolean crossProfileWidgetsChanged = false;
// Remove widgets that have both host and provider in the user.
@@ -3009,16 +3084,8 @@
}
}
- // Remove the providers and notify hosts in other profiles.
- final int providerCount = mProviders.size();
- for (int i = providerCount - 1; i >= 0; i--) {
- Provider provider = mProviders.get(i);
- if (provider.getUserId() == userId) {
- crossProfileWidgetsChanged |= !provider.widgets.isEmpty();
- providersChanged = true;
- deleteProviderLocked(provider);
- }
- }
+ // Leave the providers present as hosts will show the widgets
+ // masked while the user is stopped.
// Remove grants for this user.
final int grantCount = mPackagesWithBindWidgetPermission.size();
@@ -3041,11 +3108,6 @@
mNextAppWidgetIds.removeAt(nextIdIndex);
}
- // Announce removed provider changes to all hosts in the group.
- if (providersChanged) {
- scheduleNotifyGroupHostsForProvidersChangedLocked(userId);
- }
-
// Save state if removing a profile changed the group state.
// Nothing will be saved if the group parent was removed.
if (crossProfileWidgetsChanged) {
@@ -3277,6 +3339,35 @@
}
}
+ private boolean isProfileWithLockedParent(int userId) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ UserInfo userInfo = mUserManager.getUserInfo(userId);
+ if (userInfo != null && userInfo.isManagedProfile()) {
+ UserInfo parentInfo = mUserManager.getProfileParent(userId);
+ if (parentInfo != null
+ && !mUserManager.isUserUnlocked(parentInfo.getUserHandle())) {
+ return true;
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return false;
+ }
+
+ private boolean isProfileWithUnlockedParent(int userId) {
+ UserInfo userInfo = mUserManager.getUserInfo(userId);
+ if (userInfo != null && userInfo.isManagedProfile()) {
+ UserInfo parentInfo = mUserManager.getProfileParent(userId);
+ if (parentInfo != null
+ && mUserManager.isUserUnlocked(parentInfo.getUserHandle())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private final class CallbackHandler extends Handler {
public static final int MSG_NOTIFY_UPDATE_APP_WIDGET = 1;
public static final int MSG_NOTIFY_PROVIDER_CHANGED = 2;
@@ -3554,6 +3645,7 @@
PendingIntent broadcast;
boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
+ boolean maskedByLockedProfile;
boolean maskedByQuietProfile;
boolean maskedBySuspendedPackage;
@@ -3586,22 +3678,29 @@
return "Provider{" + id + (zombie ? " Z" : "") + '}';
}
- // returns true if the provider's masked state is changed as a result
+ // returns true if it's different from previous state.
public boolean setMaskedByQuietProfileLocked(boolean masked) {
- boolean oldMaskedState = isMaskedLocked();
+ boolean oldState = maskedByQuietProfile;
maskedByQuietProfile = masked;
- return isMaskedLocked() != oldMaskedState;
+ return masked != oldState;
}
- // returns true if the provider's masked state is changed as a result
+ // returns true if it's different from previous state.
+ public boolean setMaskedByLockedProfileLocked(boolean masked) {
+ boolean oldState = maskedByLockedProfile;
+ maskedByLockedProfile = masked;
+ return masked != oldState;
+ }
+
+ // returns true if it's different from previous state.
public boolean setMaskedBySuspendedPackageLocked(boolean masked) {
- boolean oldMaskedState = isMaskedLocked();
+ boolean oldState = maskedBySuspendedPackage;
maskedBySuspendedPackage = masked;
- return isMaskedLocked() != oldMaskedState;
+ return masked != oldState;
}
public boolean isMaskedLocked() {
- return maskedByQuietProfile || maskedBySuspendedPackage;
+ return maskedByQuietProfile || maskedByLockedProfile || maskedBySuspendedPackage;
}
}
@@ -3758,14 +3857,8 @@
return "AppWidgetId{" + appWidgetId + ':' + host + ':' + provider + '}';
}
- private boolean replaceWithMaskedViewsLocked(Context context, Bitmap icon) {
- if (maskedViews != null) {
- return false;
- }
- maskedViews = new RemoteViews(context.getPackageName(), R.layout.work_widget_mask_view);
- if (icon != null) {
- maskedViews.setImageViewBitmap(R.id.work_widget_app_icon, icon);
- }
+ private boolean replaceWithMaskedViewsLocked(RemoteViews views) {
+ maskedViews = views;
return true;
}
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index a4fc2ec..cd4d107d 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -16,6 +16,8 @@
package com.android.server.backup;
+import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
+
import android.app.ActivityManagerNative;
import android.app.AlarmManager;
import android.app.AppGlobals;
@@ -169,6 +171,10 @@
static final boolean MORE_DEBUG = false;
static final boolean DEBUG_SCHEDULING = MORE_DEBUG || true;
+ // File containing backup-enabled state. Contains a single byte;
+ // nonzero == enabled. File missing or contains a zero byte == disabled.
+ static final String BACKUP_ENABLE_FILE = "backup_enabled";
+
// System-private key used for backing up an app's widget state. Must
// begin with U+FFxx by convention (we reserve all keys starting
// with U+FF00 or higher for system use).
@@ -352,11 +358,30 @@
if (userId == UserHandle.USER_SYSTEM) {
sInstance.initialize(userId);
- ContentResolver r = sInstance.mContext.getContentResolver();
- boolean areEnabled = Settings.Secure.getIntForUser(r,
- Settings.Secure.BACKUP_ENABLED, 0, userId) != 0;
+ // Migrate legacy setting
+ if (!backupSettingMigrated(userId)) {
+ if (DEBUG) {
+ Slog.i(TAG, "Backup enable apparently not migrated");
+ }
+ final ContentResolver r = sInstance.mContext.getContentResolver();
+ final int enableState = Settings.Secure.getIntForUser(r,
+ Settings.Secure.BACKUP_ENABLED, -1, userId);
+ if (enableState >= 0) {
+ if (DEBUG) {
+ Slog.i(TAG, "Migrating enable state " + (enableState != 0));
+ }
+ writeBackupEnableState(enableState != 0, userId);
+ Settings.Secure.putStringForUser(r,
+ Settings.Secure.BACKUP_ENABLED, null, userId);
+ } else {
+ if (DEBUG) {
+ Slog.i(TAG, "Backup not yet configured; retaining null enable state");
+ }
+ }
+ }
+
try {
- sInstance.setBackupEnabled(areEnabled);
+ sInstance.setBackupEnabled(readBackupEnableState(userId));
} catch (RemoteException e) {
// can't happen; it's a local object
}
@@ -3470,9 +3495,8 @@
// The agent was running with a stub Application object, so shut it down.
// !!! We hardcode the confirmation UI's package name here rather than use a
// manifest flag! TODO something less direct.
- if (app.uid != Process.SYSTEM_UID
- && !app.packageName.equals("com.android.backupconfirm")
- && app.uid != Process.PHONE_UID) {
+ if (app.uid >= Process.FIRST_APPLICATION_UID
+ && !app.packageName.equals("com.android.backupconfirm")) {
if (MORE_DEBUG) Slog.d(TAG, "Killing agent host process");
mActivityManager.killApplicationProcess(app.processName, app.uid);
} else {
@@ -4929,7 +4953,9 @@
continue;
}
- headBusy = mActivityManager.isAppForeground(appInfo.applicationInfo.uid);
+ final int privFlags = appInfo.applicationInfo.privateFlags;
+ headBusy = (privFlags & PRIVATE_FLAG_BACKUP_IN_FOREGROUND) == 0
+ && mActivityManager.isAppForeground(appInfo.applicationInfo.uid);
if (headBusy) {
final long nextEligible = System.currentTimeMillis()
@@ -6854,7 +6880,7 @@
// The agent was running with a stub Application object, so shut it down.
// !!! We hardcode the confirmation UI's package name here rather than use a
// manifest flag! TODO something less direct.
- if (app.uid != Process.SYSTEM_UID
+ if (app.uid >= Process.FIRST_APPLICATION_UID
&& !app.packageName.equals("com.android.backupconfirm")) {
if (DEBUG) Slog.d(TAG, "Killing host process");
mActivityManager.killApplicationProcess(app.processName, app.uid);
@@ -8598,13 +8624,15 @@
// it is explicitly not killed following that operation.
//
// We execute this kill when these conditions hold:
- // 1. the app did not request its own restore (mTargetPackage == null), and either
- // 2a. the app is a full-data target (TYPE_FULL_STREAM) or
+ // 1. it's not a system-uid process,
+ // 2. the app did not request its own restore (mTargetPackage == null), and either
+ // 3a. the app is a full-data target (TYPE_FULL_STREAM) or
// b. the app does not state android:killAfterRestore="false" in its manifest
final int appFlags = mCurrentPackage.applicationInfo.flags;
final boolean killAfterRestore =
- (mRestoreDescription.getDataType() == RestoreDescription.TYPE_FULL_STREAM)
- || ((appFlags & ApplicationInfo.FLAG_KILL_AFTER_RESTORE) != 0);
+ (mCurrentPackage.applicationInfo.uid >= Process.FIRST_APPLICATION_UID)
+ && ((mRestoreDescription.getDataType() == RestoreDescription.TYPE_FULL_STREAM)
+ || ((appFlags & ApplicationInfo.FLAG_KILL_AFTER_RESTORE) != 0));
if (mTargetPackage == null && killAfterRestore) {
if (DEBUG) Slog.d(TAG, "Restore complete, killing host process of "
@@ -9310,6 +9338,58 @@
}
}
+ private static boolean backupSettingMigrated(int userId) {
+ File base = new File(Environment.getDataDirectory(), "backup");
+ File enableFile = new File(base, BACKUP_ENABLE_FILE);
+ return enableFile.exists();
+ }
+
+ private static boolean readBackupEnableState(int userId) {
+ File base = new File(Environment.getDataDirectory(), "backup");
+ File enableFile = new File(base, BACKUP_ENABLE_FILE);
+ if (enableFile.exists()) {
+ try (FileInputStream fin = new FileInputStream(enableFile)) {
+ int state = fin.read();
+ return state != 0;
+ } catch (IOException e) {
+ // can't read the file; fall through to assume disabled
+ Slog.e(TAG, "Cannot read enable state; assuming disabled");
+ }
+ } else {
+ if (DEBUG) {
+ Slog.i(TAG, "isBackupEnabled() => false due to absent settings file");
+ }
+ }
+ return false;
+ }
+
+ private static void writeBackupEnableState(boolean enable, int userId) {
+ File base = new File(Environment.getDataDirectory(), "backup");
+ File enableFile = new File(base, BACKUP_ENABLE_FILE);
+ File stage = new File(base, BACKUP_ENABLE_FILE + "-stage");
+ FileOutputStream fout = null;
+ try {
+ fout = new FileOutputStream(stage);
+ fout.write(enable ? 1 : 0);
+ fout.close();
+ stage.renameTo(enableFile);
+ // will be synced immediately by the try-with-resources call to close()
+ } catch (IOException|RuntimeException e) {
+ // Whoops; looks like we're doomed. Roll everything out, disabled,
+ // including the legacy state.
+ Slog.e(TAG, "Unable to record backup enable state; reverting to disabled: "
+ + e.getMessage());
+
+ final ContentResolver r = sInstance.mContext.getContentResolver();
+ Settings.Secure.putStringForUser(r,
+ Settings.Secure.BACKUP_ENABLED, null, userId);
+ enableFile.delete();
+ stage.delete();
+ } finally {
+ IoUtils.closeQuietly(fout);
+ }
+ }
+
// Enable/disable backups
public void setBackupEnabled(boolean enable) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
@@ -9321,8 +9401,7 @@
try {
boolean wasEnabled = mEnabled;
synchronized (this) {
- Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.BACKUP_ENABLED, enable ? 1 : 0);
+ writeBackupEnableState(enable, UserHandle.USER_SYSTEM);
mEnabled = enable;
}
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 91f58c56..32f2d59 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -31,6 +31,7 @@
import java.util.List;
import java.util.Map;
+import android.Manifest;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.AppGlobals;
@@ -67,6 +68,7 @@
import com.android.internal.os.Zygote;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import libcore.util.EmptyArray;
@@ -103,9 +105,10 @@
}
};
- final SparseArray<UidState> mUidStates = new SparseArray<>();
+ private final SparseArray<UidState> mUidStates = new SparseArray<>();
- private final SparseArray<boolean[]> mOpRestrictions = new SparseArray<boolean[]>();
+ /** These are app op restrictions imposed per user from various parties */
+ private final ArrayMap<IBinder, SparseArray<boolean[]>> mOpUserRestrictions = new ArrayMap<>();
private static final class UidState {
public final int uid;
@@ -1263,17 +1266,21 @@
private boolean isOpRestricted(int uid, int code, String packageName) {
int userHandle = UserHandle.getUserId(uid);
- boolean[] opRestrictions = mOpRestrictions.get(userHandle);
- if ((opRestrictions != null) && opRestrictions[code]) {
- if (AppOpsManager.opAllowSystemBypassRestriction(code)) {
- synchronized (this) {
- Ops ops = getOpsLocked(uid, packageName, true);
- if ((ops != null) && ops.isPrivileged) {
- return false;
+ final int restrictionSetCount = mOpUserRestrictions.size();
+ for (int i = 0; i < restrictionSetCount; i++) {
+ SparseArray<boolean[]> perUserRestrictions = mOpUserRestrictions.valueAt(i);
+ boolean[] opRestrictions = perUserRestrictions.get(userHandle);
+ if (opRestrictions != null && opRestrictions[code]) {
+ if (AppOpsManager.opAllowSystemBypassRestriction(code)) {
+ synchronized (this) {
+ Ops ops = getOpsLocked(uid, packageName, true);
+ if ((ops != null) && ops.isPrivileged) {
+ return false;
+ }
}
}
+ return true;
}
- return true;
}
return false;
}
@@ -2049,27 +2056,123 @@
}
@Override
- public void setUserRestrictions(Bundle restrictions, int userHandle) throws RemoteException {
+ public void setUserRestrictions(Bundle restrictions, IBinder token, int userHandle) {
checkSystemUid("setUserRestrictions");
- boolean[] opRestrictions = mOpRestrictions.get(userHandle);
- if (opRestrictions == null) {
- opRestrictions = new boolean[AppOpsManager._NUM_OP];
- mOpRestrictions.put(userHandle, opRestrictions);
- }
+ Preconditions.checkNotNull(token);
+ final boolean[] opRestrictions = getOrCreateUserRestrictionsForToken(token, userHandle);
for (int i = 0; i < opRestrictions.length; ++i) {
String restriction = AppOpsManager.opToRestriction(i);
- if (restriction != null) {
- opRestrictions[i] = restrictions.getBoolean(restriction, false);
- } else {
- opRestrictions[i] = false;
+ final boolean restricted = restriction != null
+ && restrictions.getBoolean(restriction, false);
+ setUserRestrictionNoCheck(i, restricted, token, userHandle);
+ }
+ }
+
+ @Override
+ public void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle) {
+ if (Binder.getCallingPid() != Process.myPid()) {
+ mContext.enforcePermission(Manifest.permission.MANAGE_APP_OPS_RESTRICTIONS,
+ Binder.getCallingPid(), Binder.getCallingUid(), null);
+ }
+ if (userHandle != UserHandle.getCallingUserId()) {
+ if (mContext.checkCallingOrSelfPermission(Manifest.permission
+ .INTERACT_ACROSS_USERS_FULL) != PackageManager.PERMISSION_GRANTED
+ && mContext.checkCallingOrSelfPermission(Manifest.permission
+ .INTERACT_ACROSS_USERS) != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Need INTERACT_ACROSS_USERS_FULL or"
+ + " INTERACT_ACROSS_USERS to interact cross user ");
}
}
+ verifyIncomingOp(code);
+ Preconditions.checkNotNull(token);
+ setUserRestrictionNoCheck(code, restricted, token, userHandle);
+ }
+
+ private void setUserRestrictionNoCheck(int code, boolean restricted, IBinder token,
+ int userHandle) {
+ final boolean[] opRestrictions = getOrCreateUserRestrictionsForToken(token, userHandle);
+ if (opRestrictions[code] == restricted) {
+ return;
+ }
+ opRestrictions[code] = restricted;
+ if (!restricted) {
+ pruneUserRestrictionsForToken(token, userHandle);
+ }
+
+ final ArrayList<Callback> clonedCallbacks;
+ synchronized (this) {
+ ArrayList<Callback> callbacks = mOpModeWatchers.get(code);
+ if (callbacks == null) {
+ return;
+ }
+ clonedCallbacks = new ArrayList<>(callbacks);
+ }
+
+ // There are components watching for mode changes such as window manager
+ // and location manager which are in our process. The callbacks in these
+ // components may require permissions our remote caller does not have.
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ final int callbackCount = clonedCallbacks.size();
+ for (int i = 0; i < callbackCount; i++) {
+ Callback callback = clonedCallbacks.get(i);
+ try {
+ callback.mCallback.opChanged(code, -1, null);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error dispatching op op change", e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
@Override
public void removeUser(int userHandle) throws RemoteException {
checkSystemUid("removeUser");
- mOpRestrictions.remove(userHandle);
+ final int tokenCount = mOpUserRestrictions.size();
+ for (int i = tokenCount - 1; i >= 0; i--) {
+ SparseArray<boolean[]> opRestrictions = mOpUserRestrictions.valueAt(i);
+ if (opRestrictions != null) {
+ opRestrictions.remove(userHandle);
+ if (opRestrictions.size() <= 0) {
+ mOpUserRestrictions.removeAt(i);
+ }
+ }
+ }
+ }
+
+
+ private void pruneUserRestrictionsForToken(IBinder token, int userHandle) {
+ SparseArray<boolean[]> perTokenRestrictions = mOpUserRestrictions.get(token);
+ if (perTokenRestrictions != null) {
+ final boolean[] opRestrictions = perTokenRestrictions.get(userHandle);
+ if (opRestrictions != null) {
+ for (boolean restriction : opRestrictions) {
+ if (restriction) {
+ return;
+ }
+ }
+ perTokenRestrictions.remove(userHandle);
+ if (perTokenRestrictions.size() <= 0) {
+ mOpUserRestrictions.remove(token);
+ }
+ }
+ }
+ }
+
+ private boolean[] getOrCreateUserRestrictionsForToken(IBinder token, int userHandle) {
+ SparseArray<boolean[]> perTokenRestrictions = mOpUserRestrictions.get(token);
+ if (perTokenRestrictions == null) {
+ perTokenRestrictions = new SparseArray<>();
+ mOpUserRestrictions.put(token, perTokenRestrictions);
+ }
+ boolean[] opRestrictions = perTokenRestrictions.get(userHandle);
+ if (opRestrictions == null) {
+ opRestrictions = new boolean[AppOpsManager._NUM_OP];
+ perTokenRestrictions.put(userHandle, opRestrictions);
+ }
+ return opRestrictions;
}
private void checkSystemUid(String function) {
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 6d0d9e9..e241a4a 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -19,7 +19,6 @@
import android.Manifest;
import android.app.ActivityManager;
import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.IBluetooth;
import android.bluetooth.IBluetoothCallback;
@@ -44,7 +43,6 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
-import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
@@ -53,10 +51,9 @@
import android.os.UserManager;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
-import android.util.Log;
+import android.util.Slog;
import java.io.FileDescriptor;
-import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
@@ -92,14 +89,15 @@
private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40;
private static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41;
private static final int MESSAGE_RESTART_BLUETOOTH_SERVICE = 42;
- private static final int MESSAGE_BLUETOOTH_STATE_CHANGE=60;
- private static final int MESSAGE_TIMEOUT_BIND =100;
- private static final int MESSAGE_TIMEOUT_UNBIND =101;
+ private static final int MESSAGE_BLUETOOTH_STATE_CHANGE = 60;
+ private static final int MESSAGE_TIMEOUT_BIND = 100;
+ private static final int MESSAGE_TIMEOUT_UNBIND = 101;
private static final int MESSAGE_USER_SWITCHED = 300;
+ private static final int MESSAGE_USER_UNLOCKED = 301;
private static final int MESSAGE_ADD_PROXY_DELAYED = 400;
private static final int MESSAGE_BIND_PROFILE_SERVICE = 401;
- private static final int MAX_SAVE_RETRIES=3;
- private static final int MAX_ERROR_RESTART_RETRIES=6;
+ private static final int MAX_SAVE_RETRIES = 3;
+ private static final int MAX_ERROR_RESTART_RETRIES = 6;
// Bluetooth persisted setting is off
private static final int BLUETOOTH_OFF=0;
@@ -176,7 +174,7 @@
String action = intent.getAction();
if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) {
String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME);
- if (DBG) Log.d(TAG, "Bluetooth Adapter name changed to " + newName);
+ if (DBG) Slog.d(TAG, "Bluetooth Adapter name changed to " + newName);
if (newName != null) {
storeNameAndAddress(newName, null);
}
@@ -195,10 +193,10 @@
try {
st = mBluetooth.getState();
} catch (RemoteException e) {
- Log.e(TAG,"Unable to call getState", e);
+ Slog.e(TAG,"Unable to call getState", e);
}
}
- Log.d(TAG, "state" + st);
+ Slog.d(TAG, "state" + st);
if (isAirplaneModeOn()) {
// Clear registered LE apps to force shut-off
@@ -214,16 +212,16 @@
mEnableExternal = false;
}
} catch(RemoteException e) {
- Log.e(TAG,"Unable to call onBrEdrDown", e);
+ Slog.e(TAG,"Unable to call onBrEdrDown", e);
}
} else if (st == BluetoothAdapter.STATE_ON){
// disable without persisting the setting
- Log.d(TAG, "Calling disable");
+ Slog.d(TAG, "Calling disable");
sendDisableMsg();
}
} else if (mEnableExternal) {
// enable without persisting the setting
- Log.d(TAG, "Calling enable");
+ Slog.d(TAG, "Calling enable");
sendEnableMsg(mQuietEnableExternal);
}
}
@@ -267,7 +265,7 @@
PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
} catch (PackageManager.NameNotFoundException e) {
// Some platforms, such as wearables do not have a system ui.
- Log.w(TAG, "Unable to resolve SystemUI's UID.", e);
+ Slog.w(TAG, "Unable to resolve SystemUI's UID.", e);
}
mSystemUiUid = sysUiUid;
}
@@ -320,17 +318,17 @@
* in the local cache
*/
private void loadStoredNameAndAddress() {
- if (DBG) Log.d(TAG, "Loading stored name and address");
+ if (DBG) Slog.d(TAG, "Loading stored name and address");
if (mContext.getResources().getBoolean
(com.android.internal.R.bool.config_bluetooth_address_validation) &&
Settings.Secure.getInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0) == 0) {
// if the valid flag is not set, don't load the address and name
- if (DBG) Log.d(TAG, "invalid bluetooth name and address stored");
+ if (DBG) Slog.d(TAG, "invalid bluetooth name and address stored");
return;
}
mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME);
mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS);
- if (DBG) Log.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress);
+ if (DBG) Slog.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress);
}
/**
@@ -343,14 +341,14 @@
if (name != null) {
Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name);
mName = name;
- if (DBG) Log.d(TAG,"Stored Bluetooth name: " +
+ if (DBG) Slog.d(TAG,"Stored Bluetooth name: " +
Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_NAME));
}
if (address != null) {
Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, address);
mAddress=address;
- if (DBG) Log.d(TAG,"Stored Bluetoothaddress: " +
+ if (DBG) Slog.d(TAG,"Stored Bluetoothaddress: " +
Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_ADDRESS));
}
@@ -361,7 +359,7 @@
public IBluetooth registerAdapter(IBluetoothManagerCallback callback){
if (callback == null) {
- Log.w(TAG, "Callback is null in registerAdapter");
+ Slog.w(TAG, "Callback is null in registerAdapter");
return null;
}
Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER);
@@ -374,7 +372,7 @@
public void unregisterAdapter(IBluetoothManagerCallback callback) {
if (callback == null) {
- Log.w(TAG, "Callback is null in unregisterAdapter");
+ Slog.w(TAG, "Callback is null in unregisterAdapter");
return;
}
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
@@ -403,7 +401,7 @@
public boolean isEnabled() {
if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
(!checkIfCallerIsForegroundUser())) {
- Log.w(TAG,"isEnabled(): not allowed for non-active and non system user");
+ Slog.w(TAG,"isEnabled(): not allowed for non-active and non system user");
return false;
}
@@ -411,7 +409,7 @@
try {
return (mBluetooth != null && mBluetooth.isEnabled());
} catch (RemoteException e) {
- Log.e(TAG, "isEnabled()", e);
+ Slog.e(TAG, "isEnabled()", e);
}
}
return false;
@@ -419,17 +417,17 @@
class ClientDeathRecipient implements IBinder.DeathRecipient {
public void binderDied() {
- if (DBG) Log.d(TAG, "Binder is dead - unregister Ble App");
+ if (DBG) Slog.d(TAG, "Binder is dead - unregister Ble App");
if (mBleAppCount > 0) --mBleAppCount;
if (mBleAppCount == 0) {
- if (DBG) Log.d(TAG, "Disabling LE only mode after application crash");
+ if (DBG) Slog.d(TAG, "Disabling LE only mode after application crash");
try {
if (mBluetooth != null) {
mBluetooth.onBrEdrDown();
}
} catch(RemoteException e) {
- Log.e(TAG,"Unable to call onBrEdrDown", e);
+ Slog.e(TAG,"Unable to call onBrEdrDown", e);
}
}
}
@@ -459,7 +457,7 @@
try {
if (mBluetooth != null) mBluetooth.onBrEdrDown();
} catch (RemoteException e) {
- Log.e(TAG, "error when disabling bluetooth", e);
+ Slog.e(TAG, "error when disabling bluetooth", e);
}
}
}
@@ -474,11 +472,11 @@
private void disableBleScanMode() {
try {
if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) {
- if (DBG) Log.d(TAG, "Reseting the mEnable flag for clean disable");
+ if (DBG) Slog.d(TAG, "Reseting the mEnable flag for clean disable");
mEnable = false;
}
} catch (RemoteException e) {
- Log.e(TAG, "getState()", e);
+ Slog.e(TAG, "getState()", e);
}
}
@@ -496,7 +494,7 @@
synchronized (this) {
++mBleAppCount;
}
- if (DBG) Log.d(TAG, "Registered for death Notification");
+ if (DBG) Slog.d(TAG, "Registered for death Notification");
}
} else {
@@ -508,10 +506,10 @@
synchronized (this) {
if (mBleAppCount > 0) --mBleAppCount;
}
- if (DBG) Log.d(TAG, "Unregistered for death Notification");
+ if (DBG) Slog.d(TAG, "Unregistered for death Notification");
}
}
- if (DBG) Log.d(TAG, "Updated BleAppCount" + mBleAppCount);
+ if (DBG) Slog.d(TAG, "Updated BleAppCount" + mBleAppCount);
if (mBleAppCount == 0 && mEnable) {
disableBleScanMode();
}
@@ -528,7 +526,7 @@
/** @hide*/
public boolean isBleAppPresent() {
- if (DBG) Log.d(TAG, "isBleAppPresent() count: " + mBleAppCount);
+ if (DBG) Slog.d(TAG, "isBleAppPresent() count: " + mBleAppCount);
return (mBleAppCount > 0);
}
@@ -536,7 +534,7 @@
* Action taken when GattService is turned off
*/
private void onBluetoothGattServiceUp() {
- if (DBG) Log.d(TAG,"BluetoothGatt Service is Up");
+ if (DBG) Slog.d(TAG,"BluetoothGatt Service is Up");
try{
if (isBleAppPresent() == false && mBluetooth != null
&& mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) {
@@ -548,7 +546,7 @@
Binder.restoreCallingIdentity(callingIdentity);
}
} catch(RemoteException e) {
- Log.e(TAG,"Unable to call onServiceUp", e);
+ Slog.e(TAG,"Unable to call onServiceUp", e);
}
}
@@ -557,10 +555,10 @@
* and turn off all service and stack if no LE app needs it
*/
private void sendBrEdrDownCallback() {
- if (DBG) Log.d(TAG,"Calling sendBrEdrDownCallback callbacks");
+ if (DBG) Slog.d(TAG,"Calling sendBrEdrDownCallback callbacks");
if(mBluetooth == null) {
- Log.w(TAG, "Bluetooth handle is null");
+ Slog.w(TAG, "Bluetooth handle is null");
return;
}
@@ -568,14 +566,14 @@
try {
mBluetooth.onBrEdrDown();
} catch(RemoteException e) {
- Log.e(TAG, "Call to onBrEdrDown() failed.", e);
+ Slog.e(TAG, "Call to onBrEdrDown() failed.", e);
}
} else {
// Need to stay at BLE ON. Disconnect all Gatt connections
try{
mBluetoothGatt.unregAll();
} catch(RemoteException e) {
- Log.e(TAG, "Unable to disconnect all apps.", e);
+ Slog.e(TAG, "Unable to disconnect all apps.", e);
}
}
}
@@ -586,7 +584,7 @@
"Need BLUETOOTH ADMIN permission");
if (DBG) {
- Log.d(TAG,"enableNoAutoConnect(): mBluetooth =" + mBluetooth +
+ Slog.d(TAG,"enableNoAutoConnect(): mBluetooth =" + mBluetooth +
" mBinding = " + mBinding);
}
int callingAppId = UserHandle.getAppId(Binder.getCallingUid());
@@ -606,14 +604,14 @@
public boolean enable() {
if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
(!checkIfCallerIsForegroundUser())) {
- Log.w(TAG,"enable(): not allowed for non-active and non system user");
+ Slog.w(TAG,"enable(): not allowed for non-active and non system user");
return false;
}
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
if (DBG) {
- Log.d(TAG,"enable(): mBluetooth =" + mBluetooth +
+ Slog.d(TAG,"enable(): mBluetooth =" + mBluetooth +
" mBinding = " + mBinding);
}
@@ -623,7 +621,7 @@
// waive WRITE_SECURE_SETTINGS permission check
sendEnableMsg(false);
}
- if (DBG) Log.d(TAG, "enable returning");
+ if (DBG) Slog.d(TAG, "enable returning");
return true;
}
@@ -633,12 +631,12 @@
if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
(!checkIfCallerIsForegroundUser())) {
- Log.w(TAG,"disable(): not allowed for non-active and non system user");
+ Slog.w(TAG,"disable(): not allowed for non-active and non system user");
return false;
}
if (DBG) {
- Log.d(TAG,"disable(): mBluetooth = " + mBluetooth +
+ Slog.d(TAG,"disable(): mBluetooth = " + mBluetooth +
" mBinding = " + mBinding);
}
@@ -657,7 +655,7 @@
public void unbindAndFinish() {
if (DBG) {
- Log.d(TAG,"unbindAndFinish(): " + mBluetooth +
+ Slog.d(TAG,"unbindAndFinish(): " + mBluetooth +
" mBinding = " + mBinding);
}
@@ -669,10 +667,10 @@
try {
mBluetooth.unregisterCallback(mBluetoothCallback);
} catch (RemoteException re) {
- Log.e(TAG, "Unable to unregister BluetoothCallback",re);
+ Slog.e(TAG, "Unable to unregister BluetoothCallback",re);
}
- if (DBG) Log.d(TAG, "Sending unbind request.");
+ if (DBG) Slog.d(TAG, "Sending unbind request.");
mBluetoothBinder = null;
mBluetooth = null;
//Unbind
@@ -696,7 +694,7 @@
IBluetoothProfileServiceConnection proxy) {
if (!mEnable) {
if (DBG) {
- Log.d(TAG, "Trying to bind to profile: " + bluetoothProfile +
+ Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile +
", while Bluetooth was disabled");
}
return false;
@@ -705,7 +703,7 @@
ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile));
if (psc == null) {
if (DBG) {
- Log.d(TAG, "Creating new ProfileServiceConnections object for"
+ Slog.d(TAG, "Creating new ProfileServiceConnections object for"
+ " profile: " + bluetoothProfile);
}
@@ -746,7 +744,7 @@
try {
mContext.unbindService(psc);
} catch (IllegalArgumentException e) {
- Log.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e);
+ Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e);
}
psc.removeAllProxies();
}
@@ -759,9 +757,9 @@
* PHASE_SYSTEM_SERVICES_READY.
*/
public void handleOnBootPhase() {
- if (DBG) Log.d(TAG, "Bluetooth boot completed");
+ if (DBG) Slog.d(TAG, "Bluetooth boot completed");
if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) {
- if (DBG) Log.d(TAG, "Auto-enabling Bluetooth.");
+ if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth.");
sendEnableMsg(mQuietEnableExternal);
}
}
@@ -770,8 +768,16 @@
* Called when switching to a different foreground user.
*/
public void handleOnSwitchUser(int userHandle) {
- if (DBG) Log.d(TAG, "Bluetooth user switched");
- mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0));
+ if (DBG) Slog.d(TAG, "User " + userHandle + " switched");
+ mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0).sendToTarget();
+ }
+
+ /**
+ * Called when user is unlocked.
+ */
+ public void handleOnUnlockUser(int userHandle) {
+ if (DBG) Slog.d(TAG, "User " + userHandle + " unlocked");
+ mHandler.obtainMessage(MESSAGE_USER_UNLOCKED, userHandle, 0).sendToTarget();
}
/**
@@ -801,7 +807,7 @@
mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
return true;
}
- Log.w(TAG, "Unable to bind with intent: " + mIntent);
+ Slog.w(TAG, "Unable to bind with intent: " + mIntent);
return false;
}
@@ -811,7 +817,7 @@
try{
proxy.onServiceConnected(mClassName, mService);
} catch (RemoteException e) {
- Log.e(TAG, "Unable to connect to proxy", e);
+ Slog.e(TAG, "Unable to connect to proxy", e);
}
} else {
if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) {
@@ -828,11 +834,11 @@
try {
proxy.onServiceDisconnected(mClassName);
} catch (RemoteException e) {
- Log.e(TAG, "Unable to disconnect proxy", e);
+ Slog.e(TAG, "Unable to disconnect proxy", e);
}
}
} else {
- Log.w(TAG, "Trying to remove a null proxy");
+ Slog.w(TAG, "Trying to remove a null proxy");
}
}
@@ -850,11 +856,11 @@
try {
mService.linkToDeath(this, 0);
} catch (RemoteException e) {
- Log.e(TAG, "Unable to linkToDeath", e);
+ Slog.e(TAG, "Unable to linkToDeath", e);
}
if (mInvokingProxyCallbacks) {
- Log.e(TAG, "Proxy callbacks already in progress.");
+ Slog.e(TAG, "Proxy callbacks already in progress.");
return;
}
mInvokingProxyCallbacks = true;
@@ -865,7 +871,7 @@
try {
mProxies.getBroadcastItem(i).onServiceConnected(className, service);
} catch (RemoteException e) {
- Log.e(TAG, "Unable to connect to proxy", e);
+ Slog.e(TAG, "Unable to connect to proxy", e);
}
}
} finally {
@@ -882,7 +888,7 @@
mClassName = null;
if (mInvokingProxyCallbacks) {
- Log.e(TAG, "Proxy callbacks already in progress.");
+ Slog.e(TAG, "Proxy callbacks already in progress.");
return;
}
mInvokingProxyCallbacks = true;
@@ -893,7 +899,7 @@
try {
mProxies.getBroadcastItem(i).onServiceDisconnected(className);
} catch (RemoteException e) {
- Log.e(TAG, "Unable to disconnect from proxy", e);
+ Slog.e(TAG, "Unable to disconnect from proxy", e);
}
}
} finally {
@@ -905,7 +911,7 @@
@Override
public void binderDied() {
if (DBG) {
- Log.w(TAG, "Profile service for profile: " + mClassName
+ Slog.w(TAG, "Profile service for profile: " + mClassName
+ " died.");
}
onServiceDisconnected(mClassName);
@@ -919,12 +925,12 @@
private void sendBluetoothStateCallback(boolean isUp) {
try {
int n = mStateChangeCallbacks.beginBroadcast();
- if (DBG) Log.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers.");
+ if (DBG) Slog.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers.");
for (int i=0; i <n;i++) {
try {
mStateChangeCallbacks.getBroadcastItem(i).onBluetoothStateChange(isUp);
} catch (RemoteException e) {
- Log.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i , e);
+ Slog.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i , e);
}
}
} finally {
@@ -936,15 +942,15 @@
* Inform BluetoothAdapter instances that Adapter service is up
*/
private void sendBluetoothServiceUpCallback() {
- if (DBG) Log.d(TAG,"Calling onBluetoothServiceUp callbacks");
+ if (DBG) Slog.d(TAG,"Calling onBluetoothServiceUp callbacks");
try {
int n = mCallbacks.beginBroadcast();
- Log.d(TAG,"Broadcasting onBluetoothServiceUp() to " + n + " receivers.");
+ Slog.d(TAG,"Broadcasting onBluetoothServiceUp() to " + n + " receivers.");
for (int i=0; i <n;i++) {
try {
mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth);
} catch (RemoteException e) {
- Log.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
+ Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
}
}
} finally {
@@ -955,15 +961,15 @@
* Inform BluetoothAdapter instances that Adapter service is down
*/
private void sendBluetoothServiceDownCallback() {
- if (DBG) Log.d(TAG,"Calling onBluetoothServiceDown callbacks");
+ if (DBG) Slog.d(TAG,"Calling onBluetoothServiceDown callbacks");
try {
int n = mCallbacks.beginBroadcast();
- Log.d(TAG,"Broadcasting onBluetoothServiceDown() to " + n + " receivers.");
+ Slog.d(TAG,"Broadcasting onBluetoothServiceDown() to " + n + " receivers.");
for (int i=0; i <n;i++) {
try {
mCallbacks.getBroadcastItem(i).onBluetoothServiceDown();
} catch (RemoteException e) {
- Log.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e);
+ Slog.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e);
}
}
} finally {
@@ -977,7 +983,7 @@
if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
(!checkIfCallerIsForegroundUser())) {
- Log.w(TAG,"getAddress(): not allowed for non-active and non system user");
+ Slog.w(TAG,"getAddress(): not allowed for non-active and non system user");
return null;
}
@@ -991,7 +997,7 @@
try {
return mBluetooth.getAddress();
} catch (RemoteException e) {
- Log.e(TAG, "getAddress(): Unable to retrieve address remotely..Returning cached address",e);
+ Slog.e(TAG, "getAddress(): Unable to retrieve address remotely..Returning cached address",e);
}
}
}
@@ -1007,7 +1013,7 @@
if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
(!checkIfCallerIsForegroundUser())) {
- Log.w(TAG,"getName(): not allowed for non-active and non system user");
+ Slog.w(TAG,"getName(): not allowed for non-active and non system user");
return null;
}
@@ -1016,7 +1022,7 @@
try {
return mBluetooth.getName();
} catch (RemoteException e) {
- Log.e(TAG, "getName(): Unable to retrieve name remotely..Returning cached name",e);
+ Slog.e(TAG, "getName(): Unable to retrieve name remotely..Returning cached name",e);
}
}
}
@@ -1028,7 +1034,7 @@
private class BluetoothServiceConnection implements ServiceConnection {
public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) Log.d(TAG, "BluetoothServiceConnection: " + className.getClassName());
+ if (DBG) Slog.d(TAG, "BluetoothServiceConnection: " + className.getClassName());
Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
// TBD if (className.getClassName().equals(IBluetooth.class.getName())) {
if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) {
@@ -1037,7 +1043,7 @@
} else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) {
msg.arg1 = SERVICE_IBLUETOOTHGATT;
} else {
- Log.e(TAG, "Unknown service connected: " + className.getClassName());
+ Slog.e(TAG, "Unknown service connected: " + className.getClassName());
return;
}
msg.obj = service;
@@ -1046,7 +1052,7 @@
public void onServiceDisconnected(ComponentName className) {
// Called if we unexpected disconnected.
- if (DBG) Log.d(TAG, "BluetoothServiceConnection, disconnected: " +
+ if (DBG) Slog.d(TAG, "BluetoothServiceConnection, disconnected: " +
className.getClassName());
Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED);
if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) {
@@ -1054,7 +1060,7 @@
} else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) {
msg.arg1 = SERVICE_IBLUETOOTHGATT;
} else {
- Log.e(TAG, "Unknown service disconnected: " + className.getClassName());
+ Slog.e(TAG, "Unknown service disconnected: " + className.getClassName());
return;
}
mHandler.sendMessage(msg);
@@ -1070,11 +1076,11 @@
@Override
public void handleMessage(Message msg) {
- if (DBG) Log.d (TAG, "Message: " + msg.what);
+ if (DBG) Slog.d (TAG, "Message: " + msg.what);
switch (msg.what) {
case MESSAGE_ENABLE:
if (DBG) {
- Log.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth);
+ Slog.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth);
}
mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
mEnable = true;
@@ -1098,14 +1104,14 @@
{
IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
boolean added = mCallbacks.register(callback);
- Log.d(TAG,"Added callback: " + (callback == null? "null": callback) +":" +added );
+ Slog.d(TAG,"Added callback: " + (callback == null? "null": callback) +":" +added );
}
break;
case MESSAGE_UNREGISTER_ADAPTER:
{
IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
boolean removed = mCallbacks.unregister(callback);
- Log.d(TAG,"Removed callback: " + (callback == null? "null": callback) +":" + removed);
+ Slog.d(TAG,"Removed callback: " + (callback == null? "null": callback) +":" + removed);
break;
}
case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK:
@@ -1148,7 +1154,7 @@
}
case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
{
- if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);
+ if (DBG) Slog.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);
IBinder service = (IBinder) msg.obj;
synchronized(mConnection) {
@@ -1169,17 +1175,17 @@
boolean enableHciSnoopLog = (Settings.Secure.getInt(mContentResolver,
Settings.Secure.BLUETOOTH_HCI_LOG, 0) == 1);
if (!mBluetooth.configHciSnoopLog(enableHciSnoopLog)) {
- Log.e(TAG,"IBluetooth.configHciSnoopLog return false");
+ Slog.e(TAG,"IBluetooth.configHciSnoopLog return false");
}
} catch (RemoteException e) {
- Log.e(TAG,"Unable to call configHciSnoopLog", e);
+ Slog.e(TAG,"Unable to call configHciSnoopLog", e);
}
//Register callback object
try {
mBluetooth.registerCallback(mBluetoothCallback);
} catch (RemoteException re) {
- Log.e(TAG, "Unable to register BluetoothCallback",re);
+ Slog.e(TAG, "Unable to register BluetoothCallback",re);
}
//Inform BluetoothAdapter instances that service is up
sendBluetoothServiceUpCallback();
@@ -1188,17 +1194,17 @@
try {
if (mQuietEnable == false) {
if(!mBluetooth.enable()) {
- Log.e(TAG,"IBluetooth.enable() returned false");
+ Slog.e(TAG,"IBluetooth.enable() returned false");
}
}
else
{
if(!mBluetooth.enableNoAutoConnect()) {
- Log.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
+ Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
}
}
} catch (RemoteException e) {
- Log.e(TAG,"Unable to call enable()",e);
+ Slog.e(TAG,"Unable to call enable()",e);
}
}
@@ -1210,7 +1216,7 @@
break;
}
case MESSAGE_TIMEOUT_BIND: {
- Log.e(TAG, "MESSAGE_TIMEOUT_BIND");
+ Slog.e(TAG, "MESSAGE_TIMEOUT_BIND");
synchronized(mConnection) {
mBinding = false;
}
@@ -1220,7 +1226,7 @@
{
int prevState = msg.arg1;
int newState = msg.arg2;
- if (DBG) Log.d(TAG, "MESSAGE_BLUETOOTH_STATE_CHANGE: prevState = " + prevState + ", newState=" + newState);
+ if (DBG) Slog.d(TAG, "MESSAGE_BLUETOOTH_STATE_CHANGE: prevState = " + prevState + ", newState=" + newState);
mState = newState;
bluetoothStateChangeHandler(prevState, newState);
// handle error state transition case from TURNING_ON to OFF
@@ -1239,7 +1245,7 @@
newState == BluetoothAdapter.STATE_BLE_ON) {
// bluetooth is working, reset the counter
if (mErrorRecoveryRetryCounter != 0) {
- Log.w(TAG, "bluetooth is recovered from error");
+ Slog.w(TAG, "bluetooth is recovered from error");
mErrorRecoveryRetryCounter = 0;
}
}
@@ -1247,7 +1253,7 @@
}
case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED:
{
- Log.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: " + msg.arg1);
+ Slog.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: " + msg.arg1);
synchronized(mConnection) {
if (msg.arg1 == SERVICE_IBLUETOOTH) {
// if service is unbinded already, do nothing and return
@@ -1257,7 +1263,7 @@
mBluetoothGatt = null;
break;
} else {
- Log.e(TAG, "Bad msg.arg1: " + msg.arg1);
+ Slog.e(TAG, "Bad msg.arg1: " + msg.arg1);
break;
}
}
@@ -1292,7 +1298,7 @@
}
case MESSAGE_RESTART_BLUETOOTH_SERVICE:
{
- Log.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE:"
+ Slog.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE:"
+" Restart IBluetooth service");
/* Enable without persisting the setting as
it doesnt change when IBluetooth
@@ -1304,19 +1310,17 @@
case MESSAGE_TIMEOUT_UNBIND:
{
- Log.e(TAG, "MESSAGE_TIMEOUT_UNBIND");
+ Slog.e(TAG, "MESSAGE_TIMEOUT_UNBIND");
synchronized(mConnection) {
mUnbinding = false;
}
break;
}
- case MESSAGE_USER_SWITCHED:
- {
- if (DBG) {
- Log.d(TAG, "MESSAGE_USER_SWITCHED");
- }
+ case MESSAGE_USER_SWITCHED: {
+ if (DBG) Slog.d(TAG, "MESSAGE_USER_SWITCHED");
mHandler.removeMessages(MESSAGE_USER_SWITCHED);
+
/* disable and enable BT when detect a user switch */
if (mEnable && mBluetooth != null) {
synchronized (mConnection) {
@@ -1325,7 +1329,7 @@
try {
mBluetooth.unregisterCallback(mBluetoothCallback);
} catch (RemoteException re) {
- Log.e(TAG, "Unable to unregister",re);
+ Slog.e(TAG, "Unable to unregister",re);
}
}
}
@@ -1379,11 +1383,25 @@
// delay sending MESSAGE_USER_SWITCHED
mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS);
if (DBG) {
- Log.d(TAG, "delay MESSAGE_USER_SWITCHED " + userMsg.arg2);
+ Slog.d(TAG, "delay MESSAGE_USER_SWITCHED " + userMsg.arg2);
}
}
break;
}
+ case MESSAGE_USER_UNLOCKED: {
+ if (DBG) Slog.d(TAG, "MESSAGE_USER_UNLOCKED");
+ mHandler.removeMessages(MESSAGE_USER_SWITCHED);
+
+ synchronized (mConnection) {
+ if (mEnable && !mBinding && (mBluetooth == null)) {
+ // We should be connected, but we gave up for some
+ // reason; maybe the Bluetooth service wasn't encryption
+ // aware, so try binding again.
+ if (DBG) Slog.d(TAG, "Enabled but not bound; retrying after unlock");
+ handleEnable(mQuietEnable);
+ }
+ }
+ }
}
}
}
@@ -1408,16 +1426,16 @@
try {
if (!mQuietEnable) {
if(!mBluetooth.enable()) {
- Log.e(TAG,"IBluetooth.enable() returned false");
+ Slog.e(TAG,"IBluetooth.enable() returned false");
}
}
else {
if(!mBluetooth.enableNoAutoConnect()) {
- Log.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
+ Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
}
}
} catch (RemoteException e) {
- Log.e(TAG,"Unable to call enable()",e);
+ Slog.e(TAG,"Unable to call enable()",e);
}
}
}
@@ -1427,7 +1445,7 @@
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
intent.setComponent(comp);
if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) {
- Log.e(TAG, "Fail to bind to: " + intent);
+ Slog.e(TAG, "Fail to bind to: " + intent);
return false;
}
return true;
@@ -1436,14 +1454,14 @@
private void handleDisable() {
synchronized(mConnection) {
if (mBluetooth != null) {
- if (DBG) Log.d(TAG,"Sending off request.");
+ if (DBG) Slog.d(TAG,"Sending off request.");
try {
if(!mBluetooth.disable()) {
- Log.e(TAG,"IBluetooth.disable() returned false");
+ Slog.e(TAG,"IBluetooth.disable() returned false");
}
} catch (RemoteException e) {
- Log.e(TAG,"Unable to call disable()",e);
+ Slog.e(TAG,"Unable to call disable()",e);
}
}
}
@@ -1466,7 +1484,7 @@
callingAppId == Process.NFC_UID ||
callingAppId == mSystemUiUid;
if (DBG) {
- Log.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid
+ Slog.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid
+ " callingUser=" + callingUser
+ " parentUser=" + parentUser
+ " foregroundUser=" + foregroundUser);
@@ -1478,7 +1496,7 @@
}
private void sendBleStateChanged(int prevState, int newState) {
- if (DBG) Log.d(TAG,"BLE State Change Intent: " + prevState + " -> " + newState);
+ if (DBG) Slog.d(TAG,"BLE State Change Intent: " + prevState + " -> " + newState);
// Send broadcast message to everyone else
Intent intent = new Intent(BluetoothAdapter.ACTION_BLE_STATE_CHANGED);
intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
@@ -1498,9 +1516,9 @@
if (newState == BluetoothAdapter.STATE_OFF) {
// If Bluetooth is off, send service down event to proxy objects, and unbind
- if (DBG) Log.d(TAG, "Bluetooth is complete turn off");
+ if (DBG) Slog.d(TAG, "Bluetooth is complete turn off");
if (canUnbindBluetoothService()) {
- if (DBG) Log.d(TAG, "Good to unbind!");
+ if (DBG) Slog.d(TAG, "Good to unbind!");
sendBluetoothServiceDownCallback();
unbindAndFinish();
sendBleStateChanged(prevState, newState);
@@ -1510,12 +1528,12 @@
} else if (!intermediate_off) {
// connect to GattService
- if (DBG) Log.d(TAG, "Bluetooth is in LE only mode");
+ if (DBG) Slog.d(TAG, "Bluetooth is in LE only mode");
if (mBluetoothGatt != null) {
- if (DBG) Log.d(TAG, "Calling BluetoothGattServiceUp");
+ if (DBG) Slog.d(TAG, "Calling BluetoothGattServiceUp");
onBluetoothGattServiceUp();
} else {
- if (DBG) Log.d(TAG, "Binding Bluetooth GATT service");
+ if (DBG) Slog.d(TAG, "Binding Bluetooth GATT service");
if (mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_BLUETOOTH_LE)) {
Intent i = new Intent(IBluetoothGatt.class.getName());
@@ -1527,7 +1545,7 @@
isStandardBroadcast = false;
} else if (intermediate_off){
- if (DBG) Log.d(TAG, "Intermediate off, back to LE only mode");
+ if (DBG) Slog.d(TAG, "Intermediate off, back to LE only mode");
// For LE only mode, broadcast as is
sendBleStateChanged(prevState, newState);
sendBluetoothStateCallback(false); // BT is OFF for general users
@@ -1583,7 +1601,7 @@
if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) return true;
}
} catch (RemoteException e) {
- Log.e(TAG, "getState()", e);
+ Slog.e(TAG, "getState()", e);
break;
}
}
@@ -1594,7 +1612,7 @@
}
i++;
}
- Log.e(TAG,"waitForOnOff time out");
+ Slog.e(TAG,"waitForOnOff time out");
return false;
}
@@ -1619,21 +1637,21 @@
if (mHandler.hasMessages(MESSAGE_BLUETOOTH_STATE_CHANGE)) return false;
return (mBluetooth.getState() == BluetoothAdapter.STATE_OFF);
} catch (RemoteException e) {
- Log.e(TAG, "getState()", e);
+ Slog.e(TAG, "getState()", e);
}
}
return false;
}
private void recoverBluetoothServiceFromError() {
- Log.e(TAG,"recoverBluetoothServiceFromError");
+ Slog.e(TAG,"recoverBluetoothServiceFromError");
synchronized (mConnection) {
if (mBluetooth != null) {
//Unregister callback object
try {
mBluetooth.unregisterCallback(mBluetoothCallback);
} catch (RemoteException re) {
- Log.e(TAG, "Unable to unregister",re);
+ Slog.e(TAG, "Unable to unregister",re);
}
}
}
@@ -1671,16 +1689,23 @@
}
@Override
- public void dump(FileDescriptor fd, PrintWriter writer, String args[]) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
- if (mBluetoothBinder == null) {
- writer.println("Bluetooth Service not connected");
- } else {
- try {
- mBluetoothBinder.dump(fd, args);
- } catch (RemoteException re) {
- writer.println("RemoteException while calling Bluetooth Service");
+ public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+ String errorMsg = null;
+ if (mBluetoothBinder == null) {
+ errorMsg = "Bluetooth Service not connected";
+ } else {
+ try {
+ mBluetoothBinder.dump(fd, args);
+ } catch (RemoteException re) {
+ errorMsg = "RemoteException while calling Bluetooth Service";
+ }
}
- }
+ if (errorMsg != null) {
+ // Silently return if we are extracting metrics in Protobuf format
+ if ((args.length > 0) && args[0].startsWith("--proto"))
+ return;
+ writer.println(errorMsg);
+ }
}
}
diff --git a/services/core/java/com/android/server/BluetoothService.java b/services/core/java/com/android/server/BluetoothService.java
index 019d03d..1bf4e3a 100644
--- a/services/core/java/com/android/server/BluetoothService.java
+++ b/services/core/java/com/android/server/BluetoothService.java
@@ -18,10 +18,8 @@
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
-import android.util.Log;
class BluetoothService extends SystemService {
- private static final String TAG = "BluetoothService";
private BluetoothManagerService mBluetoothManagerService;
public BluetoothService(Context context) {
@@ -36,17 +34,20 @@
@Override
public void onBootPhase(int phase) {
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
- Log.d(TAG, "onBootPhase: PHASE_SYSTEM_SERVICES_READY");
- publishBinderService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, mBluetoothManagerService);
+ publishBinderService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE,
+ mBluetoothManagerService);
} else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
- Log.d(TAG, "onBootPhase: PHASE_ACTIVITY_MANAGER_READY");
mBluetoothManagerService.handleOnBootPhase();
}
}
@Override
public void onSwitchUser(int userHandle) {
- Log.d(TAG, "onSwitchUser: switching to user " + userHandle);
mBluetoothManagerService.handleOnSwitchUser(userHandle);
}
+
+ @Override
+ public void onUnlockUser(int userHandle) {
+ mBluetoothManagerService.handleOnUnlockUser(userHandle);
+ }
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 4300920..86040c2 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -125,6 +125,7 @@
import com.android.server.connectivity.NetworkMonitor;
import com.android.server.connectivity.PacManager;
import com.android.server.connectivity.PermissionMonitor;
+import com.android.server.connectivity.ApfFilter;
import com.android.server.connectivity.Tethering;
import com.android.server.connectivity.Vpn;
import com.android.server.net.BaseNetworkObserver;
@@ -163,7 +164,7 @@
implements PendingIntent.OnFinished {
private static final String TAG = "ConnectivityService";
- private static final boolean DBG = true;
+ private static final boolean DBG = false;
private static final boolean VDBG = false;
private static final boolean LOGD_RULES = false;
@@ -353,6 +354,13 @@
*/
private static final int EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT = 31;
+ /**
+ * used to push APF program to NetworkAgent
+ * replyTo = NetworkAgent message handler
+ * obj = byte[] of APF program
+ */
+ private static final int EVENT_PUSH_APF_PROGRAM_TO_NETWORK = 32;
+
/** Handler thread used for both of the handlers below. */
@VisibleForTesting
protected final HandlerThread mHandlerThread;
@@ -447,7 +455,7 @@
*/
private class LegacyTypeTracker {
- private static final boolean DBG = true;
+ private static final boolean DBG = false;
private static final boolean VDBG = false;
private static final String TAG = "CSLegacyTypeTracker";
@@ -750,7 +758,7 @@
intentFilter.addAction(Intent.ACTION_USER_STOPPING);
intentFilter.addAction(Intent.ACTION_USER_ADDED);
intentFilter.addAction(Intent.ACTION_USER_REMOVED);
- intentFilter.addAction(Intent.ACTION_USER_PRESENT);
+ intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
mContext.registerReceiverAsUser(
mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null);
@@ -2190,6 +2198,7 @@
mKeepaliveTracker.handleStopAllKeepalives(nai,
ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK);
nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_DISCONNECTED);
+ if (nai.apfFilter != null) nai.apfFilter.shutdown();
mNetworkAgentInfos.remove(msg.replyTo);
updateClat(null, nai.linkProperties, nai);
synchronized (mNetworkForNetId) {
@@ -2404,6 +2413,13 @@
accept ? 1 : 0, always ? 1: 0, network));
}
+ public void pushApfProgramToNetwork(NetworkAgentInfo nai, byte[] program) {
+ enforceConnectivityInternalPermission();
+ Message msg = mHandler.obtainMessage(EVENT_PUSH_APF_PROGRAM_TO_NETWORK, program);
+ msg.replyTo = nai.messenger;
+ mHandler.sendMessage(msg);
+ }
+
private void handleSetAcceptUnvalidated(Network network, boolean accept, boolean always) {
if (DBG) log("handleSetAcceptUnvalidated network=" + network +
" accept=" + accept + " always=" + always);
@@ -2553,6 +2569,16 @@
handleMobileDataAlwaysOn();
break;
}
+ case EVENT_PUSH_APF_PROGRAM_TO_NETWORK: {
+ NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
+ if (nai == null) {
+ loge("EVENT_PUSH_APF_PROGRAM_TO_NETWORK from unknown NetworkAgent");
+ } else {
+ nai.asyncChannel.sendMessage(NetworkAgent.CMD_PUSH_APF_PROGRAM,
+ (byte[]) msg.obj);
+ }
+ break;
+ }
// Sent by KeepaliveTracker to process an app request on the state machine thread.
case NetworkAgent.CMD_START_PACKET_KEEPALIVE: {
mKeepaliveTracker.handleStartKeepalive(msg);
@@ -3633,7 +3659,7 @@
}
}
- private void onUserPresent(int userId) {
+ private void onUserUnlocked(int userId) {
// User present may be sent because of an unlock, which might mean an unlocked keystore.
if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
updateLockdownVpn();
@@ -3657,8 +3683,8 @@
onUserAdded(userId);
} else if (Intent.ACTION_USER_REMOVED.equals(action)) {
onUserRemoved(userId);
- } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
- onUserPresent(userId);
+ } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
+ onUserUnlocked(userId);
}
}
};
@@ -4068,6 +4094,9 @@
if (networkAgent.clatd != null) {
networkAgent.clatd.fixupLinkProperties(oldLp);
}
+ if (networkAgent.apfFilter != null) {
+ networkAgent.apfFilter.updateFilter();
+ }
updateInterfaces(newLp, oldLp, netId);
updateMtu(newLp, oldLp);
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 6c19c38..62fa7d5 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -132,7 +132,8 @@
private Intent mLightIdleIntent;
private Display mCurDisplay;
private AnyMotionDetector mAnyMotionDetector;
- private boolean mEnabled;
+ private boolean mLightEnabled;
+ private boolean mDeepEnabled;
private boolean mForceIdle;
private boolean mScreenOn;
private boolean mCharging;
@@ -179,7 +180,7 @@
private static final int LIGHT_STATE_IDLE = 2;
/** Device is in the light idle state, but temporarily out of idle to do regular maintenance. */
private static final int LIGHT_STATE_IDLE_MAINTENANCE = 3;
- /** Device light idle state is overriden, now applying full doze state. */
+ /** Device light idle state is overriden, now applying deep doze state. */
private static final int LIGHT_STATE_OVERRIDE = 4;
private static String lightStateToString(int state) {
switch (state) {
@@ -288,8 +289,8 @@
private static final int EVENT_NORMAL = 1;
private static final int EVENT_LIGHT_IDLE = 2;
private static final int EVENT_LIGHT_MAINTENANCE = 3;
- private static final int EVENT_FULL_IDLE = 4;
- private static final int EVENT_FULL_MAINTENANCE = 5;
+ private static final int EVENT_DEEP_IDLE = 4;
+ private static final int EVENT_DEEP_MAINTENANCE = 5;
private int[] mEventCmds = new int[EVENT_BUFFER_SIZE];
private long[] mEventTimes = new long[EVENT_BUFFER_SIZE];
@@ -835,13 +836,13 @@
case MSG_REPORT_IDLE_ON:
case MSG_REPORT_IDLE_ON_LIGHT: {
EventLogTags.writeDeviceIdleOnStart();
- final boolean fullChanged;
+ final boolean deepChanged;
final boolean lightChanged;
if (msg.what == MSG_REPORT_IDLE_ON) {
- fullChanged = mLocalPowerManager.setDeviceIdleMode(true);
+ deepChanged = mLocalPowerManager.setDeviceIdleMode(true);
lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
} else {
- fullChanged = mLocalPowerManager.setDeviceIdleMode(false);
+ deepChanged = mLocalPowerManager.setDeviceIdleMode(false);
lightChanged = mLocalPowerManager.setLightDeviceIdleMode(true);
}
try {
@@ -851,7 +852,7 @@
: BatteryStats.DEVICE_IDLE_MODE_LIGHT, null, Process.myUid());
} catch (RemoteException e) {
}
- if (fullChanged) {
+ if (deepChanged) {
getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
}
if (lightChanged) {
@@ -861,7 +862,7 @@
} break;
case MSG_REPORT_IDLE_OFF: {
EventLogTags.writeDeviceIdleOffStart("unknown");
- final boolean fullChanged = mLocalPowerManager.setDeviceIdleMode(false);
+ final boolean deepChanged = mLocalPowerManager.setDeviceIdleMode(false);
final boolean lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
try {
mNetworkPolicyManager.setDeviceIdleMode(false);
@@ -869,7 +870,7 @@
null, Process.myUid());
} catch (RemoteException e) {
}
- if (fullChanged) {
+ if (deepChanged) {
incActiveIdleOps();
getContext().sendOrderedBroadcastAsUser(mIdleIntent, UserHandle.ALL,
null, mIdleStartedDoneReceiver, null, 0, null, null);
@@ -889,7 +890,7 @@
int activeUid = msg.arg1;
EventLogTags.writeDeviceIdleOffStart(
activeReason != null ? activeReason : "unknown");
- final boolean fullChanged = mLocalPowerManager.setDeviceIdleMode(false);
+ final boolean deepChanged = mLocalPowerManager.setDeviceIdleMode(false);
final boolean lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
try {
mNetworkPolicyManager.setDeviceIdleMode(false);
@@ -897,7 +898,7 @@
activeReason, activeUid);
} catch (RemoteException e) {
}
- if (fullChanged) {
+ if (deepChanged) {
getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
}
if (lightChanged) {
@@ -1102,7 +1103,7 @@
final PackageManager pm = getContext().getPackageManager();
synchronized (this) {
- mEnabled = getContext().getResources().getBoolean(
+ mLightEnabled = mDeepEnabled = getContext().getResources().getBoolean(
com.android.internal.R.bool.config_enableAutoPowerModes);
SystemConfig sysConfig = SystemConfig.getInstance();
ArraySet<String> allowPowerExceptIdle = sysConfig.getAllowInPowerSaveExceptIdle();
@@ -1550,17 +1551,17 @@
void becomeInactiveIfAppropriateLocked() {
if (DEBUG) Slog.d(TAG, "becomeInactiveIfAppropriateLocked()");
- if (((!mScreenOn && !mCharging) || mForceIdle) && mEnabled) {
+ if ((!mScreenOn && !mCharging) || mForceIdle) {
// Screen has turned off; we are now going to become inactive and start
// waiting to see if we will ultimately go idle.
- if (mState == STATE_ACTIVE) {
+ if (mState == STATE_ACTIVE && mDeepEnabled) {
mState = STATE_INACTIVE;
if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE");
resetIdleManagementLocked();
scheduleAlarmLocked(mInactiveTimeout, false);
EventLogTags.writeDeviceIdle(mState, "no activity");
}
- if (mLightState == LIGHT_STATE_ACTIVE) {
+ if (mLightState == LIGHT_STATE_ACTIVE && mLightEnabled) {
mLightState = LIGHT_STATE_INACTIVE;
if (DEBUG) Slog.d(TAG, "Moved from LIGHT_STATE_ACTIVE to LIGHT_STATE_INACTIVE");
resetLightIdleManagementLocked();
@@ -1594,7 +1595,7 @@
void stepLightIdleStateLocked(String reason) {
if (mLightState == LIGHT_STATE_OVERRIDE) {
- // If we are already in full device idle mode, then
+ // If we are already in deep device idle mode, then
// there is nothing left to do for light mode.
return;
}
@@ -1731,7 +1732,7 @@
cancelLightAlarmLocked();
}
EventLogTags.writeDeviceIdle(mState, reason);
- addEvent(EVENT_FULL_IDLE);
+ addEvent(EVENT_DEEP_IDLE);
mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);
break;
case STATE_IDLE:
@@ -1744,7 +1745,7 @@
(long)(mNextIdlePendingDelay * mConstants.IDLE_PENDING_FACTOR));
mState = STATE_IDLE_MAINTENANCE;
EventLogTags.writeDeviceIdle(mState, reason);
- addEvent(EVENT_FULL_MAINTENANCE);
+ addEvent(EVENT_DEEP_MAINTENANCE);
mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
break;
}
@@ -1877,7 +1878,7 @@
becomeInactive = true;
}
if (mLightState == LIGHT_STATE_OVERRIDE) {
- // We went out of light idle mode because we had started full idle mode... let's
+ // We went out of light idle mode because we had started deep idle mode... let's
// now go back and reset things so we resume light idling if appropriate.
mLightState = STATE_ACTIVE;
EventLogTags.writeDeviceIdleLight(mLightState, type);
@@ -2183,11 +2184,11 @@
pw.println(" force-idle");
pw.println(" Force directly into idle mode, regardless of other device state.");
pw.println(" Use \"step\" to get out.");
- pw.println(" disable");
+ pw.println(" disable [light|deep|all]");
pw.println(" Completely disable device idle mode.");
- pw.println(" enable");
+ pw.println(" enable [light|deep|all]");
pw.println(" Re-enable device idle mode after it had previously been disabled.");
- pw.println(" enabled");
+ pw.println(" enabled [light|deep|all]");
pw.println(" Print 1 if device idle mode is currently enabled, else 0.");
pw.println(" whitelist");
pw.println(" Print currently whitelisted apps.");
@@ -2247,7 +2248,7 @@
synchronized (this) {
long token = Binder.clearCallingIdentity();
try {
- if (!mEnabled) {
+ if (!mDeepEnabled) {
pw.println("Unable to go idle; not enabled");
return -1;
}
@@ -2274,11 +2275,32 @@
null);
synchronized (this) {
long token = Binder.clearCallingIdentity();
+ String arg = shell.getNextArg();
try {
- if (mEnabled) {
- mEnabled = false;
- becomeActiveLocked("disabled", Process.myUid());
- pw.println("Idle mode disabled");
+ boolean becomeActive = false;
+ boolean valid = false;
+ if (arg == null || "deep".equals(arg) || "all".equals(arg)) {
+ valid = true;
+ if (mDeepEnabled) {
+ mDeepEnabled = false;
+ becomeActive = true;
+ pw.println("Deep idle mode disabled");
+ }
+ }
+ if (arg == null || "light".equals(arg) || "all".equals(arg)) {
+ valid = true;
+ if (mLightEnabled) {
+ mLightEnabled = false;
+ becomeActive = true;
+ pw.println("Light idle mode disabled");
+ }
+ }
+ if (becomeActive) {
+ becomeActiveLocked((arg == null ? "all" : arg) + "-disabled",
+ Process.myUid());
+ }
+ if (!valid) {
+ pw.println("Unknown idle mode: " + arg);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -2289,12 +2311,31 @@
null);
synchronized (this) {
long token = Binder.clearCallingIdentity();
+ String arg = shell.getNextArg();
try {
- exitForceIdleLocked();
- if (!mEnabled) {
- mEnabled = true;
+ boolean becomeInactive = false;
+ boolean valid = false;
+ if (arg == null || "deep".equals(arg) || "all".equals(arg)) {
+ valid = true;
+ if (!mDeepEnabled) {
+ mDeepEnabled = true;
+ becomeInactive = true;
+ pw.println("Deep idle mode enabled");
+ }
+ }
+ if (arg == null || "light".equals(arg) || "all".equals(arg)) {
+ valid = true;
+ if (!mLightEnabled) {
+ mLightEnabled = true;
+ becomeInactive = true;
+ pw.println("Light idle mode enable");
+ }
+ }
+ if (becomeInactive) {
becomeInactiveIfAppropriateLocked();
- pw.println("Idle mode enabled");
+ }
+ if (!valid) {
+ pw.println("Unknown idle mode: " + arg);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -2302,7 +2343,16 @@
}
} else if ("enabled".equals(cmd)) {
synchronized (this) {
- pw.println(mEnabled ? "1" : " 0");
+ String arg = shell.getNextArg();
+ if (arg == null || "all".equals(arg)) {
+ pw.println(mDeepEnabled && mLightEnabled ? "1" : 0);
+ } else if ("deep".equals(arg)) {
+ pw.println(mDeepEnabled ? "1" : 0);
+ } else if ("light".equals(arg)) {
+ pw.println(mLightEnabled ? "1" : 0);
+ } else {
+ pw.println("Unknown idle mode: " + arg);
+ }
}
} else if ("whitelist".equals(cmd)) {
long token = Binder.clearCallingIdentity();
@@ -2441,8 +2491,8 @@
case EVENT_NORMAL: label = " normal"; break;
case EVENT_LIGHT_IDLE: label = " light-idle"; break;
case EVENT_LIGHT_MAINTENANCE: label = "light-maint"; break;
- case EVENT_FULL_IDLE: label = " full-idle"; break;
- case EVENT_FULL_MAINTENANCE: label = " full-maint"; break;
+ case EVENT_DEEP_IDLE: label = " deep-idle"; break;
+ case EVENT_DEEP_MAINTENANCE: label = " deep-maint"; break;
default: label = " ??"; break;
}
pw.print(" ");
@@ -2519,7 +2569,8 @@
}
}
- pw.print(" mEnabled="); pw.println(mEnabled);
+ pw.print(" mLightEnabled="); pw.print(mLightEnabled);
+ pw.print(" mDeepEnabled="); pw.println(mDeepEnabled);
pw.print(" mForceIdle="); pw.println(mForceIdle);
pw.print(" mMotionSensor="); pw.println(mMotionSensor);
pw.print(" mCurDisplay="); pw.println(mCurDisplay);
diff --git a/services/core/java/com/android/server/HardwarePropertiesManagerService.java b/services/core/java/com/android/server/HardwarePropertiesManagerService.java
new file mode 100644
index 0000000..cc21e99
--- /dev/null
+++ b/services/core/java/com/android/server/HardwarePropertiesManagerService.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Binder;
+import android.os.CpuUsageInfo;
+import android.os.IHardwarePropertiesManager;
+
+import java.util.Arrays;
+
+/**
+ * Service for {@link HardwarePropertiesManager}
+ */
+public class HardwarePropertiesManagerService extends IHardwarePropertiesManager.Stub {
+
+ private static native void nativeInit();
+
+ private static native float[] nativeGetFanSpeeds();
+ private static native float[] nativeGetDeviceTemperatures(int type);
+ private static native CpuUsageInfo[] nativeGetCpuUsages();
+
+ private final Context mContext;
+ private final Object mLock = new Object();
+
+ public HardwarePropertiesManagerService(Context context) {
+ mContext = context;
+ synchronized (mLock) {
+ nativeInit();
+ }
+ }
+
+ @Override
+ public float[] getDeviceTemperatures(String callingPackage, int type) throws SecurityException {
+ enforceHardwarePropertiesRetrievalAllowed(callingPackage);
+ synchronized (mLock) {
+ return nativeGetDeviceTemperatures(type);
+ }
+ }
+
+ @Override
+ public CpuUsageInfo[] getCpuUsages(String callingPackage) throws SecurityException {
+ enforceHardwarePropertiesRetrievalAllowed(callingPackage);
+ synchronized (mLock) {
+ return nativeGetCpuUsages();
+ }
+ }
+
+ @Override
+ public float[] getFanSpeeds(String callingPackage) throws SecurityException {
+ enforceHardwarePropertiesRetrievalAllowed(callingPackage);
+ synchronized (mLock) {
+ return nativeGetFanSpeeds();
+ }
+ }
+
+ /**
+ * Throws SecurityException if the calling package is not allowed to retrieve information
+ * provided by the service.
+ *
+ * @param callingPackage The calling package name.
+ *
+ * @throws SecurityException if a non profile or device owner tries to retrieve information
+ * provided by the service.
+ */
+ private void enforceHardwarePropertiesRetrievalAllowed(String callingPackage)
+ throws SecurityException {
+ final PackageManager pm = mContext.getPackageManager();
+ try {
+ final int uid = pm.getPackageUid(callingPackage, 0);
+ if (Binder.getCallingUid() != uid) {
+ throw new SecurityException("The caller has faked the package name.");
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new SecurityException("The caller has faked the package name.");
+ }
+
+ final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
+ if (!dpm.isDeviceOwnerApp(callingPackage) && !dpm.isProfileOwnerApp(callingPackage)) {
+ throw new SecurityException("The caller is not a device or profile owner.");
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 507ac22..3b6c62b 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -61,7 +61,6 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
@@ -96,6 +95,7 @@
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.EventLog;
+import android.util.LocaleList;
import android.util.LruCache;
import android.util.Pair;
import android.util.PrintWriterPrinter;
@@ -136,7 +136,6 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
-import java.util.Locale;
/**
* This class provides a system service that manages input methods.
@@ -190,6 +189,7 @@
private InputMethodFileManager mFileManager;
private final HardKeyboardListener mHardKeyboardListener;
private final AppOpsManager mAppOpsManager;
+ private final UserManager mUserManager;
final InputBindResult mNoBinding = new InputBindResult(null, null, null, -1, -1);
@@ -446,7 +446,7 @@
private View mSwitchingDialogTitleView;
private InputMethodInfo[] mIms;
private int[] mSubtypeIds;
- private Locale mLastSystemLocale;
+ private LocaleList mLastSystemLocales;
private boolean mShowImeWithHardKeyboard;
private boolean mAccessibilityRequestingNoSoftKeyboard;
private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor();
@@ -781,6 +781,27 @@
mService.systemRunning(statusBarService);
}
}
+
+ @Override
+ public void onUnlockUser(int userHandle) {
+ mService.onUnlockUser(userHandle);
+ }
+ }
+
+ public void onUnlockUser(int userId) {
+ synchronized(mMethodMap) {
+ final int currentUserId = mSettings.getCurrentUserId();
+ if (DEBUG) {
+ Slog.d(TAG, "onUnlockUser: userId=" + userId + " curUserId=" + currentUserId);
+ }
+ if (userId != currentUserId) {
+ return;
+ }
+ mSettings.switchCurrentUser(currentUserId, !mSystemReady);
+ // We need to rebuild IMEs.
+ buildInputMethodListLocked(false /* resetDefaultEnabledIme */);
+ updateInputMethodsFromSettingsLocked(true /* enabledChanged */);
+ }
}
public InputMethodManagerService(Context context) {
@@ -800,6 +821,7 @@
}
}, true /*asyncHandler*/);
mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
+ mUserManager = mContext.getSystemService(UserManager.class);
mHardKeyboardListener = new HardKeyboardListener();
mHasFeature = context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_INPUT_METHODS);
@@ -859,39 +881,6 @@
mSettings = new InputMethodSettings(
mRes, context.getContentResolver(), mMethodMap, mMethodList, userId, !mSystemReady);
- // Let the package manager query which are the default imes
- // as they get certain permissions granted by default.
- PackageManagerInternal packageManagerInternal = LocalServices.getService(
- PackageManagerInternal.class);
- packageManagerInternal.setImePackagesProvider(
- new PackageManagerInternal.PackagesProvider() {
- @Override
- public String[] getPackages(int userId) {
- synchronized (mMethodMap) {
- final int currentUserId = mSettings.getCurrentUserId();
- // TODO: We are switching the current user id in the settings
- // object to query it and then revert the user id. Ideally, we
- // should call a API in settings with the user id as an argument.
- mSettings.switchCurrentUser(userId, true /* copyOnWrite */);
- List<InputMethodInfo> imes = mSettings
- .getEnabledInputMethodListLocked();
- String[] packageNames = null;
- if (imes != null) {
- final int imeCount = imes.size();
- packageNames = new String[imeCount];
- for (int i = 0; i < imeCount; i++) {
- InputMethodInfo ime = imes.get(i);
- packageNames[i] = ime.getPackageName();
- }
- }
- // If the system is not ready, then we use copy-on-write mode.
- final boolean useCopyOnWriteSettings = !mSystemReady;
- mSettings.switchCurrentUser(currentUserId, useCopyOnWriteSettings);
- return packageNames;
- }
- }
- });
-
updateCurrentProfileIds();
mFileManager = new InputMethodFileManager(mMethodMap, userId);
synchronized (mMethodMap) {
@@ -960,15 +949,15 @@
// not system ready
return;
}
- final Locale newLocale = mRes.getConfiguration().locale;
+ final LocaleList newLocales = mRes.getConfiguration().getLocales();
if (!updateOnlyWhenLocaleChanged
- || (newLocale != null && !newLocale.equals(mLastSystemLocale))) {
+ || (newLocales != null && !newLocales.equals(mLastSystemLocales))) {
if (!updateOnlyWhenLocaleChanged) {
hideCurrentInputLocked(0, null);
resetCurrentMethodAndClient(InputMethodClient.UNBIND_REASON_RESET_IME);
}
if (DEBUG) {
- Slog.i(TAG, "Locale has been changed to " + newLocale);
+ Slog.i(TAG, "LocaleList has been changed to " + newLocales);
}
buildInputMethodListLocked(resetDefaultEnabledIme);
if (!updateOnlyWhenLocaleChanged) {
@@ -983,7 +972,7 @@
resetDefaultImeLocked(mContext);
}
updateFromSettingsLocked(true);
- mLastSystemLocale = newLocale;
+ mLastSystemLocales = newLocales;
if (!updateOnlyWhenLocaleChanged) {
try {
startInputInnerLocked();
@@ -1006,8 +995,10 @@
// ContentObserver should be registered again when the user is changed
mSettingsObserver.registerContentObserverLocked(newUserId);
- // If the system is not ready, then we use copy-on-write settings.
- final boolean useCopyOnWriteSettings = !mSystemReady;
+ // If the system is not ready or the device is not yed unlocked by the user, then we use
+ // copy-on-write settings.
+ final boolean useCopyOnWriteSettings =
+ !mSystemReady || !mUserManager.isUserUnlocked(newUserId);
mSettings.switchCurrentUser(newUserId, useCopyOnWriteSettings);
updateCurrentProfileIds();
// InputMethodFileManager should be reset when the user is changed
@@ -1036,8 +1027,7 @@
}
void updateCurrentProfileIds() {
- List<UserInfo> profiles = mContext.getSystemService(UserManager.class)
- .getProfiles(mSettings.getCurrentUserId());
+ List<UserInfo> profiles = mUserManager.getProfiles(mSettings.getCurrentUserId());
int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null
for (int i = 0; i < currentProfileIds.length; i++) {
currentProfileIds[i] = profiles.get(i).id;
@@ -1068,7 +1058,8 @@
if (!mSystemReady) {
mSystemReady = true;
final int currentUserId = mSettings.getCurrentUserId();
- mSettings.switchCurrentUser(currentUserId, false /* copyOnWrite */);
+ mSettings.switchCurrentUser(currentUserId,
+ !mUserManager.isUserUnlocked(currentUserId));
mKeyguardManager = mContext.getSystemService(KeyguardManager.class);
mNotificationManager = mContext.getSystemService(NotificationManager.class);
mStatusBar = statusBar;
@@ -1088,7 +1079,7 @@
mSettings.getEnabledInputMethodListLocked(),
mSettings.getCurrentUserId(), mContext.getBasePackageName());
}
- mLastSystemLocale = mRes.getConfiguration().locale;
+ mLastSystemLocales = mRes.getConfiguration().getLocales();
try {
startInputInnerLocked();
} catch (RuntimeException e) {
@@ -1467,8 +1458,7 @@
return null;
}
- @Override
- public InputBindResult startInput(
+ private InputBindResult startInput(
/* @InputMethodClient.StartInputReason */ final int startInputReason,
IInputMethodClient client, IInputContext inputContext, EditorInfo attribute,
int controlFlags) {
@@ -1970,14 +1960,6 @@
throw new IllegalArgumentException("Unknown id: " + id);
}
- if (mCurClient != null && mCurAttribute != null) {
- // We have already made sure that the package name belongs to the application's UID.
- // No further UID check is required.
- if (SystemConfig.getInstance().getFixedImeApps().contains(mCurAttribute.packageName)) {
- return;
- }
- }
-
// See if we need to notify a subtype change within the same IME.
if (id.equals(mCurMethodId)) {
final int subtypeCount = info.getSubtypeCount();
@@ -2206,7 +2188,19 @@
}
@Override
- public InputBindResult windowGainedFocus(
+ public InputBindResult startInputOrWindowGainedFocus(
+ /* @InputMethodClient.StartInputReason */ final int startInputReason,
+ IInputMethodClient client, IBinder windowToken, int controlFlags, int softInputMode,
+ int windowFlags, EditorInfo attribute, IInputContext inputContext) {
+ if (windowToken != null) {
+ return windowGainedFocus(startInputReason, client, windowToken, controlFlags,
+ softInputMode, windowFlags, attribute, inputContext);
+ } else {
+ return startInput(startInputReason, client, inputContext, attribute, controlFlags);
+ }
+ }
+
+ private InputBindResult windowGainedFocus(
/* @InputMethodClient.StartInputReason */ final int startInputReason,
IInputMethodClient client, IBinder windowToken, int controlFlags, int softInputMode,
int windowFlags, EditorInfo attribute, IInputContext inputContext) {
@@ -2952,6 +2946,9 @@
// Use for queryIntentServicesAsUser
final PackageManager pm = mContext.getPackageManager();
+ // Note: We do not specify PackageManager.MATCH_ENCRYPTION_* flags here because the default
+ // behavior of PackageManager is exactly what we want. It by default picks up appropriate
+ // services depending on the unlock state for the specified user.
final List<ResolveInfo> services = pm.queryIntentServicesAsUser(
new Intent(InputMethod.SERVICE_INTERFACE),
PackageManager.GET_META_DATA | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 14ddc36..9884a70 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -214,7 +214,7 @@
private int mCurrentUserId = UserHandle.USER_SYSTEM;
private int[] mCurrentUserProfiles = new int[] { UserHandle.USER_SYSTEM };
- private GnssLocationProvider.GpsSystemInfoProvider mGpsSystemInfoProvider;
+ private GnssLocationProvider.GnssSystemInfoProvider mGnssSystemInfoProvider;
public LocationManagerService(Context context) {
super();
@@ -462,7 +462,7 @@
// Create a gps location provider
GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext, this,
mLocationHandler.getLooper());
- mGpsSystemInfoProvider = gnssProvider.getGpsSystemInfoProvider();
+ mGnssSystemInfoProvider = gnssProvider.getGnssSystemInfoProvider();
mGnssStatusProvider = gnssProvider.getGnssStatusProvider();
mNetInitiatedListener = gnssProvider.getNetInitiatedListener();
addProviderLocked(gnssProvider);
@@ -990,12 +990,12 @@
}
/**
- * Returns the system information of the GPS hardware.
+ * Returns the system information of the GNSS hardware.
*/
@Override
- public int getGpsYearOfHardware() {
+ public int getGnssYearOfHardware() {
if (mGnssNavigationMessageProvider != null) {
- return mGpsSystemInfoProvider.getGpsYearOfHardware();
+ return mGnssSystemInfoProvider.getGnssYearOfHardware();
} else {
return 0;
}
diff --git a/services/core/java/com/android/server/LockGuard.java b/services/core/java/com/android/server/LockGuard.java
new file mode 100644
index 0000000..3a381ae
--- /dev/null
+++ b/services/core/java/com/android/server/LockGuard.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Slog;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * LockGuard is a mechanism to help detect lock inversions inside the system
+ * server. It works by requiring each lock acquisition site to follow this
+ * pattern:
+ *
+ * <pre>
+ * synchronized (LockGuard.guard(lock)) {
+ * }
+ * </pre>
+ *
+ * <pre>
+ * $ find services/ -name "*.java" -exec sed -i -r \
+ * 's/synchronized.?\((.+?)\)/synchronized \(com.android.server.LockGuard.guard\(\1\)\)/' {} \;
+ * </pre>
+ *
+ * The {@link #guard(Object)} method internally verifies that all locking is
+ * done in a consistent order, and will log if any inversion is detected. For
+ * example, if the calling thread is trying to acquire the
+ * {@code ActivityManager} lock while holding the {@code PackageManager} lock,
+ * it will yell.
+ * <p>
+ * This class requires no prior knowledge of locks or their ordering; it derives
+ * all of this data at runtime. However, this means the overhead is
+ * <em>substantial</em> and it should not be enabled by default. For example,
+ * here are some benchmarked timings:
+ * <ul>
+ * <li>An unguarded synchronized block takes 40ns.
+ * <li>A guarded synchronized block takes 50ns when disabled.
+ * <li>A guarded synchronized block takes 460ns per lock checked when enabled.
+ * </ul>
+ */
+public class LockGuard {
+ private static final String TAG = "LockGuard";
+
+ private static ArrayMap<Object, LockInfo> sKnown = new ArrayMap<>(0, true);
+
+ private static class LockInfo {
+ /** Friendly label to describe this lock */
+ public String label;
+
+ /** Child locks that can be acquired while this lock is already held */
+ public ArraySet<Object> children = new ArraySet<>(0, true);
+ }
+
+ private static LockInfo findOrCreateLockInfo(Object lock) {
+ LockInfo info = sKnown.get(lock);
+ if (info == null) {
+ info = new LockInfo();
+ info.label = "0x" + Integer.toHexString(System.identityHashCode(lock)) + " ["
+ + new Throwable().getStackTrace()[2].toString() + "]";
+ sKnown.put(lock, info);
+ }
+ return info;
+ }
+
+ /**
+ * Check if the calling thread is holding any locks in an inverted order.
+ *
+ * @param lock The lock the calling thread is attempting to acquire.
+ */
+ public static Object guard(Object lock) {
+ // If we already hold this lock, ignore
+ if (lock == null || Thread.holdsLock(lock)) return lock;
+
+ // Check to see if we're already holding any child locks
+ boolean triggered = false;
+ final LockInfo info = findOrCreateLockInfo(lock);
+ for (int i = 0; i < info.children.size(); i++) {
+ final Object child = info.children.valueAt(i);
+ if (child == null) continue;
+
+ if (Thread.holdsLock(child)) {
+ Slog.w(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding "
+ + lockToString(child) + " while trying to acquire "
+ + lockToString(lock), new Throwable());
+ triggered = true;
+ }
+ }
+
+ if (!triggered) {
+ // If no trouble found above, record this lock as being a valid
+ // child of all locks currently being held
+ for (int i = 0; i < sKnown.size(); i++) {
+ final Object test = sKnown.keyAt(i);
+ if (test == null || test == lock) continue;
+
+ if (Thread.holdsLock(test)) {
+ sKnown.valueAt(i).children.add(lock);
+ }
+ }
+ }
+
+ return lock;
+ }
+
+ /**
+ * Report the given lock with a well-known label.
+ */
+ public static void installLock(Object lock, String label) {
+ final LockInfo info = findOrCreateLockInfo(lock);
+ info.label = label;
+ }
+
+ private static String lockToString(Object lock) {
+ final LockInfo info = sKnown.get(lock);
+ if (info != null) {
+ return info.label;
+ } else {
+ return "0x" + Integer.toHexString(System.identityHashCode(lock));
+ }
+ }
+
+ public static void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ for (int i = 0; i < sKnown.size(); i++) {
+ final Object lock = sKnown.keyAt(i);
+ final LockInfo info = sKnown.valueAt(i);
+ pw.println("Lock " + lockToString(lock) + ":");
+ for (int j = 0; j < info.children.size(); j++) {
+ pw.println(" Child " + lockToString(info.children.valueAt(j)));
+ }
+ pw.println();
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index c318140..6fb0671 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -345,9 +345,9 @@
final int userId = users.get(user).id;
final String OWNER_INFO = Secure.LOCK_SCREEN_OWNER_INFO;
String ownerInfo = Settings.Secure.getStringForUser(cr, OWNER_INFO, userId);
- if (ownerInfo != null) {
+ if (!TextUtils.isEmpty(ownerInfo)) {
setString(OWNER_INFO, ownerInfo, userId);
- Settings.Secure.putStringForUser(cr, ownerInfo, "", userId);
+ Settings.Secure.putStringForUser(cr, OWNER_INFO, "", userId);
}
// Migrate owner info enabled. Note there was a bug where older platforms only
@@ -545,9 +545,23 @@
final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
final KeyStore ks = KeyStore.getInstance();
- final List<UserInfo> profiles = um.getProfiles(userHandle);
- for (UserInfo pi : profiles) {
- ks.onUserPasswordChanged(pi.id, password);
+ if (um.getUserInfo(userHandle).isManagedProfile()) {
+ if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle)) {
+ ks.onUserPasswordChanged(userHandle, password);
+ } else {
+ throw new RuntimeException("Can't set keystore password on a profile that "
+ + "doesn't have a profile challenge.");
+ }
+ } else {
+ final List<UserInfo> profiles = um.getProfiles(userHandle);
+ for (UserInfo pi : profiles) {
+ // Change password on the given user and all its profiles that don't have
+ // their own profile challenge enabled.
+ if (pi.id == userHandle || (pi.isManagedProfile()
+ && !mLockPatternUtils.isSeparateProfileChallengeEnabled(pi.id))) {
+ ks.onUserPasswordChanged(pi.id, password);
+ }
+ }
}
}
@@ -555,9 +569,23 @@
final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
final KeyStore ks = KeyStore.getInstance();
- final List<UserInfo> profiles = um.getProfiles(userHandle);
- for (UserInfo pi : profiles) {
- ks.unlock(pi.id, password);
+ if (um.getUserInfo(userHandle).isManagedProfile()) {
+ if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle)) {
+ ks.unlock(userHandle, password);
+ } else {
+ throw new RuntimeException("Can't unlock a profile explicitly if it "
+ + "doesn't have a profile challenge.");
+ }
+ } else {
+ final List<UserInfo> profiles = um.getProfiles(userHandle);
+ for (UserInfo pi : profiles) {
+ // Unlock the given user and all its profiles that don't have
+ // their own profile challenge enabled.
+ if (pi.id == userHandle || (pi.isManagedProfile()
+ && !mLockPatternUtils.isSeparateProfileChallengeEnabled(pi.id))) {
+ ks.unlock(pi.id, password);
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 53923ba..a3322fc 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -1945,11 +1945,16 @@
"Emulation not available on device with native FBE");
}
- final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0;
- SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ final boolean emulateFbe = (flags & StorageManager.DEBUG_EMULATE_FBE) != 0;
+ SystemProperties.set(StorageManager.PROP_EMULATE_FBE, Boolean.toString(emulateFbe));
- // Perform hard reboot to kick policy into place
- mContext.getSystemService(PowerManager.class).reboot(null);
+ // Perform hard reboot to kick policy into place
+ mContext.getSystemService(PowerManager.class).reboot(null);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
if ((mask & StorageManager.DEBUG_FORCE_ADOPTABLE) != 0) {
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 799d0bd..329f716 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -22,8 +22,10 @@
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_NONE;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NONE;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_POWERSAVE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
import static android.net.NetworkPolicyManager.FIREWALL_TYPE_BLACKLIST;
@@ -43,7 +45,6 @@
import static com.android.server.NetworkManagementService.NetdResponseCode.TetheringStatsListResult;
import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult;
import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
-
import android.annotation.NonNull;
import android.app.ActivityManagerNative;
import android.content.Context;
@@ -226,6 +227,12 @@
*/
@GuardedBy("mQuotaLock")
private SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
+ /**
+ * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches
+ * to device on power-save mode.
+ */
+ @GuardedBy("mQuotaLock")
+ private SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
/** Set of states for the child firewall chains. True if the chain is active. */
@GuardedBy("mQuotaLock")
final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
@@ -286,8 +293,8 @@
Watchdog.getInstance().addMonitor(this);
}
- static NetworkManagementService create(Context context,
- String socket) throws InterruptedException {
+ static NetworkManagementService create(Context context, String socket)
+ throws InterruptedException {
final NetworkManagementService service = new NetworkManagementService(context, socket);
final CountDownLatch connectedSignal = service.mConnectedSignal;
if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
@@ -303,8 +310,15 @@
}
public void systemReady() {
- prepareNativeDaemon();
- if (DBG) Slog.d(TAG, "Prepared");
+ if (DBG) {
+ final long start = System.currentTimeMillis();
+ prepareNativeDaemon();
+ final long delta = System.currentTimeMillis() - start;
+ Slog.d(TAG, "Prepared in " + delta + "ms");
+ return;
+ } else {
+ prepareNativeDaemon();
+ }
}
private IBatteryStats getBatteryStats() {
@@ -339,8 +353,7 @@
for (int i = 0; i < length; i++) {
try {
mObservers.getBroadcastItem(i).interfaceStatusChanged(iface, up);
- } catch (RemoteException e) {
- } catch (RuntimeException e) {
+ } catch (RemoteException | RuntimeException e) {
}
}
} finally {
@@ -358,8 +371,7 @@
for (int i = 0; i < length; i++) {
try {
mObservers.getBroadcastItem(i).interfaceLinkStateChanged(iface, up);
- } catch (RemoteException e) {
- } catch (RuntimeException e) {
+ } catch (RemoteException | RuntimeException e) {
}
}
} finally {
@@ -376,8 +388,7 @@
for (int i = 0; i < length; i++) {
try {
mObservers.getBroadcastItem(i).interfaceAdded(iface);
- } catch (RemoteException e) {
- } catch (RuntimeException e) {
+ } catch (RemoteException | RuntimeException e) {
}
}
} finally {
@@ -399,8 +410,7 @@
for (int i = 0; i < length; i++) {
try {
mObservers.getBroadcastItem(i).interfaceRemoved(iface);
- } catch (RemoteException e) {
- } catch (RuntimeException e) {
+ } catch (RemoteException | RuntimeException e) {
}
}
} finally {
@@ -417,8 +427,7 @@
for (int i = 0; i < length; i++) {
try {
mObservers.getBroadcastItem(i).limitReached(limitName, iface);
- } catch (RemoteException e) {
- } catch (RuntimeException e) {
+ } catch (RemoteException | RuntimeException e) {
}
}
} finally {
@@ -476,8 +485,7 @@
try {
mObservers.getBroadcastItem(i).interfaceClassDataActivityChanged(
Integer.toString(type), isActive, tsNanos);
- } catch (RemoteException e) {
- } catch (RuntimeException e) {
+ } catch (RemoteException | RuntimeException e) {
}
}
} finally {
@@ -520,7 +528,7 @@
Log.wtf(TAG, "problem enabling bandwidth controls", e);
}
} else {
- Slog.d(TAG, "not enabling bandwidth control");
+ Slog.i(TAG, "not enabling bandwidth control");
}
SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0");
@@ -543,7 +551,7 @@
synchronized (mQuotaLock) {
int size = mActiveQuotas.size();
if (size > 0) {
- Slog.d(TAG, "Pushing " + size + " active quota rules");
+ if (DBG) Slog.d(TAG, "Pushing " + size + " active quota rules");
final HashMap<String, Long> activeQuotas = mActiveQuotas;
mActiveQuotas = Maps.newHashMap();
for (Map.Entry<String, Long> entry : activeQuotas.entrySet()) {
@@ -553,7 +561,7 @@
size = mActiveAlerts.size();
if (size > 0) {
- Slog.d(TAG, "Pushing " + size + " active alert rules");
+ if (DBG) Slog.d(TAG, "Pushing " + size + " active alert rules");
final HashMap<String, Long> activeAlerts = mActiveAlerts;
mActiveAlerts = Maps.newHashMap();
for (Map.Entry<String, Long> entry : activeAlerts.entrySet()) {
@@ -563,7 +571,7 @@
size = mUidRejectOnQuota.size();
if (size > 0) {
- Slog.d(TAG, "Pushing " + size + " active UID rules");
+ if (DBG) Slog.d(TAG, "Pushing " + size + " active UID rules");
final SparseBooleanArray uidRejectOnQuota = mUidRejectOnQuota;
mUidRejectOnQuota = new SparseBooleanArray();
for (int i = 0; i < uidRejectOnQuota.size(); i++) {
@@ -573,7 +581,7 @@
size = mUidCleartextPolicy.size();
if (size > 0) {
- Slog.d(TAG, "Pushing " + size + " active UID cleartext policies");
+ if (DBG) Slog.d(TAG, "Pushing " + size + " active UID cleartext policies");
final SparseIntArray local = mUidCleartextPolicy;
mUidCleartextPolicy = new SparseIntArray();
for (int i = 0; i < local.size(); i++) {
@@ -585,7 +593,7 @@
size = mUidFirewallRules.size();
if (size > 0) {
- Slog.d(TAG, "Pushing " + size + " active firewall UID rules");
+ if (DBG) Slog.d(TAG, "Pushing " + size + " active firewall UID rules");
final SparseIntArray uidFirewallRules = mUidFirewallRules;
mUidFirewallRules = new SparseIntArray();
for (int i = 0; i < uidFirewallRules.size(); i++) {
@@ -596,7 +604,7 @@
size = mUidFirewallStandbyRules.size();
if (size > 0) {
- Slog.d(TAG, "Pushing " + size + " active firewall standby UID rules");
+ if (DBG) Slog.d(TAG, "Pushing " + size + " active firewall standby UID rules");
final SparseIntArray uidFirewallRules = mUidFirewallStandbyRules;
mUidFirewallStandbyRules = new SparseIntArray();
for (int i = 0; i < uidFirewallRules.size(); i++) {
@@ -610,7 +618,7 @@
size = mUidFirewallDozableRules.size();
if (size > 0) {
- Slog.d(TAG, "Pushing " + size + " active firewall dozable UID rules");
+ if (DBG) Slog.d(TAG, "Pushing " + size + " active firewall dozable UID rules");
final SparseIntArray uidFirewallRules = mUidFirewallDozableRules;
mUidFirewallDozableRules = new SparseIntArray();
for (int i = 0; i < uidFirewallRules.size(); i++) {
@@ -621,6 +629,20 @@
if (mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE)) {
setFirewallChainEnabled(FIREWALL_CHAIN_DOZABLE, true);
}
+
+ size = mUidFirewallPowerSaveRules.size();
+ if (size > 0) {
+ Slog.d(TAG, "Pushing " + size + " active firewall powersave UID rules");
+ final SparseIntArray uidFirewallRules = mUidFirewallPowerSaveRules;
+ mUidFirewallPowerSaveRules = new SparseIntArray();
+ for (int i = 0; i < uidFirewallRules.size(); i++) {
+ setFirewallUidRuleInternal(FIREWALL_CHAIN_POWERSAVE, uidFirewallRules.keyAt(i),
+ uidFirewallRules.valueAt(i));
+ }
+ }
+ if (mFirewallChainStates.get(FIREWALL_CHAIN_POWERSAVE)) {
+ setFirewallChainEnabled(FIREWALL_CHAIN_POWERSAVE, true);
+ }
}
}
@@ -633,8 +655,7 @@
for (int i = 0; i < length; i++) {
try {
mObservers.getBroadcastItem(i).addressUpdated(iface, address);
- } catch (RemoteException e) {
- } catch (RuntimeException e) {
+ } catch (RemoteException | RuntimeException e) {
}
}
} finally {
@@ -651,8 +672,7 @@
for (int i = 0; i < length; i++) {
try {
mObservers.getBroadcastItem(i).addressRemoved(iface, address);
- } catch (RemoteException e) {
- } catch (RuntimeException e) {
+ } catch (RemoteException | RuntimeException e) {
}
}
} finally {
@@ -670,8 +690,7 @@
try {
mObservers.getBroadcastItem(i).interfaceDnsServerInfo(iface, lifetime,
addresses);
- } catch (RemoteException e) {
- } catch (RuntimeException e) {
+ } catch (RemoteException | RuntimeException e) {
}
}
} finally {
@@ -692,8 +711,7 @@
} else {
mObservers.getBroadcastItem(i).routeRemoved(route);
}
- } catch (RemoteException e) {
- } catch (RuntimeException e) {
+ } catch (RemoteException | RuntimeException e) {
}
}
} finally {
@@ -1210,7 +1228,7 @@
// TODO: remove from aidl if nobody calls externally
mContext.enforceCallingOrSelfPermission(SHUTDOWN, TAG);
- Slog.d(TAG, "Shutting down");
+ Slog.i(TAG, "Shutting down");
}
@Override
@@ -2023,6 +2041,9 @@
case FIREWALL_CHAIN_DOZABLE:
chainName = FIREWALL_CHAIN_NAME_DOZABLE;
break;
+ case FIREWALL_CHAIN_POWERSAVE:
+ chainName = FIREWALL_CHAIN_NAME_POWERSAVE;
+ break;
default:
throw new IllegalArgumentException("Bad child chain: " + chain);
}
@@ -2039,6 +2060,8 @@
return FIREWALL_TYPE_BLACKLIST;
case FIREWALL_CHAIN_DOZABLE:
return FIREWALL_TYPE_WHITELIST;
+ case FIREWALL_CHAIN_POWERSAVE:
+ return FIREWALL_TYPE_WHITELIST;
default:
return isFirewallEnabled() ? FIREWALL_TYPE_WHITELIST : FIREWALL_TYPE_BLACKLIST;
}
@@ -2138,6 +2161,8 @@
return mUidFirewallStandbyRules;
case FIREWALL_CHAIN_DOZABLE:
return mUidFirewallDozableRules;
+ case FIREWALL_CHAIN_POWERSAVE:
+ return mUidFirewallPowerSaveRules;
case FIREWALL_CHAIN_NONE:
return mUidFirewallRules;
default:
@@ -2151,6 +2176,8 @@
return FIREWALL_CHAIN_NAME_STANDBY;
case FIREWALL_CHAIN_DOZABLE:
return FIREWALL_CHAIN_NAME_DOZABLE;
+ case FIREWALL_CHAIN_POWERSAVE:
+ return FIREWALL_CHAIN_NAME_POWERSAVE;
case FIREWALL_CHAIN_NONE:
return FIREWALL_CHAIN_NAME_NONE;
default:
@@ -2225,8 +2252,7 @@
for (int i = 0; i < length; i++) {
try {
mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive();
- } catch (RemoteException e) {
- } catch (RuntimeException e) {
+ } catch (RemoteException | RuntimeException e) {
}
}
} finally {
@@ -2271,43 +2297,25 @@
}
synchronized (mUidFirewallRules) {
- pw.print("UID firewall rule: [");
- final int size = mUidFirewallRules.size();
- for (int i = 0; i < size; i++) {
- pw.print(mUidFirewallRules.keyAt(i));
- pw.print(":");
- pw.print(mUidFirewallRules.valueAt(i));
- if (i < size - 1) pw.print(",");
- }
- pw.println("]");
+ dumpUidFirewallRule(pw, "", mUidFirewallRules);
}
pw.println("UID firewall standby chain enabled: " +
mFirewallChainStates.get(FIREWALL_CHAIN_STANDBY));
synchronized (mUidFirewallStandbyRules) {
- pw.print("UID firewall standby rule: [");
- final int size = mUidFirewallStandbyRules.size();
- for (int i = 0; i < size; i++) {
- pw.print(mUidFirewallStandbyRules.keyAt(i));
- pw.print(":");
- pw.print(mUidFirewallStandbyRules.valueAt(i));
- if (i < size - 1) pw.print(",");
- }
- pw.println("]");
+ dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_STANDBY, mUidFirewallStandbyRules);
}
pw.println("UID firewall dozable chain enabled: " +
mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE));
synchronized (mUidFirewallDozableRules) {
- pw.print("UID firewall dozable rule: [");
- final int size = mUidFirewallDozableRules.size();
- for (int i = 0; i < size; i++) {
- pw.print(mUidFirewallDozableRules.keyAt(i));
- pw.print(":");
- pw.print(mUidFirewallDozableRules.valueAt(i));
- if (i < size - 1) pw.print(",");
- }
- pw.println("]");
+ dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_DOZABLE, mUidFirewallDozableRules);
+ }
+
+ pw.println("UID firewall powersave chain enabled: " +
+ mFirewallChainStates.get(FIREWALL_CHAIN_POWERSAVE));
+ synchronized (mUidFirewallPowerSaveRules) {
+ dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_POWERSAVE, mUidFirewallPowerSaveRules);
}
synchronized (mIdleTimerLock) {
@@ -2324,6 +2332,20 @@
pw.print("Firewall enabled: "); pw.println(mFirewallEnabled);
}
+ private void dumpUidFirewallRule(PrintWriter pw, String name, SparseIntArray rules) {
+ pw.print("UID firewall");
+ pw.print(name);
+ pw.print(" rule: [");
+ final int size = rules.size();
+ for (int i = 0; i < size; i++) {
+ pw.print(rules.keyAt(i));
+ pw.print(":");
+ pw.print(rules.valueAt(i));
+ if (i < size - 1) pw.print(",");
+ }
+ pw.println("]");
+ }
+
@Override
public void createPhysicalNetwork(int netId, String permission) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java
index 3f0664d..b64c65d 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java
@@ -23,8 +23,10 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.net.ConnectivityManager;
+import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -34,10 +36,14 @@
import android.provider.Settings;
import android.util.Log;
import android.util.NtpTrustedTime;
+import android.util.TimeUtils;
import android.util.TrustedTime;
import com.android.internal.telephony.TelephonyIntents;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
/**
* Monitors the network time and updates the system time if it is out of sync
* and there hasn't been any NITZ update from the carrier recently.
@@ -48,7 +54,7 @@
* available.
* </p>
*/
-public class NetworkTimeUpdateService {
+public class NetworkTimeUpdateService extends Binder {
private static final String TAG = "NetworkTimeUpdateService";
private static final boolean DBG = false;
@@ -59,6 +65,8 @@
private static final String ACTION_POLL =
"com.android.server.NetworkTimeUpdateService.action.POLL";
+
+ private static final int NETWORK_CHANGE_EVENT_DELAY_MS = 1000;
private static int POLL_REQUEST = 0;
private static final long NOT_SET = -1;
@@ -245,6 +253,7 @@
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
+ if (DBG) Log.d(TAG, "Received " + action);
if (TelephonyIntents.ACTION_NETWORK_SET_TIME.equals(action)) {
mNitzTimeSetTime = SystemClock.elapsedRealtime();
} else if (TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE.equals(action)) {
@@ -260,8 +269,11 @@
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
+ if (DBG) Log.d(TAG, "Received CONNECTIVITY_ACTION ");
// Don't bother checking if we have connectivity, NtpTrustedTime does that for us.
- mHandler.obtainMessage(EVENT_NETWORK_CHANGED).sendToTarget();
+ Message message = mHandler.obtainMessage(EVENT_NETWORK_CHANGED);
+ // Send with a short delay to make sure the network is ready for use
+ mHandler.sendMessageDelayed(message, NETWORK_CHANGE_EVENT_DELAY_MS);
}
}
};
@@ -308,4 +320,28 @@
mHandler.obtainMessage(mMsg).sendToTarget();
}
}
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump NetworkTimeUpdateService from from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid()
+ + " without permission "
+ + android.Manifest.permission.DUMP);
+ return;
+ }
+ pw.print("PollingIntervalMs: ");
+ TimeUtils.formatDuration(mPollingIntervalMs, pw);
+ pw.print("\nPollingIntervalShorterMs: ");
+ TimeUtils.formatDuration(mPollingIntervalShorterMs, pw);
+ pw.println("\nTryAgainTimesMax: " + mTryAgainTimesMax);
+ pw.print("TimeErrorThresholdMs: ");
+ TimeUtils.formatDuration(mTimeErrorThresholdMs, pw);
+ pw.println("\nTryAgainCounter: " + mTryAgainCounter);
+ pw.print("LastNtpFetchTime: ");
+ TimeUtils.formatDuration(mLastNtpFetchTime, pw);
+ pw.println();
+ }
}
diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index f4c6225..11aef17 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -58,7 +58,7 @@
private static final String TAG = "NsdService";
private static final String MDNS_TAG = "mDnsConnector";
- private static final boolean DBG = true;
+ private static final boolean DBG = false;
private Context mContext;
private ContentResolver mContentResolver;
diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java
index a291cc7..2085f32 100644
--- a/services/core/java/com/android/server/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/PersistentDataBlockService.java
@@ -27,6 +27,7 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.service.persistentdata.IPersistentDataBlockService;
+import android.service.persistentdata.PersistentDataBlockManager;
import android.util.Slog;
import com.android.internal.R;
@@ -72,6 +73,9 @@
private static final int MAX_DATA_BLOCK_SIZE = 1024 * 100;
public static final int DIGEST_SIZE_BYTES = 32;
private static final String OEM_UNLOCK_PROP = "sys.oem_unlock_allowed";
+ private static final String FLASH_LOCK_PROP = "ro.boot.flash.locked";
+ private static final String FLASH_LOCK_LOCKED = "1";
+ private static final String FLASH_LOCK_UNLOCKED = "0";
private final Context mContext;
private final String mDataBlockFile;
@@ -454,6 +458,20 @@
}
@Override
+ public int getFlashLockState() {
+ enforceOemUnlockPermission();
+ String locked = SystemProperties.get(FLASH_LOCK_PROP);
+ switch (locked) {
+ case FLASH_LOCK_LOCKED:
+ return PersistentDataBlockManager.FLASH_LOCK_LOCKED;
+ case FLASH_LOCK_UNLOCKED:
+ return PersistentDataBlockManager.FLASH_LOCK_UNLOCKED;
+ default:
+ return PersistentDataBlockManager.FLASH_LOCK_UNKNOWN;
+ }
+ }
+
+ @Override
public int getDataBlockSize() {
enforcePersistentDataBlockAccess();
diff --git a/services/core/java/com/android/server/RecoverySystemService.java b/services/core/java/com/android/server/RecoverySystemService.java
new file mode 100644
index 0000000..d284d07
--- /dev/null
+++ b/services/core/java/com/android/server/RecoverySystemService.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.content.Context;
+import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
+import android.os.IRecoverySystem;
+import android.os.IRecoverySystemProgressListener;
+import android.os.RecoverySystem;
+import android.os.RemoteException;
+import android.os.SystemProperties;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.util.Slog;
+
+import libcore.io.IoUtils;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+/**
+ * The recovery system service is responsible for coordinating recovery related
+ * functions on the device. It sets up (or clears) the bootloader control block
+ * (BCB), which will be read by the bootloader and the recovery image. It also
+ * triggers /system/bin/uncrypt via init to de-encrypt an OTA package on the
+ * /data partition so that it can be accessed under the recovery image.
+ */
+public final class RecoverySystemService extends SystemService {
+ private static final String TAG = "RecoverySystemService";
+ private static final boolean DEBUG = false;
+
+ // The socket at /dev/socket/uncrypt to communicate with uncrypt.
+ private static final String UNCRYPT_SOCKET = "uncrypt";
+
+ private static final int SOCKET_CONNECTION_MAX_RETRY = 30;
+
+ private Context mContext;
+
+ public RecoverySystemService(Context context) {
+ super(context);
+ mContext = context;
+ }
+
+ @Override
+ public void onStart() {
+ publishBinderService(Context.RECOVERY_SERVICE, new BinderService());
+ }
+
+ private final class BinderService extends IRecoverySystem.Stub {
+ @Override // Binder call
+ public boolean uncrypt(String filename, IRecoverySystemProgressListener listener) {
+ if (DEBUG) Slog.d(TAG, "uncrypt: " + filename);
+
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
+
+ // Write the filename into UNCRYPT_PACKAGE_FILE to be read by
+ // uncrypt.
+ RecoverySystem.UNCRYPT_PACKAGE_FILE.delete();
+
+ try (FileWriter uncryptFile = new FileWriter(RecoverySystem.UNCRYPT_PACKAGE_FILE)) {
+ uncryptFile.write(filename + "\n");
+ } catch (IOException e) {
+ Slog.e(TAG, "IOException when writing \"" + RecoverySystem.UNCRYPT_PACKAGE_FILE +
+ "\": " + e.getMessage());
+ return false;
+ }
+
+ // Trigger uncrypt via init.
+ SystemProperties.set("ctl.start", "uncrypt");
+
+ // Connect to the uncrypt service socket.
+ LocalSocket socket = connectService();
+ if (socket == null) {
+ Slog.e(TAG, "Failed to connect to uncrypt socket");
+ return false;
+ }
+
+ // Read the status from the socket.
+ try (DataInputStream dis = new DataInputStream(socket.getInputStream());
+ DataOutputStream dos = new DataOutputStream(socket.getOutputStream())) {
+ int lastStatus = Integer.MIN_VALUE;
+ while (true) {
+ int status = dis.readInt();
+ // Avoid flooding the log with the same message.
+ if (status == lastStatus && lastStatus != Integer.MIN_VALUE) {
+ continue;
+ }
+ lastStatus = status;
+
+ if (status >= 0 && status <= 100) {
+ // Update status
+ Slog.i(TAG, "uncrypt read status: " + status);
+ if (listener != null) {
+ try {
+ listener.onProgress(status);
+ } catch (RemoteException unused) {
+ Slog.w(TAG, "RemoteException when posting progress");
+ }
+ }
+ if (status == 100) {
+ Slog.i(TAG, "uncrypt successfully finished.");
+ // Ack receipt of the final status code. uncrypt
+ // waits for the ack so the socket won't be
+ // destroyed before we receive the code.
+ dos.writeInt(0);
+ dos.flush();
+ break;
+ }
+ } else {
+ // Error in /system/bin/uncrypt.
+ Slog.e(TAG, "uncrypt failed with status: " + status);
+ // Ack receipt of the final status code. uncrypt waits
+ // for the ack so the socket won't be destroyed before
+ // we receive the code.
+ dos.writeInt(0);
+ dos.flush();
+ return false;
+ }
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "IOException when reading status: " + e);
+ return false;
+ } finally {
+ IoUtils.closeQuietly(socket);
+ }
+
+ return true;
+ }
+
+ @Override // Binder call
+ public boolean clearBcb() {
+ if (DEBUG) Slog.d(TAG, "clearBcb");
+ return setupOrClearBcb(false, null);
+ }
+
+ @Override // Binder call
+ public boolean setupBcb(String command) {
+ if (DEBUG) Slog.d(TAG, "setupBcb: [" + command + "]");
+ return setupOrClearBcb(true, command);
+ }
+
+ private LocalSocket connectService() {
+ LocalSocket socket = new LocalSocket();
+ boolean done = false;
+ // The uncrypt socket will be created by init upon receiving the
+ // service request. It may not be ready by this point. So we will
+ // keep retrying until success or reaching timeout.
+ for (int retry = 0; retry < SOCKET_CONNECTION_MAX_RETRY; retry++) {
+ try {
+ socket.connect(new LocalSocketAddress(UNCRYPT_SOCKET,
+ LocalSocketAddress.Namespace.RESERVED));
+ done = true;
+ break;
+ } catch (IOException unused) {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ Slog.w(TAG, "Interrupted: " + e);
+ }
+ }
+ }
+ if (!done) {
+ Slog.e(TAG, "Timed out connecting to uncrypt socket");
+ return null;
+ }
+ return socket;
+ }
+
+ private boolean setupOrClearBcb(boolean isSetup, String command) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
+
+ if (isSetup) {
+ SystemProperties.set("ctl.start", "setup-bcb");
+ } else {
+ SystemProperties.set("ctl.start", "clear-bcb");
+ }
+
+ // Connect to the uncrypt service socket.
+ LocalSocket socket = connectService();
+ if (socket == null) {
+ Slog.e(TAG, "Failed to connect to uncrypt socket");
+ return false;
+ }
+
+ try (DataInputStream dis = new DataInputStream(socket.getInputStream());
+ DataOutputStream dos = new DataOutputStream(socket.getOutputStream())) {
+ // Send the BCB commands if it's to setup BCB.
+ if (isSetup) {
+ dos.writeInt(command.length());
+ dos.writeBytes(command);
+ dos.flush();
+ }
+
+ // Read the status from the socket.
+ int status = dis.readInt();
+
+ // Ack receipt of the status code. uncrypt waits for the ack so
+ // the socket won't be destroyed before we receive the code.
+ dos.writeInt(0);
+ dos.flush();
+
+ if (status == 100) {
+ Slog.i(TAG, "uncrypt " + (isSetup ? "setup" : "clear") +
+ " bcb successfully finished.");
+ } else {
+ // Error in /system/bin/uncrypt.
+ Slog.e(TAG, "uncrypt failed with status: " + status);
+ return false;
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "IOException when getting output stream: " + e);
+ return false;
+ } finally {
+ IoUtils.closeQuietly(socket);
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java
index 7bdd3e2..73d8bdd 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -101,8 +101,9 @@
// background while in power save mode, as read from the configuration files.
final ArraySet<String> mAllowInPowerSave = new ArraySet<>();
- // These are the app package names that should not allow IME switching.
- final ArraySet<String> mFixedImeApps = new ArraySet<>();
+ // These are the packages that are white-listed to be able to run in the
+ // background while in data-usage save mode, as read from the configuration files.
+ final ArraySet<String> mAllowInDataUsageSave = new ArraySet<>();
// These are the package names of apps which should be in the 'always'
// URL-handling state upon factory reset.
@@ -151,8 +152,8 @@
return mAllowInPowerSave;
}
- public ArraySet<String> getFixedImeApps() {
- return mFixedImeApps;
+ public ArraySet<String> getAllowInDataUsageSave() {
+ return mAllowInDataUsageSave;
}
public ArraySet<String> getLinkedApps() {
@@ -392,13 +393,13 @@
XmlUtils.skipCurrentTag(parser);
continue;
- } else if ("fixed-ime-app".equals(name) && allowAll) {
+ } else if ("allow-in-data-usage-save".equals(name) && allowAll) {
String pkgname = parser.getAttributeValue(null, "package");
if (pkgname == null) {
- Slog.w(TAG, "<fixed-ime-app> without package in " + permFile + " at "
- + parser.getPositionDescription());
+ Slog.w(TAG, "<allow-in-data-usage-save> without package in " + permFile
+ + " at " + parser.getPositionDescription());
} else {
- mFixedImeApps.add(pkgname);
+ mAllowInDataUsageSave.add(pkgname);
}
XmlUtils.skipCurrentTag(parser);
continue;
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 163b9be..a63faf1 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -101,9 +101,12 @@
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
@@ -122,7 +125,7 @@
private static final String TAG = "AccountManagerService";
private static final String DATABASE_NAME = "accounts.db";
- private static final int DATABASE_VERSION = 8;
+ private static final int DATABASE_VERSION = 9;
private static final int MAX_DEBUG_DB_SIZE = 64;
@@ -200,6 +203,11 @@
EXTRAS_ACCOUNTS_ID + "=(select _id FROM accounts WHERE name=? AND type=?)";
private static final String[] COLUMNS_EXTRAS_KEY_AND_VALUE = {EXTRAS_KEY, EXTRAS_VALUE};
+ private static final String META_KEY_FOR_AUTHENTICATOR_UID_FOR_TYPE_PREFIX =
+ "auth_uid_for_type:";
+ private static final String META_KEY_DELIMITER = ":";
+ private static final String SELECTION_META_BY_AUTHENTICATOR_TYPE = META_KEY + " LIKE ?";
+
private final LinkedHashMap<String, Session> mSessions = new LinkedHashMap<String, Session>();
private final AtomicInteger mNotificationIds = new AtomicInteger(1);
@@ -315,15 +323,15 @@
IntentFilter userFilter = new IntentFilter();
userFilter.addAction(Intent.ACTION_USER_REMOVED);
- userFilter.addAction(Intent.ACTION_USER_STARTED);
+ userFilter.addAction(Intent.ACTION_USER_UNLOCKED);
mContext.registerReceiverAsUser(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_USER_REMOVED.equals(action)) {
onUserRemoved(intent);
- } else if (Intent.ACTION_USER_STARTED.equals(action)) {
- onUserStarted(intent);
+ } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
+ onUserUnlocked(intent);
}
}
}, UserHandle.ALL, userFilter, null, null);
@@ -376,15 +384,69 @@
mAuthenticatorCache.invalidateCache(accounts.userId);
}
- final HashSet<AuthenticatorDescription> knownAuth = Sets.newHashSet();
+ final HashMap<String, Integer> knownAuth = new HashMap<>();
for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> service :
mAuthenticatorCache.getAllServices(accounts.userId)) {
- knownAuth.add(service.type);
+ knownAuth.put(service.type.type, service.uid);
}
synchronized (accounts.cacheLock) {
final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
boolean accountDeleted = false;
+
+ // Get a list of stored authenticator type and UID
+ Cursor metaCursor = db.query(
+ TABLE_META,
+ new String[] {META_KEY, META_VALUE},
+ SELECTION_META_BY_AUTHENTICATOR_TYPE,
+ new String[] {META_KEY_FOR_AUTHENTICATOR_UID_FOR_TYPE_PREFIX + "%"},
+ null /* groupBy */,
+ null /* having */,
+ META_KEY);
+ // Create a list of authenticator type whose previous uid no longer exists
+ HashSet<String> obsoleteAuthType = Sets.newHashSet();
+ try {
+ while (metaCursor.moveToNext()) {
+ String type = TextUtils.split(metaCursor.getString(0), META_KEY_DELIMITER)[1];
+ String uid = metaCursor.getString(1);
+ if (TextUtils.isEmpty(type) || TextUtils.isEmpty(uid)) {
+ // Should never happen.
+ Slog.e(TAG, "Auth type empty: " + TextUtils.isEmpty(type)
+ + ", uid empty: " + TextUtils.isEmpty(uid));
+ continue;
+ }
+ Integer knownUid = knownAuth.get(type);
+ if (knownUid != null && uid.equals(knownUid.toString())) {
+ // Remove it from the knownAuth list if it's unchanged.
+ knownAuth.remove(type);
+ } else {
+ // Only add it to the list if it no longer exists or uid different
+ obsoleteAuthType.add(type);
+ // And delete it from the TABLE_META
+ db.delete(
+ TABLE_META,
+ META_KEY + "=? AND " + META_VALUE + "=?",
+ new String[] {
+ META_KEY_FOR_AUTHENTICATOR_UID_FOR_TYPE_PREFIX + type,
+ uid}
+ );
+ }
+ }
+ } finally {
+ metaCursor.close();
+ }
+
+ // Add the newly registered authenticator to TABLE_META
+ Iterator<Entry<String, Integer>> iterator = knownAuth.entrySet().iterator();
+ while (iterator.hasNext()) {
+ Entry<String, Integer> entry = iterator.next();
+ ContentValues values = new ContentValues();
+ values.put(META_KEY,
+ META_KEY_FOR_AUTHENTICATOR_UID_FOR_TYPE_PREFIX + entry.getKey());
+ values.put(META_VALUE, entry.getValue());
+ db.insert(TABLE_META, null, values);
+ }
+
Cursor cursor = db.query(TABLE_ACCOUNTS,
new String[]{ACCOUNTS_ID, ACCOUNTS_TYPE, ACCOUNTS_NAME},
null, null, null, null, ACCOUNTS_ID);
@@ -397,9 +459,9 @@
final String accountType = cursor.getString(1);
final String accountName = cursor.getString(2);
- if (!knownAuth.contains(AuthenticatorDescription.newKey(accountType))) {
+ if (obsoleteAuthType.contains(accountType)) {
Slog.w(TAG, "deleting account " + accountName + " because type "
- + accountType + " no longer has a registered authenticator");
+ + accountType + "'s registered authenticator no longer exist.");
db.delete(TABLE_ACCOUNTS, ACCOUNTS_ID + "=" + accountId, null);
accountDeleted = true;
@@ -440,6 +502,18 @@
}
}
+ private static HashMap<String, Integer> getAuthenticatorTypeAndUIDForUser(
+ Context context,
+ int userId) {
+ AccountAuthenticatorCache authCache = new AccountAuthenticatorCache(context);
+ HashMap<String, Integer> knownAuth = new HashMap<>();
+ for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> service : authCache
+ .getAllServices(userId)) {
+ knownAuth.put(service.type.type, service.uid);
+ }
+ return knownAuth;
+ }
+
private UserAccounts getUserAccountsForCaller() {
return getUserAccounts(UserHandle.getCallingUserId());
}
@@ -513,7 +587,7 @@
}
}
- private void onUserStarted(Intent intent) {
+ private void onUserUnlocked(Intent intent) {
int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
if (userId < 1) return;
@@ -660,12 +734,7 @@
long identityToken = clearCallingIdentity();
try {
UserAccounts accounts = getUserAccounts(userId);
- synchronized (accounts.cacheLock) {
- if (!accountExistsCacheLocked(accounts, account)) {
- return null;
- }
- return readUserDataInternalLocked(accounts, account, key);
- }
+ return readUserDataInternal(accounts, account, key);
} finally {
restoreCallingIdentity(identityToken);
}
@@ -991,13 +1060,9 @@
for (UserInfo user : users) {
if (user.isRestricted() && (parentUserId == user.restrictedProfileParentId)) {
addSharedAccountAsUser(account, user.id);
- try {
- if (ActivityManagerNative.getDefault().isUserRunning(user.id, 0)) {
- mMessageHandler.sendMessage(mMessageHandler.obtainMessage(
- MESSAGE_COPY_SHARED_ACCOUNT, parentUserId, user.id, account));
- }
- } catch (RemoteException re) {
- // Shouldn't happen
+ if (mUserManager.isUserUnlocked(user.id)) {
+ mMessageHandler.sendMessage(mMessageHandler.obtainMessage(
+ MESSAGE_COPY_SHARED_ACCOUNT, parentUserId, user.id, account));
}
}
}
@@ -1721,58 +1786,44 @@
long identityToken = clearCallingIdentity();
try {
UserAccounts accounts = getUserAccounts(userId);
- synchronized (accounts.cacheLock) {
- if (!accountExistsCacheLocked(accounts, account)) {
- return;
- }
- setUserdataInternalLocked(accounts, account, key, value);
- }
+ setUserdataInternal(accounts, account, key, value);
} finally {
restoreCallingIdentity(identityToken);
}
}
- private boolean accountExistsCacheLocked(UserAccounts accounts, Account account) {
- if (accounts.accountCache.containsKey(account.type)) {
- for (Account acc : getUserAccountsForCaller().accountCache.get(account.type)) {
- if (acc.name.equals(account.name)) {
- return true;
- }
- }
- }
- return false;
- }
-
- private void setUserdataInternalLocked(UserAccounts accounts, Account account, String key,
+ private void setUserdataInternal(UserAccounts accounts, Account account, String key,
String value) {
if (account == null || key == null) {
return;
}
- final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
- db.beginTransaction();
- try {
- long accountId = getAccountIdLocked(db, account);
- if (accountId < 0) {
- return;
- }
- long extrasId = getExtrasIdLocked(db, accountId, key);
- if (extrasId < 0) {
- extrasId = insertExtraLocked(db, accountId, key, value);
- if (extrasId < 0) {
+ synchronized (accounts.cacheLock) {
+ final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
+ db.beginTransaction();
+ try {
+ long accountId = getAccountIdLocked(db, account);
+ if (accountId < 0) {
return;
}
- } else {
- ContentValues values = new ContentValues();
- values.put(EXTRAS_VALUE, value);
- if (1 != db.update(TABLE_EXTRAS, values, EXTRAS_ID + "=" + extrasId, null)) {
- return;
- }
+ long extrasId = getExtrasIdLocked(db, accountId, key);
+ if (extrasId < 0 ) {
+ extrasId = insertExtraLocked(db, accountId, key, value);
+ if (extrasId < 0) {
+ return;
+ }
+ } else {
+ ContentValues values = new ContentValues();
+ values.put(EXTRAS_VALUE, value);
+ if (1 != db.update(TABLE_EXTRAS, values, EXTRAS_ID + "=" + extrasId, null)) {
+ return;
+ }
+ }
+ writeUserDataIntoCacheLocked(accounts, db, account, key, value);
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
}
- writeUserDataIntoCacheLocked(accounts, db, account, key, value);
- db.setTransactionSuccessful();
- } finally {
- db.endTransaction();
}
}
@@ -3986,8 +4037,13 @@
static class DatabaseHelper extends SQLiteOpenHelper {
+ private final Context mContext;
+ private final int mUserId;
+
public DatabaseHelper(Context context, int userId) {
super(context, AccountManagerService.getDatabaseName(userId), null, DATABASE_VERSION);
+ mContext = context;
+ mUserId = userId;
}
/**
@@ -4076,6 +4132,20 @@
+ "," + GRANTS_GRANTEE_UID + "))");
}
+ private void populateMetaTableWithAuthTypeAndUID(
+ SQLiteDatabase db,
+ Map<String, Integer> authTypeAndUIDMap) {
+ Iterator<Entry<String, Integer>> iterator = authTypeAndUIDMap.entrySet().iterator();
+ while (iterator.hasNext()) {
+ Entry<String, Integer> entry = iterator.next();
+ ContentValues values = new ContentValues();
+ values.put(META_KEY,
+ META_KEY_FOR_AUTHENTICATOR_UID_FOR_TYPE_PREFIX + entry.getKey());
+ values.put(META_VALUE, entry.getValue());
+ db.insert(TABLE_META, null, values);
+ }
+ }
+
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.e(TAG, "upgrade from version " + oldVersion + " to version " + newVersion);
@@ -4119,6 +4189,13 @@
oldVersion++;
}
+ if (oldVersion == 8) {
+ populateMetaTableWithAuthTypeAndUID(
+ db,
+ AccountManagerService.getAuthenticatorTypeAndUIDForUser(mContext, mUserId));
+ oldVersion++;
+ }
+
if (oldVersion != newVersion) {
Log.e(TAG, "failed to upgrade version " + oldVersion + " to version " + newVersion);
}
@@ -4807,16 +4884,17 @@
}
}
- protected String readUserDataInternalLocked(
- UserAccounts accounts, Account account, String key) {
- HashMap<String, String> userDataForAccount = accounts.userDataCache.get(account);
- if (userDataForAccount == null) {
- // need to populate the cache for this account
- final SQLiteDatabase db = accounts.openHelper.getReadableDatabase();
- userDataForAccount = readUserDataForAccountFromDatabaseLocked(db, account);
- accounts.userDataCache.put(account, userDataForAccount);
+ protected String readUserDataInternal(UserAccounts accounts, Account account, String key) {
+ synchronized (accounts.cacheLock) {
+ HashMap<String, String> userDataForAccount = accounts.userDataCache.get(account);
+ if (userDataForAccount == null) {
+ // need to populate the cache for this account
+ final SQLiteDatabase db = accounts.openHelper.getReadableDatabase();
+ userDataForAccount = readUserDataForAccountFromDatabaseLocked(db, account);
+ accounts.userDataCache.put(account, userDataForAccount);
+ }
+ return userDataForAccount.get(key);
}
- return userDataForAccount.get(key);
}
protected HashMap<String, String> readUserDataForAccountFromDatabaseLocked(
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 8c0ec78..63a0e87 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -319,7 +319,7 @@
+ " (pid=" + Binder.getCallingPid()
+ ") when starting service " + service);
}
- callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
} else {
callerFg = true;
}
@@ -831,7 +831,7 @@
"BIND_TREAT_LIKE_ACTIVITY");
}
- final boolean callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ final boolean callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
final boolean isBindExternal = (flags & Context.BIND_EXTERNAL_SERVICE) != 0;
ServiceLookupResult res =
@@ -1138,7 +1138,7 @@
for (int i=b.apps.size()-1; i>=0; i--) {
ProcessRecord client = b.apps.valueAt(i).client;
if (client != null && client.setSchedGroup
- != Process.THREAD_GROUP_BG_NONINTERACTIVE) {
+ != ProcessList.SCHED_GROUP_BACKGROUND) {
inFg = true;
break;
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
index 4f0d4d9..f2bf4f9 100644
--- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
+++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
@@ -46,6 +46,7 @@
// Available log categories in the activity manager package.
static final boolean DEBUG_ADD_REMOVE = DEBUG_ALL_ACTIVITIES || false;
+ static final boolean DEBUG_ANR = false;
static final boolean DEBUG_APP = DEBUG_ALL_ACTIVITIES || false;
static final boolean DEBUG_BACKUP = DEBUG_ALL || false;
static final boolean DEBUG_BROADCAST = DEBUG_ALL || false;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c7f7378..8df5b2c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -45,6 +45,7 @@
import com.android.server.DeviceIdleController;
import com.android.server.IntentResolver;
import com.android.server.LocalServices;
+import com.android.server.LockGuard;
import com.android.server.ServiceThread;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
@@ -100,6 +101,8 @@
import android.app.PendingIntent;
import android.app.ProfilerInfo;
import android.app.admin.DevicePolicyManager;
+import android.app.admin.DevicePolicyManagerInternal;
+import android.app.admin.IDevicePolicyManager;
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
import android.app.backup.IBackupManager;
@@ -273,6 +276,7 @@
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RTL;
+import static android.provider.Settings.Global.LENIENT_BACKGROUND_CHECK;
import static android.provider.Settings.Global.WAIT_FOR_DEBUGGER;
import static android.provider.Settings.System.FONT_SCALE;
import static com.android.internal.util.XmlUtils.readBooleanAttribute;
@@ -282,6 +286,7 @@
import static com.android.internal.util.XmlUtils.writeIntAttribute;
import static com.android.internal.util.XmlUtils.writeLongAttribute;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKUP;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST_BACKGROUND;
@@ -1290,11 +1295,14 @@
String mOrigDebugApp = null;
boolean mOrigWaitForDebugger = false;
boolean mAlwaysFinishActivities = false;
+ boolean mLenientBackgroundCheck = false;
boolean mForceResizableActivities;
+ boolean mSupportsMultiWindow;
boolean mSupportsFreeformWindowManagement;
boolean mSupportsPictureInPicture;
Rect mDefaultPinnedStackBounds;
IActivityController mController = null;
+ boolean mControllerIsAMonkey = false;
String mProfileApp = null;
ProcessRecord mProfileProc = null;
String mProfileFile;
@@ -1369,7 +1377,6 @@
int mProcessLimitOverride = -1;
WindowManagerService mWindowManager;
-
final ActivityThread mSystemThread;
private final class AppDeathRecipient implements IBinder.DeathRecipient {
@@ -1892,7 +1899,10 @@
case SYSTEM_USER_UNLOCK_MSG: {
final int userId = msg.arg1;
mSystemServiceManager.unlockUser(userId);
- mRecentTasks.cleanupLocked(userId);
+ mRecentTasks.loadUserRecentsLocked(userId);
+ if (userId == UserHandle.USER_SYSTEM) {
+ startPersistentApps(PackageManager.MATCH_ENCRYPTION_UNAWARE);
+ }
installEncryptionUnawareProviders(userId);
break;
}
@@ -2485,7 +2495,6 @@
mActivityStarter = new ActivityStarter(this, mStackSupervisor);
mRecentTasks = new RecentTasks(this, mStackSupervisor);
-
mProcessCpuThread = new Thread("CpuTracker") {
@Override
public void run() {
@@ -2539,7 +2548,7 @@
}
void onUserStoppedLocked(int userId) {
- mRecentTasks.unloadUserRecentsLocked(userId);
+ mRecentTasks.unloadUserDataFromMemoryLocked(userId);
}
public void initPowerManagement() {
@@ -4367,7 +4376,7 @@
AppGlobals.getPackageManager().queryIntentActivities(
intent, r.resolvedType,
PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS,
- UserHandle.getCallingUserId());
+ UserHandle.getCallingUserId()).getList();
// Look for the original activity in the list...
final int N = resolves != null ? resolves.size() : 0;
@@ -5085,8 +5094,13 @@
int num = firstPids.size();
for (int i = 0; i < num; i++) {
synchronized (observer) {
+ if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for pid "
+ + firstPids.get(i));
+ final long sime = SystemClock.elapsedRealtime();
Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
- observer.wait(200); // Wait for write-close, give up after 200msec
+ observer.wait(1000); // Wait for write-close, give up after 1 sec
+ if (DEBUG_ANR) Slog.d(TAG, "Done with pid " + firstPids.get(i)
+ + " in " + (SystemClock.elapsedRealtime()-sime) + "ms");
}
}
} catch (InterruptedException e) {
@@ -5099,7 +5113,11 @@
int[] pids = Process.getPidsForCommands(nativeProcs);
if (pids != null) {
for (int pid : pids) {
+ if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for native pid " + pid);
+ final long sime = SystemClock.elapsedRealtime();
Debug.dumpNativeBacktraceToFile(pid, tracesPath);
+ if (DEBUG_ANR) Slog.d(TAG, "Done with native pid " + pid
+ + " in " + (SystemClock.elapsedRealtime()-sime) + "ms");
}
}
}
@@ -5126,13 +5144,20 @@
numProcs++;
try {
synchronized (observer) {
+ if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for extra pid "
+ + stats.pid);
+ final long stime = SystemClock.elapsedRealtime();
Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
- observer.wait(200); // Wait for write-close, give up after 200msec
+ observer.wait(1000); // Wait for write-close, give up after 1 sec
+ if (DEBUG_ANR) Slog.d(TAG, "Done with extra pid " + stats.pid
+ + " in " + (SystemClock.elapsedRealtime()-stime) + "ms");
}
} catch (InterruptedException e) {
Slog.wtf(TAG, e);
}
-
+ } else if (DEBUG_ANR) {
+ Slog.d(TAG, "Skipping next CPU consuming process, not a java proc: "
+ + stats.pid);
}
}
}
@@ -5238,9 +5263,13 @@
public boolean clearApplicationUserData(final String packageName,
final IPackageDataObserver observer, int userId) {
enforceNotIsolatedCaller("clearApplicationUserData");
- if (packageName != null && packageName.equals(mDeviceOwnerName)) {
- throw new SecurityException("Clearing DeviceOwner data is forbidden.");
+
+ final DevicePolicyManagerInternal dpmi = LocalServices
+ .getService(DevicePolicyManagerInternal.class);
+ if (dpmi != null && dpmi.hasDeviceOwnerOrProfileOwner(packageName, userId)) {
+ throw new SecurityException("Cannot clear data for a device owner or a profile owner");
}
+
int uid = Binder.getCallingUid();
int pid = Binder.getCallingPid();
userId = mUserController.handleIncomingUser(pid, uid, userId, false,
@@ -5354,17 +5383,6 @@
@Override
public void killAllBackgroundProcesses() {
- killAllBackgroundProcesses(-1);
- }
-
- /**
- * Kills all background processes with targetSdkVersion below the specified
- * target SDK version.
- *
- * @param targetSdkVersion the target SDK version below which to kill
- * processes, or {@code -1} to kill all processes
- */
- private void killAllBackgroundProcesses(int targetSdkVersion) {
if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
!= PackageManager.PERMISSION_GRANTED) {
final String msg = "Permission Denial: killAllBackgroundProcesses() from pid="
@@ -5388,10 +5406,6 @@
// We don't kill persistent processes.
continue;
}
- if (targetSdkVersion > 0
- && app.info.targetSdkVersion >= targetSdkVersion) {
- continue;
- }
if (app.removed) {
procs.add(app);
} else if (app.setAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
@@ -5416,6 +5430,55 @@
}
}
+ /**
+ * Kills all background processes, except those matching any of the
+ * specified properties.
+ *
+ * @param minTargetSdk the target SDK version at or above which to preserve
+ * processes, or {@code -1} to ignore the target SDK
+ * @param maxProcState the process state at or below which to preserve
+ * processes, or {@code -1} to ignore the process state
+ */
+ private void killAllBackgroundProcessesExcept(int minTargetSdk, int maxProcState) {
+ if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
+ != PackageManager.PERMISSION_GRANTED) {
+ final String msg = "Permission Denial: killAllBackgroundProcessesExcept() from pid="
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
+ + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
+
+ final long callingId = Binder.clearCallingIdentity();
+ try {
+ synchronized (this) {
+ final ArrayList<ProcessRecord> procs = new ArrayList<>();
+ final int NP = mProcessNames.getMap().size();
+ for (int ip = 0; ip < NP; ip++) {
+ final SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
+ final int NA = apps.size();
+ for (int ia = 0; ia < NA; ia++) {
+ final ProcessRecord app = apps.valueAt(ia);
+ if (app.removed) {
+ procs.add(app);
+ } else if ((minTargetSdk < 0 || app.info.targetSdkVersion < minTargetSdk)
+ && (maxProcState < 0 || app.setProcState > maxProcState)) {
+ app.removed = true;
+ procs.add(app);
+ }
+ }
+ }
+
+ final int N = procs.size();
+ for (int i = 0; i < N; i++) {
+ removeProcessLocked(procs.get(i), false, true, "kill all background except");
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(callingId);
+ }
+ }
+
@Override
public void forceStopPackage(final String packageName, int userId) {
if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
@@ -6172,7 +6235,7 @@
app.makeActive(thread, mProcessStats);
app.curAdj = app.setAdj = ProcessList.INVALID_ADJ;
- app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT;
+ app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.forcingToForeground = null;
updateProcessForegroundLocked(app, false, false);
app.hasShownUi = false;
@@ -6230,9 +6293,10 @@
// If the app is being launched for restore or full backup, set it up specially
boolean isRestrictedBackupMode = false;
if (mBackupTarget != null && mBackupAppName.equals(processName)) {
- isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
- || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
- || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
+ isRestrictedBackupMode = mBackupTarget.appInfo.uid >= Process.FIRST_APPLICATION_UID
+ && ((mBackupTarget.backupMode == BackupRecord.RESTORE)
+ || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
+ || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL));
}
notifyPackageUse(app.instrumentationInfo != null
@@ -6983,6 +7047,8 @@
@Override
public Intent getIntentForIntentSender(IIntentSender pendingResult) {
+ enforceCallingPermission(Manifest.permission.GET_INTENT_SENDER_INTENT,
+ "getIntentForIntentSender()");
if (!(pendingResult instanceof PendingIntentRecord)) {
return null;
}
@@ -7490,7 +7556,16 @@
int checkAllowBackgroundLocked(int uid, String packageName, int callingPid) {
UidRecord uidRec = mActiveUids.get(uid);
- if (uidRec == null || uidRec.idle) {
+ if (!mLenientBackgroundCheck) {
+ if (uidRec == null
+ || uidRec.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND) {
+ if (mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND, uid,
+ packageName) != AppOpsManager.MODE_ALLOWED) {
+ return ActivityManager.APP_START_MODE_DELAYED;
+ }
+ }
+
+ } else if (uidRec == null || uidRec.idle) {
if (callingPid >= 0) {
ProcessRecord proc;
synchronized (mPidsSelfLocked) {
@@ -8728,6 +8803,10 @@
android.Manifest.permission.GET_DETAILED_TASKS)
== PackageManager.PERMISSION_GRANTED;
+ if (!isUserRunning(userId, ActivityManager.FLAG_AND_UNLOCKED)) {
+ Slog.i(TAG, "user " + userId + " is still locked. Cannot load recents");
+ return Collections.emptyList();
+ }
mRecentTasks.loadUserRecentsLocked(userId);
final int recentsCount = mRecentTasks.size();
@@ -9148,7 +9227,7 @@
// Kill the running processes.
for (int i = 0; i < procsToKill.size(); i++) {
ProcessRecord pr = procsToKill.get(i);
- if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
+ if (pr.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND
&& pr.curReceiver == null) {
pr.kill("remove task", true);
} else {
@@ -9473,7 +9552,7 @@
* docked stack. Pass {@code null} to use default bounds.
*/
@Override
- public void moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
+ public boolean moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
Rect initialBounds) {
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveTaskToDockedStack()");
synchronized (this) {
@@ -9482,7 +9561,8 @@
if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToDockedStack: moving task=" + taskId
+ " to createMode=" + createMode + " toTop=" + toTop);
mWindowManager.setDockedStackCreateState(createMode, initialBounds);
- mStackSupervisor.moveTaskToStackLocked(taskId, DOCKED_STACK_ID, toTop, !FORCE_FOCUS,
+ return mStackSupervisor.moveTaskToStackLocked(
+ taskId, DOCKED_STACK_ID, toTop, !FORCE_FOCUS,
"moveTaskToDockedStack", animate);
} finally {
Binder.restoreCallingIdentity(ident);
@@ -9561,6 +9641,20 @@
}
@Override
+ public void resizePinnedStack(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
+ enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ "resizePinnedStack()");
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (this) {
+ mStackSupervisor.resizePinnedStackLocked(pinnedBounds, tempPinnedTaskBounds);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override
public void positionTaskInStack(int taskId, int stackId, int position) {
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "positionTaskInStack()");
if (stackId == HOME_STACK_ID) {
@@ -9814,11 +9908,11 @@
private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {
List<ProviderInfo> providers = null;
try {
- ParceledListSlice<ProviderInfo> slice = AppGlobals.getPackageManager()
+ providers = AppGlobals.getPackageManager()
.queryContentProviders(app.processName, app.uid,
STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS
- | MATCH_DEBUG_TRIAGED_MISSING);
- providers = slice != null ? slice.getList() : null;
+ | MATCH_DEBUG_TRIAGED_MISSING)
+ .getList();
} catch (RemoteException ex) {
}
if (DEBUG_MU) Slog.v(TAG_MU,
@@ -10408,7 +10502,7 @@
cpi.packageName, r.userId)) {
final boolean callerForeground = r != null ? r.setSchedGroup
- != Process.THREAD_GROUP_BG_NONINTERACTIVE : true;
+ != ProcessList.SCHED_GROUP_BACKGROUND : true;
// Show a permission review UI only for starting from a foreground app
if (!callerForeground) {
@@ -10728,12 +10822,13 @@
return;
}
- final long token = Binder.clearCallingIdentity();
- try {
- mAppErrors.appNotResponding(host, null, null, false, "ContentProvider not responding");
- } finally {
- Binder.restoreCallingIdentity(token);
- }
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mAppErrors.appNotResponding(host, null, null, false,
+ "ContentProvider not responding");
+ }
+ });
}
public final void installSystemProviders() {
@@ -10762,6 +10857,23 @@
//mUsageStatsService.monitorPackages();
}
+ private void startPersistentApps(int matchFlags) {
+ if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) return;
+
+ synchronized (this) {
+ try {
+ final List<ApplicationInfo> apps = AppGlobals.getPackageManager()
+ .getPersistentApplications(STOCK_PM_FLAGS | matchFlags).getList();
+ for (ApplicationInfo app : apps) {
+ if (!"android".equals(app.packageName)) {
+ addAppLocked(app, false, null /* ABI override */);
+ }
+ }
+ } catch (RemoteException ex) {
+ }
+ }
+ }
+
/**
* When a user is unlocked, we need to install encryption-unaware providers
* belonging to any running apps.
@@ -10778,8 +10890,7 @@
// We're only interested in providers that are encryption unaware, and
// we don't care about uninstalled apps, since there's no way they're
// running at this point.
- final int matchFlags = GET_PROVIDERS | MATCH_ENCRYPTION_UNAWARE
- | MATCH_DEBUG_TRIAGED_MISSING;
+ final int matchFlags = GET_PROVIDERS | MATCH_ENCRYPTION_UNAWARE;
synchronized (this) {
final int NP = mProcessNames.getMap().size();
@@ -11376,21 +11487,46 @@
enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
"setAlwaysFinish()");
- Settings.Global.putInt(
- mContext.getContentResolver(),
- Settings.Global.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
+ long ident = Binder.clearCallingIdentity();
+ try {
+ Settings.Global.putInt(
+ mContext.getContentResolver(),
+ Settings.Global.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
- synchronized (this) {
- mAlwaysFinishActivities = enabled;
+ synchronized (this) {
+ mAlwaysFinishActivities = enabled;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
}
@Override
- public void setActivityController(IActivityController controller) {
+ public void setLenientBackgroundCheck(boolean enabled) {
+ enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
+ "setLenientBackgroundCheck()");
+
+ long ident = Binder.clearCallingIdentity();
+ try {
+ Settings.Global.putInt(
+ mContext.getContentResolver(),
+ Settings.Global.LENIENT_BACKGROUND_CHECK, enabled ? 1 : 0);
+
+ synchronized (this) {
+ mLenientBackgroundCheck = enabled;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override
+ public void setActivityController(IActivityController controller, boolean imAMonkey) {
enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
"setActivityController()");
synchronized (this) {
mController = controller;
+ mControllerIsAMonkey = imAMonkey;
Watchdog.getInstance().setActivityController(controller);
}
}
@@ -11417,7 +11553,7 @@
public boolean isUserAMonkey() {
synchronized (this) {
// If there is a controller also implies the user is a monkey.
- return (mUserIsMonkey || mController != null);
+ return (mUserIsMonkey || (mController != null && mControllerIsAMonkey));
}
}
@@ -12252,10 +12388,11 @@
+ " from " + proc.initialIdlePss + ")", true);
}
}
- } else if (proc.setProcState < ActivityManager.PROCESS_STATE_HOME) {
+ } else if (proc.setProcState < ActivityManager.PROCESS_STATE_HOME
+ && proc.setProcState > ActivityManager.PROCESS_STATE_NONEXISTENT) {
proc.notCachedSinceIdle = true;
proc.initialIdlePss = 0;
- proc.nextPssTime = ProcessList.computeNextPssTime(proc.curProcState, true,
+ proc.nextPssTime = ProcessList.computeNextPssTime(proc.setProcState, true,
mTestPssMode, isSleeping(), now);
}
}
@@ -12274,10 +12411,13 @@
final boolean supportsPictureInPicture =
mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE);
+ final boolean supportsMultiWindow = ActivityManager.supportsMultiWindow();
final String debugApp = Settings.Global.getString(resolver, DEBUG_APP);
final boolean waitForDebugger = Settings.Global.getInt(resolver, WAIT_FOR_DEBUGGER, 0) != 0;
final boolean alwaysFinishActivities =
Settings.Global.getInt(resolver, ALWAYS_FINISH_ACTIVITIES, 0) != 0;
+ final boolean lenientBackgroundCheck =
+ Settings.Global.getInt(resolver, LENIENT_BACKGROUND_CHECK, 0) != 0;
final boolean forceRtl = Settings.Global.getInt(resolver, DEVELOPMENT_FORCE_RTL, 0) != 0;
final boolean forceResizable = Settings.Global.getInt(
resolver, DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0;
@@ -12295,10 +12435,18 @@
mDebugApp = mOrigDebugApp = debugApp;
mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
mAlwaysFinishActivities = alwaysFinishActivities;
+ mLenientBackgroundCheck = lenientBackgroundCheck;
mForceResizableActivities = forceResizable;
mWindowManager.setForceResizableTasks(mForceResizableActivities);
- mSupportsFreeformWindowManagement = freeformWindowManagement || forceResizable;
- mSupportsPictureInPicture = supportsPictureInPicture || forceResizable;
+ if (supportsMultiWindow || forceResizable) {
+ mSupportsMultiWindow = true;
+ mSupportsFreeformWindowManagement = freeformWindowManagement || forceResizable;
+ mSupportsPictureInPicture = supportsPictureInPicture || forceResizable;
+ } else {
+ mSupportsMultiWindow = false;
+ mSupportsFreeformWindowManagement = false;
+ mSupportsPictureInPicture = false;
+ }
// This happens before any activities are started, so we can
// change mConfiguration in-place.
updateConfigurationLocked(configuration, null, true);
@@ -12466,7 +12614,7 @@
List<ResolveInfo> ris = null;
try {
ris = AppGlobals.getPackageManager().queryIntentReceivers(
- intent, null, MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
+ intent, null, MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM).getList();
} catch (RemoteException e) {
}
if (ris == null) {
@@ -12522,7 +12670,7 @@
// Make sure we have the current profile info, since it is needed for security checks.
mUserController.onSystemReady();
- mRecentTasks.onSystemReady();
+ mRecentTasks.onSystemReadyLocked();
// Check to see if there are any update receivers to run.
if (!mDidUpdate) {
if (mWaitingUpdate) {
@@ -12636,26 +12784,9 @@
mSystemServiceManager.startUser(currentUserId);
synchronized (this) {
- if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
- try {
- List apps = AppGlobals.getPackageManager().
- getPersistentApplications(STOCK_PM_FLAGS);
- if (apps != null) {
- int N = apps.size();
- int i;
- for (i=0; i<N; i++) {
- ApplicationInfo info
- = (ApplicationInfo)apps.get(i);
- if (info != null &&
- !info.packageName.equals("android")) {
- addAppLocked(info, false, null /* ABI override */);
- }
- }
- }
- } catch (RemoteException ex) {
- // pm is in same process, this will never happen.
- }
- }
+ // Only start up encryption-aware persistent apps; once user is
+ // unlocked we'll come back around and start unaware apps
+ startPersistentApps(PackageManager.MATCH_ENCRYPTION_AWARE);
// Start up initial activity.
mBooting = true;
@@ -12667,7 +12798,7 @@
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0,
UserHandle.USER_SYSTEM);
} catch (RemoteException e) {
- e.rethrowAsRuntimeException();
+ throw e.rethrowAsRuntimeException();
}
}
startHomeActivityLocked(currentUserId, "systemReady");
@@ -13352,6 +13483,14 @@
}
@Override
+ public int getMemoryTrimLevel() {
+ enforceNotIsolatedCaller("getMyMemoryState");
+ synchronized (this) {
+ return mLastMemoryLevel;
+ }
+ }
+
+ @Override
public void onShellCommand(FileDescriptor in, FileDescriptor out,
FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
(new ActivityManagerShellCommand(this, false)).exec(
@@ -13532,6 +13671,8 @@
synchronized (this) {
mServices.dumpServicesLocked(fd, pw, args, opti, true, dumpClient, dumpPackage);
}
+ } else if ("locks".equals(cmd)) {
+ LockGuard.dump(fd, pw, args);
} else {
// Dumping a single activity?
if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
@@ -14074,9 +14215,13 @@
}
}
if (dumpPackage == null) {
- if (mAlwaysFinishActivities || mController != null) {
+ if (mAlwaysFinishActivities || mLenientBackgroundCheck) {
pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
- + " mController=" + mController);
+ + " mLenientBackgroundCheck=" + mLenientBackgroundCheck);
+ }
+ if (mController != null) {
+ pw.println(" mController=" + mController
+ + " mControllerIsAMonkey=" + mControllerIsAMonkey);
}
if (dumpAll) {
pw.println(" Total persistent processes: " + numPers);
@@ -14674,12 +14819,15 @@
String oomAdj = ProcessList.makeOomAdjString(r.setAdj);
char schedGroup;
switch (r.setSchedGroup) {
- case Process.THREAD_GROUP_BG_NONINTERACTIVE:
+ case ProcessList.SCHED_GROUP_BACKGROUND:
schedGroup = 'B';
break;
- case Process.THREAD_GROUP_DEFAULT:
+ case ProcessList.SCHED_GROUP_DEFAULT:
schedGroup = 'F';
break;
+ case ProcessList.SCHED_GROUP_TOP_APP:
+ schedGroup = 'T';
+ break;
default:
schedGroup = '?';
break;
@@ -15097,6 +15245,7 @@
boolean dumpFullDetails = false;
boolean dumpDalvik = false;
boolean dumpSummaryOnly = false;
+ boolean dumpUnreachable = false;
boolean oomOnly = false;
boolean isCompact = false;
boolean localOnly = false;
@@ -15125,6 +15274,8 @@
dumpSummaryOnly = true;
} else if ("-S".equals(opt)) {
dumpSwapPss = true;
+ } else if ("--unreachable".equals(opt)) {
+ dumpUnreachable = true;
} else if ("--oom".equals(opt)) {
oomOnly = true;
} else if ("--local".equals(opt)) {
@@ -15286,7 +15437,7 @@
try {
pw.flush();
thread.dumpMemInfo(fd, mi, isCheckinRequest, dumpFullDetails,
- dumpDalvik, dumpSummaryOnly, innerArgs);
+ dumpDalvik, dumpSummaryOnly, dumpUnreachable, innerArgs);
} catch (RemoteException e) {
if (!isCheckinRequest) {
pw.println("Got RemoteException!");
@@ -16812,7 +16963,7 @@
continue;
}
List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
- .queryIntentReceivers(intent, resolvedType, pmFlags, user);
+ .queryIntentReceivers(intent, resolvedType, pmFlags, user).getList();
if (user != UserHandle.USER_SYSTEM && newReceivers != null) {
// If this is not the system user, we need to check for
// any receivers that should be filtered out.
@@ -16957,7 +17108,6 @@
case Process.ROOT_UID:
case Process.SYSTEM_UID:
case Process.PHONE_UID:
- case Process.SHELL_UID:
case Process.BLUETOOTH_UID:
case Process.NFC_UID:
isCallerSystem = true;
@@ -17083,10 +17233,11 @@
String ssp;
if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
boolean removed = Intent.ACTION_PACKAGE_REMOVED.equals(action);
- boolean fullUninstall = removed &&
- !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
+ final boolean replacing =
+ intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
final boolean killProcess =
!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false);
+ final boolean fullUninstall = removed && !replacing;
if (killProcess) {
forceStopPackageLocked(ssp, UserHandle.getAppId(
intent.getIntExtra(Intent.EXTRA_UID, -1)),
@@ -17094,7 +17245,10 @@
removed ? "pkg removed" : "pkg changed");
}
if (removed) {
- sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
+ final int cmd = killProcess
+ ? IApplicationThread.PACKAGE_REMOVED
+ : IApplicationThread.PACKAGE_REMOVED_DONT_KILL;
+ sendPackageBroadcastLocked(cmd,
new String[] {ssp}, userId);
if (fullUninstall) {
mAppOpsService.packageRemoved(
@@ -17129,7 +17283,23 @@
break;
}
break;
+ case Intent.ACTION_PACKAGE_REPLACED:
+ {
+ final Uri data = intent.getData();
+ final String ssp;
+ if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
+ final ApplicationInfo aInfo =
+ getPackageManagerInternalLocked().getApplicationInfo(
+ ssp,
+ userId);
+ mStackSupervisor.updateActivityApplicationInfoLocked(aInfo);
+ sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REPLACED,
+ new String[] {ssp}, userId);
+ }
+ break;
+ }
case Intent.ACTION_PACKAGE_ADDED:
+ {
// Special case for adding a package: by default turn on compatibility mode.
Uri data = intent.getData();
String ssp;
@@ -17147,6 +17317,7 @@
}
}
break;
+ }
case Intent.ACTION_TIMEZONE_CHANGED:
// If this is the time zone changed action, queue up a message that will reset
// the timezone of all currently running processes. This message will get
@@ -17171,6 +17342,15 @@
ProxyInfo proxy = intent.getParcelableExtra(Proxy.EXTRA_PROXY_INFO);
mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY_MSG, proxy));
break;
+ case android.hardware.Camera.ACTION_NEW_PICTURE:
+ case android.hardware.Camera.ACTION_NEW_VIDEO:
+ // These broadcasts are no longer allowed by the system, since they can
+ // cause significant thrashing at a crictical point (using the camera).
+ // Apps should use JobScehduler to monitor for media provider changes.
+ Slog.w(TAG, action + " no longer allowed; dropping from "
+ + UserHandle.formatUid(callingUid));
+ // Lie; we don't want to crash the app.
+ return ActivityManager.BROADCAST_SUCCESS;
}
}
@@ -17766,36 +17946,42 @@
final long origId = Binder.clearCallingIdentity();
final ActivityStack stack = mStackSupervisor.getStack(fromStackId);
if (stack != null) {
- if (fromStackId == DOCKED_STACK_ID) {
+ mWindowManager.deferSurfaceLayout();
+ try {
+ if (fromStackId == DOCKED_STACK_ID) {
- // We are moving all tasks from the docked stack to the fullscreen stack, which
- // is dismissing the docked stack, so resize all other stacks to fullscreen here
- // already so we don't end up with resize trashing.
- for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) {
- if (StackId.isResizeableByDockedStack(i)) {
- ActivityStack otherStack = mStackSupervisor.getStack(i);
- if (otherStack != null) {
- mStackSupervisor.resizeStackLocked(i,
- null, null, null, PRESERVE_WINDOWS,
- true /* allowResizeInDockedMode */);
+ // We are moving all tasks from the docked stack to the fullscreen stack,
+ // which is dismissing the docked stack, so resize all other stacks to
+ // fullscreen here already so we don't end up with resize trashing.
+ for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) {
+ if (StackId.isResizeableByDockedStack(i)) {
+ ActivityStack otherStack = mStackSupervisor.getStack(i);
+ if (otherStack != null) {
+ mStackSupervisor.resizeStackLocked(i,
+ null, null, null, PRESERVE_WINDOWS,
+ true /* allowResizeInDockedMode */);
+ }
}
}
}
- }
- final ArrayList<TaskRecord> tasks = stack.getAllTasks();
- final int size = tasks.size();
- if (onTop) {
- for (int i = 0; i < size; i++) {
- mStackSupervisor.moveTaskToStackLocked(tasks.get(i).taskId,
- FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP, !FORCE_FOCUS,
- "moveTasksToFullscreenStack", ANIMATE);
+ final ArrayList<TaskRecord> tasks = stack.getAllTasks();
+ final int size = tasks.size();
+ if (onTop) {
+ for (int i = 0; i < size; i++) {
+ mStackSupervisor.moveTaskToStackLocked(tasks.get(i).taskId,
+ FULLSCREEN_WORKSPACE_STACK_ID, onTop, !FORCE_FOCUS,
+ "moveTasksToFullscreenStack", ANIMATE);
+ }
+ } else {
+ for (int i = size - 1; i >= 0; i--) {
+ mStackSupervisor.positionTaskInStackLocked(tasks.get(i).taskId,
+ FULLSCREEN_WORKSPACE_STACK_ID, 0);
+ }
}
- } else {
- for (int i = size - 1; i >= 0; i--) {
- mStackSupervisor.positionTaskInStackLocked(tasks.get(i).taskId,
- FULLSCREEN_WORKSPACE_STACK_ID, 0);
- }
+ } finally {
+ mWindowManager.continueSurfaceLayout();
}
+
}
Binder.restoreCallingIdentity(origId);
}
@@ -17973,7 +18159,8 @@
final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
if (isDensityChange) {
- killAllBackgroundProcesses(Build.VERSION_CODES.N);
+ killAllBackgroundProcessesExcept(Build.VERSION_CODES.N,
+ ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
}
for (int i=mLruProcesses.size()-1; i>=0; i--) {
@@ -18194,7 +18381,7 @@
if (app.thread == null) {
app.adjSeq = mAdjSeq;
- app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ app.curSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.curProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
return (app.curAdj=app.curRawAdj=ProcessList.CACHED_APP_MAX_ADJ);
}
@@ -18214,7 +18401,7 @@
app.adjSeq = mAdjSeq;
app.curRawAdj = app.maxAdj;
app.foregroundActivities = false;
- app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
+ app.curSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT;
// System processes can do UI, and when they do we want to have
// them trim their memory after the user leaves the UI. To
@@ -18251,14 +18438,14 @@
if (app == TOP_APP) {
// The last app on the list is the foreground app.
adj = ProcessList.FOREGROUND_APP_ADJ;
- schedGroup = Process.THREAD_GROUP_TOP_APP;
+ schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
app.adjType = "top-activity";
foregroundActivities = true;
procState = PROCESS_STATE_CUR_TOP;
} else if (app.instrumentationClass != null) {
// Don't want to kill running instrumentation.
adj = ProcessList.FOREGROUND_APP_ADJ;
- schedGroup = Process.THREAD_GROUP_DEFAULT;
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.adjType = "instrumentation";
procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
} else if ((queue = isReceivingBroadcast(app)) != null) {
@@ -18268,7 +18455,7 @@
// broadcast as reflected by which queue it's active in.
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = (queue == mFgBroadcastQueue)
- ? Process.THREAD_GROUP_DEFAULT : Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
app.adjType = "broadcast";
procState = ActivityManager.PROCESS_STATE_RECEIVER;
} else if (app.executingServices.size() > 0) {
@@ -18276,13 +18463,13 @@
// counts as being in the foreground.
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = app.execServicesFg ?
- Process.THREAD_GROUP_DEFAULT : Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
app.adjType = "exec-service";
procState = ActivityManager.PROCESS_STATE_SERVICE;
//Slog.i(TAG, "EXEC " + (app.execServicesFg ? "FG" : "BG") + ": " + app);
} else {
// As far as we know the process is empty. We may change our mind later.
- schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
// At this point we don't actually know the adjustment. Use the cached adj
// value that the caller wants us to.
adj = cachedAdj;
@@ -18311,7 +18498,7 @@
if (procState > PROCESS_STATE_CUR_TOP) {
procState = PROCESS_STATE_CUR_TOP;
}
- schedGroup = Process.THREAD_GROUP_DEFAULT;
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.cached = false;
app.empty = false;
foregroundActivities = true;
@@ -18330,7 +18517,7 @@
if (procState > PROCESS_STATE_CUR_TOP) {
procState = PROCESS_STATE_CUR_TOP;
}
- schedGroup = Process.THREAD_GROUP_DEFAULT;
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.cached = false;
app.empty = false;
foregroundActivities = true;
@@ -18374,7 +18561,7 @@
procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
app.cached = false;
app.adjType = "fg-service";
- schedGroup = Process.THREAD_GROUP_DEFAULT;
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
} else if (app.forcingToForeground != null) {
// The user is aware of this app, so make it visible.
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
@@ -18382,7 +18569,7 @@
app.cached = false;
app.adjType = "force-fg";
app.adjSource = app.forcingToForeground;
- schedGroup = Process.THREAD_GROUP_DEFAULT;
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
}
@@ -18390,7 +18577,7 @@
if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ) {
// We don't want to kill the current heavy-weight process.
adj = ProcessList.HEAVY_WEIGHT_APP_ADJ;
- schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.cached = false;
app.adjType = "heavy";
}
@@ -18404,7 +18591,7 @@
// This process is hosting what we currently consider to be the
// home app, so we don't want to let it go into the background.
adj = ProcessList.HOME_APP_ADJ;
- schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.cached = false;
app.adjType = "home";
}
@@ -18419,7 +18606,7 @@
// We want to try to keep it around more aggressively, to give
// a good experience around switching between two apps.
adj = ProcessList.PREVIOUS_APP_ADJ;
- schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.cached = false;
app.adjType = "previous";
}
@@ -18459,7 +18646,7 @@
for (int is = app.services.size()-1;
is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
- || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
+ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > ActivityManager.PROCESS_STATE_TOP);
is--) {
ServiceRecord s = app.services.valueAt(is);
@@ -18497,13 +18684,13 @@
}
for (int conni = s.connections.size()-1;
conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
- || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
+ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > ActivityManager.PROCESS_STATE_TOP);
conni--) {
ArrayList<ConnectionRecord> clist = s.connections.valueAt(conni);
for (int i = 0;
i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ
- || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
+ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > ActivityManager.PROCESS_STATE_TOP);
i++) {
// XXX should compute this based on the max of
@@ -18588,8 +18775,15 @@
}
}
if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
- if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
- schedGroup = Process.THREAD_GROUP_DEFAULT;
+ // This will treat important bound services identically to
+ // the top app, which may behave differently than generic
+ // foreground work.
+ if (client.curSchedGroup > schedGroup) {
+ if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
+ schedGroup = client.curSchedGroup;
+ } else {
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
+ }
}
if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) {
if (clientProcState == ActivityManager.PROCESS_STATE_TOP) {
@@ -18653,11 +18847,15 @@
final ActivityRecord a = cr.activity;
if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ &&
- (a.visible || a.state == ActivityState.RESUMED
- || a.state == ActivityState.PAUSING)) {
+ (a.visible || a.state == ActivityState.RESUMED ||
+ a.state == ActivityState.PAUSING)) {
adj = ProcessList.FOREGROUND_APP_ADJ;
if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
- schedGroup = Process.THREAD_GROUP_DEFAULT;
+ if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
+ schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
+ } else {
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
+ }
}
app.cached = false;
app.adjType = "service";
@@ -18674,13 +18872,13 @@
for (int provi = app.pubProviders.size()-1;
provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
- || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
+ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > ActivityManager.PROCESS_STATE_TOP);
provi--) {
ContentProviderRecord cpr = app.pubProviders.valueAt(provi);
for (int i = cpr.connections.size()-1;
i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
- || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
+ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > ActivityManager.PROCESS_STATE_TOP);
i--) {
ContentProviderConnection conn = cpr.connections.get(i);
@@ -18737,8 +18935,8 @@
if (procState > clientProcState) {
procState = clientProcState;
}
- if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
- schedGroup = Process.THREAD_GROUP_DEFAULT;
+ if (client.curSchedGroup > schedGroup) {
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
}
// If the provider has external (non-framework) process
@@ -18747,7 +18945,7 @@
if (cpr.hasExternalProcessHandles()) {
if (adj > ProcessList.FOREGROUND_APP_ADJ) {
adj = ProcessList.FOREGROUND_APP_ADJ;
- schedGroup = Process.THREAD_GROUP_DEFAULT;
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.cached = false;
app.adjType = "provider";
app.adjTarget = cpr.name;
@@ -18761,7 +18959,7 @@
if (app.lastProviderTime > 0 && (app.lastProviderTime+CONTENT_PROVIDER_RETAIN_TIME) > now) {
if (adj > ProcessList.PREVIOUS_APP_ADJ) {
adj = ProcessList.PREVIOUS_APP_ADJ;
- schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.cached = false;
app.adjType = "provider";
}
@@ -18840,7 +19038,7 @@
if (adj > app.maxAdj) {
adj = app.maxAdj;
if (app.maxAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
- schedGroup = Process.THREAD_GROUP_DEFAULT;
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
}
@@ -19256,17 +19454,29 @@
if (app.setSchedGroup != app.curSchedGroup) {
app.setSchedGroup = app.curSchedGroup;
if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
- "Setting process group of " + app.processName
+ "Setting sched group of " + app.processName
+ " to " + app.curSchedGroup);
if (app.waitingToKill != null && app.curReceiver == null
- && app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
+ && app.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND) {
app.kill(app.waitingToKill, true);
success = false;
} else {
+ int processGroup;
+ switch (app.curSchedGroup) {
+ case ProcessList.SCHED_GROUP_BACKGROUND:
+ processGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ break;
+ case ProcessList.SCHED_GROUP_TOP_APP:
+ processGroup = Process.THREAD_GROUP_TOP_APP;
+ break;
+ default:
+ processGroup = Process.THREAD_GROUP_DEFAULT;
+ break;
+ }
if (true) {
long oldId = Binder.clearCallingIdentity();
try {
- Process.setProcessGroup(app.pid, app.curSchedGroup);
+ Process.setProcessGroup(app.pid, processGroup);
} catch (Exception e) {
Slog.w(TAG, "Failed setting process group of " + app.pid
+ " to " + app.curSchedGroup);
@@ -19277,7 +19487,7 @@
} else {
if (app.thread != null) {
try {
- app.thread.setSchedulingGroup(app.curSchedGroup);
+ app.thread.setSchedulingGroup(processGroup);
} catch (RemoteException e) {
}
}
@@ -20440,6 +20650,10 @@
Slog.w(TAG, "No user info for user #" + targetUserId);
return false;
}
+ if (!targetUserInfo.supportsSwitchTo()) {
+ Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not supported");
+ return false;
+ }
if (targetUserInfo.isManagedProfile()) {
Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not a full user");
return false;
@@ -20681,6 +20895,20 @@
voiceSession, voiceInteractor);
}
}
+
+ @Override
+ public void notifyStartingWindowDrawn() {
+ synchronized (ActivityManagerService.this) {
+ mStackSupervisor.mActivityMetricsLogger.notifyStartingWindowDrawn();
+ }
+ }
+
+ @Override
+ public void notifyAppTransitionStarting(int reason) {
+ synchronized (ActivityManagerService.this) {
+ mStackSupervisor.mActivityMetricsLogger.notifyTransitionStarting(reason);
+ }
+ }
}
private final class SleepTokenImpl extends SleepToken {
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 8c99739..0253976 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -62,6 +62,8 @@
return runUntrackAssociations(pw);
case "is-user-stopped":
return runIsUserStopped(pw);
+ case "lenient-background-check":
+ return runLenientBackgroundCheck(pw);
default:
return handleDefaultCommands(cmd);
}
@@ -152,6 +154,22 @@
return 0;
}
+ int runLenientBackgroundCheck(PrintWriter pw) throws RemoteException {
+ String arg = getNextArg();
+ if (arg != null) {
+ boolean state = Boolean.valueOf(arg) || "1".equals(arg);
+ mInterface.setLenientBackgroundCheck(state);
+ }
+ synchronized (mInternal) {
+ if (mInternal.mLenientBackgroundCheck) {
+ pw.println("Lenient background check enabled");
+ } else {
+ pw.println("Lenient background check disabled");
+ }
+ }
+ return 0;
+ }
+
@Override
public void onHelp() {
PrintWriter pw = getOutPrintWriter();
@@ -203,6 +221,8 @@
pw.println(" Disable and clear association tracking.");
pw.println(" is-user-stopped <USER_ID>");
pw.println(" returns whether <USER_ID> has been stopped or not");
+ pw.println(" lenient-background-check [<true|false>]");
+ pw.println(" optionally controls lenient background check mode, returns current mode.");
}
}
}
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index ffb2fc4..43e1bdf 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -7,11 +7,13 @@
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
+import android.annotation.Nullable;
import android.app.ActivityManager.StackId;
import android.content.Context;
import android.os.SystemClock;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
/**
* Handles logging into Tron.
@@ -24,6 +26,8 @@
private static final int WINDOW_STATE_FREEFORM = 2;
private static final int WINDOW_STATE_INVALID = -1;
+ private static final long INVALID_START_TIME = -1;
+
// Preallocated strings we are sending to tron, so we don't have to allocate a new one every
// time we log.
private static final String[] TRON_WINDOW_STATE_VARZ_STRINGS = {
@@ -34,6 +38,11 @@
private final ActivityStackSupervisor mSupervisor;
private final Context mContext;
+ private long mCurrentTransitionStartTime = INVALID_START_TIME;
+ private boolean mLoggedWindowsDrawn;
+ private boolean mLoggedStartingWindowDrawn;
+ private boolean mLoggedTransitionStarting;
+
ActivityMetricsLogger(ActivityStackSupervisor supervisor, Context context) {
mLastLogTimeSecs = SystemClock.elapsedRealtime() / 1000;
mSupervisor = supervisor;
@@ -52,7 +61,7 @@
mLastLogTimeSecs = now;
ActivityStack stack = mSupervisor.getStack(DOCKED_STACK_ID);
- if (stack != null && stack.getStackVisibilityLocked() != STACK_INVISIBLE) {
+ if (stack != null && stack.getStackVisibilityLocked(null) != STACK_INVISIBLE) {
mWindowState = WINDOW_STATE_SIDE_BY_SIDE;
return;
}
@@ -73,4 +82,101 @@
throw new IllegalStateException("Unknown stack=" + stack);
}
}
+
+ /**
+ * Notifies the tracker at the earliest possible point when we are starting to launch an
+ * activity.
+ */
+ void notifyActivityLaunching() {
+ mCurrentTransitionStartTime = System.currentTimeMillis();
+ }
+
+ /**
+ * Notifies the tracker the the activity is actually launching.
+ *
+ * @param resultCode one of the ActivityManager.START_* flags, indicating the result of the
+ * launch
+ * @param componentName the component name of the activity being launched
+ * @param processRunning whether the process that will contains the activity is already running
+ */
+ void notifyActivityLaunched(int resultCode, @Nullable String componentName,
+ boolean processRunning) {
+
+ if (resultCode < 0 || componentName == null) {
+
+ // Failed to launch, don't track anything.
+ reset();
+ return;
+ }
+
+ MetricsLogger.action(mContext, MetricsEvent.APP_TRANSITION_COMPONENT_NAME,
+ componentName);
+ MetricsLogger.action(mContext, MetricsEvent.APP_TRANSITION_PROCESS_RUNNING,
+ processRunning);
+ MetricsLogger.action(mContext, MetricsEvent.APP_TRANSITION_DEVICE_UPTIME_SECONDS,
+ (int) (SystemClock.uptimeMillis() / 1000));
+ }
+
+ /**
+ * Notifies the tracker that all windows of the app have been drawn.
+ */
+ void notifyWindowsDrawn() {
+ if (!isTransitionActive() || mLoggedWindowsDrawn) {
+ return;
+ }
+ MetricsLogger.action(mContext, MetricsEvent.APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS,
+ calculateCurrentDelay());
+ mLoggedWindowsDrawn = true;
+ if (mLoggedTransitionStarting) {
+ reset();
+ }
+ }
+
+ /**
+ * Notifies the tracker that the starting window was drawn.
+ */
+ void notifyStartingWindowDrawn() {
+ if (!isTransitionActive() || mLoggedStartingWindowDrawn) {
+ return;
+ }
+ mLoggedStartingWindowDrawn = true;
+ MetricsLogger.action(mContext, MetricsEvent.APP_TRANSITION_STARTING_WINDOW_DELAY_MS,
+ calculateCurrentDelay());
+ }
+
+ /**
+ * Notifies the tracker that the app transition is starting.
+ *
+ * @param reason The reason why we started it. Must be on of
+ * ActivityManagerInternal.APP_TRANSITION_* reasons.
+ */
+ void notifyTransitionStarting(int reason) {
+ if (!isTransitionActive() || mLoggedTransitionStarting) {
+ return;
+ }
+ MetricsLogger.action(mContext, MetricsEvent.APP_TRANSITION_REASON, reason);
+ MetricsLogger.action(mContext, MetricsEvent.APP_TRANSITION_DELAY_MS,
+ calculateCurrentDelay());
+ mLoggedTransitionStarting = true;
+ if (mLoggedWindowsDrawn) {
+ reset();
+ }
+ }
+
+ private boolean isTransitionActive() {
+ return mCurrentTransitionStartTime != INVALID_START_TIME;
+ }
+
+ private void reset() {
+ mCurrentTransitionStartTime = INVALID_START_TIME;
+ mLoggedWindowsDrawn = false;
+ mLoggedTransitionStarting = false;
+ mLoggedStartingWindowDrawn = false;
+ }
+
+ private int calculateCurrentDelay() {
+
+ // Shouldn't take more than 25 days to launch an app, so int is fine here.
+ return (int) (System.currentTimeMillis() - mCurrentTransitionStartTime);
+ }
}
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 90a7da9..e430dad 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -76,6 +76,7 @@
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.Objects;
@@ -196,7 +197,12 @@
private boolean inHistory; // are we in the history stack?
final ActivityStackSupervisor mStackSupervisor;
- boolean mStartingWindowShown = false;
+
+ static final int STARTING_WINDOW_NOT_SHOWN = 0;
+ static final int STARTING_WINDOW_SHOWN = 1;
+ static final int STARTING_WINDOW_REMOVED = 2;
+ int mStartingWindowState = STARTING_WINDOW_NOT_SHOWN;
+
boolean mUpdateTaskThumbnailWhenHidden;
ActivityContainer mInitialActivityContainer;
@@ -214,6 +220,19 @@
boolean pendingVoiceInteractionStart; // Waiting for activity-invoked voice session
IVoiceInteractionSession voiceSession; // Voice interaction session for this activity
+ private static String startingWindowStateToString(int state) {
+ switch (state) {
+ case STARTING_WINDOW_NOT_SHOWN:
+ return "STARTING_WINDOW_NOT_SHOWN";
+ case STARTING_WINDOW_SHOWN:
+ return "STARTING_WINDOW_SHOWN";
+ case STARTING_WINDOW_REMOVED:
+ return "STARTING_WINDOW_REMOVED";
+ default:
+ return "unknown state=" + state;
+ }
+ }
+
void dump(PrintWriter pw, String prefix) {
final long now = SystemClock.uptimeMillis();
pw.print(prefix); pw.print("packageName="); pw.print(packageName);
@@ -234,6 +253,10 @@
pw.print(prefix); pw.print("resDir="); pw.println(appInfo.publicSourceDir);
}
pw.print(prefix); pw.print("dataDir="); pw.println(appInfo.dataDir);
+ if (appInfo.splitSourceDirs != null) {
+ pw.print(prefix); pw.print("splitDir=");
+ pw.println(Arrays.toString(appInfo.splitSourceDirs));
+ }
}
pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
pw.print(" componentSpecified="); pw.print(componentSpecified);
@@ -320,7 +343,9 @@
pw.print(" inHistory="); pw.print(inHistory);
pw.print(" visible="); pw.print(visible);
pw.print(" sleeping="); pw.print(sleeping);
- pw.print(" idle="); pw.println(idle);
+ pw.print(" idle="); pw.print(idle);
+ pw.print(" mStartingWindowState=");
+ pw.println(startingWindowStateToString(mStartingWindowState));
pw.print(prefix); pw.print("fullscreen="); pw.print(fullscreen);
pw.print(" noDisplay="); pw.print(noDisplay);
pw.print(" immersive="); pw.print(immersive);
@@ -1166,6 +1191,7 @@
}
void windowsDrawnLocked() {
+ mStackSupervisor.mActivityMetricsLogger.notifyWindowsDrawn();
if (displayStartTime != 0) {
reportLaunchTimeLocked(SystemClock.uptimeMillis());
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 574b9db..e50722a 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -34,6 +34,8 @@
import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
+import static com.android.server.am.ActivityRecord.STARTING_WINDOW_REMOVED;
+import static com.android.server.am.ActivityRecord.STARTING_WINDOW_SHOWN;
import static com.android.server.am.ActivityStackSupervisor.FindTaskResult;
import static com.android.server.am.ActivityStackSupervisor.MOVING;
import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
@@ -63,7 +65,7 @@
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
+import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.net.Uri;
@@ -183,7 +185,7 @@
* The back history of all previous (and possibly still
* running) activities. It contains #TaskRecord objects.
*/
- private ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();
+ private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();
/**
* Used for validating app tokens with window manager.
@@ -838,6 +840,18 @@
}
}
+ void updateActivityApplicationInfoLocked(ApplicationInfo aInfo) {
+ final String packageName = aInfo.packageName;
+ for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
+ final List<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
+ for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
+ if (packageName.equals(activities.get(activityNdx).packageName)) {
+ activities.get(activityNdx).info.applicationInfo = aInfo;
+ }
+ }
+ }
+ }
+
/**
* @return true if something must be done before going to sleep.
*/
@@ -1100,7 +1114,7 @@
r.stopped = true;
r.state = ActivityState.STOPPED;
- mWindowManager.notifyAppStopped(r.appToken);
+ mWindowManager.notifyAppStopped(r.appToken, true);
if (getVisibleBehindActivity() == r) {
mStackSupervisor.requestVisibleBehindLocked(r, false);
@@ -1149,7 +1163,7 @@
|| mService.isSleepingOrShuttingDown()) {
// If we were visible then resumeTopActivities will release resources before
// stopping.
- addToStopping(prev);
+ addToStopping(prev, true /* immediate */);
}
} else {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "App died during pause, not stopping: " + prev);
@@ -1210,15 +1224,21 @@
mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
- private void addToStopping(ActivityRecord r) {
- mStackSupervisor.mStoppingActivities.add(r);
- if (mStackSupervisor.mStoppingActivities.size() > MAX_STOPPING_TO_FORCE ||
- r.frontOfTask && mTaskHistory.size() <= 1) {
- // If we already have a few activities waiting to stop,
- // then give up on things going idle and start clearing
- // them out. Or if r is the last of activity of the last task the stack
- // will be empty and must be cleared immediately.
- if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "To many pending stops, forcing idle");
+ private void addToStopping(ActivityRecord r, boolean immediate) {
+ if (!mStackSupervisor.mStoppingActivities.contains(r)) {
+ mStackSupervisor.mStoppingActivities.add(r);
+ }
+
+ // If we already have a few activities waiting to stop, then give up
+ // on things going idle and start clearing them out. Or if r is the
+ // last of activity of the last task the stack will be empty and must
+ // be cleared immediately.
+ boolean forceIdle = mStackSupervisor.mStoppingActivities.size() > MAX_STOPPING_TO_FORCE
+ || (r.frontOfTask && mTaskHistory.size() <= 1);
+
+ if (immediate || forceIdle) {
+ if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Scheduling idle now: forceIdle="
+ + forceIdle + "immediate=" + immediate);
mStackSupervisor.scheduleIdleLocked();
} else {
mStackSupervisor.checkReadyForSleepLocked();
@@ -1347,7 +1367,7 @@
for (int i = stacks.size() - 1; i >= 0; --i) {
ActivityStack stack = stacks.get(i);
if (stack != this && stack.isFocusable()
- && stack.getStackVisibilityLocked() != STACK_INVISIBLE) {
+ && stack.getStackVisibilityLocked(null) != STACK_INVISIBLE) {
return stack;
}
}
@@ -1366,21 +1386,26 @@
return false;
}
- private boolean hasTranslucentActivity(ActivityStack stack) {
- final ArrayList<TaskRecord> tasks = stack.getAllTasks();
- for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = tasks.get(taskNdx);
+ /**
+ * Returns true if the stack is translucent and can have other contents visible behind it if
+ * needed. A stack is considered translucent if it don't contain a visible or
+ * starting (about to be visible) activity that is fullscreen (opaque).
+ * @param starting The currently starting activity or null if there is none.
+ */
+ private boolean isStackTranslucent(ActivityRecord starting) {
+ for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = mTaskHistory.get(taskNdx);
final ArrayList<ActivityRecord> activities = task.mActivities;
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = activities.get(activityNdx);
// Conditions for an activity to obscure the stack we're
// examining:
- // 1. Not Finishing AND Visible AND:
+ // 1. Not Finishing AND (Visible or the Starting activity) AND:
// 2. Either:
// - Full Screen Activity OR
// - On top of Home and our stack is NOT home
- if (!r.finishing && r.visible && (r.fullscreen ||
+ if (!r.finishing && (r.visible || r == starting) && (r.fullscreen ||
(!isHomeStack() && r.frontOfTask && task.isOverHomeStack()))) {
return false;
}
@@ -1392,8 +1417,9 @@
/**
* Returns stack's visibility: {@link #STACK_INVISIBLE}, {@link #STACK_VISIBLE} or
* {@link #STACK_VISIBLE_ACTIVITY_BEHIND}.
+ * @param starting The currently starting activity or null if there is none.
*/
- int getStackVisibilityLocked() {
+ int getStackVisibilityLocked(ActivityRecord starting) {
if (!isAttached()) {
return STACK_INVISIBLE;
}
@@ -1428,10 +1454,12 @@
if (mStackId == DOCKED_STACK_ID) {
// Docked stack is always visible, except in the case where the top running activity
- // task in the focus stack doesn't support any form of resizing.
+ // task in the focus stack doesn't support any form of resizing but we show it for the
+ // home task even though it's not resizable.
final ActivityRecord r = focusedStack.topRunningActivityLocked();
final TaskRecord task = r != null ? r.task : null;
- return task == null || task.canGoInDockedStack() ? STACK_VISIBLE : STACK_INVISIBLE;
+ return task == null || task.canGoInDockedStack() || task.isHomeTask() ? STACK_VISIBLE
+ : STACK_INVISIBLE;
}
// Find the first stack below focused stack that actually got something visible.
@@ -1447,7 +1475,7 @@
}
if (focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
- && hasTranslucentActivity(focusedStack)) {
+ && focusedStack.isStackTranslucent(starting)) {
// Stacks behind the fullscreen stack with a translucent activity are always
// visible so they can act as a backdrop to the translucent activity.
// For example, dialog activities
@@ -1482,7 +1510,7 @@
return STACK_INVISIBLE;
}
- if (!hasTranslucentActivity(stack)) {
+ if (!stack.isStackTranslucent(starting)) {
return STACK_INVISIBLE;
}
}
@@ -1520,7 +1548,7 @@
// If the top activity is not fullscreen, then we need to
// make sure any activities under it are now visible.
boolean aboveTop = top != null;
- final int stackVisibility = getStackVisibilityLocked();
+ final int stackVisibility = getStackVisibilityLocked(starting);
final boolean stackInvisible = stackVisibility != STACK_VISIBLE;
final boolean stackVisibleBehind = stackVisibility == STACK_VISIBLE_ACTIVITY_BEHIND;
boolean behindFullscreenActivity = stackInvisible;
@@ -1697,10 +1725,7 @@
if (visibleBehind == r) {
releaseBackgroundResources(r);
} else {
- if (!mStackSupervisor.mStoppingActivities.contains(r)) {
- mStackSupervisor.mStoppingActivities.add(r);
- }
- mStackSupervisor.scheduleIdleLocked();
+ addToStopping(r, true /* immediate */);
}
break;
@@ -1840,10 +1865,11 @@
continue;
}
- if (r.state == ActivityState.INITIALIZING && r.mStartingWindowShown) {
+ if (r.state == ActivityState.INITIALIZING
+ && r.mStartingWindowState == STARTING_WINDOW_SHOWN) {
if (DEBUG_VISIBILITY) Slog.w(TAG_VISIBILITY,
"Found orphaned starting window " + r);
- r.mStartingWindowShown = false;
+ r.mStartingWindowState = STARTING_WINDOW_REMOVED;
mWindowManager.removeAppStartingWindow(r.appToken);
}
}
@@ -2226,6 +2252,10 @@
next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
}
+ // Well the app will no longer be stopped.
+ // Clear app token stopped state in window manager if needed.
+ mWindowManager.notifyAppStopped(next.appToken, false);
+
EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
System.identityHashCode(next), next.task.taskId, next.shortComponentName);
@@ -2258,6 +2288,7 @@
mService.compatibilityInfoForPackageLocked(next.info.applicationInfo),
next.nonLocalizedLabel, next.labelRes, next.icon, next.logo,
next.windowFlags, null, true);
+ next.mStartingWindowState = STARTING_WINDOW_SHOWN;
}
mStackSupervisor.startSpecificActivityLocked(next, true, false);
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
@@ -2290,6 +2321,7 @@
next.nonLocalizedLabel,
next.labelRes, next.icon, next.logo, next.windowFlags,
null, true);
+ next.mStartingWindowState = STARTING_WINDOW_SHOWN;
}
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
}
@@ -2522,7 +2554,7 @@
r.info.applicationInfo), r.nonLocalizedLabel,
r.labelRes, r.icon, r.logo, r.windowFlags,
prev != null ? prev.appToken : null, showStartingIcon);
- r.mStartingWindowShown = true;
+ r.mStartingWindowState = STARTING_WINDOW_SHOWN;
}
} else {
// If this is the first activity, don't do any fancy animations,
@@ -2996,6 +3028,8 @@
if (!r.visible) {
mWindowManager.setAppVisibility(r.appToken, false);
}
+ EventLogTags.writeAmStopActivity(
+ r.userId, System.identityHashCode(r), r.shortComponentName);
r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags);
if (mService.isSleepingOrShuttingDown()) {
r.setSleeping(true);
@@ -3261,7 +3295,7 @@
// finishing until the resumed one becomes visible.
if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
if (!mStackSupervisor.mStoppingActivities.contains(r)) {
- addToStopping(r);
+ addToStopping(r, false /* immediate */);
}
if (DEBUG_STATES) Slog.v(TAG_STATES,
"Moving to STOPPING: "+ r + " (finish requested)");
@@ -3777,7 +3811,8 @@
void releaseBackgroundResources(ActivityRecord r) {
if (hasVisibleBehindActivity() &&
!mHandler.hasMessages(RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG)) {
- if (r == topRunningActivityLocked() && getStackVisibilityLocked() == STACK_VISIBLE) {
+ if (r == topRunningActivityLocked()
+ && getStackVisibilityLocked(null) == STACK_VISIBLE) {
// Don't release the top activity if it has requested to run behind the next
// activity and the stack is currently visible.
return;
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index c143474..48f31f9 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -119,6 +119,7 @@
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
@@ -400,12 +401,12 @@
// The default minimal size that will be used if the activity doesn't specify its minimal size.
// It will be calculated when the default display gets added.
- private int mDefaultMinimalSizeOfResizeableTask = -1;
+ int mDefaultMinimalSizeOfResizeableTask = -1;
// Whether tasks have moved and we need to rank the tasks before next OOM scoring
private boolean mTaskLayersChanged = true;
- private final ActivityMetricsLogger mActivityMetricsLogger;
+ final ActivityMetricsLogger mActivityMetricsLogger;
private final ResizeDockedStackTimeout mResizeDockedStackTimeout;
@@ -719,14 +720,14 @@
}
int getNextTaskIdForUserLocked(int userId) {
- mRecentTasks.loadUserRecentsLocked(userId);
final int currentTaskId = mCurTaskIdForUser.get(userId, userId * MAX_TASK_IDS_PER_USER);
// for a userId u, a taskId can only be in the range
// [u*MAX_TASK_IDS_PER_USER, (u+1)*MAX_TASK_IDS_PER_USER-1], so if MAX_TASK_IDS_PER_USER
// was 10, user 0 could only have taskIds 0 to 9, user 1: 10 to 19, user 2: 20 to 29, so on.
int candidateTaskId = currentTaskId;
- while (anyTaskForIdLocked(candidateTaskId, !RESTORE_FROM_RECENTS,
- INVALID_STACK_ID) != null) {
+ while (mRecentTasks.taskIdTakenForUserLocked(candidateTaskId, userId)
+ || anyTaskForIdLocked(candidateTaskId, !RESTORE_FROM_RECENTS,
+ INVALID_STACK_ID) != null) {
candidateTaskId++;
if (candidateTaskId == (userId + 1) * MAX_TASK_IDS_PER_USER) {
// Wrap around as there will be smaller task ids that are available now.
@@ -1699,6 +1700,15 @@
return false;
}
+ void updateActivityApplicationInfoLocked(ApplicationInfo aInfo) {
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ stacks.get(stackNdx).updateActivityApplicationInfoLocked(aInfo);
+ }
+ }
+ }
+
TaskRecord finishTopRunningActivityLocked(ProcessRecord app, String reason) {
TaskRecord finishedTask = null;
ActivityStack focusedStack = getFocusedStack();
@@ -2033,14 +2043,31 @@
|| tempOtherTaskInsetBounds != null);
}
+ void resizePinnedStackLocked(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
+ final ActivityStack stack = getStack(PINNED_STACK_ID);
+ if (stack == null) {
+ Slog.w(TAG, "resizePinnedStackLocked: pinned stack not found");
+ return;
+ }
+ Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizePinnedStack");
+ mWindowManager.deferSurfaceLayout();
+ try {
+ ActivityRecord r = stack.topRunningActivityLocked();
+ resizeStackUncheckedLocked(stack, pinnedBounds, tempPinnedTaskBounds,
+ null);
+ ensureConfigurationAndResume(stack, r, false);
+ } finally {
+ mWindowManager.continueSurfaceLayout();
+ Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+ }
+ }
+
boolean resizeTaskLocked(TaskRecord task, Rect bounds, int resizeMode, boolean preserveWindow) {
if (!task.isResizeable()) {
Slog.w(TAG, "resizeTask: task " + task + " not resizeable.");
return true;
}
- adjustForMinimalTaskDimensions(task, bounds);
-
// If this is a forced resize, let it go through even if the bounds is not changing,
// as we might need a relayout due to surface size change (to/from fullscreen).
final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
@@ -2074,7 +2101,7 @@
// to be relaunched due to configuration change.
boolean kept = true;
if (overrideConfig != null) {
- ActivityRecord r = task.topRunningActivityLocked();
+ final ActivityRecord r = task.topRunningActivityLocked();
if (r != null) {
final ActivityStack stack = task.stack;
kept = stack.ensureActivityConfigurationLocked(r, 0, preserveWindow);
@@ -2085,44 +2112,12 @@
}
}
}
- mWindowManager.resizeTask(task.taskId, bounds, task.mOverrideConfig, kept, forced);
+ mWindowManager.resizeTask(task.taskId, task.mBounds, task.mOverrideConfig, kept, forced);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
return kept;
}
- private void adjustForMinimalTaskDimensions(TaskRecord task, Rect bounds) {
- if (bounds == null) {
- return;
- }
- int minimalSize = task.mMinimalSize == -1 ? mDefaultMinimalSizeOfResizeableTask
- : task.mMinimalSize;
- final boolean adjustWidth = minimalSize > bounds.width();
- final boolean adjustHeight = minimalSize > bounds.height();
- if (!(adjustWidth || adjustHeight)) {
- return;
- }
- Rect taskBounds = task.mBounds;
- if (adjustWidth) {
- if (taskBounds != null && bounds.right == taskBounds.right) {
- bounds.left = bounds.right - minimalSize;
- } else {
- // Either left bounds match, or neither match, or the previous bounds were
- // fullscreen and we default to keeping left.
- bounds.right = bounds.left + minimalSize;
- }
- }
- if (adjustHeight) {
- if (taskBounds != null && bounds.bottom == taskBounds.bottom) {
- bounds.top = bounds.bottom - minimalSize;
- } else {
- // Either top bounds match, or neither match, or the previous bounds were
- // fullscreen and we default to keeping top.
- bounds.bottom = bounds.top + minimalSize;
- }
- }
- }
-
ActivityStack createStackOnDisplay(int stackId, int displayId, boolean onTop) {
ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
if (activityDisplay == null) {
@@ -2207,6 +2202,12 @@
*/
ActivityStack moveTaskToStackUncheckedLocked(
TaskRecord task, int stackId, boolean toTop, boolean forceFocus, String reason) {
+
+ if (StackId.isMultiWindowStack(stackId) && !mService.mSupportsMultiWindow) {
+ throw new IllegalStateException("moveTaskToStackUncheckedLocked: Device doesn't "
+ + "support multi-window task=" + task + " to stackId=" + stackId);
+ }
+
final ActivityRecord r = task.getTopActivity();
final ActivityStack prevStack = task.stack;
final boolean wasFocused = isFocusedStack(prevStack) && (topRunningActivityLocked() == r);
@@ -2217,9 +2218,7 @@
final boolean wasFront = isFrontStack(prevStack)
&& (prevStack.topRunningActivityLocked() == r);
- final int resizeMode = task.mResizeMode;
-
- if (stackId == DOCKED_STACK_ID && resizeMode == RESIZE_MODE_UNRESIZEABLE) {
+ if (stackId == DOCKED_STACK_ID && !task.isResizeable()) {
// We don't allow moving a unresizeable task to the docked stack since the docked
// stack is used for split-screen mode and will cause things like the docked divider to
// show up. We instead leave the task in its current stack or move it to the fullscreen
@@ -2246,18 +2245,23 @@
return stack;
}
- void moveTaskToStackLocked(int taskId, int stackId, boolean toTop, boolean forceFocus,
+ boolean moveTaskToStackLocked(int taskId, int stackId, boolean toTop, boolean forceFocus,
String reason, boolean animate) {
final TaskRecord task = anyTaskForIdLocked(taskId);
if (task == null) {
Slog.w(TAG, "moveTaskToStack: no task for id=" + taskId);
- return;
+ return false;
}
if (task.stack != null && task.stack.mStackId == stackId) {
// You are already in the right stack silly...
Slog.i(TAG, "moveTaskToStack: taskId=" + taskId + " already in stackId=" + stackId);
- return;
+ return true;
+ }
+
+ if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
+ throw new IllegalArgumentException("moveTaskToStack:"
+ + "Attempt to move task " + taskId + " to unsupported freeform stack");
}
final ActivityRecord topActivity = task.getTopActivity();
@@ -2294,10 +2298,13 @@
// Make sure the task has the appropriate bounds/size for the stack it is in.
if (stackId == FULLSCREEN_WORKSPACE_STACK_ID && task.mBounds != null) {
kept = resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow);
- } else if (stackId == FREEFORM_WORKSPACE_STACK_ID
- && task.mBounds == null && task.mLastNonFullscreenBounds != null) {
- kept = resizeTaskLocked(task, task.mLastNonFullscreenBounds,
- RESIZE_MODE_SYSTEM, !mightReplaceWindow);
+ } else if (stackId == FREEFORM_WORKSPACE_STACK_ID) {
+ Rect bounds = task.getLaunchBounds();
+ if (bounds == null) {
+ stack.layoutTaskInStack(task, null);
+ bounds = task.mBounds;
+ }
+ kept = resizeTaskLocked(task, bounds, RESIZE_MODE_FORCED, !mightReplaceWindow);
} else if (stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID) {
kept = resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow);
}
@@ -2318,6 +2325,8 @@
resumeFocusedStackTopActivityLocked();
showNonResizeableDockToastIfNeeded(task, preferredLaunchStackId, stackId);
+
+ return (preferredLaunchStackId == stackId);
}
boolean moveTopStackActivityToPinnedStackLocked(int stackId, Rect bounds) {
@@ -2396,6 +2405,8 @@
stack.positionTask(task, position);
// The task might have already been running and its visibility needs to be synchronized with
// the visibility of the stack / windows.
+ stack.ensureActivityConfigurationLocked(task.topRunningActivityLocked(), 0,
+ !PRESERVE_WINDOWS);
stack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
resumeFocusedStackTopActivityLocked();
}
@@ -3276,9 +3287,9 @@
return;
}
- if (!task.canGoInDockedStack() || task.inCropWindowsResizeMode()) {
+ if (!task.canGoInDockedStack() || task.mResizeMode == RESIZE_MODE_FORCE_RESIZEABLE) {
// Display warning toast if we tried to put a non-dockable task in the docked stack or
- // the task is running in cropped window mode.
+ // the task was forced to be resizable by the system.
mWindowManager.scheduleShowNonResizeableDockToast(task.taskId);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityStartInterceptor.java b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
index 9b2bca0..e4b4c2d 100644
--- a/services/core/java/com/android/server/am/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
@@ -98,15 +98,23 @@
mAInfo = aInfo;
mResolvedType = resolvedType;
mInTask = inTask;
- interceptQuietProfileIfNeeded();
- interceptSuspendPackageIfNeed();
+ if (interceptSuspendPackageIfNeed()) {
+ // Skip the rest of interceptions as the package is suspended by device admin so
+ // no user action can undo this.
+ return;
+ }
+ if (interceptQuietProfileIfNeeded()) {
+ // If work profile is turned off, skip the work challenge since the profile can only
+ // be unlocked when profile's user is running.
+ return;
+ }
interceptWorkProfileChallengeIfNeeded();
}
- private void interceptQuietProfileIfNeeded() {
+ private boolean interceptQuietProfileIfNeeded() {
// Do not intercept if the user has not turned off the profile
if (!mUserManager.isQuietModeEnabled(UserHandle.of(mUserId))) {
- return;
+ return false;
}
mIntent = UnlaunchableAppActivity.createInQuietModeDialogIntent(mUserId);
mCallingPid = mRealCallingPid;
@@ -115,15 +123,15 @@
final UserInfo parent = mUserManager.getProfileParent(mUserId);
mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, parent.id);
- mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags,
- null /*profilerInfo*/);
+ mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags, null /*profilerInfo*/);
+ return true;
}
- private void interceptSuspendPackageIfNeed() {
+ private boolean interceptSuspendPackageIfNeed() {
// Do not intercept if the admin did not suspend the package
if (mAInfo == null || mAInfo.applicationInfo == null ||
(mAInfo.applicationInfo.flags & FLAG_SUSPENDED) == 0) {
- return;
+ return false;
}
mIntent = UnlaunchableAppActivity.createPackageSuspendedDialogIntent(mAInfo.packageName,
mUserId);
@@ -137,15 +145,15 @@
} else {
mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, mUserId);
}
- mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags,
- null /*profilerInfo*/);
+ mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags, null /*profilerInfo*/);
+ return true;
}
- private void interceptWorkProfileChallengeIfNeeded() {
+ private boolean interceptWorkProfileChallengeIfNeeded() {
final Intent interceptingIntent = interceptWithConfirmCredentialsIfNeeded(mIntent,
mResolvedType, mAInfo, mCallingPackage, mUserId);
if (interceptingIntent == null) {
- return;
+ return false;
}
mIntent = interceptingIntent;
mCallingPid = mRealCallingPid;
@@ -161,8 +169,8 @@
final UserInfo parent = mUserManager.getProfileParent(mUserId);
mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, parent.id);
- mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags,
- null /*profilerInfo*/);
+ mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags, null /*profilerInfo*/);
+ return true;
}
/**
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 1166ae1..83ad2a7 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -593,6 +593,7 @@
if (intent != null && intent.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
+ mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
boolean componentSpecified = intent.getComponent() != null;
// Save a copy in case ephemeral needs it
@@ -608,7 +609,13 @@
// app in a locked managed profile from an unlocked parent allow it to resolve
// as user will be sent via confirm credentials to unlock the profile.
UserManager userManager = UserManager.get(mService.mContext);
- UserInfo parent = userManager.getProfileParent(userId);
+ UserInfo parent = null;
+ long token = Binder.clearCallingIdentity();
+ try {
+ parent = userManager.getProfileParent(userId);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
if (parent != null
&& userManager.isUserUnlocked(parent.getUserHandle())
&& !userManager.isUserUnlocked(userInfo.getUserHandle())) {
@@ -716,11 +723,13 @@
}
}
+ final ActivityRecord[] outRecord = new ActivityRecord[1];
int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor,
resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
- options, ignoreTargetSecurity, componentSpecified, null, container, inTask);
+ options, ignoreTargetSecurity, componentSpecified, outRecord, container,
+ inTask);
Binder.restoreCallingIdentity(origId);
@@ -767,6 +776,13 @@
}
}
+ final String componentName = outRecord[0] != null ? outRecord[0].shortComponentName
+ : null;
+ final boolean processRunning = outRecord[0] != null &&
+ mService.mProcessNames.get(outRecord[0].processName,
+ outRecord[0].appInfo.uid) != null;
+ mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, componentName,
+ processRunning);
return res;
}
}
@@ -1037,6 +1053,9 @@
// make sure it becomes visible as it starts (this will also trigger entry
// animation). An example of this are PIP activities.
mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ // Go ahead and tell window manager to execute app transition for this activity
+ // since the app transition will not be triggered through the resume channel.
+ mWindowManager.executeAppTransition();
}
} else {
mTargetStack.addRecentActivityLocked(mStartActivity);
@@ -1397,7 +1416,7 @@
}
intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
mStartActivity.launchedFromPackage);
- } else if (!mStartActivity.intent.filterEquals(intentActivity.intent)) {
+ } else if (!intentActivity.task.isSameIntentResolution(mStartActivity)) {
// In this case we are launching the root activity of the task, but with a
// different intent. We should start a new instance on top.
mAddingToTask = true;
@@ -1738,7 +1757,7 @@
// and if yes, we will launch into that stack. If not, we just put the new
// activity into parent's stack, because we can't find a better place.
final ActivityStack stack = mSupervisor.getStack(DOCKED_STACK_ID);
- if (stack != null && stack.getStackVisibilityLocked() == STACK_INVISIBLE) {
+ if (stack != null && stack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
// There is a docked stack, but it isn't visible, so we can't launch into that.
return null;
} else {
@@ -1753,12 +1772,13 @@
return false;
}
- if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
- return true;
+ if (stackId != FULLSCREEN_WORKSPACE_STACK_ID
+ && (!mService.mSupportsMultiWindow || !r.isResizeableOrForced())) {
+ return false;
}
- if (stackId != FULLSCREEN_WORKSPACE_STACK_ID && !r.isResizeableOrForced()) {
- return false;
+ if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
+ return true;
}
if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
diff --git a/services/core/java/com/android/server/am/AppErrorDialog.java b/services/core/java/com/android/server/am/AppErrorDialog.java
index b746a4b..ddfab4d 100644
--- a/services/core/java/com/android/server/am/AppErrorDialog.java
+++ b/services/core/java/com/android/server/am/AppErrorDialog.java
@@ -25,6 +25,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.text.BidiFormatter;
import android.util.Slog;
import android.view.LayoutInflater;
import android.view.View;
@@ -37,6 +38,7 @@
import static com.android.server.am.ActivityManagerService.IS_USER_BUILD;
final class AppErrorDialog extends BaseErrorDialog implements View.OnClickListener {
+
private final ActivityManagerService mService;
private final AppErrorResult mResult;
private final ProcessRecord mProc;
@@ -44,12 +46,17 @@
private CharSequence mName;
+ static int CANT_SHOW = -1;
+ static int BACKGROUND_USER = -2;
+ static int ALREADY_SHOWING = -3;
+
// Event 'what' codes
static final int FORCE_QUIT = 1;
static final int FORCE_QUIT_AND_REPORT = 2;
static final int RESTART = 3;
static final int RESET = 4;
static final int MUTE = 5;
+ static final int TIMEOUT = 6;
// 5-minute timeout, then we automatically dismiss the crash dialog
static final long DISMISS_TIMEOUT = 1000 * 60 * 5;
@@ -62,18 +69,21 @@
mProc = data.proc;
mResult = data.result;
mRepeating = data.repeating;
+ BidiFormatter bidi = BidiFormatter.getInstance();
+
if ((mProc.pkgList.size() == 1) &&
(mName = context.getPackageManager().getApplicationLabel(mProc.info)) != null) {
setTitle(res.getString(
mRepeating ? com.android.internal.R.string.aerr_application_repeated
: com.android.internal.R.string.aerr_application,
- mName.toString(), mProc.info.processName));
+ bidi.unicodeWrap(mName.toString()),
+ bidi.unicodeWrap(mProc.info.processName)));
} else {
mName = mProc.processName;
setTitle(res.getString(
mRepeating ? com.android.internal.R.string.aerr_process_repeated
: com.android.internal.R.string.aerr_process,
- mName.toString()));
+ bidi.unicodeWrap(mName.toString())));
}
setCancelable(false);
@@ -89,7 +99,7 @@
// After the timeout, pretend the user clicked the quit button
mHandler.sendMessageDelayed(
- mHandler.obtainMessage(FORCE_QUIT),
+ mHandler.obtainMessage(TIMEOUT),
DISMISS_TIMEOUT);
}
@@ -132,7 +142,7 @@
mResult.set(result);
// Make sure we don't have time timeout still hanging around.
- removeMessages(FORCE_QUIT);
+ removeMessages(TIMEOUT);
dismiss();
}
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 190e9e1..6cd7561 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -17,6 +17,8 @@
package com.android.server.am;
import com.android.internal.app.ProcessMap;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto;
import com.android.internal.os.ProcessCpuTracker;
import com.android.server.Watchdog;
@@ -59,6 +61,7 @@
import java.util.concurrent.Semaphore;
import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityManagerService.MY_PID;
@@ -403,6 +406,10 @@
Intent appErrorIntent = null;
final long ident = Binder.clearCallingIdentity();
try {
+ MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_CRASH, res);
+ if (res == AppErrorDialog.TIMEOUT) {
+ res = AppErrorDialog.FORCE_QUIT;
+ }
if (res == AppErrorDialog.RESET) {
String[] packageList = r.getPackageList();
if (packageList != null) {
@@ -697,7 +704,7 @@
if (proc != null && proc.crashDialog != null) {
Slog.e(TAG, "App already has crash dialog: " + proc);
if (res != null) {
- res.set(0);
+ res.set(AppErrorDialog.ALREADY_SHOWING);
}
return;
}
@@ -710,7 +717,7 @@
if (isBackground && !showBackground) {
Slog.w(TAG, "Skipping crash dialog of " + proc + ": background");
if (res != null) {
- res.set(0);
+ res.set(AppErrorDialog.BACKGROUND_USER);
}
return;
}
@@ -724,7 +731,7 @@
// The device is asleep, so just pretend that the user
// saw a crash dialog and hit "force quit".
if (res != null) {
- res.set(0);
+ res.set(AppErrorDialog.CANT_SHOW);
}
}
}
@@ -800,8 +807,10 @@
if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
if (r.persistent) {
firstPids.add(pid);
+ if (DEBUG_ANR) Slog.i(TAG, "Adding persistent proc: " + r);
} else {
lastPids.put(pid, Boolean.TRUE);
+ if (DEBUG_ANR) Slog.i(TAG, "Adding ANR proc: " + r);
}
}
}
@@ -920,6 +929,8 @@
ProcessRecord proc = (ProcessRecord)data.get("app");
if (proc != null && proc.anrDialog != null) {
Slog.e(TAG, "App already has anr dialog: " + proc);
+ MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
+ AppNotRespondingDialog.ALREADY_SHOWING);
return;
}
@@ -939,6 +950,8 @@
d.show();
proc.anrDialog = d;
} else {
+ MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
+ AppNotRespondingDialog.CANT_SHOW);
// Just kill the app if there is no dialog to be shown.
mService.killAppAtUsersRequest(proc, null);
}
diff --git a/services/core/java/com/android/server/am/AppNotRespondingDialog.java b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
index 9875887..c6befd7 100644
--- a/services/core/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
@@ -16,6 +16,9 @@
package com.android.server.am;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto;
+
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
@@ -24,6 +27,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.text.BidiFormatter;
import android.util.Slog;
import android.view.LayoutInflater;
import android.view.View;
@@ -41,6 +45,9 @@
static final int WAIT = 2;
static final int WAIT_AND_REPORT = 3;
+ public static final int CANT_SHOW = -1;
+ public static final int ALREADY_SHOWING = -2;
+
private final ActivityManagerService mService;
private final ProcessRecord mProc;
@@ -78,9 +85,11 @@
}
}
+ BidiFormatter bidi = BidiFormatter.getInstance();
+
setTitle(name2 != null
- ? res.getString(resid, name1.toString(), name2.toString())
- : res.getString(resid, name1.toString()));
+ ? res.getString(resid, bidi.unicodeWrap(name1.toString()), bidi.unicodeWrap(name2.toString()))
+ : res.getString(resid, bidi.unicodeWrap(name1.toString())));
if (aboveSystem) {
getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
@@ -132,6 +141,10 @@
private final Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
Intent appErrorIntent = null;
+
+ MetricsLogger.action(getContext(), MetricsProto.MetricsEvent.ACTION_APP_ANR,
+ msg.what);
+
switch (msg.what) {
case FORCE_CLOSE:
// Kill the application.
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 37b0af1..45e3a76 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -654,7 +654,7 @@
}
final boolean callerForeground = receiverRecord.callerApp != null
- ? receiverRecord.callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE
+ ? receiverRecord.callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND
: true;
// Show a permission review UI only for explicit broadcast from a foreground app
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index f2e8d09..2329b2f 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -54,9 +54,9 @@
# An activity has been relaunched:
30020 am_relaunch_activity (User|1|5),(Token|1|5),(Task ID|1|5),(Component Name|3)
# The activity's onPause has been called.
-30021 am_on_paused_called (User|1|5),(Component Name|3)
+30021 am_on_paused_called (User|1|5),(Component Name|3),(Reason|3)
# The activity's onResume has been called.
-30022 am_on_resume_called (User|1|5),(Component Name|3)
+30022 am_on_resume_called (User|1|5),(Component Name|3),(Reason|3)
# Kill a process to reclaim memory.
30023 am_kill (User|1|5),(PID|1|5),(Process Name|3),(OomAdj|1|5),(Reason|3)
# Discard an undelivered serialized broadcast (timeout/ANR/crash)
@@ -103,3 +103,8 @@
30046 am_meminfo (Cached|2|2),(Free|2|2),(Zram|2|2),(Kernel|2|2),(Native|2|2)
# Report collection of memory used by a process
30047 am_pss (Pid|1|5),(UID|1|5),(Process Name|3),(Pss|2|2),(Uss|2|2),(SwapPss|2|2)
+
+# Attempting to stop an activity
+30048 am_stop_activity (User|1|5),(Token|1|5),(Component Name|3)
+# The activity's onStop has been called.
+30049 am_on_stop_called (User|1|5),(Component Name|3),(Reason|3)
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index b49370b..f073e5c 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -124,6 +124,13 @@
// Memory pages are 4K.
static final int PAGE_SIZE = 4*1024;
+ // Activity manager's version of Process.THREAD_GROUP_BG_NONINTERACTIVE
+ static final int SCHED_GROUP_BACKGROUND = 0;
+ // Activity manager's version of Process.THREAD_GROUP_DEFAULT
+ static final int SCHED_GROUP_DEFAULT = 1;
+ // Activity manager's version of Process.THREAD_GROUP_TOP_APP
+ static final int SCHED_GROUP_TOP_APP = 2;
+
// The minimum number of cached apps we want to be able to keep around,
// without empty apps being able to push them out of memory.
static final int MIN_CACHED_APPS = 2;
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index 9c139d5..7209814 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -37,8 +37,12 @@
import android.graphics.Bitmap;
import android.os.Environment;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.UserHandle;
+import android.provider.Settings.System;
+import android.util.ArraySet;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.SparseBooleanArray;
import java.io.File;
@@ -59,12 +63,22 @@
// Maximum number recent bitmaps to keep in memory.
private static final int MAX_RECENT_BITMAPS = 3;
+ private static final int DEFAULT_INITIAL_CAPACITY = 5;
/**
* Save recent tasks information across reboots.
*/
private final TaskPersister mTaskPersister;
- private final SparseBooleanArray mUsersWithRecentsLoaded = new SparseBooleanArray(5);
+ private final ActivityManagerService mService;
+ private final SparseBooleanArray mUsersWithRecentsLoaded = new SparseBooleanArray(
+ DEFAULT_INITIAL_CAPACITY);
+
+ /**
+ * Stores for each user task ids that are taken by tasks residing in persistent storage. These
+ * tasks may or may not currently be in memory.
+ */
+ final SparseArray<SparseBooleanArray> mPersistedTaskIds = new SparseArray<>(
+ DEFAULT_INITIAL_CAPACITY);
// Mainly to avoid object recreation on multiple calls.
private final ArrayList<TaskRecord> mTmpRecents = new ArrayList<TaskRecord>();
@@ -75,6 +89,7 @@
RecentTasks(ActivityManagerService service, ActivityStackSupervisor mStackSupervisor) {
File systemDir = Environment.getDataSystemDirectory();
+ mService = service;
mTaskPersister = new TaskPersister(systemDir, mStackSupervisor, service, this);
mStackSupervisor.setRecentTasks(this);
}
@@ -87,6 +102,8 @@
*/
void loadUserRecentsLocked(int userId) {
if (!mUsersWithRecentsLoaded.get(userId)) {
+ // Load the task ids if not loaded.
+ loadPersistedTaskIdsForUserLocked(userId);
Slog.i(TAG, "Loading recents for user " + userId + " into memory.");
addAll(mTaskPersister.restoreTasksForUserLocked(userId));
cleanupLocked(userId);
@@ -94,21 +111,49 @@
}
}
+ private void loadPersistedTaskIdsForUserLocked(int userId) {
+ // An empty instead of a null set here means that no persistent taskIds were present
+ // on file when we loaded them.
+ if (mPersistedTaskIds.get(userId) == null) {
+ mPersistedTaskIds.put(userId, mTaskPersister.loadPersistedTaskIdsForUser(userId));
+ }
+ }
+
+ boolean taskIdTakenForUserLocked(int taskId, int userId) {
+ loadPersistedTaskIdsForUserLocked(userId);
+ return mPersistedTaskIds.get(userId).get(taskId);
+ }
+
void notifyTaskPersisterLocked(TaskRecord task, boolean flush) {
if (task != null && task.stack != null && task.stack.isHomeStack()) {
// Never persist the home stack.
return;
}
+ syncPersistentTaskIdsLocked();
mTaskPersister.wakeup(task, flush);
}
- void onSystemReady() {
- clear();
- loadUserRecentsLocked(UserHandle.USER_SYSTEM);
- startPersisting();
+ private void syncPersistentTaskIdsLocked() {
+ for (int i = mPersistedTaskIds.size() - 1; i >= 0; i--) {
+ int userId = mPersistedTaskIds.keyAt(i);
+ if (mUsersWithRecentsLoaded.get(userId)) {
+ // Recents are loaded only after task ids are loaded. Therefore, the set of taskids
+ // referenced here should not be null.
+ mPersistedTaskIds.valueAt(i).clear();
+ }
+ }
+ for (int i = size() - 1; i >= 0; i--) {
+ TaskRecord task = get(i);
+ if (task.isPersistable && (task.stack == null || !task.stack.isHomeStack())) {
+ // Set of persisted taskIds for task.userId should not be null here
+ mPersistedTaskIds.get(task.userId).put(task.taskId, true);
+ }
+ }
}
- void startPersisting() {
+
+ void onSystemReadyLocked() {
+ clear();
mTaskPersister.startPersisting();
}
@@ -125,11 +170,14 @@
}
void flush() {
+ synchronized (mService) {
+ syncPersistentTaskIdsLocked();
+ }
mTaskPersister.flush();
}
/**
- * Returns all userIds for which recents from storage are loaded
+ * Returns all userIds for which recents from persistent storage are loaded into this list.
*
* @return an array of userIds.
*/
@@ -149,12 +197,7 @@
return usersWithRecentsLoaded;
}
- /**
- * Removes recent tasks for this user if they are loaded, does not do anything otherwise.
- *
- * @param userId the user id.
- */
- void unloadUserRecentsLocked(int userId) {
+ private void unloadUserRecentsLocked(int userId) {
if (mUsersWithRecentsLoaded.get(userId)) {
Slog.i(TAG, "Unloading recents for user " + userId + " from memory.");
mUsersWithRecentsLoaded.delete(userId);
@@ -162,6 +205,18 @@
}
}
+ /**
+ * Removes recent tasks and any other state kept in memory for the passed in user. Does not
+ * touch the information present on persistent storage.
+ *
+ * @param userId the id of the user
+ */
+ void unloadUserDataFromMemoryLocked(int userId) {
+ unloadUserRecentsLocked(userId);
+ mPersistedTaskIds.delete(userId);
+ mTaskPersister.unloadUserDataFromMemory(userId);
+ }
+
TaskRecord taskForIdLocked(int id) {
final int recentsCount = size();
for (int i = 0; i < recentsCount; i++) {
diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java
index 283939e..11fd3bc 100644
--- a/services/core/java/com/android/server/am/TaskPersister.java
+++ b/services/core/java/com/android/server/am/TaskPersister.java
@@ -16,6 +16,9 @@
package com.android.server.am;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Debug;
@@ -26,11 +29,13 @@
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.Slog;
+import android.util.SparseArray;
+import android.util.SparseBooleanArray;
import android.util.Xml;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
-
import libcore.io.IoUtils;
import org.xmlpull.v1.XmlPullParser;
@@ -38,9 +43,12 @@
import org.xmlpull.v1.XmlSerializer;
import java.io.BufferedReader;
+import java.io.BufferedWriter;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
+import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
@@ -71,6 +79,7 @@
private static final String TASKS_DIRNAME = "recent_tasks";
private static final String TASK_EXTENSION = ".xml";
private static final String IMAGES_DIRNAME = "recent_images";
+ private static final String PERSISTED_TASK_IDS_FILENAME = "persisted_taskIds.txt";
static final String IMAGE_EXTENSION = ".png";
private static final String TAG_TASK = "task";
@@ -78,6 +87,7 @@
private final ActivityManagerService mService;
private final ActivityStackSupervisor mStackSupervisor;
private final RecentTasks mRecentTasks;
+ private final SparseArray<SparseBooleanArray> mTaskIdsInFile = new SparseArray<>();
/**
* Value determines write delay mode as follows: < 0 We are Flushing. No delays between writes
@@ -170,6 +180,64 @@
}
}
+ @NonNull
+ SparseBooleanArray loadPersistedTaskIdsForUser(int userId) {
+ if (mTaskIdsInFile.get(userId) != null) {
+ return mTaskIdsInFile.get(userId).clone();
+ }
+ final SparseBooleanArray persistedTaskIds = new SparseBooleanArray();
+ BufferedReader reader = null;
+ String line;
+ try {
+ reader = new BufferedReader(new FileReader(getUserPersistedTaskIdsFile(userId)));
+ while ((line = reader.readLine()) != null) {
+ for (String taskIdString : line.split("\\s+")) {
+ int id = Integer.parseInt(taskIdString);
+ persistedTaskIds.put(id, true);
+ }
+ }
+ } catch (FileNotFoundException e) {
+ // File doesn't exist. Ignore.
+ } catch (Exception e) {
+ Slog.e(TAG, "Error while reading taskIds file for user " + userId, e);
+ } finally {
+ IoUtils.closeQuietly(reader);
+ }
+ mTaskIdsInFile.put(userId, persistedTaskIds);
+ return persistedTaskIds.clone();
+ }
+
+ private void maybeWritePersistedTaskIdsForUser(@NonNull SparseBooleanArray taskIds,
+ int userId) {
+ if (userId < 0) {
+ return;
+ }
+ SparseBooleanArray persistedIdsInFile = mTaskIdsInFile.get(userId);
+ if (persistedIdsInFile != null && persistedIdsInFile.equals(taskIds)) {
+ return;
+ }
+ final File persistedTaskIdsFile = getUserPersistedTaskIdsFile(userId);
+ BufferedWriter writer = null;
+ try {
+ writer = new BufferedWriter(new FileWriter(persistedTaskIdsFile));
+ for (int i = 0; i < taskIds.size(); i++) {
+ if (taskIds.valueAt(i)) {
+ writer.write(String.valueOf(taskIds.keyAt(i)));
+ writer.newLine();
+ }
+ }
+ } catch (Exception e) {
+ Slog.e(TAG, "Error while writing taskIds file for user " + userId, e);
+ } finally {
+ IoUtils.closeQuietly(writer);
+ }
+ mTaskIdsInFile.put(userId, taskIds.clone());
+ }
+
+ void unloadUserDataFromMemory(int userId) {
+ mTaskIdsInFile.delete(userId);
+ }
+
void wakeup(TaskRecord task, boolean flush) {
synchronized (this) {
if (task != null) {
@@ -336,14 +404,16 @@
File[] recentFiles = userTasksDir.listFiles();
if (recentFiles == null) {
- Slog.e(TAG, "restoreTasksForUser: Unable to list files from " + userTasksDir);
+ Slog.e(TAG, "restoreTasksForUserLocked: Unable to list files from " + userTasksDir);
return tasks;
}
for (int taskNdx = 0; taskNdx < recentFiles.length; ++taskNdx) {
File taskFile = recentFiles[taskNdx];
- if (DEBUG) Slog.d(TAG, "restoreTasksForUser: userId=" + userId
- + ", taskFile=" + taskFile.getName());
+ if (DEBUG) {
+ Slog.d(TAG, "restoreTasksForUserLocked: userId=" + userId
+ + ", taskFile=" + taskFile.getName());
+ }
BufferedReader reader = null;
boolean deleteFile = false;
try {
@@ -366,20 +436,29 @@
// out the stuff we just read, if we don't write it we will
// read the same thing again.
// mWriteQueue.add(new TaskWriteQueueItem(task));
+
final int taskId = task.taskId;
- mStackSupervisor.setNextTaskIdForUserLocked(taskId, userId);
- // Check if it's a valid user id. Don't add tasks for removed users.
- if (userId == task.userId) {
+ if (mStackSupervisor.anyTaskForIdLocked(taskId,
+ /* restoreFromRecents= */ false, 0) != null) {
+ // Should not happen.
+ Slog.wtf(TAG, "Existing task with taskId " + taskId + "found");
+ } else if (userId != task.userId) {
+ // Should not happen.
+ Slog.wtf(TAG, "Task with userId " + task.userId + " found in "
+ + userTasksDir.getAbsolutePath());
+ } else {
+ // Looks fine.
+ mStackSupervisor.setNextTaskIdForUserLocked(taskId, userId);
task.isPersistable = true;
tasks.add(task);
recoveredTaskIds.add(taskId);
}
} else {
- Slog.e(TAG, "restoreTasksForUser: Unable to restore taskFile="
+ Slog.e(TAG, "restoreTasksForUserLocked: Unable to restore taskFile="
+ taskFile + ": " + fileToString(taskFile));
}
} else {
- Slog.wtf(TAG, "restoreTasksForUser: Unknown xml event=" + event
+ Slog.wtf(TAG, "restoreTasksForUserLocked: Unknown xml event=" + event
+ " name=" + name);
}
}
@@ -454,6 +533,20 @@
}
}
+ private void writeTaskIdsFiles() {
+ int candidateUserIds[];
+ synchronized (mService) {
+ candidateUserIds = mRecentTasks.usersWithRecentsLoadedLocked();
+ }
+ SparseBooleanArray taskIdsToSave;
+ for (int userId : candidateUserIds) {
+ synchronized (mService) {
+ taskIdsToSave = mRecentTasks.mPersistedTaskIds.get(userId).clone();
+ }
+ maybeWritePersistedTaskIdsForUser(taskIdsToSave, userId);
+ }
+ }
+
private void removeObsoleteFiles(ArraySet<Integer> persistentTaskIds) {
int[] candidateUserIds;
synchronized (mService) {
@@ -472,8 +565,12 @@
return BitmapFactory.decodeFile(filename);
}
+ static File getUserPersistedTaskIdsFile(int userId) {
+ return new File(Environment.getDataSystemDeDirectory(userId), PERSISTED_TASK_IDS_FILENAME);
+ }
+
static File getUserTasksDir(int userId) {
- File userTasksDir = new File(Environment.getUserSystemDirectory(userId), TASKS_DIRNAME);
+ File userTasksDir = new File(Environment.getDataSystemCeDirectory(userId), TASKS_DIRNAME);
if (!userTasksDir.exists()) {
if (!userTasksDir.mkdir()) {
@@ -485,7 +582,7 @@
}
static File getUserImagesDir(int userId) {
- File userImagesDir = new File(Environment.getUserSystemDirectory(userId), IMAGES_DIRNAME);
+ File userImagesDir = new File(Environment.getDataSystemCeDirectory(userId), IMAGES_DIRNAME);
if (!userImagesDir.exists()) {
if (!userImagesDir.mkdir()) {
@@ -535,6 +632,7 @@
}
removeObsoleteFiles(persistentTaskIds);
}
+ writeTaskIdsFiles();
// If mNextWriteTime, then don't delay between each call to saveToXml().
final WriteQueueItem item;
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 16fd909..62275a9 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -243,6 +243,8 @@
// Bounds of the Task. null for fullscreen tasks.
Rect mBounds = null;
+ private final Rect mTmpStableBounds = new Rect();
+ private final Rect mTmpNonDecorBounds = new Rect();
private final Rect mTmpRect = new Rect();
private final Rect mTmpRect2 = new Rect();
@@ -467,6 +469,19 @@
setLockTaskAuth();
}
+ /**
+ * Return true if the input activity has the same intent resolution as the intent this task
+ * record is based on (normally the root activity intent).
+ */
+ boolean isSameIntentResolution(ActivityRecord r) {
+ final Intent intent = new Intent(r.intent);
+ // Correct the activity intent for aliasing. The task record intent will always be based on
+ // the real activity that will be launched not the alias, so we need to use an intent with
+ // the component name pointing to the real activity not the alias in the activity record.
+ intent.setComponent(r.realActivity);
+ return this.intent.filterEquals(intent);
+ }
+
void setTaskToReturnTo(int taskToReturnTo) {
mTaskToReturnTo = (taskToReturnTo == RECENTS_ACTIVITY_TYPE)
? HOME_ACTIVITY_TYPE : taskToReturnTo;
@@ -1313,6 +1328,38 @@
return task;
}
+ private void adjustForMinimalTaskDimensions(Rect bounds) {
+ if (bounds == null) {
+ return;
+ }
+ final int minimalSize = mMinimalSize == -1
+ ? mService.mStackSupervisor.mDefaultMinimalSizeOfResizeableTask : mMinimalSize;
+ final boolean adjustWidth = minimalSize > bounds.width();
+ final boolean adjustHeight = minimalSize > bounds.height();
+ if (!(adjustWidth || adjustHeight)) {
+ return;
+ }
+
+ if (adjustWidth) {
+ if (mBounds != null && bounds.right == mBounds.right) {
+ bounds.left = bounds.right - minimalSize;
+ } else {
+ // Either left bounds match, or neither match, or the previous bounds were
+ // fullscreen and we default to keeping left.
+ bounds.right = bounds.left + minimalSize;
+ }
+ }
+ if (adjustHeight) {
+ if (mBounds != null && bounds.bottom == mBounds.bottom) {
+ bounds.top = bounds.bottom - minimalSize;
+ } else {
+ // Either top bounds match, or neither match, or the previous bounds were
+ // fullscreen and we default to keeping top.
+ bounds.bottom = bounds.top + minimalSize;
+ }
+ }
+ }
+
/**
* Update task's override configuration based on the bounds.
* @param bounds The bounds of the task.
@@ -1345,20 +1392,17 @@
mBounds = null;
mOverrideConfig = Configuration.EMPTY;
} else {
+ mTmpRect.set(bounds);
+ adjustForMinimalTaskDimensions(mTmpRect);
if (mBounds == null) {
- mBounds = new Rect(bounds);
+ mBounds = new Rect(mTmpRect);
} else {
- mBounds.set(bounds);
+ mBounds.set(mTmpRect);
}
if (stack == null || StackId.persistTaskBounds(stack.mStackId)) {
mLastNonFullscreenBounds = mBounds;
}
-
- // Stable insets need to be subtracted because we also subtract it in the fullscreen
- // configuration.
- mTmpRect.set(bounds);
- subtractStableInsets(mTmpRect, insetBounds != null ? insetBounds : mTmpRect);
- mOverrideConfig = calculateOverrideConfig(mTmpRect);
+ mOverrideConfig = calculateOverrideConfig(mTmpRect, insetBounds);
}
if (mFullscreen != oldFullscreen) {
@@ -1368,6 +1412,16 @@
return !mOverrideConfig.equals(oldConfig) ? mOverrideConfig : null;
}
+ private void subtractNonDecorInsets(Rect inOutBounds, Rect inInsetBounds) {
+ mTmpRect2.set(inInsetBounds);
+ mService.mWindowManager.subtractNonDecorInsets(mTmpRect2);
+ int leftInset = mTmpRect2.left - inInsetBounds.left;
+ int topInset = mTmpRect2.top - inInsetBounds.top;
+ int rightInset = inInsetBounds.right - mTmpRect2.right;
+ int bottomInset = inInsetBounds.bottom - mTmpRect2.bottom;
+ inOutBounds.inset(leftInset, topInset, rightInset, bottomInset);
+ }
+
private void subtractStableInsets(Rect inOutBounds, Rect inInsetBounds) {
mTmpRect2.set(inInsetBounds);
mService.mWindowManager.subtractStableInsets(mTmpRect2);
@@ -1378,23 +1432,39 @@
inOutBounds.inset(leftInset, topInset, rightInset, bottomInset);
}
- Configuration calculateOverrideConfig(Rect bounds) {
+ private Configuration calculateOverrideConfig(Rect bounds, Rect insetBounds) {
+ mTmpNonDecorBounds.set(bounds);
+ mTmpStableBounds.set(bounds);
+ subtractNonDecorInsets(
+ mTmpNonDecorBounds, insetBounds != null ? insetBounds : bounds);
+ subtractStableInsets(
+ mTmpStableBounds, insetBounds != null ? insetBounds : bounds);
+
+ // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen area,
+ // i.e. the screen area without the system bars.
final Configuration serviceConfig = mService.mConfiguration;
final Configuration config = new Configuration(Configuration.EMPTY);
// TODO(multidisplay): Update Dp to that of display stack is on.
final float density = serviceConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
config.screenWidthDp =
- Math.min((int)(bounds.width() / density), serviceConfig.screenWidthDp);
+ Math.min((int)(mTmpStableBounds.width() / density), serviceConfig.screenWidthDp);
config.screenHeightDp =
- Math.min((int)(bounds.height() / density), serviceConfig.screenHeightDp);
- config.smallestScreenWidthDp =
- Math.min(config.screenWidthDp, config.screenHeightDp);
+ Math.min((int)(mTmpStableBounds.height() / density), serviceConfig.screenHeightDp);
+ config.smallestScreenWidthDp = Math.min(config.screenWidthDp, config.screenHeightDp);
+
+ // TODO: Orientation?
config.orientation = (config.screenWidthDp <= config.screenHeightDp)
? Configuration.ORIENTATION_PORTRAIT
: Configuration.ORIENTATION_LANDSCAPE;
+
+ // For calculating screen layout, we need to use the non-decor inset screen area for the
+ // calculation for compatibility reasons, i.e. screen area without system bars that could
+ // never go away in Honeycomb.
+ final int compatScreenWidthDp = (int)(mTmpNonDecorBounds.width() / density);
+ final int compatScreenHeightDp = (int)(mTmpNonDecorBounds.height() / density);
final int sl = Configuration.resetScreenLayout(serviceConfig.screenLayout);
- int longSize = Math.max(config.screenWidthDp, config.screenHeightDp);
- int shortSize = Math.min(config.screenWidthDp, config.screenHeightDp);
+ final int longSize = Math.max(compatScreenHeightDp, compatScreenWidthDp);
+ final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);
config.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);
return config;
}
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 4e6dc3a..addffd3 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -68,6 +68,7 @@
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.UserManagerInternal;
import android.os.storage.IMountService;
import android.os.storage.StorageManager;
import android.provider.Settings;
@@ -82,6 +83,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
import com.android.internal.widget.LockPatternUtils;
+import com.android.server.LocalServices;
import com.android.server.pm.UserManagerService;
import java.io.PrintWriter;
@@ -561,6 +563,10 @@
continue;
}
UserInfo userInfo = getUserInfo(oldUserId);
+ if (userInfo.isEphemeral()) {
+ LocalServices.getService(UserManagerInternal.class)
+ .onEphemeralUserStop(oldUserId);
+ }
if (userInfo.isGuest() || userInfo.isEphemeral()) {
// This is a user to be stopped.
stopUsersLocked(oldUserId, true, null);
@@ -1375,6 +1381,11 @@
* intercept activity launches for work apps when the Work Challenge is present.
*/
boolean shouldConfirmCredentials(int userId) {
+ synchronized (mService) {
+ if (mStartedUsers.get(userId) == null) {
+ return false;
+ }
+ }
if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
return false;
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 548f563..f2a9c2c 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -222,7 +222,6 @@
private static final int MSG_UNMUTE_STREAM = 24;
private static final int MSG_DYN_POLICY_MIX_STATE_UPDATE = 25;
private static final int MSG_INDICATE_SYSTEM_READY = 26;
- private static final int MSG_PERSIST_MASTER_MONO = 27;
// start of messages handled under wakelock
// these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
// and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
@@ -827,10 +826,7 @@
}
// Restore mono mode
- final boolean masterMono = System.getIntForUser(
- mContentResolver, System.MASTER_MONO,
- 0 /* default */, UserHandle.USER_CURRENT) == 1;
- AudioSystem.setMasterMono(masterMono);
+ updateMasterMono(mContentResolver);
// Restore ringer mode
setRingerModeInt(getRingerModeInternal(), false);
@@ -853,6 +849,7 @@
AudioSystem.setForceUse(AudioSystem.FOR_DOCK,
mDockAudioMediaEnabled ?
AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE);
+ sendEncodedSurroundMode(mContentResolver);
}
if (mHdmiManager != null) {
synchronized (mHdmiManager) {
@@ -1015,6 +1012,55 @@
0);
}
+
+ private void updateMasterMono(ContentResolver cr)
+ {
+ final boolean masterMono = System.getIntForUser(
+ cr, System.MASTER_MONO, 0 /* default */, UserHandle.USER_CURRENT) == 1;
+ if (DEBUG_VOL) {
+ Log.d(TAG, String.format("Master mono %b", masterMono));
+ }
+ AudioSystem.setMasterMono(masterMono);
+ }
+
+ private void sendEncodedSurroundMode(ContentResolver cr)
+ {
+ int encodedSurroundMode = Settings.Global.getInt(
+ cr, Settings.Global.ENCODED_SURROUND_OUTPUT,
+ Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
+ sendEncodedSurroundMode(encodedSurroundMode);
+ }
+
+ private void sendEncodedSurroundMode(int encodedSurroundMode)
+ {
+ // initialize to guaranteed bad value
+ int forceSetting = AudioSystem.NUM_FORCE_CONFIG;
+ switch (encodedSurroundMode) {
+ case Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO:
+ forceSetting = AudioSystem.FORCE_NONE;
+ break;
+ case Settings.Global.ENCODED_SURROUND_OUTPUT_NEVER:
+ forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_NEVER;
+ break;
+ case Settings.Global.ENCODED_SURROUND_OUTPUT_ALWAYS:
+ forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_ALWAYS;
+ break;
+ default:
+ Log.e(TAG, "updateSurroundSoundSettings: illegal value "
+ + encodedSurroundMode);
+ break;
+ }
+ if (forceSetting != AudioSystem.NUM_FORCE_CONFIG) {
+ sendMsg(mAudioHandler,
+ MSG_SET_FORCE_USE,
+ SENDMSG_QUEUE,
+ AudioSystem.FOR_ENCODED_SURROUND,
+ forceSetting,
+ null,
+ 0);
+ }
+ }
+
private void readPersistedSettings() {
final ContentResolver cr = mContentResolver;
@@ -1056,6 +1102,7 @@
updateRingerModeAffectedStreams();
readDockAudioSettings(cr);
+ sendEncodedSurroundMode(cr);
}
mMuteAffectedStreams = System.getIntForUser(cr,
@@ -1091,13 +1138,7 @@
}
AudioSystem.muteMicrophone(microphoneMute);
- final boolean masterMono = System.getIntForUser(
- cr, System.MASTER_MONO, 0 /* default */, UserHandle.USER_CURRENT) == 1;
- if (DEBUG_VOL) {
- Log.d(TAG, String.format("Master mono %b, user=%d", masterMono, currentUser));
- }
- AudioSystem.setMasterMono(masterMono);
- broadcastMasterMonoStatus(masterMono);
+ updateMasterMono(cr);
// Each stream will read its own persisted settings
@@ -1855,52 +1896,6 @@
userId);
}
- /** @hide */
- public boolean isMasterMono() {
- return AudioSystem.getMasterMono();
- }
-
- /** @hide */
- public void setMasterMono(boolean mono, String callingPackage, int userId) {
- int callingUid = Binder.getCallingUid();
- // If we are being called by the system check for user we are going to change
- // so we handle user restrictions correctly.
- if (callingUid == android.os.Process.SYSTEM_UID) {
- callingUid = UserHandle.getUid(userId, UserHandle.getAppId(callingUid));
- }
-
- if (userId != UserHandle.getCallingUserId() &&
- mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
- != PackageManager.PERMISSION_GRANTED) {
- return;
- }
- if (DEBUG_VOL) {
- Log.d(TAG, String.format("Master mono %b, user=%d", mono, userId));
- }
-
- if (getCurrentUserId() == userId) {
- if (mono != AudioSystem.getMasterMono()) {
- AudioSystem.setMasterMono(mono);
- // Post a persist master mono msg
- sendMsg(mAudioHandler, MSG_PERSIST_MASTER_MONO, SENDMSG_REPLACE, mono ? 1
- : 0 /* value */, userId, null /* obj */, 0 /* delay */);
- // notify apps and settings
- broadcastMasterMonoStatus(mono);
- }
- } else {
- // Post a persist master mono msg
- sendMsg(mAudioHandler, MSG_PERSIST_MASTER_MONO, SENDMSG_REPLACE, mono ? 1
- : 0 /* value */, userId, null /* obj */, 0 /* delay */);
- }
- }
-
- private void broadcastMasterMonoStatus(boolean mono) {
- Intent intent = new Intent(AudioManager.MASTER_MONO_CHANGED_ACTION);
- intent.putExtra(AudioManager.EXTRA_MASTER_MONO, mono);
- sendBroadcastToAll(intent);
- }
-
/** @see AudioManager#getStreamVolume(int) */
public int getStreamVolume(int streamType) {
ensureValidStreamType(streamType);
@@ -4641,25 +4636,28 @@
case MSG_DYN_POLICY_MIX_STATE_UPDATE:
onDynPolicyMixStateUpdate((String) msg.obj, msg.arg1);
break;
-
- case MSG_PERSIST_MASTER_MONO:
- Settings.System.putIntForUser(mContentResolver,
- Settings.System.MASTER_MONO,
- msg.arg1 /* value */,
- msg.arg2 /* userHandle */);
- break;
}
}
}
private class SettingsObserver extends ContentObserver {
+ private int mEncodedSurroundMode;
+
SettingsObserver() {
super(new Handler());
mContentResolver.registerContentObserver(Settings.System.getUriFor(
Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this);
mContentResolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this);
+ mContentResolver.registerContentObserver(Settings.System.getUriFor(
+ Settings.System.MASTER_MONO), false, this);
+
+ mEncodedSurroundMode = Settings.Global.getInt(
+ mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
+ Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
+ mContentResolver.registerContentObserver(Settings.Global.getUriFor(
+ Settings.Global.ENCODED_SURROUND_OUTPUT), false, this);
}
@Override
@@ -4678,6 +4676,34 @@
setRingerModeInt(getRingerModeInternal(), false);
}
readDockAudioSettings(mContentResolver);
+ updateMasterMono(mContentResolver);
+ updateEncodedSurroundOutput();
+ }
+ }
+
+ private void updateEncodedSurroundOutput() {
+ int newSurroundMode = Settings.Global.getInt(
+ mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
+ Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
+ // Did it change?
+ if (mEncodedSurroundMode != newSurroundMode) {
+ // Send to AudioPolicyManager
+ sendEncodedSurroundMode(newSurroundMode);
+ synchronized(mConnectedDevices) {
+ // Is HDMI connected?
+ String key = makeDeviceListKey(AudioSystem.DEVICE_OUT_HDMI, "");
+ DeviceListSpec deviceSpec = mConnectedDevices.get(key);
+ if (deviceSpec != null) {
+ // Toggle HDMI to retrigger broadcast with proper formats.
+ setWiredDeviceConnectionState(AudioSystem.DEVICE_OUT_HDMI,
+ AudioSystem.DEVICE_STATE_UNAVAILABLE, "", "",
+ "android"); // disconnect
+ setWiredDeviceConnectionState(AudioSystem.DEVICE_OUT_HDMI,
+ AudioSystem.DEVICE_STATE_AVAILABLE, "", "",
+ "android"); // reconnect
+ }
+ }
+ mEncodedSurroundMode = newSurroundMode;
}
}
}
@@ -6365,4 +6391,4 @@
if (DEBUG_VOL) Log.d(TAG, "Reloaded controller service: " + this);
}
}
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/audio/RecordingActivityMonitor.java b/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
index a6325a4..86dcd0f 100644
--- a/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
@@ -16,6 +16,7 @@
package com.android.server.audio;
+import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecordConfiguration;
import android.media.AudioSystem;
@@ -48,16 +49,20 @@
/**
* Implementation of android.media.AudioSystem.AudioRecordingCallback
*/
- public void onRecordingConfigurationChanged(int event, int session, int source) {
+ public void onRecordingConfigurationChanged(int event, int session, int source,
+ int[] recordingInfo) {
if (MediaRecorder.isSystemOnlyAudioSource(source)) {
return;
}
- if (updateSnapshot(event, session, source)) {
- final Iterator<RecMonitorClient> clientIterator = mClients.iterator();
+ final AudioRecordConfiguration[] configs =
+ updateSnapshot(event, session, source, recordingInfo);
+ if (configs != null){
synchronized(mClients) {
+ final Iterator<RecMonitorClient> clientIterator = mClients.iterator();
while (clientIterator.hasNext()) {
try {
- clientIterator.next().mDispatcherCb.dispatchRecordingConfigChange();
+ clientIterator.next().mDispatcherCb.dispatchRecordingConfigChange(
+ configs);
} catch (RemoteException e) {
Log.w(TAG, "Could not call dispatchRecordingConfigChange() on client", e);
}
@@ -110,31 +115,68 @@
* @param event
* @param session
* @param source
- * @return true if the list of active recording sessions has been modified, false otherwise.
+ * @param recordingFormat see
+ * {@link AudioSystem.AudioRecordingCallback#onRecordingConfigurationChanged(int, int, int, int[])}
+ * for the definition of the contents of the array
+ * @return null if the list of active recording sessions has not been modified, an array
+ * with the current active configurations otherwise.
*/
- private boolean updateSnapshot(int event, int session, int source) {
+ private AudioRecordConfiguration[] updateSnapshot(int event, int session, int source,
+ int[] recordingInfo) {
+ final boolean configChanged;
+ final AudioRecordConfiguration[] configs;
synchronized(mRecordConfigs) {
switch (event) {
case AudioManager.RECORD_CONFIG_EVENT_STOP:
// return failure if an unknown recording session stopped
- return (mRecordConfigs.remove(new Integer(session)) != null);
+ configChanged = (mRecordConfigs.remove(new Integer(session)) != null);
+ break;
case AudioManager.RECORD_CONFIG_EVENT_START:
- if (mRecordConfigs.containsKey(new Integer(session))) {
- // start of session that's already tracked, not worth an update
- // TO DO in the future when tracking record format: there might be a record
- // format change during a recording that requires reporting
- return false;
+ final AudioFormat clientFormat = new AudioFormat.Builder()
+ .setEncoding(recordingInfo[0])
+ // FIXME this doesn't support index-based masks
+ .setChannelMask(recordingInfo[1])
+ .setSampleRate(recordingInfo[2])
+ .build();
+ final AudioFormat deviceFormat = new AudioFormat.Builder()
+ .setEncoding(recordingInfo[3])
+ // FIXME this doesn't support index-based masks
+ .setChannelMask(recordingInfo[4])
+ .setSampleRate(recordingInfo[5])
+ .build();
+ final int patchHandle = recordingInfo[6];
+ final Integer sessionKey = new Integer(session);
+ if (mRecordConfigs.containsKey(sessionKey)) {
+ final AudioRecordConfiguration updatedConfig =
+ new AudioRecordConfiguration(session, source,
+ clientFormat, deviceFormat, patchHandle);
+ if (updatedConfig.equals(mRecordConfigs.get(sessionKey))) {
+ configChanged = false;
+ } else {
+ // config exists but has been modified
+ mRecordConfigs.remove(sessionKey);
+ mRecordConfigs.put(sessionKey, updatedConfig);
+ configChanged = true;
+ }
} else {
- mRecordConfigs.put(new Integer(session),
- new AudioRecordConfiguration(session, source));
- return true;
+ mRecordConfigs.put(sessionKey,
+ new AudioRecordConfiguration(session, source,
+ clientFormat, deviceFormat, patchHandle));
+ configChanged = true;
}
+ break;
default:
Log.e(TAG, String.format("Unknown event %d for session %d, source %d",
event, session, source));
- return false;
+ configChanged = false;
+ }
+ if (configChanged) {
+ configs = mRecordConfigs.values().toArray(new AudioRecordConfiguration[0]);
+ } else {
+ configs = null;
}
}
+ return configs;
}
/**
diff --git a/services/core/java/com/android/server/camera/CameraService.java b/services/core/java/com/android/server/camera/CameraService.java
index f82454a..cd8eb4e 100644
--- a/services/core/java/com/android/server/camera/CameraService.java
+++ b/services/core/java/com/android/server/camera/CameraService.java
@@ -60,10 +60,6 @@
public static final String CAMERA_SERVICE_PROXY_BINDER_NAME = "media.camera.proxy";
- // Event arguments to use with the camera service notifySystemEvent call:
- public static final int NO_EVENT = 0; // NOOP
- public static final int USER_SWITCHED = 1; // User changed, argument is the new user handle
-
// State arguments to use with the notifyCameraState call from camera service:
public static final int CAMERA_STATE_OPEN = 0;
public static final int CAMERA_STATE_ACTIVE = 1;
@@ -224,7 +220,7 @@
if (mEnabledCameraUsers == null || !mEnabledCameraUsers.equals(currentUserHandles)) {
// Some user handles have been added or removed, update mediaserver.
mEnabledCameraUsers = currentUserHandles;
- notifyMediaserverLocked(USER_SWITCHED, currentUserHandles);
+ notifyMediaserverLocked(ICameraService.EVENT_USER_SWITCHED, currentUserHandles);
}
}
@@ -244,7 +240,7 @@
if (mEnabledCameraUsers == null) {
return;
}
- if (notifyMediaserverLocked(USER_SWITCHED, mEnabledCameraUsers)) {
+ if (notifyMediaserverLocked(ICameraService.EVENT_USER_SWITCHED, mEnabledCameraUsers)) {
retries = 0;
}
}
diff --git a/services/core/java/com/android/server/connectivity/ApfFilter.java b/services/core/java/com/android/server/connectivity/ApfFilter.java
new file mode 100644
index 0000000..25c84e1
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/ApfFilter.java
@@ -0,0 +1,499 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity;
+
+import static android.system.OsConstants.*;
+
+import android.net.NetworkUtils;
+import android.net.apf.ApfGenerator;
+import android.net.apf.ApfGenerator.IllegalInstructionException;
+import android.net.apf.ApfGenerator.Register;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.PacketSocketAddress;
+import android.util.Log;
+import android.util.Pair;
+
+import com.android.internal.util.HexDump;
+import com.android.server.ConnectivityService;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.lang.Thread;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import libcore.io.IoBridge;
+
+/**
+ * For networks that support packet filtering via APF programs, {@code ApfFilter}
+ * listens for IPv6 ICMPv6 router advertisements (RAs) and generates APF programs to
+ * filter out redundant duplicate ones.
+ *
+ * @hide
+ */
+public class ApfFilter {
+ // Thread to listen for RAs.
+ private class ReceiveThread extends Thread {
+ private final byte[] mPacket = new byte[1514];
+ private final FileDescriptor mSocket;
+ private volatile boolean mStopped;
+
+ public ReceiveThread(FileDescriptor socket) {
+ mSocket = socket;
+ }
+
+ public void halt() {
+ mStopped = true;
+ try {
+ // Interrupts the read() call the thread is blocked in.
+ IoBridge.closeAndSignalBlockedThreads(mSocket);
+ } catch (IOException ignored) {}
+ }
+
+ @Override
+ public void run() {
+ log("begin monitoring");
+ while (!mStopped) {
+ try {
+ int length = Os.read(mSocket, mPacket, 0, mPacket.length);
+ processRa(mPacket, length);
+ } catch (IOException|ErrnoException e) {
+ if (!mStopped) {
+ Log.e(TAG, "Read error", e);
+ }
+ }
+ }
+ }
+ }
+
+ private static final String TAG = "ApfFilter";
+
+ private final ConnectivityService mConnectivityService;
+ private final NetworkAgentInfo mNai;
+ private ReceiveThread mReceiveThread;
+ private String mIfaceName;
+ private long mUniqueCounter;
+
+ private ApfFilter(ConnectivityService connectivityService, NetworkAgentInfo nai) {
+ mConnectivityService = connectivityService;
+ mNai = nai;
+ maybeStartFilter();
+ }
+
+ private void log(String s) {
+ Log.d(TAG, "(" + mNai.network.netId + "): " + s);
+ }
+
+ private long getUniqueNumber() {
+ return mUniqueCounter++;
+ }
+
+ /**
+ * Attempt to start listening for RAs and, if RAs are received, generating and installing
+ * filters to ignore useless RAs.
+ */
+ private void maybeStartFilter() {
+ mIfaceName = mNai.linkProperties.getInterfaceName();
+ if (mIfaceName == null) return;
+ FileDescriptor socket;
+ try {
+ socket = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IPV6);
+ PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IPV6,
+ NetworkInterface.getByName(mIfaceName).getIndex());
+ Os.bind(socket, addr);
+ NetworkUtils.attachRaFilter(socket, mNai.networkMisc.apfPacketFormat);
+ } catch(SocketException|ErrnoException e) {
+ Log.e(TAG, "Error filtering raw socket", e);
+ return;
+ }
+ mReceiveThread = new ReceiveThread(socket);
+ mReceiveThread.start();
+ }
+
+ /**
+ * mNai's LinkProperties may have changed, take appropriate action.
+ */
+ public void updateFilter() {
+ // If we're not listening for RAs, try starting.
+ if (mReceiveThread == null) {
+ maybeStartFilter();
+ // If interface name has changed, restart.
+ } else if (!mIfaceName.equals(mNai.linkProperties.getInterfaceName())) {
+ shutdown();
+ maybeStartFilter();
+ }
+ }
+
+ // Returns seconds since Unix Epoch.
+ private static long curTime() {
+ return System.currentTimeMillis() / 1000L;
+ }
+
+ // A class to hold information about an RA.
+ private class Ra {
+ private static final int ETH_HEADER_LEN = 14;
+
+ private static final int IPV6_HEADER_LEN = 40;
+
+ // From RFC4861:
+ private static final int ICMP6_RA_HEADER_LEN = 16;
+ private static final int ICMP6_RA_OPTION_OFFSET =
+ ETH_HEADER_LEN + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN;
+ private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET =
+ ETH_HEADER_LEN + IPV6_HEADER_LEN + 6;
+ private static final int ICMP6_RA_ROUTER_LIFETIME_LEN = 2;
+ // Prefix information option.
+ private static final int ICMP6_PREFIX_OPTION_TYPE = 3;
+ private static final int ICMP6_PREFIX_OPTION_LEN = 32;
+ private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET = 4;
+ private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_LEN = 4;
+ private static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET = 8;
+ private static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_LEN = 4;
+
+ // From RFC6106: Recursive DNS Server option
+ private static final int ICMP6_RDNSS_OPTION_TYPE = 25;
+ // From RFC6106: DNS Search List option
+ private static final int ICMP6_DNSSL_OPTION_TYPE = 31;
+
+ // From RFC4191: Route Information option
+ private static final int ICMP6_ROUTE_INFO_OPTION_TYPE = 24;
+ // Above three options all have the same format:
+ private static final int ICMP6_4_BYTE_LIFETIME_OFFSET = 4;
+ private static final int ICMP6_4_BYTE_LIFETIME_LEN = 4;
+
+ private final ByteBuffer mPacket;
+ // List of binary ranges that include the whole packet except the lifetimes.
+ // Pairs consist of offset and length.
+ private final ArrayList<Pair<Integer, Integer>> mNonLifetimes =
+ new ArrayList<Pair<Integer, Integer>>();
+ // Minimum lifetime in packet
+ long mMinLifetime;
+ // When the packet was last captured, in seconds since Unix Epoch
+ long mLastSeen;
+
+ /**
+ * Add a binary range of the packet that does not include a lifetime to mNonLifetimes.
+ * Assumes mPacket.position() is as far as we've parsed the packet.
+ * @param lastNonLifetimeStart offset within packet of where the last binary range of
+ * data not including a lifetime.
+ * @param lifetimeOffset offset from mPacket.position() to the next lifetime data.
+ * @param lifetimeLength length of the next lifetime data.
+ * @return offset within packet of where the next binary range of data not including
+ * a lifetime. This can be passed into the next invocation of this function
+ * via {@code lastNonLifetimeStart}.
+ */
+ private int addNonLifetime(int lastNonLifetimeStart, int lifetimeOffset,
+ int lifetimeLength) {
+ lifetimeOffset += mPacket.position();
+ mNonLifetimes.add(new Pair<Integer, Integer>(lastNonLifetimeStart,
+ lifetimeOffset - lastNonLifetimeStart));
+ return lifetimeOffset + lifetimeLength;
+ }
+
+ // Note that this parses RA and may throw IllegalArgumentException (from
+ // Buffer.position(int) ) or IndexOutOfBoundsException (from ByteBuffer.get(int) ) if
+ // parsing encounters something non-compliant with specifications.
+ Ra(byte[] packet, int length) {
+ mPacket = ByteBuffer.allocate(length).put(ByteBuffer.wrap(packet, 0, length));
+ mPacket.clear();
+ mLastSeen = curTime();
+
+ // Parse router lifetime
+ int lastNonLifetimeStart = addNonLifetime(0, ICMP6_RA_ROUTER_LIFETIME_OFFSET,
+ ICMP6_RA_ROUTER_LIFETIME_LEN);
+ // Parse ICMP6 options
+ mPacket.position(ICMP6_RA_OPTION_OFFSET);
+ while (mPacket.hasRemaining()) {
+ int optionType = ((int)mPacket.get(mPacket.position())) & 0xff;
+ int optionLength = (((int)mPacket.get(mPacket.position() + 1)) & 0xff) * 8;
+ switch (optionType) {
+ case ICMP6_PREFIX_OPTION_TYPE:
+ // Parse valid lifetime
+ lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
+ ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET,
+ ICMP6_PREFIX_OPTION_VALID_LIFETIME_LEN);
+ // Parse preferred lifetime
+ lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
+ ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET,
+ ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_LEN);
+ break;
+ // These three options have the same lifetime offset and size, so process
+ // together:
+ case ICMP6_ROUTE_INFO_OPTION_TYPE:
+ case ICMP6_RDNSS_OPTION_TYPE:
+ case ICMP6_DNSSL_OPTION_TYPE:
+ // Parse lifetime
+ lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
+ ICMP6_4_BYTE_LIFETIME_OFFSET,
+ ICMP6_4_BYTE_LIFETIME_LEN);
+ break;
+ default:
+ // RFC4861 section 4.2 dictates we ignore unknown options for fowards
+ // compatibility.
+ break;
+ }
+ mPacket.position(mPacket.position() + optionLength);
+ }
+ // Mark non-lifetime bytes since last lifetime.
+ addNonLifetime(lastNonLifetimeStart, 0, 0);
+ mMinLifetime = minLifetime(packet, length);
+ }
+
+ // Ignoring lifetimes (which may change) does {@code packet} match this RA?
+ boolean matches(byte[] packet, int length) {
+ if (length != mPacket.limit()) return false;
+ ByteBuffer a = ByteBuffer.wrap(packet);
+ ByteBuffer b = mPacket;
+ for (Pair<Integer, Integer> nonLifetime : mNonLifetimes) {
+ a.clear();
+ b.clear();
+ a.position(nonLifetime.first);
+ b.position(nonLifetime.first);
+ a.limit(nonLifetime.first + nonLifetime.second);
+ b.limit(nonLifetime.first + nonLifetime.second);
+ if (a.compareTo(b) != 0) return false;
+ }
+ return true;
+ }
+
+ // What is the minimum of all lifetimes within {@code packet} in seconds?
+ // Precondition: matches(packet, length) already returned true.
+ long minLifetime(byte[] packet, int length) {
+ long minLifetime = Long.MAX_VALUE;
+ // Wrap packet in ByteBuffer so we can read big-endian values easily
+ ByteBuffer byteBuffer = ByteBuffer.wrap(packet);
+ for (int i = 0; (i + 1) < mNonLifetimes.size(); i++) {
+ int offset = mNonLifetimes.get(i).first + mNonLifetimes.get(i).second;
+ int lifetimeLength = mNonLifetimes.get(i+1).first - offset;
+ long val;
+ switch (lifetimeLength) {
+ case 2: val = byteBuffer.getShort(offset); break;
+ case 4: val = byteBuffer.getInt(offset); break;
+ default: throw new IllegalStateException("bogus lifetime size " + length);
+ }
+ // Mask to size, converting signed to unsigned
+ val &= (1L << (lifetimeLength * 8)) - 1;
+ minLifetime = Math.min(minLifetime, val);
+ }
+ return minLifetime;
+ }
+
+ // How many seconds does this RA's have to live, taking into account the fact
+ // that we might have seen it a while ago.
+ long currentLifetime() {
+ return mMinLifetime - (curTime() - mLastSeen);
+ }
+
+ boolean isExpired() {
+ return currentLifetime() < 0;
+ }
+
+ // Append a filter for this RA to {@code gen}. Jump to DROP_LABEL if it should be dropped.
+ // Jump to the next filter if packet doesn't match this RA.
+ long generateFilter(ApfGenerator gen) throws IllegalInstructionException {
+ String nextFilterLabel = "Ra" + getUniqueNumber();
+ // Skip if packet is not the right size
+ gen.addLoadFromMemory(Register.R0, gen.PACKET_SIZE_MEMORY_SLOT);
+ gen.addJumpIfR0NotEquals(mPacket.limit(), nextFilterLabel);
+ int filterLifetime = (int)(currentLifetime() / FRACTION_OF_LIFETIME_TO_FILTER);
+ // Skip filter if expired
+ gen.addLoadFromMemory(Register.R0, gen.FILTER_AGE_MEMORY_SLOT);
+ gen.addJumpIfR0GreaterThan(filterLifetime, nextFilterLabel);
+ for (int i = 0; i < mNonLifetimes.size(); i++) {
+ // Generate code to match the packet bytes
+ Pair<Integer, Integer> nonLifetime = mNonLifetimes.get(i);
+ gen.addLoadImmediate(Register.R0, nonLifetime.first);
+ gen.addJumpIfBytesNotEqual(Register.R0,
+ Arrays.copyOfRange(mPacket.array(), nonLifetime.first,
+ nonLifetime.first + nonLifetime.second),
+ nextFilterLabel);
+ // Generate code to test the lifetimes haven't gone down too far
+ if ((i + 1) < mNonLifetimes.size()) {
+ Pair<Integer, Integer> nextNonLifetime = mNonLifetimes.get(i + 1);
+ int offset = nonLifetime.first + nonLifetime.second;
+ int length = nextNonLifetime.first - offset;
+ switch (length) {
+ case 4: gen.addLoad32(Register.R0, offset); break;
+ case 2: gen.addLoad16(Register.R0, offset); break;
+ default: throw new IllegalStateException("bogus lifetime size " + length);
+ }
+ gen.addJumpIfR0LessThan(filterLifetime, nextFilterLabel);
+ }
+ }
+ gen.addJump(gen.DROP_LABEL);
+ gen.defineLabel(nextFilterLabel);
+ return filterLifetime;
+ }
+ }
+
+ // Maximum number of RAs to filter for.
+ private static final int MAX_RAS = 10;
+ private ArrayList<Ra> mRas = new ArrayList<Ra>();
+
+ // There is always some marginal benefit to updating the installed APF program when an RA is
+ // seen because we can extend the program's lifetime slightly, but there is some cost to
+ // updating the program, so don't bother unless the program is going to expire soon. This
+ // constant defines "soon" in seconds.
+ private static final long MAX_PROGRAM_LIFETIME_WORTH_REFRESHING = 30;
+ // We don't want to filter an RA for it's whole lifetime as it'll be expired by the time we ever
+ // see a refresh. Using half the lifetime might be a good idea except for the fact that
+ // packets may be dropped, so let's use 6.
+ private static final int FRACTION_OF_LIFETIME_TO_FILTER = 6;
+
+ // When did we last install a filter program? In seconds since Unix Epoch.
+ private long mLastTimeInstalledProgram;
+ // How long should the last installed filter program live for? In seconds.
+ private long mLastInstalledProgramMinLifetime;
+
+ private void installNewProgram() {
+ if (mRas.size() == 0) return;
+ final byte[] program;
+ long programMinLifetime = Long.MAX_VALUE;
+ try {
+ ApfGenerator gen = new ApfGenerator();
+ // This is guaranteed to return true because of the check in maybeInstall.
+ gen.setApfVersion(mNai.networkMisc.apfVersionSupported);
+ // Step 1: Determine how many RA filters we can fit in the program.
+ int ras = 0;
+ for (Ra ra : mRas) {
+ if (ra.isExpired()) continue;
+ ra.generateFilter(gen);
+ if (gen.programLengthOverEstimate() > mNai.networkMisc.maximumApfProgramSize) {
+ // We went too far. Use prior number of RAs in "ras".
+ break;
+ } else {
+ // Yay! this RA filter fits, increment "ras".
+ ras++;
+ }
+ }
+ // Step 2: Generate RA filters
+ gen = new ApfGenerator();
+ // This is guaranteed to return true because of the check in maybeInstall.
+ gen.setApfVersion(mNai.networkMisc.apfVersionSupported);
+ for (Ra ra : mRas) {
+ if (ras-- == 0) break;
+ if (ra.isExpired()) continue;
+ programMinLifetime = Math.min(programMinLifetime, ra.generateFilter(gen));
+ }
+ // Execution will reach the end of the program if no filters match, which will pass the
+ // packet to the AP.
+ program = gen.generate();
+ } catch (IllegalInstructionException e) {
+ Log.e(TAG, "Program failed to generate: ", e);
+ return;
+ }
+ mLastTimeInstalledProgram = curTime();
+ mLastInstalledProgramMinLifetime = programMinLifetime;
+ hexDump("Installing filter: ", program, program.length);
+ mConnectivityService.pushApfProgramToNetwork(mNai, program);
+ }
+
+ // Install a new filter program if the last installed one will die soon.
+ private void maybeInstallNewProgram() {
+ if (mRas.size() == 0) return;
+ // If the current program doesn't expire for a while, don't bother updating.
+ long expiry = mLastTimeInstalledProgram + mLastInstalledProgramMinLifetime;
+ if (expiry < curTime() + MAX_PROGRAM_LIFETIME_WORTH_REFRESHING) {
+ installNewProgram();
+ }
+ }
+
+ private void hexDump(String msg, byte[] packet, int length) {
+ log(msg + HexDump.toHexString(packet, 0, length));
+ }
+
+ private void processRa(byte[] packet, int length) {
+ hexDump("Read packet = ", packet, length);
+
+ // Have we seen this RA before?
+ for (int i = 0; i < mRas.size(); i++) {
+ Ra ra = mRas.get(i);
+ if (ra.matches(packet, length)) {
+ log("matched RA");
+ // Update lifetimes.
+ ra.mLastSeen = curTime();
+ ra.mMinLifetime = ra.minLifetime(packet, length);
+
+ // Keep mRas in LRU order so as to prioritize generating filters for recently seen
+ // RAs. LRU prioritizes this because RA filters are generated in order from mRas
+ // until the filter program exceeds the maximum filter program size allowed by the
+ // chipset, so RAs appearing earlier in mRas are more likely to make it into the
+ // filter program.
+ // TODO: consider sorting the RAs in order of increasing expiry time as well.
+ // Swap to front of array.
+ mRas.add(0, mRas.remove(i));
+
+ maybeInstallNewProgram();
+ return;
+ }
+ }
+ // Purge expired RAs.
+ for (int i = 0; i < mRas.size();) {
+ if (mRas.get(i).isExpired()) {
+ log("expired RA");
+ mRas.remove(i);
+ } else {
+ i++;
+ }
+ }
+ // TODO: figure out how to proceed when we've received more then MAX_RAS RAs.
+ if (mRas.size() >= MAX_RAS) return;
+ try {
+ log("adding RA");
+ mRas.add(new Ra(packet, length));
+ } catch (Exception e) {
+ Log.e(TAG, "Error parsing RA: " + e);
+ return;
+ }
+ installNewProgram();
+ }
+
+ /**
+ * Install an {@link ApfFilter} on {@code nai} if {@code nai} supports packet
+ * filtering using APF programs.
+ */
+ public static void maybeInstall(ConnectivityService connectivityService, NetworkAgentInfo nai) {
+ if (nai.networkMisc == null) return;
+ if (nai.networkMisc.apfVersionSupported == 0) return;
+ if (nai.networkMisc.maximumApfProgramSize < 200) {
+ Log.e(TAG, "Uselessly small APF size limit: " + nai.networkMisc.maximumApfProgramSize);
+ return;
+ }
+ // For now only support generating programs for Ethernet frames. If this restriction is
+ // lifted:
+ // 1. the program generator will need its offsets adjusted.
+ // 2. the packet filter attached to our packet socket will need its offset adjusted.
+ if (nai.networkMisc.apfPacketFormat != ARPHRD_ETHER) return;
+ if (!new ApfGenerator().setApfVersion(nai.networkMisc.apfVersionSupported)) {
+ Log.e(TAG, "Unsupported APF version: " + nai.networkMisc.apfVersionSupported);
+ return;
+ }
+ nai.apfFilter = new ApfFilter(connectivityService, nai);
+ }
+
+ public void shutdown() {
+ if (mReceiveThread != null) {
+ log("shuting down");
+ mReceiveThread.halt(); // Also closes socket.
+ mReceiveThread = null;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
index 90c9ddf..9e1f6b8 100644
--- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
+++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
@@ -60,7 +60,7 @@
public class KeepaliveTracker {
private static final String TAG = "KeepaliveTracker";
- private static final boolean DBG = true;
+ private static final boolean DBG = false;
public static final String PERMISSION = android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD;
diff --git a/services/core/java/com/android/server/connectivity/MetricsLoggerService.java b/services/core/java/com/android/server/connectivity/MetricsLoggerService.java
new file mode 100644
index 0000000..f6dc9b9
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/MetricsLoggerService.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity;
+
+import com.android.server.SystemService;
+
+import android.content.Context;
+import android.net.ConnectivityMetricsEvent;
+import android.net.ConnectivityMetricsLogger;
+import android.net.IConnectivityMetricsLogger;
+import android.net.IConnectivityMetricsLoggerSubscriber;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** {@hide} */
+public class MetricsLoggerService extends SystemService {
+ private static String TAG = "ConnectivityMetricsLoggerService";
+ private static final boolean DBG = true;
+ private static final boolean VDBG = false;
+
+ public MetricsLoggerService(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onStart() {
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
+ Log.d(TAG, "onBootPhase: PHASE_SYSTEM_SERVICES_READY");
+ publishBinderService(ConnectivityMetricsLogger.CONNECTIVITY_METRICS_LOGGER_SERVICE,
+ mBinder);
+ }
+ }
+
+ private final int MAX_NUMBER_OF_EVENTS = 100;
+ private final int MAX_TIME_OFFSET = 15*60*1000; // 15 minutes
+ private final List<ConnectivityMetricsEvent> mEvents = new ArrayList<>();
+ private long mLastSentEventTimeMillis = System.currentTimeMillis();
+
+ private final void enforceConnectivityInternalPermission() {
+ getContext().enforceCallingPermission(
+ android.Manifest.permission.CONNECTIVITY_INTERNAL,
+ "MetricsLoggerService");
+ }
+
+ /**
+ * Implementation of the IConnectivityMetricsLogger interface.
+ */
+ private final IConnectivityMetricsLogger.Stub mBinder = new IConnectivityMetricsLogger.Stub() {
+
+ private final ArrayMap<IConnectivityMetricsLoggerSubscriber,
+ IBinder.DeathRecipient> mSubscribers = new ArrayMap<>();
+
+
+ private ConnectivityMetricsEvent[] prepareEventsToSendIfReady() {
+ ConnectivityMetricsEvent[] eventsToSend = null;
+ final long currentTimeMillis = System.currentTimeMillis();
+ final long timeOffset = currentTimeMillis - mLastSentEventTimeMillis;
+ if (timeOffset >= MAX_TIME_OFFSET
+ || timeOffset < 0 // system time has changed
+ || mEvents.size() >= MAX_NUMBER_OF_EVENTS) {
+ // batch events
+ mLastSentEventTimeMillis = currentTimeMillis;
+ eventsToSend = new ConnectivityMetricsEvent[mEvents.size()];
+ mEvents.toArray(eventsToSend);
+ mEvents.clear();
+ }
+ return eventsToSend;
+ }
+
+ private void maybeSendEventsToSubscribers(ConnectivityMetricsEvent[] eventsToSend) {
+ if (eventsToSend == null || eventsToSend.length == 0) return;
+ synchronized (mSubscribers) {
+ for (IConnectivityMetricsLoggerSubscriber s : mSubscribers.keySet()) {
+ try {
+ s.onEvents(eventsToSend);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "RemoteException " + ex);
+ }
+ }
+ }
+ }
+
+ public void logEvent(ConnectivityMetricsEvent event) {
+ ConnectivityMetricsEvent[] events = new ConnectivityMetricsEvent[]{event};
+ logEvents(events);
+ }
+
+ public void logEvents(ConnectivityMetricsEvent[] events) {
+ enforceConnectivityInternalPermission();
+ ConnectivityMetricsEvent[] eventsToSend;
+
+ if (VDBG) {
+ for (ConnectivityMetricsEvent e : events) {
+ Log.v(TAG, "writeEvent(" + e.toString() + ")");
+ }
+ }
+
+ synchronized (mEvents) {
+ for (ConnectivityMetricsEvent e : events) {
+ mEvents.add(e);
+ }
+
+ eventsToSend = prepareEventsToSendIfReady();
+ }
+
+ maybeSendEventsToSubscribers(eventsToSend);
+ }
+
+ public boolean subscribe(IConnectivityMetricsLoggerSubscriber subscriber) {
+ enforceConnectivityInternalPermission();
+ if (VDBG) Log.v(TAG, "subscribe");
+
+ synchronized (mSubscribers) {
+ if (mSubscribers.containsKey(subscriber)) {
+ Log.e(TAG, "subscriber is already subscribed");
+ return false;
+ }
+ final IConnectivityMetricsLoggerSubscriber s = subscriber;
+ IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
+ @Override
+ public void binderDied() {
+ if (VDBG) Log.v(TAG, "subscriber died");
+ synchronized (mSubscribers) {
+ mSubscribers.remove(s);
+ }
+ }
+ };
+
+ try {
+ subscriber.asBinder().linkToDeath(dr, 0);
+ mSubscribers.put(subscriber, dr);
+ } catch (RemoteException e) {
+ Log.e(TAG, "subscribe failed: " + e);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public void unsubscribe(IConnectivityMetricsLoggerSubscriber subscriber) {
+ enforceConnectivityInternalPermission();
+ if (VDBG) Log.v(TAG, "unsubscribe");
+ synchronized (mSubscribers) {
+ IBinder.DeathRecipient dr = mSubscribers.remove(subscriber);
+ if (dr == null) {
+ Log.e(TAG, "subscriber is not subscribed");
+ return;
+ }
+ subscriber.asBinder().unlinkToDeath(dr, 0);
+ }
+ }
+ };
+}
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
index a9eaeee..b390884 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
@@ -16,13 +16,11 @@
package com.android.server.connectivity;
-import static android.net.ConnectivityManager.TYPE_MOBILE;
-import static android.net.ConnectivityManager.TYPE_WIFI;
-
import java.net.Inet4Address;
import android.content.Context;
import android.net.InterfaceConfiguration;
+import android.net.ConnectivityManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.NetworkAgent;
@@ -34,6 +32,7 @@
import android.util.Slog;
import com.android.server.net.BaseNetworkObserver;
+import com.android.internal.util.ArrayUtils;
/**
* @hide
@@ -46,6 +45,13 @@
// This must match the interface prefix in clatd.c.
private static final String CLAT_PREFIX = "v4-";
+ // The network types we will start clatd on.
+ private static final int[] NETWORK_TYPES = {
+ ConnectivityManager.TYPE_MOBILE,
+ ConnectivityManager.TYPE_WIFI,
+ ConnectivityManager.TYPE_ETHERNET,
+ };
+
private final INetworkManagementService mNMService;
// ConnectivityService Handler for LinkProperties updates.
@@ -90,7 +96,7 @@
(nai.linkProperties != null) ? nai.linkProperties.hasIPv4Address() : false;
// Only support clat on mobile and wifi for now, because these are the only IPv6-only
// networks we can connect to.
- return connected && !hasIPv4Address && (netType == TYPE_MOBILE || netType == TYPE_WIFI);
+ return connected && !hasIPv4Address && ArrayUtils.contains(NETWORK_TYPES, netType);
}
/**
@@ -221,7 +227,7 @@
}
private void maybeSetIpv6NdOffload(String iface, boolean on) {
- if (mNetwork.networkInfo.getType() != TYPE_WIFI) {
+ if (mNetwork.networkInfo.getType() != ConnectivityManager.TYPE_WIFI) {
return;
}
try {
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index c5d38cb..b4c71c1 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -32,6 +32,7 @@
import com.android.internal.util.AsyncChannel;
import com.android.server.ConnectivityService;
import com.android.server.connectivity.NetworkMonitor;
+import com.android.server.connectivity.ApfFilter;
import java.util.ArrayList;
import java.util.Comparator;
@@ -163,6 +164,8 @@
// Used by ConnectivityService to keep track of 464xlat.
public Nat464Xlat clatd;
+ public ApfFilter apfFilter;
+
public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info,
LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler,
NetworkMisc misc, NetworkRequest defaultRequest, ConnectivityService connService) {
@@ -175,6 +178,7 @@
currentScore = score;
networkMonitor = connService.createNetworkMonitor(context, handler, this, defaultRequest);
networkMisc = misc;
+ apfFilter.maybeInstall(connService, this);
}
/**
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 4504bdb..73da427 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -76,7 +76,7 @@
* {@hide}
*/
public class NetworkMonitor extends StateMachine {
- private static final boolean DBG = true;
+ private static final boolean DBG = false;
private static final String TAG = "NetworkMonitor";
private static final String DEFAULT_SERVER = "connectivitycheck.gstatic.com";
private static final int SOCKET_TIMEOUT_MS = 10000;
@@ -566,7 +566,7 @@
@Override
public void enter() {
final String cmdName = ACTION_LINGER_EXPIRED + "." + mNetworkAgentInfo.network.netId;
- mWakeupMessage = new WakeupMessage(mContext, getHandler(), cmdName, CMD_LINGER_EXPIRED);
+ mWakeupMessage = makeWakeupMessage(mContext, getHandler(), cmdName, CMD_LINGER_EXPIRED);
long wakeupTime = SystemClock.elapsedRealtime() + mLingerDelayMs;
mWakeupMessage.schedule(wakeupTime);
}
@@ -823,4 +823,9 @@
}
DEFAULT_LINGER_DELAY_MS = time_ms;
}
+
+ @VisibleForTesting
+ protected WakeupMessage makeWakeupMessage(Context c, Handler h, String s, int i) {
+ return new WakeupMessage(c, h, s, i);
+ }
}
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index debda14..22cefd1 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -54,7 +54,7 @@
*/
public class PermissionMonitor {
private static final String TAG = "PermissionMonitor";
- private static final boolean DBG = true;
+ private static final boolean DBG = false;
private static final boolean SYSTEM = true;
private static final boolean NETWORK = false;
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 760b218..4eecc81 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -90,7 +90,7 @@
private Context mContext;
private final static String TAG = "Tethering";
- private final static boolean DBG = true;
+ private final static boolean DBG = false;
private final static boolean VDBG = false;
// TODO - remove both of these - should be part of interface inspection/selection stuff
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 0d97434..95a9875 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -453,48 +453,10 @@
}
}
}
- ensureDefaultPeriodicSyncsH();
}
});
}
- private void ensureDefaultPeriodicSyncsH() {
-
- long defaultPeriod = SyncStorageEngine.DEFAULT_POLL_FREQUENCY_SECONDS;
- long defaultFlex = SyncStorageEngine.calculateDefaultFlexTime(defaultPeriod);
-
- List<AuthorityInfo> authorities = mSyncStorageEngine.getAllAuthorities();
- List<SyncOperation> syncs = getAllPendingSyncsFromCache();
- for (AuthorityInfo authority: authorities) {
- boolean foundPeriodicSync = false;
- for (SyncOperation op: syncs) {
- if (op.isPeriodic && authority.target.matchesSpec(op.target)) {
- foundPeriodicSync = true;
- break;
- }
- }
- if (!foundPeriodicSync) {
- EndPoint target = authority.target;
- final RegisteredServicesCache.ServiceInfo<SyncAdapterType>
- syncAdapterInfo = mSyncAdapters.getServiceInfo(
- SyncAdapterType.newKey(
- target.provider, target.account.type),
- target.userId);
- if (syncAdapterInfo == null) {
- continue;
- }
- scheduleSyncOperationH(
- new SyncOperation(target, syncAdapterInfo.uid,
- syncAdapterInfo.componentName.getPackageName(),
- SyncOperation.REASON_PERIODIC, SyncStorageEngine.SOURCE_PERIODIC,
- new Bundle(), syncAdapterInfo.type.allowParallelSyncs(),
- true /* periodic */, SyncOperation.NO_JOB_ID, defaultPeriod * 1000L,
- defaultFlex * 1000L)
- );
- }
- }
- }
-
private synchronized void verifyJobScheduler() {
if (mJobScheduler != null) {
return;
@@ -1357,7 +1319,7 @@
}
getJobScheduler().scheduleAsPackage(b.build(), syncOperation.owningPackage,
- syncOperation.target.userId);
+ syncOperation.target.userId, "sync");
}
/**
@@ -2271,6 +2233,7 @@
void checkIfDeviceReady() {
if (mProvisioned && mBootCompleted) {
synchronized(this) {
+ mSyncStorageEngine.restoreAllPeriodicSyncs();
// Dispatch any stashed messages.
obtainMessage(MESSAGE_RELEASE_MESSAGES_FROM_QUEUE).sendToTarget();
}
@@ -2622,7 +2585,6 @@
}
if (mBootCompleted) {
doDatabaseCleanup();
- mSyncStorageEngine.restoreAllPeriodicSyncs();
}
AccountAndUser[] accounts = mRunningAccounts;
diff --git a/services/core/java/com/android/server/content/SyncOperation.java b/services/core/java/com/android/server/content/SyncOperation.java
index 957b087..804be4e 100644
--- a/services/core/java/com/android/server/content/SyncOperation.java
+++ b/services/core/java/com/android/server/content/SyncOperation.java
@@ -17,6 +17,7 @@
package com.android.server.content;
import android.accounts.Account;
+import android.app.job.JobInfo;
import android.content.pm.PackageManager;
import android.content.ContentResolver;
import android.os.Bundle;
@@ -320,11 +321,11 @@
int findPriority() {
if (isInitialization()) {
- return 2;
+ return JobInfo.PRIORITY_SYNC_INITIALIZATION;
} else if (isExpedited()) {
- return 1;
+ return JobInfo.PRIORITY_SYNC_EXPEDITED;
}
- return 0;
+ return JobInfo.PRIORITY_DEFAULT;
}
private String toKey() {
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index cefaa8d..bc3fc6a 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -80,7 +80,7 @@
private static final String XML_TAG_LISTEN_FOR_TICKLES = "listenForTickles";
/** Default time for a periodic sync. */
- static final long DEFAULT_POLL_FREQUENCY_SECONDS = 60 * 60 * 24; // One day
+ private static final long DEFAULT_POLL_FREQUENCY_SECONDS = 60 * 60 * 24; // One day
/** Percentage of period that is flex by default, if no flexMillis is set. */
private static final double DEFAULT_FLEX_PERCENT_SYNC = 0.04;
@@ -857,16 +857,6 @@
}
}
- List<AuthorityInfo> getAllAuthorities() {
- List<AuthorityInfo> authorities = new ArrayList<AuthorityInfo>();
- synchronized (mAuthorities) {
- for (int i = 0; i < mAuthorities.size(); i++) {
- authorities.add(mAuthorities.valueAt(i));
- }
- }
- return authorities;
- }
-
/**
* Returns true if there is currently a sync operation being actively processed for the given
* target.
@@ -1500,6 +1490,9 @@
if (authority.ident > highestAuthorityId) {
highestAuthorityId = authority.ident;
}
+ } else {
+ EventLog.writeEvent(0x534e4554, "26513719", -1,
+ "Malformed authority");
}
} else if (XML_TAG_LISTEN_FOR_TICKLES.equals(tagName)) {
parseListenForTickles(parser);
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 1908f72..5c80d04 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -60,22 +60,8 @@
// non-zero, which in turn ensures that the total weight is non-zero.
private static final long AMBIENT_LIGHT_PREDICTION_TIME_MILLIS = 100;
- // If true, enables the use of the current time as an auto-brightness adjustment.
- // The basic idea here is to expand the dynamic range of auto-brightness
- // when it is especially dark outside. The light sensor tends to perform
- // poorly at low light levels so we compensate for it by making an
- // assumption about the environment.
- private static final boolean USE_TWILIGHT_ADJUSTMENT =
- PowerManager.useTwilightAdjustmentFeature();
-
// Specifies the maximum magnitude of the time of day adjustment.
- private static final float TWILIGHT_ADJUSTMENT_MAX_GAMMA = 1.5f;
-
- // The amount of time after or before sunrise over which to start adjusting
- // the gamma. We want the change to happen gradually so that it is below the
- // threshold of perceptibility and so that the adjustment has maximum effect
- // well after dusk.
- private static final long TWILIGHT_ADJUSTMENT_TIME = DateUtils.HOUR_IN_MILLIS * 2;
+ private static final float TWILIGHT_ADJUSTMENT_MAX_GAMMA = 1f;
// Debounce for sampling user-initiated changes in display brightness to ensure
// the user is satisfied with the result before storing the sample.
@@ -193,6 +179,8 @@
private int mBrightnessAdjustmentSampleOldBrightness;
private float mBrightnessAdjustmentSampleOldGamma;
+ private boolean mUseTwilight;
+
public AutomaticBrightnessController(Callbacks callbacks, Looper looper,
SensorManager sensorManager, Spline autoBrightnessSpline, int lightSensorWarmUpTime,
int brightnessMin, int brightnessMax, float dozeScaleFactor,
@@ -221,10 +209,6 @@
if (!DEBUG_PRETEND_LIGHT_SENSOR_ABSENT) {
mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
}
-
- if (USE_TWILIGHT_ADJUSTMENT) {
- mTwilight.registerListener(mTwilightListener, mHandler);
- }
}
public int getAutomaticScreenBrightness() {
@@ -235,7 +219,7 @@
}
public void configure(boolean enable, float adjustment, boolean dozing,
- boolean userInitiatedChange) {
+ boolean userInitiatedChange, boolean useTwilight) {
// While dozing, the application processor may be suspended which will prevent us from
// receiving new information from the light sensor. On some devices, we may be able to
// switch to a wake-up light sensor instead but for now we will simply disable the sensor
@@ -244,6 +228,7 @@
mDozing = dozing;
boolean changed = setLightSensorEnabled(enable && !dozing);
changed |= setScreenAutoBrightnessAdjustment(adjustment);
+ changed |= setUseTwilight(useTwilight);
if (changed) {
updateAutoBrightness(false /*sendUpdate*/);
}
@@ -252,6 +237,17 @@
}
}
+ private boolean setUseTwilight(boolean useTwilight) {
+ if (mUseTwilight == useTwilight) return false;
+ if (useTwilight) {
+ mTwilight.registerListener(mTwilightListener, mHandler);
+ } else {
+ mTwilight.unregisterListener(mTwilightListener);
+ }
+ mUseTwilight = useTwilight;
+ return true;
+ }
+
public void dump(PrintWriter pw) {
pw.println();
pw.println("Automatic Brightness Controller Configuration:");
@@ -484,18 +480,13 @@
}
}
- if (USE_TWILIGHT_ADJUSTMENT) {
+ if (mUseTwilight) {
TwilightState state = mTwilight.getCurrentState();
if (state != null && state.isNight()) {
final long now = System.currentTimeMillis();
- final float earlyGamma =
- getTwilightGamma(now, state.getYesterdaySunset(), state.getTodaySunrise());
- final float lateGamma =
- getTwilightGamma(now, state.getTodaySunset(), state.getTomorrowSunrise());
- gamma *= earlyGamma * lateGamma;
+ gamma *= 1 + state.getAmount() * TWILIGHT_ADJUSTMENT_MAX_GAMMA;
if (DEBUG) {
- Slog.d(TAG, "updateAutoBrightness: earlyGamma=" + earlyGamma
- + ", lateGamma=" + lateGamma);
+ Slog.d(TAG, "updateAutoBrightness: twilight amount=" + state.getAmount());
}
}
}
@@ -579,25 +570,6 @@
}
}
- private static float getTwilightGamma(long now, long lastSunset, long nextSunrise) {
- if (lastSunset < 0 || nextSunrise < 0
- || now < lastSunset || now > nextSunrise) {
- return 1.0f;
- }
-
- if (now < lastSunset + TWILIGHT_ADJUSTMENT_TIME) {
- return MathUtils.lerp(1.0f, TWILIGHT_ADJUSTMENT_MAX_GAMMA,
- (float)(now - lastSunset) / TWILIGHT_ADJUSTMENT_TIME);
- }
-
- if (now > nextSunrise - TWILIGHT_ADJUSTMENT_TIME) {
- return MathUtils.lerp(1.0f, TWILIGHT_ADJUSTMENT_MAX_GAMMA,
- (float)(nextSunrise - now) / TWILIGHT_ADJUSTMENT_TIME);
- }
-
- return TWILIGHT_ADJUSTMENT_MAX_GAMMA;
- }
-
private final class AutomaticBrightnessHandler extends Handler {
public AutomaticBrightnessHandler(Looper looper) {
super(looper, null, true /*async*/);
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 1038d97..1ed7070 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -615,7 +615,7 @@
&& mPowerRequest.brightnessSetByUser;
mAutomaticBrightnessController.configure(autoBrightnessEnabled,
mPowerRequest.screenAutoBrightnessAdjustment, state != Display.STATE_ON,
- userInitiatedChange);
+ userInitiatedChange, mPowerRequest.useTwilight);
}
// Apply brightness boost.
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 13e7648..7b134ca 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -62,6 +62,7 @@
import android.hardware.fingerprint.IFingerprintDaemonCallback;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
+import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
import static android.Manifest.permission.MANAGE_FINGERPRINT;
import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT;
@@ -504,6 +505,9 @@
}
public boolean hasEnrolledFingerprints(int userId) {
+ if (userId != UserHandle.getCallingUserId()) {
+ checkPermission(INTERACT_ACROSS_USERS);
+ }
return mFingerprintUtils.getFingerprintsForUser(mContext, userId).size() > 0;
}
@@ -901,13 +905,15 @@
// Group ID is arbitrarily set to parent profile user ID. It just represents
// the default fingerprints for the user.
- final int effectiveGroupId = getEffectiveUserId(groupId);
+ if (!isCurrentUserOrProfile(groupId)) {
+ return;
+ }
final boolean restricted = isRestricted();
mHandler.post(new Runnable() {
@Override
public void run() {
- startEnrollment(token, cryptoClone, effectiveGroupId, receiver, flags, restricted);
+ startEnrollment(token, cryptoClone, groupId, receiver, flags, restricted);
}
});
}
@@ -1007,15 +1013,14 @@
@Override // Binder call
public void rename(final int fingerId, final int groupId, final String name) {
checkPermission(MANAGE_FINGERPRINT);
-
- // Group ID is arbitrarily set to parent profile user ID. It just represents
- // the default fingerprints for the user.
- final int effectiveGroupId = getEffectiveUserId(groupId);
+ if (!isCurrentUserOrProfile(groupId)) {
+ return;
+ }
mHandler.post(new Runnable() {
@Override
public void run() {
mFingerprintUtils.renameFingerprintForUser(mContext, fingerId,
- effectiveGroupId, name);
+ groupId, name);
}
});
}
@@ -1025,9 +1030,11 @@
if (!canUseFingerprint(opPackageName, false /* foregroundOnly */)) {
return Collections.emptyList();
}
- int effectiveUserId = getEffectiveUserId(userId);
+ if (!isCurrentUserOrProfile(userId)) {
+ return Collections.emptyList();
+ }
- return FingerprintService.this.getEnrolledFingerprints(effectiveUserId);
+ return FingerprintService.this.getEnrolledFingerprints(userId);
}
@Override // Binder call
@@ -1036,8 +1043,10 @@
return false;
}
- int effectiveUserId = getEffectiveUserId(userId);
- return FingerprintService.this.hasEnrolledFingerprints(effectiveUserId);
+ if (!isCurrentUserOrProfile(userId)) {
+ return false;
+ }
+ return FingerprintService.this.hasEnrolledFingerprints(userId);
}
@Override // Binder call
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 57cede8..fba7e7d 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -19,6 +19,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
@@ -49,14 +50,17 @@
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
-import android.os.Process;
-import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseIntArray;
+import android.util.TimeUtils;
import com.android.internal.app.IBatteryStats;
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.app.ProcessStats;
import com.android.server.DeviceIdleController;
import com.android.server.LocalServices;
+import com.android.server.job.JobStore.JobStatusFunctor;
import com.android.server.job.controllers.AppIdleController;
import com.android.server.job.controllers.BatteryController;
import com.android.server.job.controllers.ConnectivityController;
@@ -66,6 +70,8 @@
import com.android.server.job.controllers.StateController;
import com.android.server.job.controllers.TimeController;
+import libcore.util.EmptyArray;
+
/**
* Responsible for taking jobs representing work to be performed by a client app, and determining
* based on the criteria specified when that job should be run against the client application's
@@ -78,13 +84,20 @@
* Any function with the suffix 'Locked' also needs to lock on {@link #mJobs}.
* @hide
*/
-public class JobSchedulerService extends com.android.server.SystemService
+public final class JobSchedulerService extends com.android.server.SystemService
implements StateChangedListener, JobCompletedListener {
- public static final boolean DEBUG = false;
- /** The number of concurrent jobs we run at one time. */
- private static final int MAX_JOB_CONTEXTS_COUNT
- = ActivityManager.isLowRamDeviceStatic() ? 3 : 6;
static final String TAG = "JobSchedulerService";
+ public static final boolean DEBUG = false;
+
+ /** The maximum number of concurrent jobs we run at one time. */
+ private static final int MAX_JOB_CONTEXTS_COUNT = 8;
+ /** Enforce a per-app limit on scheduled jobs? */
+ private static final boolean ENFORCE_MAX_JOBS = true;
+ /** The maximum number of jobs that we allow an unprivileged app to schedule */
+ private static final int MAX_JOBS_PER_APP = 100;
+
+ /** Global local for all job scheduler state. */
+ final Object mLock = new Object();
/** Master list of jobs. */
final JobStore mJobs;
@@ -134,7 +147,7 @@
*/
final ArrayList<JobStatus> mPendingJobs = new ArrayList<>();
- final ArrayList<Integer> mStartedUsers = new ArrayList<>();
+ int[] mStartedUsers = EmptyArray.INT;
final JobHandler mHandler;
final JobSchedulerStub mJobSchedulerStub;
@@ -154,11 +167,40 @@
boolean mDeviceIdleMode;
/**
- * What we last reported to DeviceIdleController about wheter we are active.
+ * What we last reported to DeviceIdleController about whether we are active.
*/
boolean mReportedActive;
/**
+ * Current limit on the number of concurrent JobServiceContext entries we want to
+ * keep actively running a job.
+ */
+ int mMaxActiveJobs = MAX_JOB_CONTEXTS_COUNT - 2;
+
+ /**
+ * Which uids are currently in the foreground.
+ */
+ final SparseIntArray mUidPriorityOverride = new SparseIntArray();
+
+ // -- Pre-allocated temporaries only for use in assignJobsToContextsLocked --
+
+ /**
+ * This array essentially stores the state of mActiveServices array.
+ * The ith index stores the job present on the ith JobServiceContext.
+ * We manipulate this array until we arrive at what jobs should be running on
+ * what JobServiceContext.
+ */
+ JobStatus[] mTmpAssignContextIdToJobMap = new JobStatus[MAX_JOB_CONTEXTS_COUNT];
+ /**
+ * Indicates whether we need to act on this jobContext id
+ */
+ boolean[] mTmpAssignAct = new boolean[MAX_JOB_CONTEXTS_COUNT];
+ /**
+ * The uid whose jobs we would like to assign to a context.
+ */
+ int[] mTmpAssignPreferredUidForContext = new int[MAX_JOB_CONTEXTS_COUNT];
+
+ /**
* Cleans up outstanding jobs when a package is removed. Even if it's being replaced later we
* still clean up. On reinstall the package will have a new uid.
*/
@@ -194,9 +236,11 @@
final private IUidObserver mUidObserver = new IUidObserver.Stub() {
@Override public void onUidStateChanged(int uid, int procState) throws RemoteException {
+ updateUidState(uid, procState);
}
@Override public void onUidGone(int uid) throws RemoteException {
+ updateUidState(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
}
@Override public void onUidActive(int uid) throws RemoteException {
@@ -207,16 +251,26 @@
}
};
+ public Object getLock() {
+ return mLock;
+ }
+
@Override
public void onStartUser(int userHandle) {
- mStartedUsers.add(userHandle);
+ mStartedUsers = ArrayUtils.appendInt(mStartedUsers, userHandle);
+ // Let's kick any outstanding jobs for this user.
+ mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
+ }
+
+ @Override
+ public void onUnlockUser(int userHandle) {
// Let's kick any outstanding jobs for this user.
mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
}
@Override
public void onStopUser(int userHandle) {
- mStartedUsers.remove(Integer.valueOf(userHandle));
+ mStartedUsers = ArrayUtils.removeInt(mStartedUsers, userHandle);
}
/**
@@ -227,11 +281,12 @@
* @return Result of this operation. See <code>JobScheduler#RESULT_*</code> return codes.
*/
public int schedule(JobInfo job, int uId) {
- return scheduleAsPackage(job, uId, null, -1);
+ return scheduleAsPackage(job, uId, null, -1, null);
}
- public int scheduleAsPackage(JobInfo job, int uId, String packageName, int userId) {
- JobStatus jobStatus = new JobStatus(job, uId, packageName, userId);
+ public int scheduleAsPackage(JobInfo job, int uId, String packageName, int userId,
+ String tag) {
+ JobStatus jobStatus = JobStatus.createFromJobInfo(job, uId, packageName, userId, tag);
try {
if (ActivityManagerNative.getDefault().getAppStartMode(uId,
job.getService().getPackageName()) == ActivityManager.APP_START_MODE_DISABLED) {
@@ -243,7 +298,16 @@
}
if (DEBUG) Slog.d(TAG, "SCHEDULE: " + jobStatus.toShortString());
JobStatus toCancel;
- synchronized (mJobs) {
+ synchronized (mLock) {
+ // Jobs on behalf of others don't apply to the per-app job cap
+ if (ENFORCE_MAX_JOBS && packageName == null) {
+ if (mJobs.countJobsForUid(uId) > MAX_JOBS_PER_APP) {
+ Slog.w(TAG, "Too many jobs for uid " + uId);
+ throw new IllegalStateException("Apps may not schedule more than "
+ + MAX_JOBS_PER_APP + " distinct jobs");
+ }
+ }
+
toCancel = mJobs.getJobByUidAndJobId(uId, job.getId());
}
startTrackingJob(jobStatus, toCancel);
@@ -255,22 +319,20 @@
}
public List<JobInfo> getPendingJobs(int uid) {
- ArrayList<JobInfo> outList = new ArrayList<JobInfo>();
- synchronized (mJobs) {
- ArraySet<JobStatus> jobs = mJobs.getJobs();
- for (int i=0; i<jobs.size(); i++) {
- JobStatus job = jobs.valueAt(i);
- if (job.getUid() == uid) {
- outList.add(job.getJob());
- }
+ synchronized (mLock) {
+ List<JobStatus> jobs = mJobs.getJobsByUid(uid);
+ ArrayList<JobInfo> outList = new ArrayList<JobInfo>(jobs.size());
+ for (int i = jobs.size() - 1; i >= 0; i--) {
+ JobStatus job = jobs.get(i);
+ outList.add(job.getJob());
}
+ return outList;
}
- return outList;
}
void cancelJobsForUser(int userHandle) {
List<JobStatus> jobsForUser;
- synchronized (mJobs) {
+ synchronized (mLock) {
jobsForUser = mJobs.getJobsByUser(userHandle);
}
for (int i=0; i<jobsForUser.size(); i++) {
@@ -289,7 +351,7 @@
*/
public void cancelJobsForUid(int uid, boolean forceAll) {
List<JobStatus> jobsForUid;
- synchronized (mJobs) {
+ synchronized (mLock) {
jobsForUid = mJobs.getJobsByUid(uid);
}
for (int i=0; i<jobsForUid.size(); i++) {
@@ -317,7 +379,7 @@
*/
public void cancelJob(int uid, int jobId) {
JobStatus toCancel;
- synchronized (mJobs) {
+ synchronized (mLock) {
toCancel = mJobs.getJobByUidAndJobId(uid, jobId);
}
if (toCancel != null) {
@@ -328,7 +390,7 @@
private void cancelJobImpl(JobStatus cancelled) {
if (DEBUG) Slog.d(TAG, "CANCEL: " + cancelled.toShortString());
stopTrackingJob(cancelled, true /* writeBack */);
- synchronized (mJobs) {
+ synchronized (mLock) {
// Remove from pending queue.
mPendingJobs.remove(cancelled);
// Cancel if running.
@@ -337,10 +399,25 @@
}
}
+ void updateUidState(int uid, int procState) {
+ synchronized (mLock) {
+ if (procState == ActivityManager.PROCESS_STATE_TOP) {
+ // Only use this if we are exactly the top app. All others can live
+ // 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) {
+ mUidPriorityOverride.put(uid, JobInfo.PRIORITY_FOREGROUND_APP);
+ } else {
+ mUidPriorityOverride.delete(uid);
+ }
+ }
+ }
+
void updateIdleMode(boolean enabled) {
boolean changed = false;
boolean rocking;
- synchronized (mJobs) {
+ synchronized (mLock) {
if (mDeviceIdleMode != enabled) {
changed = true;
}
@@ -352,7 +429,7 @@
mControllers.get(i).deviceIdleModeChanged(enabled);
}
}
- synchronized (mJobs) {
+ synchronized (mLock) {
mDeviceIdleMode = enabled;
if (enabled) {
// When becoming idle, make sure no jobs are actively running.
@@ -446,12 +523,13 @@
mPowerManager = (PowerManager)getContext().getSystemService(Context.POWER_SERVICE);
try {
ActivityManagerNative.getDefault().registerUidObserver(mUidObserver,
- ActivityManager.UID_OBSERVER_IDLE);
+ ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE
+ | ActivityManager.UID_OBSERVER_IDLE);
} catch (RemoteException e) {
// ignored; both services live in system_server
}
} else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
- synchronized (mJobs) {
+ synchronized (mLock) {
// Let's go!
mReadyToRock = true;
mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
@@ -465,14 +543,16 @@
getContext().getMainLooper()));
}
// Attach jobs to their controllers.
- ArraySet<JobStatus> jobs = mJobs.getJobs();
- for (int i=0; i<jobs.size(); i++) {
- JobStatus job = jobs.valueAt(i);
- for (int controller=0; controller<mControllers.size(); controller++) {
- mControllers.get(controller).deviceIdleModeChanged(mDeviceIdleMode);
- mControllers.get(controller).maybeStartTrackingJob(job, null);
+ mJobs.forEachJob(new JobStatusFunctor() {
+ @Override
+ public void process(JobStatus job) {
+ for (int controller = 0; controller < mControllers.size(); controller++) {
+ final StateController sc = mControllers.get(controller);
+ sc.deviceIdleModeChanged(mDeviceIdleMode);
+ sc.maybeStartTrackingJobLocked(job, null);
+ }
}
- }
+ });
// GO GO GO!
mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
}
@@ -485,19 +565,16 @@
* about.
*/
private void startTrackingJob(JobStatus jobStatus, JobStatus lastJob) {
- boolean update;
- boolean rocking;
- synchronized (mJobs) {
- update = mJobs.add(jobStatus);
- rocking = mReadyToRock;
- }
- if (rocking) {
- for (int i=0; i<mControllers.size(); i++) {
- StateController controller = mControllers.get(i);
- if (update) {
- controller.maybeStopTrackingJob(jobStatus, true);
+ synchronized (mLock) {
+ final boolean update = mJobs.add(jobStatus);
+ if (mReadyToRock) {
+ for (int i = 0; i < mControllers.size(); i++) {
+ StateController controller = mControllers.get(i);
+ if (update) {
+ controller.maybeStopTrackingJobLocked(jobStatus, true);
+ }
+ controller.maybeStartTrackingJobLocked(jobStatus, lastJob);
}
- controller.maybeStartTrackingJob(jobStatus, lastJob);
}
}
}
@@ -507,20 +584,17 @@
* object removed.
*/
private boolean stopTrackingJob(JobStatus jobStatus, boolean writeBack) {
- boolean removed;
- boolean rocking;
- synchronized (mJobs) {
+ synchronized (mLock) {
// Remove from store as well as controllers.
- removed = mJobs.remove(jobStatus, writeBack);
- rocking = mReadyToRock;
- }
- if (removed && rocking) {
- for (int i=0; i<mControllers.size(); i++) {
- StateController controller = mControllers.get(i);
- controller.maybeStopTrackingJob(jobStatus, false);
+ final boolean removed = mJobs.remove(jobStatus, writeBack);
+ if (removed && mReadyToRock) {
+ for (int i=0; i<mControllers.size(); i++) {
+ StateController controller = mControllers.get(i);
+ controller.maybeStopTrackingJobLocked(jobStatus, false);
+ }
}
+ return removed;
}
- return removed;
}
private boolean stopJobOnServiceContextLocked(JobStatus job, int reason) {
@@ -693,14 +767,14 @@
@Override
public void handleMessage(Message message) {
- synchronized (mJobs) {
+ synchronized (mLock) {
if (!mReadyToRock) {
return;
}
}
switch (message.what) {
case MSG_JOB_EXPIRED:
- synchronized (mJobs) {
+ synchronized (mLock) {
JobStatus runNow = (JobStatus) message.obj;
// runNow can be null, which is a controller's way of indicating that its
// state is such that all ready jobs should be run immediately.
@@ -712,7 +786,7 @@
}
break;
case MSG_CHECK_JOB:
- synchronized (mJobs) {
+ synchronized (mLock) {
if (mReportedActive) {
// if jobs are currently being run, queue all ready jobs for execution.
queueReadyJobsForExecutionLockedH();
@@ -723,7 +797,7 @@
}
break;
case MSG_CHECK_JOB_GREEDY:
- synchronized (mJobs) {
+ synchronized (mLock) {
queueReadyJobsForExecutionLockedH();
}
break;
@@ -741,23 +815,13 @@
* as many as we can.
*/
private void queueReadyJobsForExecutionLockedH() {
- ArraySet<JobStatus> jobs = mJobs.getJobs();
- mPendingJobs.clear();
if (DEBUG) {
Slog.d(TAG, "queuing all ready jobs for execution:");
}
- for (int i=0; i<jobs.size(); i++) {
- JobStatus job = jobs.valueAt(i);
- if (isReadyToBeExecutedLocked(job)) {
- if (DEBUG) {
- Slog.d(TAG, " queued " + job.toShortString());
- }
- mPendingJobs.add(job);
- } else if (areJobConstraintsNotSatisfied(job)) {
- stopJobOnServiceContextLocked(job,
- JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED);
- }
- }
+ mPendingJobs.clear();
+ mJobs.forEachJob(mReadyQueueFunctor);
+ mReadyQueueFunctor.postProcess();
+
if (DEBUG) {
final int queuedJobs = mPendingJobs.size();
if (queuedJobs == 0) {
@@ -768,6 +832,34 @@
}
}
+ class ReadyJobQueueFunctor implements JobStatusFunctor {
+ ArrayList<JobStatus> newReadyJobs;
+
+ @Override
+ public void process(JobStatus job) {
+ if (isReadyToBeExecutedLocked(job)) {
+ if (DEBUG) {
+ Slog.d(TAG, " queued " + job.toShortString());
+ }
+ if (newReadyJobs == null) {
+ newReadyJobs = new ArrayList<JobStatus>();
+ }
+ newReadyJobs.add(job);
+ } else if (areJobConstraintsNotSatisfiedLocked(job)) {
+ stopJobOnServiceContextLocked(job,
+ JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED);
+ }
+ }
+
+ public void postProcess() {
+ if (newReadyJobs != null) {
+ mPendingJobs.addAll(newReadyJobs);
+ }
+ newReadyJobs = null;
+ }
+ }
+ private final ReadyJobQueueFunctor mReadyQueueFunctor = new ReadyJobQueueFunctor();
+
/**
* The state of at least one job has changed. Here is where we could enforce various
* policies on when we want to execute jobs.
@@ -777,18 +869,21 @@
* If more than 4 jobs total are ready we send them all off.
* TODO: It would be nice to consolidate these sort of high-level policies somewhere.
*/
- private void maybeQueueReadyJobsForExecutionLockedH() {
- mPendingJobs.clear();
- int chargingCount = 0;
- int idleCount = 0;
- int backoffCount = 0;
- int connectivityCount = 0;
- int contentCount = 0;
- List<JobStatus> runnableJobs = null;
- ArraySet<JobStatus> jobs = mJobs.getJobs();
- if (DEBUG) Slog.d(TAG, "Maybe queuing ready jobs...");
- for (int i=0; i<jobs.size(); i++) {
- JobStatus job = jobs.valueAt(i);
+ class MaybeReadyJobQueueFunctor implements JobStatusFunctor {
+ int chargingCount;
+ int idleCount;
+ int backoffCount;
+ int connectivityCount;
+ int contentCount;
+ List<JobStatus> runnableJobs;
+
+ public MaybeReadyJobQueueFunctor() {
+ reset();
+ }
+
+ // Functor method invoked for each job via JobStore.forEachJob()
+ @Override
+ public void process(JobStatus job) {
if (isReadyToBeExecutedLocked(job)) {
try {
if (ActivityManagerNative.getDefault().getAppStartMode(job.getUid(),
@@ -797,7 +892,7 @@
Slog.w(TAG, "Aborting job " + job.getUid() + ":"
+ job.getJob().toString() + " -- package not allowed to start");
mHandler.obtainMessage(MSG_STOP_JOB, job).sendToTarget();
- continue;
+ return;
}
} catch (RemoteException e) {
}
@@ -820,28 +915,50 @@
runnableJobs = new ArrayList<>();
}
runnableJobs.add(job);
- } else if (areJobConstraintsNotSatisfied(job)) {
+ } else if (areJobConstraintsNotSatisfiedLocked(job)) {
stopJobOnServiceContextLocked(job,
JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED);
}
}
- if (backoffCount > 0 ||
- idleCount >= MIN_IDLE_COUNT ||
- connectivityCount >= MIN_CONNECTIVITY_COUNT ||
- chargingCount >= MIN_CHARGING_COUNT ||
- contentCount >= MIN_CONTENT_COUNT ||
- (runnableJobs != null && runnableJobs.size() >= MIN_READY_JOBS_COUNT)) {
- if (DEBUG) {
- Slog.d(TAG, "maybeQueueReadyJobsForExecutionLockedH: Running jobs.");
+
+ public void postProcess() {
+ if (backoffCount > 0 ||
+ idleCount >= MIN_IDLE_COUNT ||
+ connectivityCount >= MIN_CONNECTIVITY_COUNT ||
+ chargingCount >= MIN_CHARGING_COUNT ||
+ contentCount >= MIN_CONTENT_COUNT ||
+ (runnableJobs != null && runnableJobs.size() >= MIN_READY_JOBS_COUNT)) {
+ if (DEBUG) {
+ Slog.d(TAG, "maybeQueueReadyJobsForExecutionLockedH: Running jobs.");
+ }
+ mPendingJobs.addAll(runnableJobs);
+ } else {
+ if (DEBUG) {
+ Slog.d(TAG, "maybeQueueReadyJobsForExecutionLockedH: Not running anything.");
+ }
}
- for (int i=0; i<runnableJobs.size(); i++) {
- mPendingJobs.add(runnableJobs.get(i));
- }
- } else {
- if (DEBUG) {
- Slog.d(TAG, "maybeQueueReadyJobsForExecutionLockedH: Not running anything.");
- }
+
+ // Be ready for next time
+ reset();
}
+
+ private void reset() {
+ chargingCount = 0;
+ idleCount = 0;
+ backoffCount = 0;
+ connectivityCount = 0;
+ contentCount = 0;
+ runnableJobs = null;
+ }
+ }
+ private final MaybeReadyJobQueueFunctor mMaybeQueueFunctor = new MaybeReadyJobQueueFunctor();
+
+ private void maybeQueueReadyJobsForExecutionLockedH() {
+ if (DEBUG) Slog.d(TAG, "Maybe queuing ready jobs...");
+
+ mPendingJobs.clear();
+ mJobs.forEachJob(mMaybeQueueFunctor);
+ mMaybeQueueFunctor.postProcess();
}
/**
@@ -850,18 +967,31 @@
* - It's not pending.
* - It's not already running on a JSC.
* - The user that requested the job is running.
+ * - The component is enabled and runnable.
*/
private boolean isReadyToBeExecutedLocked(JobStatus job) {
final boolean jobReady = job.isReady();
final boolean jobPending = mPendingJobs.contains(job);
final boolean jobActive = isCurrentlyActiveLocked(job);
- final boolean userRunning = mStartedUsers.contains(job.getUserId());
+
+ final int userId = job.getUserId();
+ final boolean userStarted = ArrayUtils.contains(mStartedUsers, userId);
+ final boolean componentPresent;
+ try {
+ componentPresent = (AppGlobals.getPackageManager().getServiceInfo(
+ job.getServiceComponent(), PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
+ userId) != null);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+
if (DEBUG) {
Slog.v(TAG, "isReadyToBeExecutedLocked: " + job.toShortString()
+ " ready=" + jobReady + " pending=" + jobPending
- + " active=" + jobActive + " userRunning=" + userRunning);
+ + " active=" + jobActive + " userStarted=" + userStarted
+ + " componentPresent=" + componentPresent);
}
- return userRunning && jobReady && !jobPending && !jobActive;
+ return userStarted && componentPresent && jobReady && !jobPending && !jobActive;
}
/**
@@ -869,7 +999,7 @@
* - It's not ready
* - It's running on a JSC.
*/
- private boolean areJobConstraintsNotSatisfied(JobStatus job) {
+ private boolean areJobConstraintsNotSatisfiedLocked(JobStatus job) {
return !job.isReady() && isCurrentlyActiveLocked(job);
}
@@ -879,7 +1009,7 @@
* here is where we decide whether to actually execute it.
*/
private void maybeRunPendingJobsH() {
- synchronized (mJobs) {
+ synchronized (mLock) {
if (mDeviceIdleMode) {
// If device is idle, we will not schedule jobs to run.
return;
@@ -887,41 +1017,73 @@
if (DEBUG) {
Slog.d(TAG, "pending queue: " + mPendingJobs.size() + " jobs.");
}
- assignJobsToContextsH();
+ assignJobsToContextsLocked();
reportActive();
}
}
}
+ private int evaluateJobPriorityLocked(JobStatus job) {
+ int priority = job.getPriority();
+ if (priority >= JobInfo.PRIORITY_FOREGROUND_APP) {
+ return priority;
+ }
+ int override = mUidPriorityOverride.get(job.getSourceUid(), 0);
+ if (override != 0) {
+ return override;
+ }
+ return priority;
+ }
+
/**
* Takes jobs from pending queue and runs them on available contexts.
* If no contexts are available, preempts lower priority jobs to
* run higher priority ones.
* Lock on mJobs before calling this function.
*/
- private void assignJobsToContextsH() {
+ private void assignJobsToContextsLocked() {
if (DEBUG) {
Slog.d(TAG, printPendingQueue());
}
- // This array essentially stores the state of mActiveServices array.
- // ith index stores the job present on the ith JobServiceContext.
- // We manipulate this array until we arrive at what jobs should be running on
- // what JobServiceContext.
- JobStatus[] contextIdToJobMap = new JobStatus[MAX_JOB_CONTEXTS_COUNT];
- // Indicates whether we need to act on this jobContext id
- boolean[] act = new boolean[MAX_JOB_CONTEXTS_COUNT];
- int[] preferredUidForContext = new int[MAX_JOB_CONTEXTS_COUNT];
- for (int i=0; i<mActiveServices.size(); i++) {
- contextIdToJobMap[i] = mActiveServices.get(i).getRunningJob();
- preferredUidForContext[i] = mActiveServices.get(i).getPreferredUid();
+ int memLevel;
+ try {
+ memLevel = ActivityManagerNative.getDefault().getMemoryTrimLevel();
+ } catch (RemoteException e) {
+ memLevel = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
+ }
+ switch (memLevel) {
+ case ProcessStats.ADJ_MEM_FACTOR_MODERATE:
+ mMaxActiveJobs = ((MAX_JOB_CONTEXTS_COUNT - 2) * 2) / 3;
+ break;
+ case ProcessStats.ADJ_MEM_FACTOR_LOW:
+ mMaxActiveJobs = (MAX_JOB_CONTEXTS_COUNT - 2) / 3;
+ break;
+ case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
+ mMaxActiveJobs = 1;
+ break;
+ default:
+ mMaxActiveJobs = MAX_JOB_CONTEXTS_COUNT - 2;
+ break;
+ }
+
+ JobStatus[] contextIdToJobMap = mTmpAssignContextIdToJobMap;
+ boolean[] act = mTmpAssignAct;
+ int[] preferredUidForContext = mTmpAssignPreferredUidForContext;
+ int numActive = 0;
+ for (int i=0; i<MAX_JOB_CONTEXTS_COUNT; i++) {
+ final JobServiceContext js = mActiveServices.get(i);
+ if ((contextIdToJobMap[i] = js.getRunningJob()) != null) {
+ numActive++;
+ }
+ act[i] = false;
+ preferredUidForContext[i] = js.getPreferredUid();
}
if (DEBUG) {
Slog.d(TAG, printContextIdToJobMap(contextIdToJobMap, "running jobs initial"));
}
- Iterator<JobStatus> it = mPendingJobs.iterator();
- while (it.hasNext()) {
- JobStatus nextPending = it.next();
+ for (int i=0; i<mPendingJobs.size(); i++) {
+ JobStatus nextPending = mPendingJobs.get(i);
// If job is already running, go to next job.
int jobRunningContext = findJobContextIdFromMap(nextPending, contextIdToJobMap);
@@ -929,33 +1091,41 @@
continue;
}
+ final int priority = evaluateJobPriorityLocked(nextPending);
+ nextPending.lastEvaluatedPriority = priority;
+
// Find a context for nextPending. The context should be available OR
// it should have lowest priority among all running jobs
// (sharing the same Uid as nextPending)
int minPriority = Integer.MAX_VALUE;
int minPriorityContextId = -1;
- for (int i=0; i<mActiveServices.size(); i++) {
- JobStatus job = contextIdToJobMap[i];
- int preferredUid = preferredUidForContext[i];
- if (job == null && (preferredUid == nextPending.getUid() ||
- preferredUid == JobServiceContext.NO_PREFERRED_UID) ) {
- minPriorityContextId = i;
- break;
- }
+ for (int j=0; j<MAX_JOB_CONTEXTS_COUNT; j++) {
+ JobStatus job = contextIdToJobMap[j];
+ int preferredUid = preferredUidForContext[j];
if (job == null) {
+ if ((numActive < mMaxActiveJobs || priority >= JobInfo.PRIORITY_TOP_APP) &&
+ (preferredUid == nextPending.getUid() ||
+ preferredUid == JobServiceContext.NO_PREFERRED_UID)) {
+ // This slot is free, and we haven't yet hit the limit on
+ // concurrent jobs... we can just throw the job in to here.
+ minPriorityContextId = j;
+ numActive++;
+ break;
+ }
// No job on this context, but nextPending can't run here because
- // the context has a preferred Uid.
+ // the context has a preferred Uid or we have reached the limit on
+ // concurrent jobs.
continue;
}
if (job.getUid() != nextPending.getUid()) {
continue;
}
- if (job.getPriority() >= nextPending.getPriority()) {
+ if (evaluateJobPriorityLocked(job) >= nextPending.lastEvaluatedPriority) {
continue;
}
- if (minPriority > nextPending.getPriority()) {
- minPriority = nextPending.getPriority();
- minPriorityContextId = i;
+ if (minPriority > nextPending.lastEvaluatedPriority) {
+ minPriority = nextPending.lastEvaluatedPriority;
+ minPriorityContextId = j;
}
}
if (minPriorityContextId != -1) {
@@ -966,7 +1136,7 @@
if (DEBUG) {
Slog.d(TAG, printContextIdToJobMap(contextIdToJobMap, "running jobs final"));
}
- for (int i=0; i<mActiveServices.size(); i++) {
+ for (int i=0; i<MAX_JOB_CONTEXTS_COUNT; i++) {
boolean preservePreferredUid = false;
if (act[i]) {
JobStatus js = mActiveServices.get(i).getRunningJob();
@@ -978,18 +1148,18 @@
mActiveServices.get(i).preemptExecutingJob();
preservePreferredUid = true;
} else {
+ final JobStatus pendingJob = contextIdToJobMap[i];
if (DEBUG) {
Slog.d(TAG, "About to run job on context "
- + String.valueOf(i) + ", job: " + contextIdToJobMap[i]);
+ + String.valueOf(i) + ", job: " + pendingJob);
}
for (int ic=0; ic<mControllers.size(); ic++) {
- StateController controller = mControllers.get(ic);
- controller.prepareForExecution(contextIdToJobMap[i]);
+ mControllers.get(ic).prepareForExecutionLocked(pendingJob);
}
- if (!mActiveServices.get(i).executeRunnableJob(contextIdToJobMap[i])) {
- Slog.d(TAG, "Error executing " + contextIdToJobMap[i]);
+ if (!mActiveServices.get(i).executeRunnableJob(pendingJob)) {
+ Slog.d(TAG, "Error executing " + pendingJob);
}
- mPendingJobs.remove(contextIdToJobMap[i]);
+ mPendingJobs.remove(pendingJob);
}
}
if (!preservePreferredUid) {
@@ -1024,7 +1194,8 @@
final ComponentName service = job.getService();
try {
ServiceInfo si = pm.getServiceInfo(service,
- PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(uid));
+ PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE,
+ UserHandle.getUserId(uid));
if (si == null) {
throw new IllegalArgumentException("No such service " + service);
}
@@ -1088,19 +1259,29 @@
}
@Override
- public int scheduleAsPackage(JobInfo job, String packageName, int userId)
+ public int scheduleAsPackage(JobInfo job, String packageName, int userId, String tag)
throws RemoteException {
+ final int callerUid = Binder.getCallingUid();
if (DEBUG) {
- Slog.d(TAG, "Scheduling job: " + job.toString() + " on behalf of " + packageName);
+ Slog.d(TAG, "Caller uid " + callerUid + " scheduling job: " + job.toString()
+ + " on behalf of " + packageName);
}
- final int uid = Binder.getCallingUid();
- if (uid != Process.SYSTEM_UID) {
- throw new IllegalArgumentException("Only system process is allowed"
- + "to set packageName");
+
+ if (packageName == null) {
+ throw new NullPointerException("Must specify a package for scheduleAsPackage()");
}
+
+ int mayScheduleForOthers = getContext().checkCallingOrSelfPermission(
+ android.Manifest.permission.UPDATE_DEVICE_STATS);
+ if (mayScheduleForOthers != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Caller uid " + callerUid
+ + " not permitted to schedule jobs for other apps");
+ }
+
long ident = Binder.clearCallingIdentity();
try {
- return JobSchedulerService.this.scheduleAsPackage(job, uid, packageName, userId);
+ return JobSchedulerService.this.scheduleAsPackage(job, callerUid,
+ packageName, userId, tag);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -1183,64 +1364,86 @@
return s.toString();
}
- void dumpInternal(PrintWriter pw) {
+ void dumpInternal(final PrintWriter pw) {
final long now = SystemClock.elapsedRealtime();
- synchronized (mJobs) {
- pw.print("Started users: ");
- for (int i=0; i<mStartedUsers.size(); i++) {
- pw.print("u" + mStartedUsers.get(i) + " ");
- }
- pw.println();
+ synchronized (mLock) {
+ pw.println("Started users: " + Arrays.toString(mStartedUsers));
pw.println("Registered jobs:");
if (mJobs.size() > 0) {
- ArraySet<JobStatus> jobs = mJobs.getJobs();
- for (int i=0; i<jobs.size(); i++) {
- JobStatus job = jobs.valueAt(i);
- pw.print(" Job #"); pw.print(i); pw.print(": ");
- pw.println(job.toShortString());
- job.dump(pw, " ");
- pw.print(" Ready: ");
- pw.print(mHandler.isReadyToBeExecutedLocked(job));
- pw.print(" (job=");
- pw.print(job.isReady());
- pw.print(" pending=");
- pw.print(mPendingJobs.contains(job));
- pw.print(" active=");
- pw.print(isCurrentlyActiveLocked(job));
- pw.print(" user=");
- pw.print(mStartedUsers.contains(job.getUserId()));
- pw.println(")");
- }
+ mJobs.forEachJob(new JobStatusFunctor() {
+ private int index = 0;
+
+ @Override
+ public void process(JobStatus job) {
+ pw.print(" Job #"); pw.print(index++); pw.print(": ");
+ pw.println(job.toShortString());
+ job.dump(pw, " ", true);
+ pw.print(" Ready: ");
+ pw.print(mHandler.isReadyToBeExecutedLocked(job));
+ pw.print(" (job=");
+ pw.print(job.isReady());
+ pw.print(" pending=");
+ pw.print(mPendingJobs.contains(job));
+ pw.print(" active=");
+ pw.print(isCurrentlyActiveLocked(job));
+ pw.print(" user=");
+ pw.print(ArrayUtils.contains(mStartedUsers, job.getUserId()));
+ pw.println(")");
+ }
+ });
} else {
pw.println(" None.");
}
for (int i=0; i<mControllers.size(); i++) {
pw.println();
- mControllers.get(i).dumpControllerState(pw);
+ mControllers.get(i).dumpControllerStateLocked(pw);
}
pw.println();
- pw.println(printPendingQueue());
+ pw.println("Uid priority overrides:");
+ for (int i=0; i< mUidPriorityOverride.size(); i++) {
+ pw.print(" "); pw.print(UserHandle.formatUid(mUidPriorityOverride.keyAt(i)));
+ pw.print(": "); pw.println(mUidPriorityOverride.valueAt(i));
+ }
+ pw.println();
+ pw.println("Pending queue:");
+ for (int i=0; i<mPendingJobs.size(); i++) {
+ JobStatus job = mPendingJobs.get(i);
+ pw.print(" Pending #"); pw.print(i); pw.print(": ");
+ pw.println(job.toShortString());
+ job.dump(pw, " ", false);
+ int priority = evaluateJobPriorityLocked(job);
+ if (priority != JobInfo.PRIORITY_DEFAULT) {
+ pw.print(" Evaluated priority: "); pw.println(priority);
+ }
+ pw.print(" Tag: "); pw.println(job.getTag());
+ }
pw.println();
pw.println("Active jobs:");
for (int i=0; i<mActiveServices.size(); i++) {
JobServiceContext jsc = mActiveServices.get(i);
+ pw.print(" Slot #"); pw.print(i); pw.print(": ");
if (jsc.getRunningJob() == null) {
+ pw.println("inactive");
continue;
} else {
- final long timeout = jsc.getTimeoutElapsed();
- pw.print("Running for: ");
- pw.print((now - jsc.getExecutionStartTimeElapsed())/1000);
- pw.print("s timeout=");
- pw.print(timeout);
- pw.print(" fromnow=");
- pw.println(timeout-now);
- jsc.getRunningJob().dump(pw, " ");
+ pw.println(jsc.getRunningJob().toShortString());
+ pw.print(" Running for: ");
+ TimeUtils.formatDuration(now - jsc.getExecutionStartTimeElapsed(), pw);
+ pw.print(", timeout at: ");
+ TimeUtils.formatDuration(jsc.getTimeoutElapsed() - now, pw);
+ pw.println();
+ jsc.getRunningJob().dump(pw, " ", false);
+ int priority = evaluateJobPriorityLocked(jsc.getRunningJob());
+ if (priority != JobInfo.PRIORITY_DEFAULT) {
+ pw.print(" Evaluated priority: "); pw.println(priority);
+ }
}
}
pw.println();
pw.print("mReadyToRock="); pw.println(mReadyToRock);
pw.print("mDeviceIdleMode="); pw.println(mDeviceIdleMode);
pw.print("mReportedActive="); pw.println(mReportedActive);
+ pw.print("mMaxActiveJobs="); pw.println(mMaxActiveJobs);
}
pw.println();
}
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index b249739..4239248 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -103,6 +103,7 @@
private final JobCompletedListener mCompletedListener;
/** Used for service binding, etc. */
private final Context mContext;
+ private final Object mLock;
private final IBatteryStats mBatteryStats;
private PowerManager.WakeLock mWakeLock;
@@ -124,7 +125,6 @@
private int mPreferredUid;
IJobService service;
- private final Object mLock = new Object();
/**
* Whether this context is free. This is set to false at the start of execution, and reset to
* true when execution is complete.
@@ -137,13 +137,14 @@
private long mTimeoutElapsed;
JobServiceContext(JobSchedulerService service, IBatteryStats batteryStats, Looper looper) {
- this(service.getContext(), batteryStats, service, looper);
+ this(service.getContext(), service.getLock(), batteryStats, service, looper);
}
@VisibleForTesting
- JobServiceContext(Context context, IBatteryStats batteryStats,
+ JobServiceContext(Context context, Object lock, IBatteryStats batteryStats,
JobCompletedListener completedListener, Looper looper) {
mContext = context;
+ mLock = lock;
mBatteryStats = batteryStats;
mCallbackHandler = new JobServiceHandler(looper);
mCompletedListener = completedListener;
@@ -203,7 +204,7 @@
return false;
}
try {
- mBatteryStats.noteJobStart(job.getName(), job.getSourceUid());
+ mBatteryStats.noteJobStart(job.getBatteryName(), job.getSourceUid());
} catch (RemoteException e) {
// Whatever.
}
@@ -368,6 +369,13 @@
}
break;
case MSG_CANCEL:
+ if (mVerb == VERB_FINISHED) {
+ if (DEBUG) {
+ Slog.d(TAG,
+ "Trying to process cancel for torn-down context, ignoring.");
+ }
+ return;
+ }
mParams.setStopReason(message.arg1);
if (message.arg1 == JobParameters.REASON_PREEMPT) {
mPreferredUid = mRunningJob != null ? mRunningJob.getUid() :
@@ -477,12 +485,6 @@
* _ENDING -> No point in doing anything here, so we ignore.
*/
private void handleCancelH() {
- if (mRunningJob == null) {
- if (DEBUG) {
- Slog.d(TAG, "Trying to process cancel for torn-down context, ignoring.");
- }
- return;
- }
if (JobSchedulerService.DEBUG) {
Slog.d(TAG, "Handling cancel for: " + mRunningJob.getJobId() + " "
+ VERB_STRINGS[mVerb]);
@@ -510,7 +512,6 @@
/** Process MSG_TIMEOUT here. */
private void handleOpTimeoutH() {
- mParams.setStopReason(JobParameters.REASON_TIMEOUT);
switch (mVerb) {
case VERB_BINDING:
Slog.e(TAG, "Time-out while trying to bind " + mRunningJob.toShortString() +
@@ -535,6 +536,7 @@
// Not an error - client ran out of time.
Slog.i(TAG, "Client timed out while executing (no jobFinished received)." +
" sending onStop. " + mRunningJob.toShortString());
+ mParams.setStopReason(JobParameters.REASON_TIMEOUT);
sendStopMessageH();
break;
default:
@@ -579,7 +581,8 @@
}
completedJob = mRunningJob;
try {
- mBatteryStats.noteJobFinish(mRunningJob.getName(), mRunningJob.getSourceUid());
+ mBatteryStats.noteJobFinish(mRunningJob.getBatteryName(),
+ mRunningJob.getSourceUid());
} catch (RemoteException e) {
// Whatever.
}
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index 3565fc1..9837a56 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -29,6 +29,7 @@
import android.util.ArraySet;
import android.util.Pair;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.Xml;
import com.android.internal.annotations.VisibleForTesting;
@@ -44,7 +45,6 @@
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
-import java.util.Iterator;
import java.util.List;
import java.util.Set;
@@ -69,7 +69,8 @@
/** Threshold to adjust how often we want to write to the db. */
private static final int MAX_OPS_BEFORE_WRITE = 1;
- final ArraySet<JobStatus> mJobSet;
+ final Object mLock;
+ final JobSet mJobSet; // per-caller-uid tracking
final Context mContext;
private int mDirtyOperations;
@@ -85,7 +86,7 @@
synchronized (sSingletonLock) {
if (sSingleton == null) {
sSingleton = new JobStore(jobManagerService.getContext(),
- Environment.getDataDirectory());
+ jobManagerService.getLock(), Environment.getDataDirectory());
}
return sSingleton;
}
@@ -96,7 +97,7 @@
*/
@VisibleForTesting
public static JobStore initAndGetForTesting(Context context, File dataDir) {
- JobStore jobStoreUnderTest = new JobStore(context, dataDir);
+ JobStore jobStoreUnderTest = new JobStore(context, new Object(), dataDir);
jobStoreUnderTest.clear();
return jobStoreUnderTest;
}
@@ -104,7 +105,8 @@
/**
* Construct the instance of the job store. This results in a blocking read from disk.
*/
- private JobStore(Context context, File dataDir) {
+ private JobStore(Context context, Object lock, File dataDir) {
+ mLock = lock;
mContext = context;
mDirtyOperations = 0;
@@ -113,7 +115,7 @@
jobDir.mkdirs();
mJobsFile = new AtomicFile(new File(jobDir, "jobs.xml"));
- mJobSet = new ArraySet<JobStatus>();
+ mJobSet = new JobSet();
readJobMapFromDisk(mJobSet);
}
@@ -136,19 +138,6 @@
return replaced;
}
- /**
- * Whether this jobStatus object already exists in the JobStore.
- */
- public boolean containsJobIdForUid(int jobId, int uId) {
- for (int i=mJobSet.size()-1; i>=0; i--) {
- JobStatus ts = mJobSet.valueAt(i);
- if (ts.getUid() == uId && ts.getJobId() == jobId) {
- return true;
- }
- }
- return false;
- }
-
boolean containsJob(JobStatus jobStatus) {
return mJobSet.contains(jobStatus);
}
@@ -157,6 +146,10 @@
return mJobSet.size();
}
+ public int countJobsForUid(int uid) {
+ return mJobSet.countJobsForUid(uid);
+ }
+
/**
* Remove the provided job. Will also delete the job if it was persisted.
* @param writeBack If true, the job will be deleted (if it was persisted) immediately.
@@ -187,14 +180,7 @@
* @return A list of all the jobs scheduled by the provided user. Never null.
*/
public List<JobStatus> getJobsByUser(int userHandle) {
- List<JobStatus> matchingJobs = new ArrayList<JobStatus>();
- for (int i=mJobSet.size()-1; i>=0; i--) {
- JobStatus ts = mJobSet.valueAt(i);
- if (UserHandle.getUserId(ts.getUid()) == userHandle) {
- matchingJobs.add(ts);
- }
- }
- return matchingJobs;
+ return mJobSet.getJobsByUser(userHandle);
}
/**
@@ -202,14 +188,7 @@
* @return All JobStatus objects for a given uid from the master list. Never null.
*/
public List<JobStatus> getJobsByUid(int uid) {
- List<JobStatus> matchingJobs = new ArrayList<JobStatus>();
- for (int i=mJobSet.size()-1; i>=0; i--) {
- JobStatus ts = mJobSet.valueAt(i);
- if (ts.getUid() == uid) {
- matchingJobs.add(ts);
- }
- }
- return matchingJobs;
+ return mJobSet.getJobsByUid(uid);
}
/**
@@ -218,20 +197,21 @@
* @return the JobStatus that matches the provided uId and jobId, or null if none found.
*/
public JobStatus getJobByUidAndJobId(int uid, int jobId) {
- for (int i=mJobSet.size()-1; i>=0; i--) {
- JobStatus ts = mJobSet.valueAt(i);
- if (ts.getUid() == uid && ts.getJobId() == jobId) {
- return ts;
- }
- }
- return null;
+ return mJobSet.get(uid, jobId);
}
/**
- * @return The live array of JobStatus objects.
+ * Iterate over the set of all jobs, invoking the supplied functor on each. This is for
+ * customers who need to examine each job; we'd much rather not have to generate
+ * transient unified collections for them to iterate over and then discard, or creating
+ * iterators every time a client needs to perform a sweep.
*/
- public ArraySet<JobStatus> getJobs() {
- return mJobSet;
+ public void forEachJob(JobStatusFunctor functor) {
+ mJobSet.forEachJob(functor);
+ }
+
+ public interface JobStatusFunctor {
+ public void process(JobStatus jobStatus);
}
/** Version of the db schema. */
@@ -260,33 +240,31 @@
}
@VisibleForTesting
- public void readJobMapFromDisk(ArraySet<JobStatus> jobSet) {
+ public void readJobMapFromDisk(JobSet jobSet) {
new ReadJobMapFromDiskRunnable(jobSet).run();
}
/**
* Runnable that writes {@link #mJobSet} out to xml.
- * NOTE: This Runnable locks on JobStore.this
+ * NOTE: This Runnable locks on mLock
*/
private class WriteJobsMapToDiskRunnable implements Runnable {
@Override
public void run() {
final long startElapsed = SystemClock.elapsedRealtime();
- List<JobStatus> mStoreCopy = new ArrayList<JobStatus>();
- synchronized (JobStore.this) {
- // Copy over the jobs so we can release the lock before writing.
- for (int i=0; i<mJobSet.size(); i++) {
- JobStatus jobStatus = mJobSet.valueAt(i);
-
- if (!jobStatus.isPersisted()){
- continue;
+ final List<JobStatus> storeCopy = new ArrayList<JobStatus>();
+ synchronized (mLock) {
+ // Clone the jobs so we can release the lock before writing.
+ mJobSet.forEachJob(new JobStatusFunctor() {
+ @Override
+ public void process(JobStatus job) {
+ if (job.isPersisted()) {
+ storeCopy.add(new JobStatus(job));
+ }
}
-
- JobStatus copy = new JobStatus(jobStatus);
- mStoreCopy.add(copy);
- }
+ });
}
- writeJobsMapImpl(mStoreCopy);
+ writeJobsMapImpl(storeCopy);
if (JobSchedulerService.DEBUG) {
Slog.v(TAG, "Finished writing, took " + (SystemClock.elapsedRealtime()
- startElapsed) + "ms");
@@ -345,6 +323,9 @@
if (jobStatus.getSourcePackageName() != null) {
out.attribute(null, "sourcePackageName", jobStatus.getSourcePackageName());
}
+ if (jobStatus.getSourceTag() != null) {
+ out.attribute(null, "sourceTag", jobStatus.getSourceTag());
+ }
out.attribute(null, "sourceUserId", String.valueOf(jobStatus.getSourceUserId()));
out.attribute(null, "uid", Integer.toString(jobStatus.getUid()));
out.attribute(null, "priority", String.valueOf(jobStatus.getPriority()));
@@ -439,13 +420,13 @@
* need to go through {@link JobStore#add(com.android.server.job.controllers.JobStatus)}.
*/
private class ReadJobMapFromDiskRunnable implements Runnable {
- private final ArraySet<JobStatus> jobSet;
+ private final JobSet jobSet;
/**
* @param jobSet Reference to the (empty) set of JobStatus objects that back the JobStore,
* so that after disk read we can populate it directly.
*/
- ReadJobMapFromDiskRunnable(ArraySet<JobStatus> jobSet) {
+ ReadJobMapFromDiskRunnable(JobSet jobSet) {
this.jobSet = jobSet;
}
@@ -454,7 +435,7 @@
try {
List<JobStatus> jobs;
FileInputStream fis = mJobsFile.openRead();
- synchronized (JobStore.this) {
+ synchronized (mLock) {
jobs = readJobMapImpl(fis);
if (jobs != null) {
for (int i=0; i<jobs.size(); i++) {
@@ -562,7 +543,9 @@
return null;
}
- final String sourcePackageName = parser.getAttributeValue(null, "sourcePackageName");
+ String sourcePackageName = parser.getAttributeValue(null, "sourcePackageName");
+
+ final String sourceTag = parser.getAttributeValue(null, "sourceTag");
int eventType;
// Read out constraints tag.
@@ -677,9 +660,21 @@
jobBuilder.setExtras(extras);
parser.nextTag(); // Consume </extras>
+ // Migrate sync jobs forward from earlier, incomplete representation
+ if ("android".equals(sourcePackageName)
+ && extras != null
+ && extras.getBoolean("SyncManagerJob", false)) {
+ sourcePackageName = extras.getString("owningPackage", sourcePackageName);
+ if (DEBUG) {
+ Slog.i(TAG, "Fixing up sync job source package name from 'android' to '"
+ + sourcePackageName + "'");
+ }
+ }
+
+ // And now we're done
JobStatus js = new JobStatus(
- jobBuilder.build(), uid, sourcePackageName, sourceUserId, elapsedRuntimes.first,
- elapsedRuntimes.second);
+ jobBuilder.build(), uid, sourcePackageName, sourceUserId, sourceTag,
+ elapsedRuntimes.first, elapsedRuntimes.second);
return js;
}
@@ -758,4 +753,122 @@
return Pair.create(earliestRunTimeElapsed, latestRunTimeElapsed);
}
}
+
+ static class JobSet {
+ // Key is the getUid() originator of the jobs in each sheaf
+ private SparseArray<ArraySet<JobStatus>> mJobs;
+
+ public JobSet() {
+ mJobs = new SparseArray<ArraySet<JobStatus>>();
+ }
+
+ public List<JobStatus> getJobsByUid(int uid) {
+ ArrayList<JobStatus> matchingJobs = new ArrayList<JobStatus>();
+ ArraySet<JobStatus> jobs = mJobs.get(uid);
+ if (jobs != null) {
+ matchingJobs.addAll(jobs);
+ }
+ return matchingJobs;
+ }
+
+ // By user, not by uid, so we need to traverse by key and check
+ public List<JobStatus> getJobsByUser(int userId) {
+ ArrayList<JobStatus> result = new ArrayList<JobStatus>();
+ for (int i = mJobs.size() - 1; i >= 0; i--) {
+ if (UserHandle.getUserId(mJobs.keyAt(i)) == userId) {
+ ArraySet<JobStatus> jobs = mJobs.get(i);
+ if (jobs != null) {
+ result.addAll(jobs);
+ }
+ }
+ }
+ return result;
+ }
+
+ public boolean add(JobStatus job) {
+ final int uid = job.getUid();
+ ArraySet<JobStatus> jobs = mJobs.get(uid);
+ if (jobs == null) {
+ jobs = new ArraySet<JobStatus>();
+ mJobs.put(uid, jobs);
+ }
+ return jobs.add(job);
+ }
+
+ public boolean remove(JobStatus job) {
+ final int uid = job.getUid();
+ ArraySet<JobStatus> jobs = mJobs.get(uid);
+ boolean didRemove = (jobs != null) ? jobs.remove(job) : false;
+ if (didRemove && jobs.size() == 0) {
+ // no more jobs for this uid; let the now-empty set object be GC'd.
+ mJobs.remove(uid);
+ }
+ return didRemove;
+ }
+
+ public boolean contains(JobStatus job) {
+ final int uid = job.getUid();
+ ArraySet<JobStatus> jobs = mJobs.get(uid);
+ return jobs != null && jobs.contains(job);
+ }
+
+ public JobStatus get(int uid, int jobId) {
+ ArraySet<JobStatus> jobs = mJobs.get(uid);
+ if (jobs != null) {
+ for (int i = jobs.size() - 1; i >= 0; i--) {
+ JobStatus job = jobs.valueAt(i);
+ if (job.getJobId() == jobId) {
+ return job;
+ }
+ }
+ }
+ return null;
+ }
+
+ // Inefficient; use only for testing
+ public List<JobStatus> getAllJobs() {
+ ArrayList<JobStatus> allJobs = new ArrayList<JobStatus>(size());
+ for (int i = mJobs.size(); i >= 0; i--) {
+ allJobs.addAll(mJobs.valueAt(i));
+ }
+ return allJobs;
+ }
+
+ public void clear() {
+ mJobs.clear();
+ }
+
+ public int size() {
+ int total = 0;
+ for (int i = mJobs.size() - 1; i >= 0; i--) {
+ total += mJobs.valueAt(i).size();
+ }
+ return total;
+ }
+
+ // We only want to count the jobs that this uid has scheduled on its own
+ // behalf, not those that the app has scheduled on someone else's behalf.
+ public int countJobsForUid(int uid) {
+ int total = 0;
+ ArraySet<JobStatus> jobs = mJobs.get(uid);
+ if (jobs != null) {
+ for (int i = jobs.size() - 1; i >= 0; i--) {
+ JobStatus job = jobs.valueAt(i);
+ if (job.getUid() == job.getSourceUid()) {
+ total++;
+ }
+ }
+ }
+ return total;
+ }
+
+ public void forEachJob(JobStatusFunctor functor) {
+ for (int uidIndex = mJobs.size() - 1; uidIndex >= 0; uidIndex--) {
+ ArraySet<JobStatus> jobs = mJobs.valueAt(uidIndex);
+ for (int i = jobs.size() - 1; i >= 0; i--) {
+ functor.process(jobs.valueAt(i));
+ }
+ }
+ }
+ }
}
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 5f3da75..f0c579f 100644
--- a/services/core/java/com/android/server/job/controllers/AppIdleController.java
+++ b/services/core/java/com/android/server/job/controllers/AppIdleController.java
@@ -48,59 +48,56 @@
public static AppIdleController get(JobSchedulerService service) {
synchronized (sCreationLock) {
if (sController == null) {
- sController = new AppIdleController(service, service.getContext());
+ sController = new AppIdleController(service, service.getContext(),
+ service.getLock());
}
return sController;
}
}
- private AppIdleController(StateChangedListener stateChangedListener, Context context) {
- super(stateChangedListener, context);
+ private AppIdleController(StateChangedListener stateChangedListener, Context context,
+ Object lock) {
+ super(stateChangedListener, context, lock);
mUsageStatsInternal = LocalServices.getService(UsageStatsManagerInternal.class);
mAppIdleParoleOn = mUsageStatsInternal.isAppIdleParoleOn();
mUsageStatsInternal.addAppIdleStateChangeListener(new AppIdleStateChangeListener());
}
@Override
- public void maybeStartTrackingJob(JobStatus jobStatus, JobStatus lastJob) {
- synchronized (mTrackedTasks) {
- mTrackedTasks.add(jobStatus);
- String packageName = jobStatus.getSourcePackageName();
- final boolean appIdle = !mAppIdleParoleOn && mUsageStatsInternal.isAppIdle(packageName,
- jobStatus.getSourceUid(), jobStatus.getSourceUserId());
- if (DEBUG) {
- Slog.d(LOG_TAG, "Start tracking, setting idle state of "
- + packageName + " to " + appIdle);
- }
- jobStatus.appNotIdleConstraintSatisfied.set(!appIdle);
+ public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
+ mTrackedTasks.add(jobStatus);
+ String packageName = jobStatus.getSourcePackageName();
+ final boolean appIdle = !mAppIdleParoleOn && mUsageStatsInternal.isAppIdle(packageName,
+ jobStatus.getSourceUid(), jobStatus.getSourceUserId());
+ if (DEBUG) {
+ Slog.d(LOG_TAG, "Start tracking, setting idle state of "
+ + packageName + " to " + appIdle);
}
+ jobStatus.setAppNotIdleConstraintSatisfied(!appIdle);
}
@Override
- public void maybeStopTrackingJob(JobStatus jobStatus, boolean forUpdate) {
- synchronized (mTrackedTasks) {
- mTrackedTasks.remove(jobStatus);
- }
+ public void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate) {
+ mTrackedTasks.remove(jobStatus);
}
@Override
- public void dumpControllerState(PrintWriter pw) {
+ public void dumpControllerStateLocked(PrintWriter pw) {
pw.println("AppIdle");
pw.println("Parole On: " + mAppIdleParoleOn);
- synchronized (mTrackedTasks) {
- for (JobStatus task : mTrackedTasks) {
- pw.print(task.getSourcePackageName());
- pw.print(":idle=" + !task.appNotIdleConstraintSatisfied.get());
- pw.print(", ");
- }
- pw.println();
+ for (JobStatus task : mTrackedTasks) {
+ pw.print(task.getSourcePackageName());
+ pw.print(":idle="
+ + ((task.satisfiedConstraints&JobStatus.CONSTRAINT_APP_NOT_IDLE) != 0));
+ pw.print(", ");
}
+ pw.println();
}
void setAppIdleParoleOn(boolean isAppIdleParoleOn) {
// Flag if any app's idle state has changed
boolean changed = false;
- synchronized (mTrackedTasks) {
+ synchronized (mLock) {
if (mAppIdleParoleOn == isAppIdleParoleOn) {
return;
}
@@ -112,8 +109,7 @@
if (DEBUG) {
Slog.d(LOG_TAG, "Setting idle state of " + packageName + " to " + appIdle);
}
- if (task.appNotIdleConstraintSatisfied.get() == appIdle) {
- task.appNotIdleConstraintSatisfied.set(!appIdle);
+ if (task.setAppNotIdleConstraintSatisfied(!appIdle)) {
changed = true;
}
}
@@ -128,19 +124,18 @@
@Override
public void onAppIdleStateChanged(String packageName, int userId, boolean idle) {
boolean changed = false;
- synchronized (mTrackedTasks) {
+ synchronized (mLock) {
if (mAppIdleParoleOn) {
return;
}
for (JobStatus task : mTrackedTasks) {
if (task.getSourcePackageName().equals(packageName)
&& task.getSourceUserId() == userId) {
- if (task.appNotIdleConstraintSatisfied.get() != !idle) {
+ if (task.setAppNotIdleConstraintSatisfied(!idle)) {
if (DEBUG) {
Slog.d(LOG_TAG, "App Idle state changed, setting idle state of "
+ packageName + " to " + idle);
}
- task.appNotIdleConstraintSatisfied.set(!idle);
changed = true;
}
}
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 b322a3e..ac9f425 100644
--- a/services/core/java/com/android/server/job/controllers/BatteryController.java
+++ b/services/core/java/com/android/server/job/controllers/BatteryController.java
@@ -53,7 +53,7 @@
synchronized (sCreationLock) {
if (sController == null) {
sController = new BatteryController(taskManagerService,
- taskManagerService.getContext());
+ taskManagerService.getContext(), taskManagerService.getLock());
}
}
return sController;
@@ -67,32 +67,29 @@
@VisibleForTesting
public static BatteryController getForTesting(StateChangedListener stateChangedListener,
Context context) {
- return new BatteryController(stateChangedListener, context);
+ return new BatteryController(stateChangedListener, context, new Object());
}
- private BatteryController(StateChangedListener stateChangedListener, Context context) {
- super(stateChangedListener, context);
+ private BatteryController(StateChangedListener stateChangedListener, Context context,
+ Object lock) {
+ super(stateChangedListener, context, lock);
mChargeTracker = new ChargingTracker();
mChargeTracker.startTracking();
}
@Override
- public void maybeStartTrackingJob(JobStatus taskStatus, JobStatus lastJob) {
+ public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
final boolean isOnStablePower = mChargeTracker.isOnStablePower();
if (taskStatus.hasChargingConstraint()) {
- synchronized (mTrackedTasks) {
- mTrackedTasks.add(taskStatus);
- taskStatus.chargingConstraintSatisfied.set(isOnStablePower);
- }
+ mTrackedTasks.add(taskStatus);
+ taskStatus.setChargingConstraintSatisfied(isOnStablePower);
}
}
@Override
- public void maybeStopTrackingJob(JobStatus taskStatus, boolean forUpdate) {
+ public void maybeStopTrackingJobLocked(JobStatus taskStatus, boolean forUpdate) {
if (taskStatus.hasChargingConstraint()) {
- synchronized (mTrackedTasks) {
- mTrackedTasks.remove(taskStatus);
- }
+ mTrackedTasks.remove(taskStatus);
}
}
@@ -102,9 +99,9 @@
Slog.d(TAG, "maybeReportNewChargingState: " + stablePower);
}
boolean reportChange = false;
- synchronized (mTrackedTasks) {
+ synchronized (mLock) {
for (JobStatus ts : mTrackedTasks) {
- boolean previous = ts.chargingConstraintSatisfied.getAndSet(stablePower);
+ boolean previous = ts.setChargingConstraintSatisfied(stablePower);
if (previous != stablePower) {
reportChange = true;
}
@@ -197,18 +194,16 @@
}
@Override
- public void dumpControllerState(PrintWriter pw) {
+ public void dumpControllerStateLocked(PrintWriter pw) {
pw.println("Batt.");
pw.println("Stable power: " + mChargeTracker.isOnStablePower());
- synchronized (mTrackedTasks) {
- Iterator<JobStatus> it = mTrackedTasks.iterator();
- if (it.hasNext()) {
- pw.print(String.valueOf(it.next().hashCode()));
- }
- while (it.hasNext()) {
- pw.print("," + String.valueOf(it.next().hashCode()));
- }
- pw.println();
+ Iterator<JobStatus> it = mTrackedTasks.iterator();
+ if (it.hasNext()) {
+ pw.print(String.valueOf(it.next().hashCode()));
}
+ while (it.hasNext()) {
+ pw.print("," + String.valueOf(it.next().hashCode()));
+ }
+ pw.println();
}
}
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 b84658a..bd06645 100644
--- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
@@ -58,14 +58,15 @@
public static ConnectivityController get(JobSchedulerService jms) {
synchronized (sCreationLock) {
if (mSingleton == null) {
- mSingleton = new ConnectivityController(jms, jms.getContext());
+ mSingleton = new ConnectivityController(jms, jms.getContext(), jms.getLock());
}
return mSingleton;
}
}
- private ConnectivityController(StateChangedListener stateChangedListener, Context context) {
- super(stateChangedListener, context);
+ private ConnectivityController(StateChangedListener stateChangedListener, Context context,
+ Object lock) {
+ super(stateChangedListener, context, lock);
// Register connectivity changed BR.
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
@@ -82,22 +83,18 @@
}
@Override
- public void maybeStartTrackingJob(JobStatus jobStatus, JobStatus lastJob) {
+ public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()) {
- synchronized (mTrackedJobs) {
- jobStatus.connectivityConstraintSatisfied.set(mNetworkConnected);
- jobStatus.unmeteredConstraintSatisfied.set(mNetworkUnmetered);
- mTrackedJobs.add(jobStatus);
- }
+ jobStatus.setConnectivityConstraintSatisfied(mNetworkConnected);
+ jobStatus.setUnmeteredConstraintSatisfied(mNetworkUnmetered);
+ mTrackedJobs.add(jobStatus);
}
}
@Override
- public void maybeStopTrackingJob(JobStatus jobStatus, boolean forUpdate) {
+ public void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate) {
if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()) {
- synchronized (mTrackedJobs) {
- mTrackedJobs.remove(jobStatus);
- }
+ mTrackedJobs.remove(jobStatus);
}
}
@@ -105,18 +102,14 @@
* @param userId Id of the user for whom we are updating the connectivity state.
*/
private void updateTrackedJobs(int userId) {
- synchronized (mTrackedJobs) {
+ synchronized (mLock) {
boolean changed = false;
for (JobStatus js : mTrackedJobs) {
if (js.getUserId() != userId) {
continue;
}
- boolean prevIsConnected =
- js.connectivityConstraintSatisfied.getAndSet(mNetworkConnected);
- boolean prevIsMetered = js.unmeteredConstraintSatisfied.getAndSet(mNetworkUnmetered);
- if (prevIsConnected != mNetworkConnected || prevIsMetered != mNetworkUnmetered) {
- changed = true;
- }
+ changed |= js.setConnectivityConstraintSatisfied(mNetworkConnected);
+ changed |= js.setUnmeteredConstraintSatisfied(mNetworkUnmetered);
}
if (changed) {
mStateChangedListener.onControllerStateChanged();
@@ -128,7 +121,7 @@
* We know the network has just come up. We want to run any jobs that are ready.
*/
public synchronized void onNetworkActive() {
- synchronized (mTrackedJobs) {
+ synchronized (mLock) {
for (JobStatus js : mTrackedJobs) {
if (js.isReady()) {
if (DEBUG) {
@@ -188,7 +181,7 @@
};
@Override
- public void dumpControllerState(PrintWriter pw) {
+ public void dumpControllerStateLocked(PrintWriter pw) {
pw.println("Conn.");
pw.println("connected: " + mNetworkConnected + " unmetered: " + mNetworkUnmetered);
for (JobStatus js: mTrackedJobs) {
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 212cc94..c5cf30f 100644
--- a/services/core/java/com/android/server/job/controllers/ContentObserverController.java
+++ b/services/core/java/com/android/server/job/controllers/ContentObserverController.java
@@ -57,7 +57,7 @@
synchronized (sCreationLock) {
if (sController == null) {
sController = new ContentObserverController(taskManagerService,
- taskManagerService.getContext());
+ taskManagerService.getContext(), taskManagerService.getLock());
}
}
return sController;
@@ -66,95 +66,90 @@
@VisibleForTesting
public static ContentObserverController getForTesting(StateChangedListener stateChangedListener,
Context context) {
- return new ContentObserverController(stateChangedListener, context);
+ return new ContentObserverController(stateChangedListener, context, new Object());
}
- private ContentObserverController(StateChangedListener stateChangedListener, Context context) {
- super(stateChangedListener, context);
+ private ContentObserverController(StateChangedListener stateChangedListener, Context context,
+ Object lock) {
+ super(stateChangedListener, context, lock);
}
@Override
- public void maybeStartTrackingJob(JobStatus taskStatus, JobStatus lastJob) {
+ public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
if (taskStatus.hasContentTriggerConstraint()) {
- synchronized (mTrackedTasks) {
- if (taskStatus.contentObserverJobInstance == null) {
- taskStatus.contentObserverJobInstance = new JobInstance(taskStatus);
- }
- mTrackedTasks.add(taskStatus);
- boolean havePendingUris = false;
- // If there is a previous job associated with the new job, propagate over
- // any pending content URI trigger reports.
- if (lastJob != null && lastJob.contentObserverJobInstance != null
- && lastJob.contentObserverJobInstance
- != taskStatus.contentObserverJobInstance
- && lastJob.contentObserverJobInstance.mChangedAuthorities != null) {
- havePendingUris = true;
+ if (taskStatus.contentObserverJobInstance == null) {
+ taskStatus.contentObserverJobInstance = new JobInstance(taskStatus);
+ }
+ mTrackedTasks.add(taskStatus);
+ boolean havePendingUris = false;
+ // If there is a previous job associated with the new job, propagate over
+ // any pending content URI trigger reports.
+ if (lastJob != null && lastJob.contentObserverJobInstance != null
+ && lastJob.contentObserverJobInstance
+ != taskStatus.contentObserverJobInstance
+ && lastJob.contentObserverJobInstance.mChangedAuthorities != null) {
+ havePendingUris = true;
+ taskStatus.contentObserverJobInstance.mChangedAuthorities
+ = lastJob.contentObserverJobInstance.mChangedAuthorities;
+ taskStatus.contentObserverJobInstance.mChangedUris
+ = lastJob.contentObserverJobInstance.mChangedUris;
+ lastJob.contentObserverJobInstance.mChangedAuthorities = null;
+ lastJob.contentObserverJobInstance.mChangedUris = null;
+ }
+ // If we have previously reported changed authorities/uris, then we failed
+ // to complete the job with them so will re-record them to report again.
+ if (taskStatus.changedAuthorities != null) {
+ havePendingUris = true;
+ if (taskStatus.contentObserverJobInstance.mChangedAuthorities == null) {
taskStatus.contentObserverJobInstance.mChangedAuthorities
- = lastJob.contentObserverJobInstance.mChangedAuthorities;
- taskStatus.contentObserverJobInstance.mChangedUris
- = lastJob.contentObserverJobInstance.mChangedUris;
- lastJob.contentObserverJobInstance.mChangedAuthorities = null;
- lastJob.contentObserverJobInstance.mChangedUris = null;
+ = new ArraySet<>();
}
- // If we have previously reported changed authorities/uris, then we failed
- // to complete the job with them so will re-record them to report again.
- if (taskStatus.changedAuthorities != null) {
- havePendingUris = true;
- if (taskStatus.contentObserverJobInstance.mChangedAuthorities == null) {
- taskStatus.contentObserverJobInstance.mChangedAuthorities
- = new ArraySet<>();
+ for (String auth : taskStatus.changedAuthorities) {
+ taskStatus.contentObserverJobInstance.mChangedAuthorities.add(auth);
+ }
+ if (taskStatus.changedUris != null) {
+ if (taskStatus.contentObserverJobInstance.mChangedUris == null) {
+ taskStatus.contentObserverJobInstance.mChangedUris = new ArraySet<>();
}
- for (String auth : taskStatus.changedAuthorities) {
- taskStatus.contentObserverJobInstance.mChangedAuthorities.add(auth);
+ for (Uri uri : taskStatus.changedUris) {
+ taskStatus.contentObserverJobInstance.mChangedUris.add(uri);
}
- if (taskStatus.changedUris != null) {
- if (taskStatus.contentObserverJobInstance.mChangedUris == null) {
- taskStatus.contentObserverJobInstance.mChangedUris = new ArraySet<>();
- }
- for (Uri uri : taskStatus.changedUris) {
- taskStatus.contentObserverJobInstance.mChangedUris.add(uri);
- }
- }
- taskStatus.changedAuthorities = null;
- taskStatus.changedUris = null;
}
taskStatus.changedAuthorities = null;
taskStatus.changedUris = null;
- taskStatus.contentTriggerConstraintSatisfied.set(havePendingUris);
+ }
+ taskStatus.changedAuthorities = null;
+ taskStatus.changedUris = null;
+ taskStatus.setContentTriggerConstraintSatisfied(havePendingUris);
+ }
+ }
+
+ @Override
+ public void prepareForExecutionLocked(JobStatus taskStatus) {
+ if (taskStatus.hasContentTriggerConstraint()) {
+ if (taskStatus.contentObserverJobInstance != null) {
+ taskStatus.changedUris = taskStatus.contentObserverJobInstance.mChangedUris;
+ taskStatus.changedAuthorities
+ = taskStatus.contentObserverJobInstance.mChangedAuthorities;
+ taskStatus.contentObserverJobInstance.mChangedUris = null;
+ taskStatus.contentObserverJobInstance.mChangedAuthorities = null;
}
}
}
@Override
- public void prepareForExecution(JobStatus taskStatus) {
+ public void maybeStopTrackingJobLocked(JobStatus taskStatus, boolean forUpdate) {
if (taskStatus.hasContentTriggerConstraint()) {
- synchronized (mTrackedTasks) {
+ if (!forUpdate) {
+ // We won't do this reset if being called for an update, because
+ // we know it will be immediately followed by maybeStartTrackingJobLocked...
+ // and we don't want to lose any content changes in-between.
if (taskStatus.contentObserverJobInstance != null) {
- taskStatus.changedUris = taskStatus.contentObserverJobInstance.mChangedUris;
- taskStatus.changedAuthorities
- = taskStatus.contentObserverJobInstance.mChangedAuthorities;
- taskStatus.contentObserverJobInstance.mChangedUris = null;
- taskStatus.contentObserverJobInstance.mChangedAuthorities = null;
+ taskStatus.contentObserverJobInstance.detach();
+ taskStatus.contentObserverJobInstance = null;
}
}
- }
- }
-
- @Override
- public void maybeStopTrackingJob(JobStatus taskStatus, boolean forUpdate) {
- if (taskStatus.hasContentTriggerConstraint()) {
- synchronized (mTrackedTasks) {
- if (!forUpdate) {
- // We won't do this reset if being called for an update, because
- // we know it will be immediately followed by maybeStartTrackingJob...
- // and we don't want to lose any content changes in-between.
- if (taskStatus.contentObserverJobInstance != null) {
- taskStatus.contentObserverJobInstance.detach();
- taskStatus.contentObserverJobInstance = null;
- }
- }
- mTrackedTasks.remove(taskStatus);
- }
+ mTrackedTasks.remove(taskStatus);
}
}
@@ -162,7 +157,7 @@
public void rescheduleForFailure(JobStatus newJob, JobStatus failureToReschedule) {
if (failureToReschedule.hasContentTriggerConstraint()
&& newJob.hasContentTriggerConstraint()) {
- synchronized (mTrackedTasks) {
+ synchronized (mLock) {
// Our job has failed, and we are scheduling a new job for it.
// Copy the last reported content changes in to the new job, so when
// we schedule the new one we will pick them up and report them again.
@@ -184,7 +179,7 @@
@Override
public void onChange(boolean selfChange, Uri uri) {
boolean reportChange = false;
- synchronized (mTrackedTasks) {
+ synchronized (mLock) {
final int N = mJobs.size();
for (int i=0; i<N; i++) {
JobInstance inst = mJobs.get(i);
@@ -198,9 +193,7 @@
inst.mChangedAuthorities = new ArraySet<>();
}
inst.mChangedAuthorities.add(uri.getAuthority());
- boolean previous
- = inst.mJobStatus.contentTriggerConstraintSatisfied.getAndSet(true);
- if (!previous) {
+ if (inst.mJobStatus.setContentTriggerConstraintSatisfied(true)) {
reportChange = true;
}
}
@@ -254,50 +247,48 @@
}
@Override
- public void dumpControllerState(PrintWriter pw) {
+ public void dumpControllerStateLocked(PrintWriter pw) {
pw.println("Content.");
- synchronized (mTrackedTasks) {
- Iterator<JobStatus> it = mTrackedTasks.iterator();
- if (it.hasNext()) {
- pw.print(String.valueOf(it.next().hashCode()));
- }
- while (it.hasNext()) {
- pw.print("," + String.valueOf(it.next().hashCode()));
- }
- pw.println();
- int N = mObservers.size();
- if (N > 0) {
- pw.println("URIs:");
- for (int i = 0; i < N; i++) {
- ObserverInstance obs = mObservers.valueAt(i);
- pw.print(" ");
- pw.print(mObservers.keyAt(i));
- pw.println(":");
- pw.print(" ");
- pw.println(obs);
- pw.println(" Jobs:");
- int M = obs.mJobs.size();
- for (int j=0; j<M; j++) {
- JobInstance inst = obs.mJobs.get(j);
- pw.print(" ");
- pw.print(inst.hashCode());
- if (inst.mChangedAuthorities != null) {
- pw.println(":");
- pw.println(" Changed Authorities:");
- for (int k=0; k<inst.mChangedAuthorities.size(); k++) {
- pw.print(" ");
- pw.println(inst.mChangedAuthorities.valueAt(k));
- }
- if (inst.mChangedUris != null) {
- pw.println(" Changed URIs:");
- for (int k = 0; k<inst.mChangedUris.size(); k++) {
- pw.print(" ");
- pw.println(inst.mChangedUris.valueAt(k));
- }
- }
- } else {
- pw.println();
+ Iterator<JobStatus> it = mTrackedTasks.iterator();
+ if (it.hasNext()) {
+ pw.print(String.valueOf(it.next().hashCode()));
+ }
+ while (it.hasNext()) {
+ pw.print("," + String.valueOf(it.next().hashCode()));
+ }
+ pw.println();
+ int N = mObservers.size();
+ if (N > 0) {
+ pw.println("URIs:");
+ for (int i = 0; i < N; i++) {
+ ObserverInstance obs = mObservers.valueAt(i);
+ pw.print(" ");
+ pw.print(mObservers.keyAt(i));
+ pw.println(":");
+ pw.print(" ");
+ pw.println(obs);
+ pw.println(" Jobs:");
+ int M = obs.mJobs.size();
+ for (int j=0; j<M; j++) {
+ JobInstance inst = obs.mJobs.get(j);
+ pw.print(" ");
+ pw.print(inst.hashCode());
+ if (inst.mChangedAuthorities != null) {
+ pw.println(":");
+ pw.println(" Changed Authorities:");
+ for (int k=0; k<inst.mChangedAuthorities.size(); k++) {
+ pw.print(" ");
+ pw.println(inst.mChangedAuthorities.valueAt(k));
}
+ if (inst.mChangedUris != null) {
+ pw.println(" Changed URIs:");
+ for (int k = 0; k<inst.mChangedUris.size(); k++) {
+ pw.print(" ");
+ pw.println(inst.mChangedUris.valueAt(k));
+ }
+ }
+ } else {
+ pw.println();
}
}
}
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 9f4cdef..7638494 100644
--- a/services/core/java/com/android/server/job/controllers/IdleController.java
+++ b/services/core/java/com/android/server/job/controllers/IdleController.java
@@ -51,14 +51,15 @@
public static IdleController get(JobSchedulerService service) {
synchronized (sCreationLock) {
if (sController == null) {
- sController = new IdleController(service, service.getContext());
+ sController = new IdleController(service, service.getContext(), service.getLock());
}
return sController;
}
}
- private IdleController(StateChangedListener stateChangedListener, Context context) {
- super(stateChangedListener, context);
+ private IdleController(StateChangedListener stateChangedListener, Context context,
+ Object lock) {
+ super(stateChangedListener, context, lock);
initIdleStateTracking();
}
@@ -66,29 +67,25 @@
* StateController interface
*/
@Override
- public void maybeStartTrackingJob(JobStatus taskStatus, JobStatus lastJob) {
+ public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
if (taskStatus.hasIdleConstraint()) {
- synchronized (mTrackedTasks) {
- mTrackedTasks.add(taskStatus);
- taskStatus.idleConstraintSatisfied.set(mIdleTracker.isIdle());
- }
+ mTrackedTasks.add(taskStatus);
+ taskStatus.setIdleConstraintSatisfied(mIdleTracker.isIdle());
}
}
@Override
- public void maybeStopTrackingJob(JobStatus taskStatus, boolean forUpdate) {
- synchronized (mTrackedTasks) {
- mTrackedTasks.remove(taskStatus);
- }
+ public void maybeStopTrackingJobLocked(JobStatus taskStatus, boolean forUpdate) {
+ mTrackedTasks.remove(taskStatus);
}
/**
* Interaction with the task manager service
*/
void reportNewIdleState(boolean isIdle) {
- synchronized (mTrackedTasks) {
+ synchronized (mLock) {
for (JobStatus task : mTrackedTasks) {
- task.idleConstraintSatisfied.set(isIdle);
+ task.setIdleConstraintSatisfied(isIdle);
}
}
mStateChangedListener.onControllerStateChanged();
@@ -193,17 +190,15 @@
}
@Override
- public void dumpControllerState(PrintWriter pw) {
- synchronized (mTrackedTasks) {
- pw.print("Idle: ");
- pw.println(mIdleTracker.isIdle() ? "true" : "false");
- pw.println(mTrackedTasks.size());
- for (int i = 0; i < mTrackedTasks.size(); i++) {
- final JobStatus js = mTrackedTasks.get(i);
- pw.print(" ");
- pw.print(String.valueOf(js.hashCode()).substring(0, 3));
- pw.println("..");
- }
+ public void dumpControllerStateLocked(PrintWriter pw) {
+ pw.print("Idle: ");
+ pw.println(mIdleTracker.isIdle() ? "true" : "false");
+ pw.println(mTrackedTasks.size());
+ for (int i = 0; i < mTrackedTasks.size(); i++) {
+ final JobStatus js = mTrackedTasks.get(i);
+ pw.print(" ");
+ pw.print(String.valueOf(js.hashCode()).substring(0, 3));
+ pw.println("..");
}
}
}
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 c4d564c..98bf8a9 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -42,65 +42,71 @@
* but we don't enforce that so this is safer.
* @hide
*/
-public class JobStatus {
+public final class JobStatus {
public static final long NO_LATEST_RUNTIME = Long.MAX_VALUE;
public static final long NO_EARLIEST_RUNTIME = 0L;
+ static final int CONSTRAINT_CHARGING = 1<<0;
+ static final int CONSTRAINT_TIMING_DELAY = 1<<1;
+ static final int CONSTRAINT_DEADLINE = 1<<2;
+ static final int CONSTRAINT_IDLE = 1<<3;
+ static final int CONSTRAINT_UNMETERED = 1<<4;
+ static final int CONSTRAINT_CONNECTIVITY = 1<<5;
+ static final int CONSTRAINT_APP_NOT_IDLE = 1<<6;
+ static final int CONSTRAINT_CONTENT_TRIGGER = 1<<7;
+
final JobInfo job;
/** Uid of the package requesting this job. */
final int callingUid;
- final String name;
- final String tag;
+ final String batteryName;
final String sourcePackageName;
final int sourceUserId;
final int sourceUid;
+ final String sourceTag;
+
+ final String tag;
+
+ /**
+ * Earliest point in the future at which this job will be eligible to run. A value of 0
+ * indicates there is no delay constraint. See {@link #hasTimingDelayConstraint()}.
+ */
+ private final long earliestRunTimeElapsedMillis;
+ /**
+ * Latest point in the future at which this job must be run. A value of {@link Long#MAX_VALUE}
+ * indicates there is no deadline constraint. See {@link #hasDeadlineConstraint()}.
+ */
+ private final long latestRunTimeElapsedMillis;
+
+ /** How many times this job has failed, used to compute back-off. */
+ private final int numFailures;
// Constraints.
- final AtomicBoolean chargingConstraintSatisfied = new AtomicBoolean();
- final AtomicBoolean timeDelayConstraintSatisfied = new AtomicBoolean();
- final AtomicBoolean deadlineConstraintSatisfied = new AtomicBoolean();
- final AtomicBoolean idleConstraintSatisfied = new AtomicBoolean();
- final AtomicBoolean unmeteredConstraintSatisfied = new AtomicBoolean();
- final AtomicBoolean connectivityConstraintSatisfied = new AtomicBoolean();
- final AtomicBoolean appNotIdleConstraintSatisfied = new AtomicBoolean();
- final AtomicBoolean contentTriggerConstraintSatisfied = new AtomicBoolean();
+ final int requiredConstraints;
+ int satisfiedConstraints = 0;
// These are filled in by controllers when preparing for execution.
public ArraySet<Uri> changedUris;
public ArraySet<String> changedAuthorities;
+ public int lastEvaluatedPriority;
+
/**
* For use only by ContentObserverController: state it is maintaining about content URIs
* being observed.
*/
ContentObserverController.JobInstance contentObserverJobInstance;
- /**
- * Earliest point in the future at which this job will be eligible to run. A value of 0
- * indicates there is no delay constraint. See {@link #hasTimingDelayConstraint()}.
- */
- private long earliestRunTimeElapsedMillis;
- /**
- * Latest point in the future at which this job must be run. A value of {@link Long#MAX_VALUE}
- * indicates there is no deadline constraint. See {@link #hasDeadlineConstraint()}.
- */
- private long latestRunTimeElapsedMillis;
- /** How many times this job has failed, used to compute back-off. */
- private final int numFailures;
-
/** Provide a handle to the service that this job will be run on. */
public int getServiceToken() {
return callingUid;
}
- private JobStatus(JobInfo job, int callingUid, String sourcePackageName, int sourceUserId,
- int numFailures) {
+ private JobStatus(JobInfo job, int callingUid, String sourcePackageName,
+ int sourceUserId, String tag, int numFailures, long earliestRunTimeElapsedMillis,
+ long latestRunTimeElapsedMillis) {
this.job = job;
this.callingUid = callingUid;
- this.name = job.getService().flattenToShortString();
- this.tag = "*job*/" + this.name;
- this.numFailures = numFailures;
int tempSourceUid = -1;
if (sourceUserId != -1 && sourcePackageName != null) {
@@ -115,43 +121,64 @@
this.sourceUid = callingUid;
this.sourceUserId = UserHandle.getUserId(callingUid);
this.sourcePackageName = job.getService().getPackageName();
+ this.sourceTag = null;
} else {
this.sourceUid = tempSourceUid;
this.sourceUserId = sourceUserId;
this.sourcePackageName = sourcePackageName;
+ this.sourceTag = tag;
}
+
+ if (this.sourceTag != null) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(job.getService().getPackageName());
+ sb.append('/');
+ sb.append(this.sourceTag);
+ if (sourcePackageName != null) {
+ sb.append('/');
+ sb.append(this.sourcePackageName);
+ }
+ this.batteryName = sb.toString();
+ } else {
+ this.batteryName = job.getService().flattenToShortString();
+ }
+ this.tag = "*job*/" + this.batteryName;
+
+ this.earliestRunTimeElapsedMillis = earliestRunTimeElapsedMillis;
+ this.latestRunTimeElapsedMillis = latestRunTimeElapsedMillis;
+ this.numFailures = numFailures;
+
+ int requiredConstraints = 0;
+ if (job.getNetworkType() == JobInfo.NETWORK_TYPE_ANY) {
+ requiredConstraints |= CONSTRAINT_CONNECTIVITY;
+ }
+ if (job.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED) {
+ requiredConstraints |= CONSTRAINT_UNMETERED;
+ }
+ if (job.isRequireCharging()) {
+ requiredConstraints |= CONSTRAINT_CHARGING;
+ }
+ if (earliestRunTimeElapsedMillis != NO_EARLIEST_RUNTIME) {
+ requiredConstraints |= CONSTRAINT_TIMING_DELAY;
+ }
+ if (latestRunTimeElapsedMillis != NO_LATEST_RUNTIME) {
+ requiredConstraints |= CONSTRAINT_DEADLINE;
+ }
+ if (job.isRequireDeviceIdle()) {
+ requiredConstraints |= CONSTRAINT_IDLE;
+ }
+ if (job.getTriggerContentUris() != null) {
+ requiredConstraints |= CONSTRAINT_CONTENT_TRIGGER;
+ }
+ this.requiredConstraints = requiredConstraints;
}
/** Copy constructor. */
public JobStatus(JobStatus jobStatus) {
- this(jobStatus.getJob(), jobStatus.getUid(), jobStatus.getSourcePackageName(),
- jobStatus.getSourceUserId(), jobStatus.getNumFailures());
- this.earliestRunTimeElapsedMillis = jobStatus.getEarliestRunTime();
- this.latestRunTimeElapsedMillis = jobStatus.getLatestRunTimeElapsed();
- }
-
- /**
- * Create a newly scheduled job.
- * @param callingUid Uid of the package that scheduled this job.
- * @param sourcePackageName Package name on whose behalf this job is scheduled. Null indicates
- * the calling package is the source.
- * @param sourceUserId User id for whom this job is scheduled. -1 indicates this is same as the
- * calling userId.
- */
- public JobStatus(JobInfo job, int callingUid, String sourcePackageName, int sourceUserId) {
- this(job, callingUid, sourcePackageName, sourceUserId, 0);
-
- final long elapsedNow = SystemClock.elapsedRealtime();
-
- if (job.isPeriodic()) {
- latestRunTimeElapsedMillis = elapsedNow + job.getIntervalMillis();
- earliestRunTimeElapsedMillis = latestRunTimeElapsedMillis - job.getFlexMillis();
- } else {
- earliestRunTimeElapsedMillis = job.hasEarlyConstraint() ?
- elapsedNow + job.getMinLatencyMillis() : NO_EARLIEST_RUNTIME;
- latestRunTimeElapsedMillis = job.hasLateConstraint() ?
- elapsedNow + job.getMaxExecutionDelayMillis() : NO_LATEST_RUNTIME;
- }
+ this(jobStatus.getJob(), jobStatus.getUid(),
+ jobStatus.getSourcePackageName(), jobStatus.getSourceUserId(),
+ jobStatus.getSourceTag(), jobStatus.getNumFailures(),
+ jobStatus.getEarliestRunTime(), jobStatus.getLatestRunTimeElapsed());
}
/**
@@ -162,21 +189,42 @@
* We consider a freshly loaded job to no longer be in back-off.
*/
public JobStatus(JobInfo job, int callingUid, String sourcePackageName, int sourceUserId,
- long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis) {
- this(job, callingUid, sourcePackageName, sourceUserId, 0);
-
- this.earliestRunTimeElapsedMillis = earliestRunTimeElapsedMillis;
- this.latestRunTimeElapsedMillis = latestRunTimeElapsedMillis;
+ String sourceTag, long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis) {
+ this(job, callingUid, sourcePackageName, sourceUserId, sourceTag, 0,
+ earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis);
}
/** Create a new job to be rescheduled with the provided parameters. */
public JobStatus(JobStatus rescheduling, long newEarliestRuntimeElapsedMillis,
long newLatestRuntimeElapsedMillis, int backoffAttempt) {
- this(rescheduling.job, rescheduling.getUid(), rescheduling.getSourcePackageName(),
- rescheduling.getSourceUserId(), backoffAttempt);
+ this(rescheduling.job, rescheduling.getUid(),
+ rescheduling.getSourcePackageName(), rescheduling.getSourceUserId(),
+ rescheduling.getSourceTag(), backoffAttempt, newEarliestRuntimeElapsedMillis,
+ newLatestRuntimeElapsedMillis);
+ }
- earliestRunTimeElapsedMillis = newEarliestRuntimeElapsedMillis;
- latestRunTimeElapsedMillis = newLatestRuntimeElapsedMillis;
+ /**
+ * Create a newly scheduled job.
+ * @param callingUid Uid of the package that scheduled this job.
+ * @param sourcePackageName Package name on whose behalf this job is scheduled. Null indicates
+ * the calling package is the source.
+ * @param sourceUserId User id for whom this job is scheduled. -1 indicates this is same as the
+ */
+ public static JobStatus createFromJobInfo(JobInfo job, int callingUid, String sourcePackageName,
+ int sourceUserId, String tag) {
+ final long elapsedNow = SystemClock.elapsedRealtime();
+ final long earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis;
+ if (job.isPeriodic()) {
+ latestRunTimeElapsedMillis = elapsedNow + job.getIntervalMillis();
+ earliestRunTimeElapsedMillis = latestRunTimeElapsedMillis - job.getFlexMillis();
+ } else {
+ earliestRunTimeElapsedMillis = job.hasEarlyConstraint() ?
+ elapsedNow + job.getMinLatencyMillis() : NO_EARLIEST_RUNTIME;
+ latestRunTimeElapsedMillis = job.hasLateConstraint() ?
+ elapsedNow + job.getMaxExecutionDelayMillis() : NO_LATEST_RUNTIME;
+ }
+ return new JobStatus(job, callingUid, sourcePackageName, sourceUserId, tag, 0,
+ earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis);
}
public JobInfo getJob() {
@@ -211,12 +259,16 @@
return UserHandle.getUserId(callingUid);
}
+ public String getSourceTag() {
+ return sourceTag;
+ }
+
public int getUid() {
return callingUid;
}
- public String getName() {
- return name;
+ public String getBatteryName() {
+ return batteryName;
}
public String getTag() {
@@ -232,31 +284,31 @@
}
public boolean hasConnectivityConstraint() {
- return job.getNetworkType() == JobInfo.NETWORK_TYPE_ANY;
+ return (requiredConstraints&CONSTRAINT_CONNECTIVITY) != 0;
}
public boolean hasUnmeteredConstraint() {
- return job.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED;
+ return (requiredConstraints&CONSTRAINT_UNMETERED) != 0;
}
public boolean hasChargingConstraint() {
- return job.isRequireCharging();
+ return (requiredConstraints&CONSTRAINT_CHARGING) != 0;
}
public boolean hasTimingDelayConstraint() {
- return earliestRunTimeElapsedMillis != NO_EARLIEST_RUNTIME;
+ return (requiredConstraints&CONSTRAINT_TIMING_DELAY) != 0;
}
public boolean hasDeadlineConstraint() {
- return latestRunTimeElapsedMillis != NO_LATEST_RUNTIME;
+ return (requiredConstraints&CONSTRAINT_DEADLINE) != 0;
}
public boolean hasIdleConstraint() {
- return job.isRequireDeviceIdle();
+ return (requiredConstraints&CONSTRAINT_IDLE) != 0;
}
public boolean hasContentTriggerConstraint() {
- return job.getTriggerContentUris() != null;
+ return (requiredConstraints&CONSTRAINT_CONTENT_TRIGGER) != 0;
}
public boolean isPersisted() {
@@ -271,31 +323,74 @@
return latestRunTimeElapsedMillis;
}
+ boolean setChargingConstraintSatisfied(boolean state) {
+ return setConstraintSatisfied(CONSTRAINT_CHARGING, state);
+ }
+
+ boolean setTimingDelayConstraintSatisfied(boolean state) {
+ return setConstraintSatisfied(CONSTRAINT_TIMING_DELAY, state);
+ }
+
+ boolean setDeadlineConstraintSatisfied(boolean state) {
+ return setConstraintSatisfied(CONSTRAINT_DEADLINE, state);
+ }
+
+ boolean setIdleConstraintSatisfied(boolean state) {
+ return setConstraintSatisfied(CONSTRAINT_IDLE, state);
+ }
+
+ boolean setUnmeteredConstraintSatisfied(boolean state) {
+ return setConstraintSatisfied(CONSTRAINT_UNMETERED, state);
+ }
+
+ boolean setConnectivityConstraintSatisfied(boolean state) {
+ return setConstraintSatisfied(CONSTRAINT_CONNECTIVITY, state);
+ }
+
+ boolean setAppNotIdleConstraintSatisfied(boolean state) {
+ return setConstraintSatisfied(CONSTRAINT_APP_NOT_IDLE, state);
+ }
+
+ boolean setContentTriggerConstraintSatisfied(boolean state) {
+ return setConstraintSatisfied(CONSTRAINT_CONTENT_TRIGGER, state);
+ }
+
+ boolean setConstraintSatisfied(int constraint, boolean state) {
+ boolean old = (satisfiedConstraints&constraint) != 0;
+ if (old == state) {
+ return false;
+ }
+ satisfiedConstraints = (satisfiedConstraints&~constraint) | (state ? constraint : 0);
+ return true;
+ }
+
/**
* @return Whether or not this job is ready to run, based on its requirements. This is true if
* the constraints are satisfied <strong>or</strong> the deadline on the job has expired.
*/
- public synchronized boolean isReady() {
+ public boolean isReady() {
// Deadline constraint trumps other constraints (except for periodic jobs where deadline
// (is an implementation detail. A periodic job should only run if it's constraints are
// satisfied).
// AppNotIdle implicit constraint trumps all!
return (isConstraintsSatisfied()
- || (!job.isPeriodic()
- && hasDeadlineConstraint() && deadlineConstraintSatisfied.get()))
- && appNotIdleConstraintSatisfied.get();
+ || (!job.isPeriodic()
+ && hasDeadlineConstraint() && (satisfiedConstraints&CONSTRAINT_DEADLINE) != 0))
+ && (satisfiedConstraints&CONSTRAINT_APP_NOT_IDLE) != 0;
}
+ static final int CONSTRAINTS_OF_INTEREST =
+ CONSTRAINT_CHARGING | CONSTRAINT_TIMING_DELAY |
+ CONSTRAINT_CONNECTIVITY | CONSTRAINT_UNMETERED |
+ CONSTRAINT_IDLE | CONSTRAINT_CONTENT_TRIGGER;
+
/**
* @return Whether the constraints set on this job are satisfied.
*/
- public synchronized boolean isConstraintsSatisfied() {
- return (!hasChargingConstraint() || chargingConstraintSatisfied.get())
- && (!hasTimingDelayConstraint() || timeDelayConstraintSatisfied.get())
- && (!hasConnectivityConstraint() || connectivityConstraintSatisfied.get())
- && (!hasUnmeteredConstraint() || unmeteredConstraintSatisfied.get())
- && (!hasIdleConstraint() || idleConstraintSatisfied.get())
- && (!hasContentTriggerConstraint() || contentTriggerConstraintSatisfied.get());
+ public boolean isConstraintsSatisfied() {
+ final int req = requiredConstraints & CONSTRAINTS_OF_INTEREST;
+ final int sat = satisfiedConstraints & CONSTRAINTS_OF_INTEREST;
+ return (sat & req) == req;
}
public boolean matches(int uid, int jobId) {
@@ -314,7 +409,7 @@
+ ",I=" + job.isRequireDeviceIdle()
+ ",U=" + (job.getTriggerContentUris() != null)
+ ",F=" + numFailures + ",P=" + job.isPersisted()
- + ",ANI=" + appNotIdleConstraintSatisfied.get()
+ + ",ANI=" + ((satisfiedConstraints&CONSTRAINT_APP_NOT_IDLE) != 0)
+ (isReady() ? "(READY)" : "")
+ "]";
}
@@ -342,109 +437,105 @@
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(" jId=");
sb.append(job.getId());
- sb.append(" uid=");
+ sb.append(' ');
UserHandle.formatUid(sb, callingUid);
sb.append(' ');
- sb.append(job.getService().flattenToShortString());
+ sb.append(batteryName);
return sb.toString();
}
+ void dumpConstraints(PrintWriter pw, int constraints) {
+ if ((constraints&CONSTRAINT_CHARGING) != 0) {
+ pw.print(" CHARGING");
+ }
+ if ((constraints&CONSTRAINT_TIMING_DELAY) != 0) {
+ pw.print(" TIMING_DELAY");
+ }
+ if ((constraints&CONSTRAINT_DEADLINE) != 0) {
+ pw.print(" DEADLINE");
+ }
+ if ((constraints&CONSTRAINT_IDLE) != 0) {
+ pw.print(" IDLE");
+ }
+ if ((constraints&CONSTRAINT_UNMETERED) != 0) {
+ pw.print(" UNMETERED");
+ }
+ if ((constraints&CONSTRAINT_CONNECTIVITY) != 0) {
+ pw.print(" CONNECTIVITY");
+ }
+ if ((constraints&CONSTRAINT_APP_NOT_IDLE) != 0) {
+ pw.print(" APP_NOT_IDLE");
+ }
+ if ((constraints&CONSTRAINT_CONTENT_TRIGGER) != 0) {
+ pw.print(" CONTENT_TRIGGER");
+ }
+ }
+
// Dumpsys infrastructure
- public void dump(PrintWriter pw, String prefix) {
+ public void dump(PrintWriter pw, String prefix, boolean full) {
pw.print(prefix); UserHandle.formatUid(pw, callingUid);
pw.print(" tag="); pw.println(tag);
pw.print(prefix);
pw.print("Source: uid="); UserHandle.formatUid(pw, getSourceUid());
pw.print(" user="); pw.print(getSourceUserId());
pw.print(" pkg="); pw.println(getSourcePackageName());
- pw.print(prefix); pw.println("JobInfo:");
- pw.print(prefix); pw.print(" Service: ");
- pw.println(job.getService().flattenToShortString());
- if (job.isPeriodic()) {
- pw.print(prefix); pw.print(" PERIODIC: interval=");
- TimeUtils.formatDuration(job.getIntervalMillis(), pw);
- pw.print(" flex=");
- TimeUtils.formatDuration(job.getFlexMillis(), pw);
+ if (full) {
+ pw.print(prefix); pw.println("JobInfo:"); pw.print(prefix);
+ pw.print(" Service: "); pw.println(job.getService().flattenToShortString());
+ if (job.isPeriodic()) {
+ pw.print(prefix); pw.print(" PERIODIC: interval=");
+ TimeUtils.formatDuration(job.getIntervalMillis(), pw);
+ pw.print(" flex="); TimeUtils.formatDuration(job.getFlexMillis(), pw);
+ pw.println();
+ }
+ if (job.isPersisted()) {
+ pw.print(prefix); pw.println(" PERSISTED");
+ }
+ if (job.getPriority() != 0) {
+ pw.print(prefix); pw.print(" Priority: "); pw.println(job.getPriority());
+ }
+ pw.print(prefix); pw.print(" Requires: charging=");
+ pw.print(job.isRequireCharging()); pw.print(" deviceIdle=");
+ pw.println(job.isRequireDeviceIdle());
+ if (job.getTriggerContentUris() != null) {
+ pw.print(prefix); pw.println(" Trigger content URIs:");
+ for (int i = 0; i < job.getTriggerContentUris().length; i++) {
+ JobInfo.TriggerContentUri trig = job.getTriggerContentUris()[i];
+ pw.print(prefix); pw.print(" ");
+ pw.print(Integer.toHexString(trig.getFlags()));
+ pw.print(' '); pw.println(trig.getUri());
+ }
+ }
+ if (job.getNetworkType() != JobInfo.NETWORK_TYPE_NONE) {
+ pw.print(prefix); pw.print(" Network type: "); pw.println(job.getNetworkType());
+ }
+ if (job.getMinLatencyMillis() != 0) {
+ pw.print(prefix); pw.print(" Minimum latency: ");
+ TimeUtils.formatDuration(job.getMinLatencyMillis(), pw);
+ pw.println();
+ }
+ if (job.getMaxExecutionDelayMillis() != 0) {
+ pw.print(prefix); pw.print(" Max execution delay: ");
+ TimeUtils.formatDuration(job.getMaxExecutionDelayMillis(), pw);
+ pw.println();
+ }
+ pw.print(prefix); pw.print(" Backoff: policy="); pw.print(job.getBackoffPolicy());
+ pw.print(" initial="); TimeUtils.formatDuration(job.getInitialBackoffMillis(), pw);
pw.println();
- }
- if (job.isPersisted()) {
- pw.print(prefix); pw.println(" PERSISTED");
- }
- if (job.getPriority() != 0) {
- pw.print(prefix); pw.print(" Priority: ");
- pw.println(job.getPriority());
- }
- pw.print(prefix); pw.print(" Requires: charging=");
- pw.print(job.isRequireCharging());
- pw.print(" deviceIdle=");
- pw.println(job.isRequireDeviceIdle());
- if (job.getTriggerContentUris() != null) {
- pw.print(prefix); pw.println(" Trigger content URIs:");
- for (int i=0; i<job.getTriggerContentUris().length; i++) {
- JobInfo.TriggerContentUri trig = job.getTriggerContentUris()[i];
- pw.print(prefix); pw.print(" ");
- pw.print(Integer.toHexString(trig.getFlags()));
- pw.print(' ' );
- pw.println(trig.getUri());
+ if (job.hasEarlyConstraint()) {
+ pw.print(prefix); pw.println(" Has early constraint");
+ }
+ if (job.hasLateConstraint()) {
+ pw.print(prefix); pw.println(" Has late constraint");
}
}
- if (job.getNetworkType() != JobInfo.NETWORK_TYPE_NONE) {
- pw.print(prefix); pw.print(" Network type: ");
- pw.println(job.getNetworkType());
- }
- if (job.getMinLatencyMillis() != 0) {
- pw.print(prefix); pw.print(" Minimum latency: ");
- TimeUtils.formatDuration(job.getMinLatencyMillis(), pw);
- pw.println();
- }
- if (job.getMaxExecutionDelayMillis() != 0) {
- pw.print(prefix); pw.print(" Max execution delay: ");
- TimeUtils.formatDuration(job.getMaxExecutionDelayMillis(), pw);
- pw.println();
- }
- pw.print(prefix); pw.print(" Backoff: policy=");
- pw.print(job.getBackoffPolicy());
- pw.print(" initial=");
- TimeUtils.formatDuration(job.getInitialBackoffMillis(), pw);
+ pw.print(prefix); pw.print("Required constraints:");
+ dumpConstraints(pw, requiredConstraints);
pw.println();
- if (job.hasEarlyConstraint()) {
- pw.print(prefix); pw.println(" Has early constraint");
- }
- if (job.hasLateConstraint()) {
- pw.print(prefix); pw.println(" Has late constraint");
- }
- pw.print(prefix); pw.println("Constraints:");
- if (hasChargingConstraint()) {
- pw.print(prefix); pw.print(" Charging: ");
- pw.println(chargingConstraintSatisfied.get());
- }
- if (hasTimingDelayConstraint()) {
- pw.print(prefix); pw.print(" Time delay: ");
- pw.println(timeDelayConstraintSatisfied.get());
- }
- if (hasDeadlineConstraint()) {
- pw.print(prefix); pw.print(" Deadline: ");
- pw.println(deadlineConstraintSatisfied.get());
- }
- if (hasIdleConstraint()) {
- pw.print(prefix); pw.print(" System idle: ");
- pw.println(idleConstraintSatisfied.get());
- }
- if (hasUnmeteredConstraint()) {
- pw.print(prefix); pw.print(" Unmetered: ");
- pw.println(unmeteredConstraintSatisfied.get());
- }
- if (hasConnectivityConstraint()) {
- pw.print(prefix); pw.print(" Connectivity: ");
- pw.println(connectivityConstraintSatisfied.get());
- }
- if (hasIdleConstraint()) {
- pw.print(prefix); pw.print(" App not idle: ");
- pw.println(appNotIdleConstraintSatisfied.get());
- }
- if (hasContentTriggerConstraint()) {
- pw.print(prefix); pw.print(" Content trigger: ");
- pw.println(contentTriggerConstraintSatisfied.get());
+ if (full) {
+ pw.print(prefix); pw.print("Satisfied constraints:");
+ dumpConstraints(pw, satisfiedConstraints);
+ pw.println();
}
if (changedAuthorities != null) {
pw.print(prefix); pw.println("Changed authorities:");
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 b619ea8..7882bc4d 100644
--- a/services/core/java/com/android/server/job/controllers/StateController.java
+++ b/services/core/java/com/android/server/job/controllers/StateController.java
@@ -30,13 +30,16 @@
*/
public abstract class StateController {
protected static final boolean DEBUG = JobSchedulerService.DEBUG;
- protected Context mContext;
- protected StateChangedListener mStateChangedListener;
+ protected final Context mContext;
+ protected final Object mLock;
+ protected final StateChangedListener mStateChangedListener;
protected boolean mDeviceIdleMode;
- public StateController(StateChangedListener stateChangedListener, Context context) {
+ public StateController(StateChangedListener stateChangedListener, Context context,
+ Object lock) {
mStateChangedListener = stateChangedListener;
mContext = context;
+ mLock = lock;
}
public void deviceIdleModeChanged(boolean enabled) {
@@ -49,21 +52,21 @@
* Also called when updating a task, so implementing controllers have to be aware of
* preexisting tasks.
*/
- public abstract void maybeStartTrackingJob(JobStatus jobStatus, JobStatus lastJob);
+ public abstract void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob);
/**
* Optionally implement logic here to prepare the job to be executed.
*/
- public void prepareForExecution(JobStatus jobStatus) {
+ public void prepareForExecutionLocked(JobStatus jobStatus) {
}
/**
* Remove task - this will happen if the task is cancelled, completed, etc.
*/
- public abstract void maybeStopTrackingJob(JobStatus jobStatus, boolean forUpdate);
+ public abstract void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate);
/**
* Called when a new job is being created to reschedule an old failed job.
*/
public void rescheduleForFailure(JobStatus newJob, JobStatus failureToReschedule) {
}
- public abstract void dumpControllerState(PrintWriter pw);
+ public abstract void dumpControllerStateLocked(PrintWriter pw);
}
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 a68c3ad..620800c 100644
--- a/services/core/java/com/android/server/job/controllers/TimeController.java
+++ b/services/core/java/com/android/server/job/controllers/TimeController.java
@@ -54,13 +54,14 @@
public static synchronized TimeController get(JobSchedulerService jms) {
if (mSingleton == null) {
- mSingleton = new TimeController(jms, jms.getContext());
+ mSingleton = new TimeController(jms, jms.getContext(), jms.getLock());
}
return mSingleton;
}
- private TimeController(StateChangedListener stateChangedListener, Context context) {
- super(stateChangedListener, context);
+ private TimeController(StateChangedListener stateChangedListener, Context context,
+ Object lock) {
+ super(stateChangedListener, context, lock);
mNextJobExpiredElapsedMillis = Long.MAX_VALUE;
mNextDelayExpiredElapsedMillis = Long.MAX_VALUE;
@@ -71,9 +72,9 @@
* list.
*/
@Override
- public synchronized void maybeStartTrackingJob(JobStatus job, JobStatus lastJob) {
+ public void maybeStartTrackingJobLocked(JobStatus job, JobStatus lastJob) {
if (job.hasTimingDelayConstraint() || job.hasDeadlineConstraint()) {
- maybeStopTrackingJob(job, false);
+ maybeStopTrackingJobLocked(job, false);
boolean isInsert = false;
ListIterator<JobStatus> it = mTrackedJobs.listIterator(mTrackedJobs.size());
while (it.hasPrevious()) {
@@ -84,12 +85,11 @@
break;
}
}
- if(isInsert)
- {
+ if (isInsert) {
it.next();
}
it.add(job);
- maybeUpdateAlarms(
+ maybeUpdateAlarmsLocked(
job.hasTimingDelayConstraint() ? job.getEarliestRunTime() : Long.MAX_VALUE,
job.hasDeadlineConstraint() ? job.getLatestRunTimeElapsed() : Long.MAX_VALUE);
}
@@ -101,7 +101,7 @@
* Really an == comparison should be enough, but why play with fate? We'll do <=.
*/
@Override
- public synchronized void maybeStopTrackingJob(JobStatus job, boolean forUpdate) {
+ public void maybeStopTrackingJobLocked(JobStatus job, boolean forUpdate) {
if (mTrackedJobs.remove(job)) {
checkExpiredDelaysAndResetAlarm();
checkExpiredDeadlinesAndResetAlarm();
@@ -114,14 +114,14 @@
* the job's deadline is fulfilled - unlike other controllers a time constraint can't toggle
* back and forth.
*/
- private boolean canStopTrackingJob(JobStatus job) {
+ private boolean canStopTrackingJobLocked(JobStatus job) {
return (!job.hasTimingDelayConstraint() ||
- job.timeDelayConstraintSatisfied.get()) &&
+ (job.satisfiedConstraints&JobStatus.CONSTRAINT_TIMING_DELAY) != 0) &&
(!job.hasDeadlineConstraint() ||
- job.deadlineConstraintSatisfied.get());
+ (job.satisfiedConstraints&JobStatus.CONSTRAINT_DEADLINE) != 0);
}
- private void ensureAlarmService() {
+ private void ensureAlarmServiceLocked() {
if (mAlarmService == null) {
mAlarmService = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
}
@@ -131,71 +131,75 @@
* Checks list of jobs for ones that have an expired deadline, sending them to the JobScheduler
* if so, removing them from this list, and updating the alarm for the next expiry time.
*/
- private synchronized void checkExpiredDeadlinesAndResetAlarm() {
- long nextExpiryTime = Long.MAX_VALUE;
- final long nowElapsedMillis = SystemClock.elapsedRealtime();
+ private void checkExpiredDeadlinesAndResetAlarm() {
+ synchronized (mLock) {
+ long nextExpiryTime = Long.MAX_VALUE;
+ final long nowElapsedMillis = SystemClock.elapsedRealtime();
- Iterator<JobStatus> it = mTrackedJobs.iterator();
- while (it.hasNext()) {
- JobStatus job = it.next();
- if (!job.hasDeadlineConstraint()) {
- continue;
- }
- final long jobDeadline = job.getLatestRunTimeElapsed();
+ Iterator<JobStatus> it = mTrackedJobs.iterator();
+ while (it.hasNext()) {
+ JobStatus job = it.next();
+ if (!job.hasDeadlineConstraint()) {
+ continue;
+ }
+ final long jobDeadline = job.getLatestRunTimeElapsed();
- if (jobDeadline <= nowElapsedMillis) {
- job.deadlineConstraintSatisfied.set(true);
- mStateChangedListener.onRunJobNow(job);
- it.remove();
- } else { // Sorted by expiry time, so take the next one and stop.
- nextExpiryTime = jobDeadline;
- break;
+ if (jobDeadline <= nowElapsedMillis) {
+ job.setDeadlineConstraintSatisfied(true);
+ mStateChangedListener.onRunJobNow(job);
+ it.remove();
+ } else { // Sorted by expiry time, so take the next one and stop.
+ nextExpiryTime = jobDeadline;
+ break;
+ }
}
+ setDeadlineExpiredAlarmLocked(nextExpiryTime);
}
- setDeadlineExpiredAlarm(nextExpiryTime);
}
/**
* Handles alarm that notifies us that a job's delay has expired. Iterates through the list of
* tracked jobs and marks them as ready as appropriate.
*/
- private synchronized void checkExpiredDelaysAndResetAlarm() {
- final long nowElapsedMillis = SystemClock.elapsedRealtime();
- long nextDelayTime = Long.MAX_VALUE;
- boolean ready = false;
- Iterator<JobStatus> it = mTrackedJobs.iterator();
- while (it.hasNext()) {
- final JobStatus job = it.next();
- if (!job.hasTimingDelayConstraint()) {
- continue;
- }
- final long jobDelayTime = job.getEarliestRunTime();
- if (jobDelayTime <= nowElapsedMillis) {
- job.timeDelayConstraintSatisfied.set(true);
- if (canStopTrackingJob(job)) {
- it.remove();
+ private void checkExpiredDelaysAndResetAlarm() {
+ synchronized (mLock) {
+ final long nowElapsedMillis = SystemClock.elapsedRealtime();
+ long nextDelayTime = Long.MAX_VALUE;
+ boolean ready = false;
+ Iterator<JobStatus> it = mTrackedJobs.iterator();
+ while (it.hasNext()) {
+ final JobStatus job = it.next();
+ if (!job.hasTimingDelayConstraint()) {
+ continue;
}
- if (job.isReady()) {
- ready = true;
- }
- } else { // Keep going through list to get next delay time.
- if (nextDelayTime > jobDelayTime) {
- nextDelayTime = jobDelayTime;
+ final long jobDelayTime = job.getEarliestRunTime();
+ if (jobDelayTime <= nowElapsedMillis) {
+ job.setTimingDelayConstraintSatisfied(true);
+ if (canStopTrackingJobLocked(job)) {
+ it.remove();
+ }
+ if (job.isReady()) {
+ ready = true;
+ }
+ } else { // Keep going through list to get next delay time.
+ if (nextDelayTime > jobDelayTime) {
+ nextDelayTime = jobDelayTime;
+ }
}
}
+ if (ready) {
+ mStateChangedListener.onControllerStateChanged();
+ }
+ setDelayExpiredAlarmLocked(nextDelayTime);
}
- if (ready) {
- mStateChangedListener.onControllerStateChanged();
- }
- setDelayExpiredAlarm(nextDelayTime);
}
- private void maybeUpdateAlarms(long delayExpiredElapsed, long deadlineExpiredElapsed) {
+ private void maybeUpdateAlarmsLocked(long delayExpiredElapsed, long deadlineExpiredElapsed) {
if (delayExpiredElapsed < mNextDelayExpiredElapsedMillis) {
- setDelayExpiredAlarm(delayExpiredElapsed);
+ setDelayExpiredAlarmLocked(delayExpiredElapsed);
}
if (deadlineExpiredElapsed < mNextJobExpiredElapsedMillis) {
- setDeadlineExpiredAlarm(deadlineExpiredElapsed);
+ setDeadlineExpiredAlarmLocked(deadlineExpiredElapsed);
}
}
@@ -204,10 +208,11 @@
* delay will expire.
* This alarm <b>will</b> wake up the phone.
*/
- private void setDelayExpiredAlarm(long alarmTimeElapsedMillis) {
+ private void setDelayExpiredAlarmLocked(long alarmTimeElapsedMillis) {
alarmTimeElapsedMillis = maybeAdjustAlarmTime(alarmTimeElapsedMillis);
mNextDelayExpiredElapsedMillis = alarmTimeElapsedMillis;
- updateAlarmWithListener(DELAY_TAG, mNextDelayExpiredListener, mNextDelayExpiredElapsedMillis);
+ updateAlarmWithListenerLocked(DELAY_TAG, mNextDelayExpiredListener,
+ mNextDelayExpiredElapsedMillis);
}
/**
@@ -215,10 +220,11 @@
* deadline will expire.
* This alarm <b>will</b> wake up the phone.
*/
- private void setDeadlineExpiredAlarm(long alarmTimeElapsedMillis) {
+ private void setDeadlineExpiredAlarmLocked(long alarmTimeElapsedMillis) {
alarmTimeElapsedMillis = maybeAdjustAlarmTime(alarmTimeElapsedMillis);
mNextJobExpiredElapsedMillis = alarmTimeElapsedMillis;
- updateAlarmWithListener(DEADLINE_TAG, mDeadlineExpiredListener, mNextJobExpiredElapsedMillis);
+ updateAlarmWithListenerLocked(DEADLINE_TAG, mDeadlineExpiredListener,
+ mNextJobExpiredElapsedMillis);
}
private long maybeAdjustAlarmTime(long proposedAlarmTimeElapsedMillis) {
@@ -229,9 +235,9 @@
return proposedAlarmTimeElapsedMillis;
}
- private void updateAlarmWithListener(String tag, OnAlarmListener listener,
+ private void updateAlarmWithListenerLocked(String tag, OnAlarmListener listener,
long alarmTimeElapsed) {
- ensureAlarmService();
+ ensureAlarmServiceLocked();
if (alarmTimeElapsed == Long.MAX_VALUE) {
mAlarmService.cancel(listener);
} else {
@@ -266,7 +272,7 @@
};
@Override
- public void dumpControllerState(PrintWriter pw) {
+ public void dumpControllerStateLocked(PrintWriter pw) {
final long nowElapsed = SystemClock.elapsedRealtime();
pw.println("Alarms (" + SystemClock.elapsedRealtime() + ")");
pw.println(
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index c1eb844..e08fad4 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -508,18 +508,18 @@
};
private void subscriptionOrSimChanged(Context context) {
- Log.d(TAG, "received SIM related action: ");
+ if (DEBUG) Log.d(TAG, "received SIM related action: ");
TelephonyManager phone = (TelephonyManager)
mContext.getSystemService(Context.TELEPHONY_SERVICE);
String mccMnc = phone.getSimOperator();
if (!TextUtils.isEmpty(mccMnc)) {
- Log.d(TAG, "SIM MCC/MNC is available: " + mccMnc);
+ if (DEBUG) Log.d(TAG, "SIM MCC/MNC is available: " + mccMnc);
synchronized (mLock) {
reloadGpsProperties(context, mProperties);
mNIHandler.setSuplEsEnabled(mSuplEsEnabled);
}
} else {
- Log.d(TAG, "SIM MCC/MNC is still not available");
+ if (DEBUG) Log.d(TAG, "SIM MCC/MNC is still not available");
}
}
@@ -569,7 +569,7 @@
}
private void reloadGpsProperties(Context context, Properties properties) {
- Log.d(TAG, "Reset GPS properties, previous size = " + properties.size());
+ if (DEBUG) Log.d(TAG, "Reset GPS properties, previous size = " + properties.size());
loadPropertiesFromResource(context, properties);
boolean isPropertiesLoadedFromFile = false;
final String gpsHardware = SystemProperties.get("ro.hardware.gps");
@@ -582,7 +582,7 @@
if (!isPropertiesLoadedFromFile) {
loadPropertiesFromFile(DEFAULT_PROPERTIES_FILE, properties);
}
- Log.d(TAG, "GPS properties reloaded, size = " + properties.size());
+ if (DEBUG) Log.d(TAG, "GPS properties reloaded, size = " + properties.size());
// TODO: we should get rid of C2K specific setting.
setSuplHostPort(properties.getProperty("SUPL_HOST"),
@@ -603,7 +603,7 @@
ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
properties.store(baos, null);
native_configuration_update(baos.toString());
- Log.d(TAG, "final config = " + baos.toString());
+ if (DEBUG) Log.d(TAG, "final config = " + baos.toString());
} catch (IOException ex) {
Log.e(TAG, "failed to dump properties contents");
}
@@ -628,7 +628,7 @@
String[] configValues = context.getResources().getStringArray(
com.android.internal.R.array.config_gpsParameters);
for (String item : configValues) {
- Log.d(TAG, "GpsParamsResource: " + item);
+ if (DEBUG) Log.d(TAG, "GpsParamsResource: " + item);
// We need to support "KEY =", but not "=VALUE".
String[] split = item.split("=");
if (split.length == 2) {
@@ -917,11 +917,13 @@
long certainty = mNtpTime.getCacheCertainty();
long now = System.currentTimeMillis();
- Log.d(TAG, "NTP server returned: "
- + time + " (" + new Date(time)
- + ") reference: " + timeReference
- + " certainty: " + certainty
- + " system time offset: " + (time - now));
+ if (DEBUG) {
+ Log.d(TAG, "NTP server returned: "
+ + time + " (" + new Date(time)
+ + ") reference: " + timeReference
+ + " certainty: " + certainty
+ + " system time offset: " + (time - now));
+ }
native_inject_time(time, timeReference, (int) certainty);
delay = NTP_INTERVAL;
@@ -1557,11 +1559,11 @@
* called from native code to update SV info
*/
private void reportSvStatus() {
- int svCount = native_read_sv_status(mSvidWithFlags, mSnrs, mSvElevations, mSvAzimuths);
+ int svCount = native_read_sv_status(mSvidWithFlags, mCn0s, mSvElevations, mSvAzimuths);
mListenerHelper.onSvStatusChanged(
svCount,
mSvidWithFlags,
- mSnrs,
+ mCn0s,
mSvElevations,
mSvAzimuths);
@@ -1576,7 +1578,7 @@
}
if (VERBOSE) {
Log.v(TAG, "svid: " + (mSvidWithFlags[i] >> GnssStatus.SVID_SHIFT_WIDTH) +
- " snr: " + mSnrs[i]/10 +
+ " cn0: " + mCn0s[i]/10 +
" elev: " + mSvElevations[i] +
" azimuth: " + mSvAzimuths[i] +
((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) == 0
@@ -1633,7 +1635,7 @@
if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
break;
default:
- Log.d(TAG, "Received Unknown AGPS status: " + status);
+ if (DEBUG) Log.d(TAG, "Received Unknown AGPS status: " + status);
}
}
@@ -1684,25 +1686,25 @@
/**
* Called from native code to inform us the hardware information.
*/
- private void setGpsYearOfHardware(int yearOfHardware) {
- if (DEBUG) Log.d(TAG, "setGpsYearOfHardware called with " + yearOfHardware);
+ private void setGnssYearOfHardware(int yearOfHardware) {
+ if (DEBUG) Log.d(TAG, "setGnssYearOfHardware called with " + yearOfHardware);
mYearOfHardware = yearOfHardware;
}
- public interface GpsSystemInfoProvider {
+ public interface GnssSystemInfoProvider {
/**
* Returns the year of GPS hardware.
*/
- int getGpsYearOfHardware();
+ int getGnssYearOfHardware();
}
/**
* @hide
*/
- public GpsSystemInfoProvider getGpsSystemInfoProvider() {
- return new GpsSystemInfoProvider() {
+ public GnssSystemInfoProvider getGnssSystemInfoProvider() {
+ return new GnssSystemInfoProvider() {
@Override
- public int getGpsYearOfHardware() {
+ public int getGnssYearOfHardware() {
return mYearOfHardware;
}
};
@@ -2400,7 +2402,7 @@
// preallocated arrays, to avoid memory allocation in reportStatus()
private int mSvidWithFlags[] = new int[MAX_SVS];
- private float mSnrs[] = new float[MAX_SVS];
+ private float mCn0s[] = new float[MAX_SVS];
private float mSvElevations[] = new float[MAX_SVS];
private float mSvAzimuths[] = new float[MAX_SVS];
private int mSvCount;
@@ -2422,7 +2424,7 @@
private native void native_delete_aiding_data(int flags);
// returns number of SVs
// mask[0] is ephemeris mask and mask[1] is almanac mask
- private native int native_read_sv_status(int[] prnWithFlags, float[] snrs, float[] elevations,
+ private native int native_read_sv_status(int[] prnWithFlags, float[] cn0s, float[] elevations,
float[] azimuths);
private native int native_read_nmea(byte[] buffer, int bufferSize);
private native void native_inject_location(double latitude, double longitude, float accuracy);
diff --git a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
index d9e8e91..734a8d4 100644
--- a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
@@ -72,7 +72,7 @@
status = GnssMeasurementsEvent.STATUS_NOT_SUPPORTED;
break;
case RESULT_GPS_LOCATION_DISABLED:
- status = GnssMeasurementsEvent.STATUS_GPS_LOCATION_DISABLED;
+ status = GnssMeasurementsEvent.STATUS_GNSS_LOCATION_DISABLED;
break;
case RESULT_UNKNOWN:
return null;
diff --git a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
index 57bce4b..fdef31f 100644
--- a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
+++ b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
@@ -73,7 +73,8 @@
status = GnssNavigationMessageEvent.STATUS_NOT_SUPPORTED;
break;
case RESULT_GPS_LOCATION_DISABLED:
- status = GnssNavigationMessageEvent.STATUS_GPS_LOCATION_DISABLED;
+ status = GnssNavigationMessageEvent
+ .STATUS_GNSS_LOCATION_DISABLED;
break;
case RESULT_UNKNOWN:
return null;
diff --git a/services/core/java/com/android/server/location/GnssStatusListenerHelper.java b/services/core/java/com/android/server/location/GnssStatusListenerHelper.java
index 0b3111c..d471e45 100644
--- a/services/core/java/com/android/server/location/GnssStatusListenerHelper.java
+++ b/services/core/java/com/android/server/location/GnssStatusListenerHelper.java
@@ -75,7 +75,7 @@
public void onSvStatusChanged(
final int svCount,
final int[] prnWithFlags,
- final float[] snrs,
+ final float[] cn0s,
final float[] elevations,
final float[] azimuths) {
Operation operation = new Operation() {
@@ -84,7 +84,7 @@
listener.onSvStatusChanged(
svCount,
prnWithFlags,
- snrs,
+ cn0s,
elevations,
azimuths);
}
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 246da2e..29c54e9 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -77,6 +77,8 @@
*/
private static final int OPTIMISTIC_VOLUME_TIMEOUT = 1000;
+ private static final int UID_NOT_SET = -1;
+
private final MessageHandler mHandler;
private final int mOwnerPid;
@@ -122,6 +124,9 @@
private boolean mIsActive = false;
private boolean mDestroyed = false;
+ private int mCallingUid = UID_NOT_SET;
+ private String mCallingPackage;
+
public MediaSessionRecord(int ownerPid, int ownerUid, int userId, String ownerPackageName,
ISessionCallback cb, String tag, MediaSessionService service, Handler handler) {
mOwnerPid = ownerPid;
@@ -419,7 +424,9 @@
return mSessionCb.mCb;
}
- public void sendMediaButton(KeyEvent ke, int sequenceId, ResultReceiver cb) {
+ public void sendMediaButton(KeyEvent ke, int sequenceId,
+ ResultReceiver cb, int uid, String packageName) {
+ updateCallingPackage(uid, packageName);
mSessionCb.sendMediaButton(ke, sequenceId, cb);
}
@@ -680,6 +687,33 @@
return -1;
}
+ private void updateCallingPackage() {
+ updateCallingPackage(UID_NOT_SET, null);
+ }
+
+ private void updateCallingPackage(int uid, String packageName) {
+ if (uid == UID_NOT_SET) {
+ uid = Binder.getCallingUid();
+ }
+ synchronized (mLock) {
+ if (mCallingUid == UID_NOT_SET || mCallingUid != uid) {
+ mCallingUid = uid;
+ mCallingPackage = packageName;
+ if (mCallingPackage != null) {
+ return;
+ }
+ Context context = mService.getContext();
+ if (context == null) {
+ return;
+ }
+ String[] packages = context.getPackageManager().getPackagesForUid(uid);
+ if (packages != null && packages.length > 0) {
+ mCallingPackage = packages[0];
+ }
+ }
+ }
+ }
+
private final Runnable mClearOptimisticVolumeRunnable = new Runnable() {
@Override
public void run() {
@@ -831,6 +865,11 @@
mHandler.post(MessageHandler.MSG_UPDATE_VOLUME);
}
}
+
+ @Override
+ public String getCallingPackage() {
+ return mCallingPackage;
+ }
}
class SessionCb {
@@ -868,6 +907,38 @@
}
}
+ public void prepare() {
+ try {
+ mCb.onPrepare();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote failure in prepare.", e);
+ }
+ }
+
+ public void prepareFromMediaId(String mediaId, Bundle extras) {
+ try {
+ mCb.onPrepareFromMediaId(mediaId, extras);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote failure in prepareFromMediaId.", e);
+ }
+ }
+
+ public void prepareFromSearch(String query, Bundle extras) {
+ try {
+ mCb.onPrepareFromSearch(query, extras);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote failure in prepareFromSearch.", e);
+ }
+ }
+
+ public void prepareFromUri(Uri uri, Bundle extras) {
+ try {
+ mCb.onPrepareFromUri(uri, extras);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote failure in prepareFromUri.", e);
+ }
+ }
+
public void play() {
try {
mCb.onPlay();
@@ -880,7 +951,7 @@
try {
mCb.onPlayFromMediaId(mediaId, extras);
} catch (RemoteException e) {
- Slog.e(TAG, "Remote failure in playUri.", e);
+ Slog.e(TAG, "Remote failure in playFromMediaId.", e);
}
}
@@ -993,11 +1064,13 @@
@Override
public void sendCommand(String command, Bundle args, ResultReceiver cb)
throws RemoteException {
+ updateCallingPackage();
mSessionCb.sendCommand(command, args, cb);
}
@Override
public boolean sendMediaButton(KeyEvent mediaButtonIntent) {
+ updateCallingPackage();
return mSessionCb.sendMediaButton(mediaButtonIntent, 0, null);
}
@@ -1079,6 +1152,7 @@
@Override
public void adjustVolume(int direction, int flags, String packageName) {
+ updateCallingPackage();
int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
@@ -1090,6 +1164,7 @@
@Override
public void setVolumeTo(int value, int flags, String packageName) {
+ updateCallingPackage();
int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
@@ -1100,74 +1175,112 @@
}
@Override
+ public void prepare() throws RemoteException {
+ updateCallingPackage();
+ mSessionCb.prepare();
+ }
+
+ @Override
+ public void prepareFromMediaId(String mediaId, Bundle extras)
+ throws RemoteException {
+ updateCallingPackage();
+ mSessionCb.prepareFromMediaId(mediaId, extras);
+ }
+
+ @Override
+ public void prepareFromSearch(String query, Bundle extras) throws RemoteException {
+ updateCallingPackage();
+ mSessionCb.prepareFromSearch(query, extras);
+ }
+
+ @Override
+ public void prepareFromUri(Uri uri, Bundle extras) throws RemoteException {
+ updateCallingPackage();
+ mSessionCb.prepareFromUri(uri, extras);
+ }
+
+ @Override
public void play() throws RemoteException {
+ updateCallingPackage();
mSessionCb.play();
}
@Override
public void playFromMediaId(String mediaId, Bundle extras) throws RemoteException {
+ updateCallingPackage();
mSessionCb.playFromMediaId(mediaId, extras);
}
@Override
public void playFromSearch(String query, Bundle extras) throws RemoteException {
+ updateCallingPackage();
mSessionCb.playFromSearch(query, extras);
}
@Override
public void playFromUri(Uri uri, Bundle extras) throws RemoteException {
+ updateCallingPackage();
mSessionCb.playFromUri(uri, extras);
}
@Override
public void skipToQueueItem(long id) {
+ updateCallingPackage();
mSessionCb.skipToTrack(id);
}
-
@Override
public void pause() throws RemoteException {
+ updateCallingPackage();
mSessionCb.pause();
}
@Override
public void stop() throws RemoteException {
+ updateCallingPackage();
mSessionCb.stop();
}
@Override
public void next() throws RemoteException {
+ updateCallingPackage();
mSessionCb.next();
}
@Override
public void previous() throws RemoteException {
+ updateCallingPackage();
mSessionCb.previous();
}
@Override
public void fastForward() throws RemoteException {
+ updateCallingPackage();
mSessionCb.fastForward();
}
@Override
public void rewind() throws RemoteException {
+ updateCallingPackage();
mSessionCb.rewind();
}
@Override
public void seekTo(long pos) throws RemoteException {
+ updateCallingPackage();
mSessionCb.seekTo(pos);
}
@Override
public void rate(Rating rating) throws RemoteException {
+ updateCallingPackage();
mSessionCb.rate(rating);
}
@Override
public void sendCustomAction(String action, Bundle args)
throws RemoteException {
+ updateCallingPackage();
mSessionCb.sendCustomAction(action, args);
}
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 745f476..e3c540a 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -946,7 +946,8 @@
// won't release it later
session.sendMediaButton(keyEvent,
needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
- mKeyEventReceiver);
+ mKeyEventReceiver, getContext().getApplicationInfo().uid,
+ getContext().getPackageName());
} else {
// Launch the last PendingIntent we had with priority
UserRecord user = mUserRecords.get(mCurrentUserId);
diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java
index 90e26d8..2807ec8 100644
--- a/services/core/java/com/android/server/net/IpConfigStore.java
+++ b/services/core/java/com/android/server/net/IpConfigStore.java
@@ -40,7 +40,7 @@
public class IpConfigStore {
private static final String TAG = "IpConfigStore";
- private static final boolean DBG = true;
+ private static final boolean DBG = false;
protected final DelayedDiskWrite mWriter;
@@ -59,8 +59,12 @@
protected static final int IPCONFIG_FILE_VERSION = 2;
+ public IpConfigStore(DelayedDiskWrite writer) {
+ mWriter = writer;
+ }
+
public IpConfigStore() {
- mWriter = new DelayedDiskWrite();
+ this(new DelayedDiskWrite());
}
private boolean writeConfig(DataOutputStream out, int configKey,
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index bc5b561..3acd2ca 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -28,6 +28,7 @@
import static android.content.Intent.ACTION_USER_ADDED;
import static android.content.Intent.ACTION_USER_REMOVED;
import static android.content.Intent.EXTRA_UID;
+
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_WIMAX;
@@ -41,6 +42,7 @@
import static android.net.NetworkPolicy.WARNING_DISABLED;
import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_POWERSAVE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
@@ -67,6 +69,7 @@
import static android.net.wifi.WifiManager.EXTRA_WIFI_CONFIGURATION;
import static android.net.wifi.WifiManager.EXTRA_WIFI_INFO;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
+
import static com.android.internal.util.ArrayUtils.appendInt;
import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.internal.util.XmlUtils.readBooleanAttribute;
@@ -165,6 +168,7 @@
import com.android.server.DeviceIdleController;
import com.android.server.EventLogTags;
import com.android.server.LocalServices;
+import com.android.server.SystemConfig;
import com.google.android.collect.Lists;
import org.xmlpull.v1.XmlPullParser;
@@ -221,6 +225,7 @@
private static final String TAG_APP_POLICY = "app-policy";
private static final String TAG_WHITELIST = "whitelist";
private static final String TAG_RESTRICT_BACKGROUND = "restrict-background";
+ private static final String TAG_REVOKED_RESTRICT_BACKGROUND = "revoked-restrict-background";
private static final String ATTR_VERSION = "version";
private static final String ATTR_RESTRICT_BACKGROUND = "restrictBackground";
@@ -240,8 +245,6 @@
private static final String ATTR_APP_ID = "appId";
private static final String ATTR_POLICY = "policy";
- private static final String TAG_ALLOW_BACKGROUND = TAG + ":allowBackground";
-
private static final String ACTION_ALLOW_BACKGROUND =
"com.android.server.net.action.ALLOW_BACKGROUND";
private static final String ACTION_SNOOZE_WARNING =
@@ -293,6 +296,7 @@
final SparseIntArray mUidFirewallStandbyRules = new SparseIntArray();
final SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
+ final SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
/** Set of states for the child firewall chains. True if the chain is active. */
final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
@@ -318,6 +322,19 @@
*/
private final SparseBooleanArray mRestrictBackgroundWhitelistUids = new SparseBooleanArray();
+ /**
+ * UIDs that have been initially white-listed by system to avoid restricted background.
+ */
+ private final SparseBooleanArray mDefaultRestrictBackgroundWhitelistUids =
+ new SparseBooleanArray();
+
+ /**
+ * UIDs that have been initially white-listed by system to avoid restricted background,
+ * but later revoked by user.
+ */
+ private final SparseBooleanArray mRestrictBackgroundWhitelistRevokedUids =
+ new SparseBooleanArray();
+
/** Set of ifaces that are metered. */
private ArraySet<String> mMeteredIfaces = new ArraySet<>();
/** Set of over-limit templates that have been notified. */
@@ -414,6 +431,53 @@
}
}
+ /**
+ * Whitelists pre-defined apps for restrict background, but only if the user didn't already
+ * revoke the whitelist.
+ *
+ * @return whether any uid has been added to {@link #mRestrictBackgroundWhitelistUids}.
+ */
+ boolean addDefaultRestrictBackgroundWhitelistUids() {
+ final SystemConfig sysConfig = SystemConfig.getInstance();
+ final PackageManager pm = mContext.getPackageManager();
+ final List<UserInfo> users = mUserManager.getUsers();
+ final int numberUsers = users.size();
+
+ final ArraySet<String> allowDataUsage = sysConfig.getAllowInDataUsageSave();
+ boolean changed = false;
+ for (int i = 0; i < allowDataUsage.size(); i++) {
+ final String pkg = allowDataUsage.valueAt(i);
+ if (LOGD)
+ Slog.d(TAG, "checking restricted background whitelisting for package " + pkg);
+ final ApplicationInfo app;
+ try {
+ app = pm.getApplicationInfo(pkg, PackageManager.MATCH_SYSTEM_ONLY);
+ } catch (PackageManager.NameNotFoundException e) {
+ // Should not happen
+ Slog.wtf(TAG, "No ApplicationInfo for package " + pkg);
+ continue;
+ }
+ if (!app.isPrivilegedApp()) {
+ Slog.w(TAG, "getAllowInDataUsageSave() returned non-privileged app: " + pkg);
+ continue;
+ }
+ for (int j = 0; j < numberUsers; j++) {
+ final UserInfo user = users.get(i);
+ final int uid = UserHandle.getUid(user.id, app.uid);
+ mDefaultRestrictBackgroundWhitelistUids.append(uid, true);
+ if (LOGD) Slog.d(TAG, "revoked whistelist status for uid " + uid + ": "
+ + mRestrictBackgroundWhitelistRevokedUids.get(uid));
+ if (!mRestrictBackgroundWhitelistRevokedUids.get(uid)) {
+ Slog.i(TAG, "adding default package " + pkg + " (uid " + uid + " for user "
+ + user.id + ") to restrict background whitelist");
+ mRestrictBackgroundWhitelistUids.append(uid, true);
+ changed = true;
+ }
+ }
+ }
+ return changed;
+ }
+
void updatePowerSaveTempWhitelistLocked() {
try {
// Clear the states of the current whitelist
@@ -461,9 +525,11 @@
new PowerManagerInternal.LowPowerModeListener() {
@Override
public void onLowPowerModeChanged(boolean enabled) {
+ if (LOGD) Slog.d(TAG, "onLowPowerModeChanged(" + enabled + ")");
synchronized (mRulesLock) {
if (mRestrictPower != enabled) {
mRestrictPower = enabled;
+ updateRulesForRestrictPowerLocked();
updateRulesForGlobalChangeLocked(true);
}
}
@@ -475,6 +541,10 @@
// read policy from disk
readPolicyLocked();
+ if (addDefaultRestrictBackgroundWhitelistUids()) {
+ writePolicyLocked();
+ }
+
updateRulesForGlobalChangeLocked(false);
updateNotificationsLocked();
}
@@ -844,11 +914,6 @@
}
}
- // ongoing notification when restricting background data
- if (mRestrictBackground) {
- enqueueRestrictedNotification(TAG_ALLOW_BACKGROUND);
- }
-
// cancel stale notifications that we didn't renew above
for (int i = beforeNotifs.size()-1; i >= 0; i--) {
final String tag = beforeNotifs.valueAt(i);
@@ -1026,42 +1091,6 @@
}
}
- /**
- * Show ongoing notification to reflect that {@link #mRestrictBackground}
- * has been enabled.
- */
- private void enqueueRestrictedNotification(String tag) {
- final Resources res = mContext.getResources();
- final Notification.Builder builder = new Notification.Builder(mContext);
-
- final CharSequence title = res.getText(R.string.data_usage_restricted_title);
- final CharSequence body = res.getString(R.string.data_usage_restricted_body);
-
- builder.setOnlyAlertOnce(true);
- builder.setOngoing(true);
- builder.setSmallIcon(R.drawable.stat_notify_error);
- builder.setTicker(title);
- builder.setContentTitle(title);
- builder.setContentText(body);
- builder.setColor(mContext.getColor(
- com.android.internal.R.color.system_notification_accent_color));
-
- final Intent intent = buildAllowBackgroundDataIntent();
- builder.setContentIntent(
- PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
-
- // TODO: move to NotificationManager once we can mock it
- try {
- final String packageName = mContext.getPackageName();
- final int[] idReceived = new int[1];
- mNotifManager.enqueueNotificationWithTag(packageName, packageName, tag,
- 0x0, builder.getNotification(), idReceived, UserHandle.USER_ALL);
- mActiveNotifs.add(tag);
- } catch (RemoteException e) {
- // ignored; service lives in system_server
- }
- }
-
private void cancelNotification(String tag) {
// TODO: move to NotificationManager once we can mock it
try {
@@ -1151,13 +1180,6 @@
return;
}
- // If we are in restrict power mode, we want to treat all interfaces
- // as metered, to restrict access to the network by uid. However, we
- // will not have a bandwidth limit. Also only do this if restrict
- // background data use is *not* enabled, since that takes precedence
- // use over those networks can have a cost associated with it).
- final boolean powerSave = mRestrictPower && !mRestrictBackground;
-
// First, generate identities of all connected networks so we can
// quickly compare them against all defined policies below.
final ArrayList<Pair<String, NetworkIdentity>> connIdents = new ArrayList<>(states.length);
@@ -1169,9 +1191,6 @@
final String baseIface = state.linkProperties.getInterfaceName();
if (baseIface != null) {
connIdents.add(Pair.create(baseIface, ident));
- if (powerSave) {
- connIfaces.add(baseIface);
- }
}
// Stacked interfaces are considered to have same identity as
@@ -1181,9 +1200,6 @@
final String stackedIface = stackedLink.getInterfaceName();
if (stackedIface != null) {
connIdents.add(Pair.create(stackedIface, ident));
- if (powerSave) {
- connIfaces.add(stackedIface);
- }
}
}
}
@@ -1230,8 +1246,7 @@
}
if (LOGD) {
- Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces "
- + Arrays.toString(ifaces));
+ Slog.d(TAG, "applying policy " + policy + " to ifaces " + Arrays.toString(ifaces));
}
final boolean hasWarning = policy.warningBytes != LIMIT_DISABLED;
@@ -1262,9 +1277,6 @@
removeInterfaceQuota(iface);
setInterfaceQuota(iface, quotaBytes);
newMeteredIfaces.add(iface);
- if (powerSave) {
- connIfaces.remove(iface);
- }
}
}
@@ -1464,6 +1476,9 @@
} else if (TAG_RESTRICT_BACKGROUND.equals(tag) && insideWhitelist) {
final int uid = readIntAttribute(in, ATTR_UID);
mRestrictBackgroundWhitelistUids.put(uid, true);
+ } else if (TAG_REVOKED_RESTRICT_BACKGROUND.equals(tag) && insideWhitelist) {
+ final int uid = readIntAttribute(in, ATTR_UID);
+ mRestrictBackgroundWhitelistRevokedUids.put(uid, true);
}
} else if (type == END_TAG) {
if (TAG_WHITELIST.equals(tag)) {
@@ -1562,7 +1577,7 @@
out.startTag(null, TAG_WHITELIST);
// restrict background whitelist
- final int size = mRestrictBackgroundWhitelistUids.size();
+ int size = mRestrictBackgroundWhitelistUids.size();
for (int i = 0; i < size; i++) {
final int uid = mRestrictBackgroundWhitelistUids.keyAt(i);
out.startTag(null, TAG_RESTRICT_BACKGROUND);
@@ -1570,6 +1585,15 @@
out.endTag(null, TAG_RESTRICT_BACKGROUND);
}
+ // revoked restrict background whitelist
+ size = mRestrictBackgroundWhitelistRevokedUids.size();
+ for (int i = 0; i < size; i++) {
+ final int uid = mRestrictBackgroundWhitelistRevokedUids.keyAt(i);
+ out.startTag(null, TAG_REVOKED_RESTRICT_BACKGROUND);
+ writeIntAttribute(out, ATTR_UID, uid);
+ out.endTag(null, TAG_REVOKED_RESTRICT_BACKGROUND);
+ }
+
out.endTag(null, TAG_WHITELIST);
out.endDocument();
@@ -1595,7 +1619,7 @@
try {
final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
if (oldPolicy != policy) {
- setUidPolicyUncheckedLocked(uid, policy, true);
+ setUidPolicyUncheckedLocked(uid, oldPolicy, policy, true);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -1615,7 +1639,7 @@
final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
policy |= oldPolicy;
if (oldPolicy != policy) {
- setUidPolicyUncheckedLocked(uid, policy, true);
+ setUidPolicyUncheckedLocked(uid, oldPolicy, policy, true);
}
}
}
@@ -1632,11 +1656,22 @@
final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
policy = oldPolicy & ~policy;
if (oldPolicy != policy) {
- setUidPolicyUncheckedLocked(uid, policy, true);
+ setUidPolicyUncheckedLocked(uid, oldPolicy, policy, true);
}
}
}
+ private void setUidPolicyUncheckedLocked(int uid, int oldPolicy, int policy, boolean persist) {
+ setUidPolicyUncheckedLocked(uid, policy, persist);
+
+ // Checks if app was added or removed to the blacklist.
+ if ((oldPolicy == POLICY_NONE && policy == POLICY_REJECT_METERED_BACKGROUND)
+ || (oldPolicy == POLICY_REJECT_METERED_BACKGROUND && policy == POLICY_NONE)) {
+ mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED, uid, 0)
+ .sendToTarget();
+ }
+ }
+
private void setUidPolicyUncheckedLocked(int uid, int policy, boolean persist) {
mUidPolicy.put(uid, policy);
@@ -1742,13 +1777,18 @@
public void setNetworkPolicies(NetworkPolicy[] policies) {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
- maybeRefreshTrustedTime();
- synchronized (mRulesLock) {
- normalizePoliciesLocked(policies);
- updateNetworkEnabledLocked();
- updateNetworkRulesLocked();
- updateNotificationsLocked();
- writePolicyLocked();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ maybeRefreshTrustedTime();
+ synchronized (mRulesLock) {
+ normalizePoliciesLocked(policies);
+ updateNetworkEnabledLocked();
+ updateNetworkRulesLocked();
+ updateNotificationsLocked();
+ writePolicyLocked();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
@@ -1851,13 +1891,18 @@
@Override
public void setRestrictBackground(boolean restrictBackground) {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ maybeRefreshTrustedTime();
+ synchronized (mRulesLock) {
+ mRestrictBackground = restrictBackground;
+ updateRulesForGlobalChangeLocked(true);
+ updateNotificationsLocked();
+ writePolicyLocked();
+ }
- maybeRefreshTrustedTime();
- synchronized (mRulesLock) {
- mRestrictBackground = restrictBackground;
- updateRulesForGlobalChangeLocked(true);
- updateNotificationsLocked();
- writePolicyLocked();
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_CHANGED, restrictBackground ? 1 : 0, 0)
@@ -1877,6 +1922,12 @@
}
Slog.i(TAG, "adding uid " + uid + " to restrict background whitelist");
mRestrictBackgroundWhitelistUids.append(uid, true);
+ if (mDefaultRestrictBackgroundWhitelistUids.get(uid)
+ && mRestrictBackgroundWhitelistRevokedUids.get(uid)) {
+ if (LOGD) Slog.d(TAG, "Removing uid " + uid
+ + " from revoked restrict background whitelist");
+ mRestrictBackgroundWhitelistRevokedUids.delete(uid);
+ }
changed = mRestrictBackground && !oldStatus;
if (changed && hasInternetPermissions(uid)) {
setUidNetworkRules(uid, false);
@@ -1912,6 +1963,12 @@
Slog.i(TAG, "removing uid " + uid + " from restrict background whitelist");
final boolean changed = mRestrictBackground && oldStatus;
mRestrictBackgroundWhitelistUids.delete(uid);
+ if (mDefaultRestrictBackgroundWhitelistUids.get(uid)
+ && !mRestrictBackgroundWhitelistRevokedUids.get(uid)) {
+ if (LOGD) Slog.d(TAG, "Adding uid " + uid
+ + " to revoked restrict background whitelist");
+ mRestrictBackgroundWhitelistRevokedUids.append(uid, true);
+ }
if (updateNow) {
if (changed && hasInternetPermissions(uid)) {
setUidNetworkRules(uid, true);
@@ -1942,7 +1999,20 @@
public int getRestrictBackgroundByCaller() {
mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
final int uid = Binder.getCallingUid();
+
synchronized (mRulesLock) {
+ // Must clear identity because getUidPolicy() is restricted to system.
+ final long token = Binder.clearCallingIdentity();
+ final int policy;
+ try {
+ policy = getUidPolicy(uid);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ if (policy == POLICY_REJECT_METERED_BACKGROUND) {
+ // App is blacklisted.
+ return RESTRICT_BACKGROUND_STATUS_ENABLED;
+ }
if (!mRestrictBackground) {
return RESTRICT_BACKGROUND_STATUS_DISABLED;
}
@@ -2158,6 +2228,30 @@
fout.decreaseIndent();
}
+ size = mDefaultRestrictBackgroundWhitelistUids.size();
+ if (size > 0) {
+ fout.println("Default restrict background whitelist uids:");
+ fout.increaseIndent();
+ for (int i = 0; i < size; i++) {
+ fout.print("UID=");
+ fout.print(mDefaultRestrictBackgroundWhitelistUids.keyAt(i));
+ fout.println();
+ }
+ fout.decreaseIndent();
+ }
+
+ size = mRestrictBackgroundWhitelistRevokedUids.size();
+ if (size > 0) {
+ fout.println("Default restrict background whitelist uids revoked by users:");
+ fout.increaseIndent();
+ for (int i = 0; i < size; i++) {
+ fout.print("UID=");
+ fout.print(mRestrictBackgroundWhitelistRevokedUids.keyAt(i));
+ fout.println();
+ }
+ fout.decreaseIndent();
+ }
+
final SparseBooleanArray knownUids = new SparseBooleanArray();
collectKeys(mUidState, knownUids);
collectKeys(mUidRules, knownUids);
@@ -2217,9 +2311,14 @@
// state changed, push updated rules
mUidState.put(uid, uidState);
updateRulesForUidStateChangeLocked(uid, oldUidState, uidState);
- if (mDeviceIdleMode && isProcStateAllowedWhileIdle(oldUidState)
- != isProcStateAllowedWhileIdle(uidState)) {
- updateRuleForDeviceIdleLocked(uid);
+ if (isProcStateAllowedWhileIdleOrPowerSaveMode(oldUidState)
+ != isProcStateAllowedWhileIdleOrPowerSaveMode(uidState) ) {
+ if (mDeviceIdleMode) {
+ updateRuleForDeviceIdleLocked(uid);
+ }
+ if (mRestrictPower) {
+ updateRulesForRestrictPowerLocked(uid);
+ }
}
}
}
@@ -2235,6 +2334,9 @@
if (mDeviceIdleMode) {
updateRuleForDeviceIdleLocked(uid);
}
+ if (mRestrictPower) {
+ updateRulesForRestrictPowerLocked(uid);
+ }
}
}
}
@@ -2272,15 +2374,36 @@
}
}
- static boolean isProcStateAllowedWhileIdle(int procState) {
+ static boolean isProcStateAllowedWhileIdleOrPowerSaveMode(int procState) {
return procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
}
+ void updateRulesForRestrictPowerLocked() {
+ updateRulesForWhitelistedPowerSaveLocked(mRestrictPower, FIREWALL_CHAIN_POWERSAVE,
+ mUidFirewallPowerSaveRules);
+ }
+
+ void updateRulesForRestrictPowerLocked(int uid) {
+ updateRulesForWhitelistedPowerSaveLocked(uid, mRestrictPower, FIREWALL_CHAIN_POWERSAVE);
+ }
+
void updateRulesForDeviceIdleLocked() {
- if (mDeviceIdleMode) {
- // sync the whitelists before enable dozable chain. We don't care about the rules if
+ updateRulesForWhitelistedPowerSaveLocked(mDeviceIdleMode, FIREWALL_CHAIN_DOZABLE,
+ mUidFirewallDozableRules);
+ }
+
+ void updateRuleForDeviceIdleLocked(int uid) {
+ updateRulesForWhitelistedPowerSaveLocked(uid, mDeviceIdleMode, FIREWALL_CHAIN_DOZABLE);
+ }
+
+ // NOTE: since both fw_dozable and fw_powersave uses the same map (mPowerSaveTempWhitelistAppIds)
+ // for whitelisting, we can reuse their logic in this method.
+ private void updateRulesForWhitelistedPowerSaveLocked(boolean enabled, int chain,
+ SparseIntArray rules) {
+ if (enabled) {
+ // Sync the whitelists before enabling the chain. We don't care about the rules if
// we are disabling the chain.
- final SparseIntArray uidRules = mUidFirewallDozableRules;
+ final SparseIntArray uidRules = rules;
uidRules.clear();
final List<UserInfo> users = mUserManager.getUsers();
for (int ui = users.size() - 1; ui >= 0; ui--) {
@@ -2299,24 +2422,26 @@
}
}
for (int i = mUidState.size() - 1; i >= 0; i--) {
- if (isProcStateAllowedWhileIdle(mUidState.valueAt(i))) {
+ if (isProcStateAllowedWhileIdleOrPowerSaveMode(mUidState.valueAt(i))) {
uidRules.put(mUidState.keyAt(i), FIREWALL_RULE_ALLOW);
}
}
- setUidFirewallRules(FIREWALL_CHAIN_DOZABLE, uidRules);
+ setUidFirewallRules(chain, uidRules);
}
- enableFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, mDeviceIdleMode);
+ enableFirewallChainLocked(chain, enabled);
}
- void updateRuleForDeviceIdleLocked(int uid) {
- if (mDeviceIdleMode) {
+ // NOTE: since both fw_dozable and fw_powersave uses the same map (mPowerSaveTempWhitelistAppIds)
+ // for whitelisting, we can reuse their logic in this method.
+ private void updateRulesForWhitelistedPowerSaveLocked(int uid, boolean enabled, int chain) {
+ if (enabled) {
int appId = UserHandle.getAppId(uid);
if (mPowerSaveTempWhitelistAppIds.get(appId) || mPowerSaveWhitelistAppIds.get(appId)
- || isProcStateAllowedWhileIdle(mUidState.get(uid))) {
- setUidFirewallRule(FIREWALL_CHAIN_DOZABLE, uid, FIREWALL_RULE_ALLOW);
+ || isProcStateAllowedWhileIdleOrPowerSaveMode(mUidState.get(uid))) {
+ setUidFirewallRule(chain, uid, FIREWALL_RULE_ALLOW);
} else {
- setUidFirewallRule(FIREWALL_CHAIN_DOZABLE, uid, FIREWALL_RULE_DEFAULT);
+ setUidFirewallRule(chain, uid, FIREWALL_RULE_DEFAULT);
}
}
@@ -2372,10 +2497,14 @@
* {@link #mRestrictPower}, or {@link #mDeviceIdleMode} value.
*/
void updateRulesForGlobalChangeLocked(boolean restrictedNetworksChanged) {
+ long start;
+ if (LOGD) start = System.currentTimeMillis();
+
final PackageManager pm = mContext.getPackageManager();
updateRulesForDeviceIdleLocked();
updateRulesForAppIdleLocked();
+ updateRulesForRestrictPowerLocked();
// update rules for all installed applications
final List<UserInfo> users = mUserManager.getUsers();
@@ -2383,8 +2512,12 @@
PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_DISABLED_COMPONENTS
| PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE);
- for (UserInfo user : users) {
- for (ApplicationInfo app : apps) {
+ final int usersSize = users.size();
+ final int appsSize = apps.size();
+ for (int i = 0; i < usersSize; i++) {
+ final UserInfo user = users.get(i);
+ for (int j = 0; j < appsSize; j++) {
+ final ApplicationInfo app = apps.get(j);
final int uid = UserHandle.getUid(user.id, app.uid);
updateRulesForUidLocked(uid);
}
@@ -2399,16 +2532,23 @@
normalizePoliciesLocked();
updateNetworkRulesLocked();
}
+ if (LOGD) {
+ final long delta = System.currentTimeMillis() - start;
+ Slog.d(TAG, "updateRulesForGlobalChangeLocked(" + restrictedNetworksChanged + ") took "
+ + delta + "ms");
+ }
}
void updateRulesForTempWhitelistChangeLocked() {
final List<UserInfo> users = mUserManager.getUsers();
- for (UserInfo user : users) {
- for (int i = mPowerSaveTempWhitelistAppIds.size() - 1; i >= 0; i--) {
- int appId = mPowerSaveTempWhitelistAppIds.keyAt(i);
+ for (int i = 0; i < users.size(); i++) {
+ final UserInfo user = users.get(i);
+ for (int j = mPowerSaveTempWhitelistAppIds.size() - 1; j >= 0; j--) {
+ int appId = mPowerSaveTempWhitelistAppIds.keyAt(j);
int uid = UserHandle.getUid(user.id, appId);
updateRuleForAppIdleLocked(uid);
updateRuleForDeviceIdleLocked(uid);
+ updateRulesForRestrictPowerLocked(uid);
}
}
}
@@ -2501,6 +2641,12 @@
uidRules = RULE_REJECT_ALL;
}
+ // Check powersave state, which is whitelist
+ if (mFirewallChainStates.get(FIREWALL_CHAIN_POWERSAVE)
+ && mUidFirewallPowerSaveRules.get(uid, FIREWALL_RULE_DEFAULT) != FIREWALL_RULE_ALLOW) {
+ uidRules = RULE_REJECT_ALL;
+ }
+
// Check standby state, which is blacklist
if (mFirewallChainStates.get(FIREWALL_CHAIN_STANDBY)
&& mUidFirewallStandbyRules.get(uid, FIREWALL_RULE_DEFAULT) == FIREWALL_RULE_DENY) {
@@ -2728,6 +2874,8 @@
mUidFirewallDozableRules.put(uid, rule);
} else if (chain == FIREWALL_CHAIN_STANDBY) {
mUidFirewallStandbyRules.put(uid, rule);
+ } else if (chain == FIREWALL_CHAIN_POWERSAVE) {
+ mUidFirewallPowerSaveRules.put(uid, rule);
}
try {
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java b/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
index 5cd1025..a626b5b 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
@@ -16,6 +16,8 @@
package com.android.server.net;
+import static android.net.NetworkPolicyManager.POLICY_NONE;
+import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
import static android.net.wifi.WifiInfo.removeDoubleQuotes;
import static com.android.server.net.NetworkPolicyManagerService.newWifiPolicy;
import static com.android.server.net.NetworkPolicyManagerService.TAG;
@@ -83,6 +85,8 @@
pw.println("");
pw.println(" add restrict-background-whitelist UID");
pw.println(" Adds a UID to the whitelist for restrict background usage.");
+ pw.println(" add restrict-background-blacklist UID");
+ pw.println(" Adds a UID to the blacklist for restrict background usage.");
pw.println(" get metered-network ID");
pw.println(" Checks whether the given non-mobile network is metered or not.");
pw.println(" get restrict-background");
@@ -93,8 +97,12 @@
pw.println(" networks.");
pw.println(" list restrict-background-whitelist");
pw.println(" Lists UIDs that are whitelisted for restrict background usage.");
+ pw.println(" list restrict-background-blacklist");
+ pw.println(" Lists UIDs that are blacklisted for restrict background usage.");
pw.println(" remove restrict-background-whitelist UID");
pw.println(" Removes a UID from the whitelist for restrict background usage.");
+ pw.println(" remove restrict-background-blacklist UID");
+ pw.println(" Removes a UID from the blacklist for restrict background usage.");
pw.println(" set metered-network ID BOOLEAN");
pw.println(" Toggles whether the given non-mobile network is metered.");
pw.println(" set restrict-background BOOLEAN");
@@ -147,6 +155,8 @@
return listMeteredWifiNetworks();
case "restrict-background-whitelist":
return listRestrictBackgroundWhitelist();
+ case "restrict-background-blacklist":
+ return listRestrictBackgroundBlacklist();
}
pw.println("Error: unknown list type '" + type + "'");
return -1;
@@ -162,6 +172,8 @@
switch(type) {
case "restrict-background-whitelist":
return addRestrictBackgroundWhitelist();
+ case "restrict-background-blacklist":
+ return addRestrictBackgroundBlacklist();
}
pw.println("Error: unknown add type '" + type + "'");
return -1;
@@ -177,6 +189,8 @@
switch(type) {
case "restrict-background-whitelist":
return removeRestrictBackgroundWhitelist();
+ case "restrict-background-blacklist":
+ return removeRestrictBackgroundBlacklist();
}
pw.println("Error: unknown remove type '" + type + "'");
return -1;
@@ -199,6 +213,24 @@
return 0;
}
+ private int listRestrictBackgroundBlacklist() throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+
+ final int[] uids = mInterface.getUidsWithPolicy(POLICY_REJECT_METERED_BACKGROUND);
+ pw.print("Restrict background blacklisted UIDs: ");
+ if (uids.length == 0) {
+ pw.println("none");
+ } else {
+ for (int i = 0; i < uids.length; i++) {
+ int uid = uids[i];
+ pw.print(uid);
+ pw.print(' ');
+ }
+ }
+ pw.println();
+ return 0;
+ }
+
private int getRestrictBackground() throws RemoteException {
final PrintWriter pw = getOutPrintWriter();
pw.print("Restrict background status: ");
@@ -211,12 +243,7 @@
if (enabled < 0) {
return enabled;
}
- final long token = Binder.clearCallingIdentity();
- try {
- mInterface.setRestrictBackground(enabled > 0);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
+ mInterface.setRestrictBackground(enabled > 0);
return 0;
}
@@ -225,12 +252,7 @@
if (uid < 0) {
return uid;
}
- final long token = Binder.clearCallingIdentity();
- try {
- mInterface.addRestrictBackgroundWhitelistedUid(uid);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
+ mInterface.addRestrictBackgroundWhitelistedUid(uid);
return 0;
}
@@ -239,12 +261,25 @@
if (uid < 0) {
return uid;
}
- final long token = Binder.clearCallingIdentity();
- try {
- mInterface.removeRestrictBackgroundWhitelistedUid(uid);
- } finally {
- Binder.restoreCallingIdentity(token);
+ mInterface.removeRestrictBackgroundWhitelistedUid(uid);
+ return 0;
+ }
+
+ private int addRestrictBackgroundBlacklist() throws RemoteException {
+ final int uid = getUidFromNextArg();
+ if (uid < 0) {
+ return uid;
}
+ mInterface.setUidPolicy(uid, POLICY_REJECT_METERED_BACKGROUND);
+ return 0;
+ }
+
+ private int removeRestrictBackgroundBlacklist() throws RemoteException {
+ final int uid = getUidFromNextArg();
+ if (uid < 0) {
+ return uid;
+ }
+ mInterface.setUidPolicy(uid, POLICY_NONE);
return 0;
}
diff --git a/services/core/java/com/android/server/notification/TopicImportanceExtractor.java b/services/core/java/com/android/server/notification/ImportanceExtractor.java
similarity index 84%
rename from services/core/java/com/android/server/notification/TopicImportanceExtractor.java
rename to services/core/java/com/android/server/notification/ImportanceExtractor.java
index c6b3e0f..885b9b7 100644
--- a/services/core/java/com/android/server/notification/TopicImportanceExtractor.java
+++ b/services/core/java/com/android/server/notification/ImportanceExtractor.java
@@ -21,7 +21,7 @@
/**
* Determines the importance of the given notification.
*/
-public class TopicImportanceExtractor implements NotificationSignalExtractor {
+public class ImportanceExtractor implements NotificationSignalExtractor {
private static final String TAG = "ImportantTopicExtractor";
private static final boolean DBG = false;
@@ -42,9 +42,8 @@
return null;
}
- final int topicImportance = mConfig.getImportance(record.sbn.getPackageName(),
- record.sbn.getUid(), record.sbn.getNotification().getTopic());
- record.setTopicImportance(topicImportance);
+ record.setUserImportance(
+ mConfig.getImportance(record.sbn.getPackageName(), record.sbn.getUid()));
return null;
}
diff --git a/services/core/java/com/android/server/notification/NotificationComparator.java b/services/core/java/com/android/server/notification/NotificationComparator.java
index 5e4703d..7dff2c1 100644
--- a/services/core/java/com/android/server/notification/NotificationComparator.java
+++ b/services/core/java/com/android/server/notification/NotificationComparator.java
@@ -28,10 +28,11 @@
final int leftImportance = left.getImportance();
final int rightImportance = right.getImportance();
if (leftImportance != rightImportance) {
- // by priority, high to low
+ // by importance, high to low
return -1 * Integer.compare(leftImportance, rightImportance);
}
+ // Whether or not the notification can bypass DND.
final int leftPackagePriority = left.getPackagePriority();
final int rightPackagePriority = right.getPackagePriority();
if (leftPackagePriority != rightPackagePriority) {
@@ -39,6 +40,13 @@
return -1 * Integer.compare(leftPackagePriority, rightPackagePriority);
}
+ final int leftPriority = left.sbn.getNotification().priority;
+ final int rightPriority = right.sbn.getNotification().priority;
+ if (leftPriority != rightPriority) {
+ // by priority, high to low
+ return -1 * Integer.compare(leftPriority, rightPriority);
+ }
+
final float leftPeople = left.getContactAffinity();
final float rightPeople = right.getContactAffinity();
if (leftPeople != rightPeople) {
diff --git a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
index b57cc75..bcdeb66 100644
--- a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
+++ b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
@@ -23,7 +23,7 @@
import android.util.Slog;
/**
- * This {@link com.android.server.notification.NotificationSignalExtractor} noticies noisy
+ * This {@link com.android.server.notification.NotificationSignalExtractor} notices noisy
* notifications and marks them to get a temporary ranking bump.
*/
public class NotificationIntrusivenessExtractor implements NotificationSignalExtractor {
@@ -44,9 +44,15 @@
return null;
}
- final Notification notification = record.getNotification();
- if (record.getImportance() > NotificationListenerService.Ranking.IMPORTANCE_DEFAULT) {
- record.setRecentlyIntrusive(true);
+ if (record.getImportance() >= NotificationListenerService.Ranking.IMPORTANCE_DEFAULT) {
+ final Notification notification = record.getNotification();
+ if ((notification.defaults & Notification.DEFAULT_VIBRATE) != 0 ||
+ notification.vibrate != null ||
+ (notification.defaults & Notification.DEFAULT_SOUND) != 0 ||
+ notification.sound != null ||
+ notification.fullScreenIntent != null) {
+ record.setRecentlyIntrusive(true);
+ }
}
return new RankingReconsideration(record.getKey(), HANG_TIME_MS) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index ede1a2f..3855579 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -30,14 +30,13 @@
import static android.service.notification.NotificationAssistantService.REASON_PACKAGE_CHANGED;
import static android.service.notification.NotificationAssistantService.REASON_PACKAGE_SUSPENDED;
import static android.service.notification.NotificationAssistantService.REASON_PROFILE_TURNED_OFF;
-import static android.service.notification.NotificationAssistantService.REASON_TOPIC_BANNED;
import static android.service.notification.NotificationAssistantService.REASON_USER_STOPPED;
import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_EFFECTS;
import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_OFF;
import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_ON;
import static android.service.notification.NotificationListenerService.TRIM_FULL;
import static android.service.notification.NotificationListenerService.TRIM_LIGHT;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
+import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_DEFAULT;
import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_NONE;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.END_TAG;
@@ -754,7 +753,7 @@
for (String pkgName : pkgList) {
if (cancelNotifications) {
cancelAllNotificationsInt(MY_UID, MY_PID, pkgName, 0, 0, !queryRestart,
- changeUserId, reason, null, null);
+ changeUserId, reason, null);
}
}
}
@@ -787,14 +786,14 @@
int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
if (userHandle >= 0) {
cancelAllNotificationsInt(MY_UID, MY_PID, null, 0, 0, true, userHandle,
- REASON_USER_STOPPED, null, null);
+ REASON_USER_STOPPED, null);
}
} else if (action.equals(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED)) {
boolean inQuietMode = intent.getBooleanExtra(Intent.EXTRA_QUIET_MODE, false);
int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
if (inQuietMode && userHandle >= 0) {
cancelAllNotificationsInt(MY_UID, MY_PID, null, 0, 0, true, userHandle,
- REASON_PROFILE_TURNED_OFF, null, null);
+ REASON_PROFILE_TURNED_OFF, null);
}
} else if (action.equals(Intent.ACTION_USER_PRESENT)) {
// turn off LED when user passes through lock screen
@@ -1086,7 +1085,7 @@
// Now, cancel any outstanding notifications that are part of a just-disabled app
if (ENABLE_BLOCKED_NOTIFICATIONS && !enabled) {
cancelAllNotificationsInt(MY_UID, MY_PID, pkg, 0, 0, true, UserHandle.getUserId(uid),
- REASON_PACKAGE_BANNED, null, null);
+ REASON_PACKAGE_BANNED, null);
}
}
@@ -1250,7 +1249,7 @@
// running foreground services.
cancelAllNotificationsInt(Binder.getCallingUid(), Binder.getCallingPid(),
pkg, 0, Notification.FLAG_FOREGROUND_SERVICE, true, userId,
- REASON_APP_CANCEL_ALL, null, null);
+ REASON_APP_CANCEL_ALL, null);
}
@Override
@@ -1279,79 +1278,50 @@
}
@Override
- public boolean hasBannedTopics(String pkg, int uid) {
+ public void setPriority(String pkg, int uid, int priority) {
checkCallerIsSystem();
- return mRankingHelper.hasBannedTopics(pkg, uid);
- }
-
- @Override
- public ParceledListSlice<Notification.Topic> getTopics(String pkg, int uid) {
- checkCallerIsSystem();
- return new ParceledListSlice<Notification.Topic>(mRankingHelper.getTopics(pkg, uid));
- }
-
- @Override
- public void setPriority(String pkg, int uid, Notification.Topic topic, int priority) {
- checkCallerIsSystem();
- mRankingHelper.setPriority(pkg, uid, topic, priority);
+ mRankingHelper.setPriority(pkg, uid, priority);
savePolicyFile();
}
@Override
- public int getPriority(String pkg, int uid, Notification.Topic topic) {
+ public int getPriority(String pkg, int uid) {
checkCallerIsSystem();
- return mRankingHelper.getPriority(pkg, uid, topic);
+ return mRankingHelper.getPriority(pkg, uid);
}
@Override
- public void setVisibilityOverride(String pkg, int uid, Notification.Topic topic,
- int visibility) {
+ public void setVisibilityOverride(String pkg, int uid, int visibility) {
checkCallerIsSystem();
- mRankingHelper.setVisibilityOverride(pkg, uid, topic, visibility);
+ mRankingHelper.setVisibilityOverride(pkg, uid, visibility);
savePolicyFile();
}
@Override
- public int getVisibilityOverride(String pkg, int uid, Notification.Topic topic) {
+ public int getVisibilityOverride(String pkg, int uid) {
checkCallerIsSystem();
- return mRankingHelper.getVisibilityOverride(pkg, uid, topic);
+ return mRankingHelper.getVisibilityOverride(pkg, uid);
}
@Override
- public void setImportance(String pkg, int uid, Notification.Topic topic,
- int importance) {
+ public void setImportance(String pkg, int uid, int importance) {
enforceSystemOrSystemUI("Caller not system or systemui");
- if (topic == null) {
- // App wide, potentially store block in app ops.
- setNotificationsEnabledForPackageImpl(pkg, uid,
- importance != NotificationListenerService.Ranking.IMPORTANCE_NONE);
- } else {
- if (NotificationListenerService.Ranking.IMPORTANCE_NONE == importance) {
- cancelAllNotificationsInt(MY_UID, MY_PID, pkg, 0, 0, true,
- UserHandle.getUserId(uid),
- REASON_TOPIC_BANNED, topic, null);
- }
- }
- mRankingHelper.setImportance(pkg, uid, topic, importance);
+ setNotificationsEnabledForPackageImpl(pkg, uid,
+ importance != NotificationListenerService.Ranking.IMPORTANCE_NONE);
+ mRankingHelper.setImportance(pkg, uid, importance);
savePolicyFile();
}
@Override
- public int getTopicImportance(String pkg, String topicId) {
+ public int getPackageImportance(String pkg) {
checkCallerIsSystemOrSameApp(pkg);
- return mRankingHelper.getImportance(pkg, Binder.getCallingUid(), topicId);
+ return mRankingHelper.getImportance(pkg, Binder.getCallingUid());
}
@Override
- public int getImportance(String pkg, int uid, Notification.Topic topic) {
- checkCallerIsSystem();
- return mRankingHelper.getImportance(pkg, uid, topic);
- }
-
- @Override
- public boolean doesUserUseTopics(String pkg, int uid) {
+ public int getImportance(String pkg, int uid) {
enforceSystemOrSystemUI("Caller not system or systemui");
- return mRankingHelper.doesUserUseTopics(pkg, uid);
+ return mRankingHelper.getImportance(pkg, uid);
}
/**
@@ -1728,9 +1698,9 @@
}
@Override
- public List<AutomaticZenRule> getAutomaticZenRules() throws RemoteException {
+ public List<ZenModeConfig.ZenRule> getZenRules() throws RemoteException {
enforcePolicyAccess(Binder.getCallingUid(), "getAutomaticZenRules");
- return mZenModeHelper.getAutomaticZenRules();
+ return mZenModeHelper.getZenRules();
}
@Override
@@ -1741,7 +1711,7 @@
}
@Override
- public AutomaticZenRule addAutomaticZenRule(AutomaticZenRule automaticZenRule)
+ public String addAutomaticZenRule(AutomaticZenRule automaticZenRule)
throws RemoteException {
Preconditions.checkNotNull(automaticZenRule, "automaticZenRule is null");
Preconditions.checkNotNull(automaticZenRule.getName(), "Name is null");
@@ -1754,7 +1724,7 @@
}
@Override
- public boolean updateAutomaticZenRule(AutomaticZenRule automaticZenRule)
+ public boolean updateAutomaticZenRule(String id, AutomaticZenRule automaticZenRule)
throws RemoteException {
Preconditions.checkNotNull(automaticZenRule, "automaticZenRule is null");
Preconditions.checkNotNull(automaticZenRule.getName(), "Name is null");
@@ -1762,7 +1732,7 @@
Preconditions.checkNotNull(automaticZenRule.getConditionId(), "ConditionId is null");
enforcePolicyAccess(Binder.getCallingUid(), "updateAutomaticZenRule");
- return mZenModeHelper.updateAutomaticZenRule(automaticZenRule,
+ return mZenModeHelper.updateAutomaticZenRule(id, automaticZenRule,
"updateAutomaticZenRule");
}
@@ -2337,7 +2307,7 @@
synchronized (mNotificationList) {
final StatusBarNotification n = r.sbn;
- Slog.d(TAG, "EnqueueNotificationRunnable.run for: " + n.getKey());
+ if (DBG) Slog.d(TAG, "EnqueueNotificationRunnable.run for: " + n.getKey());
NotificationRecord old = mNotificationsByKey.get(n.getKey());
if (old != null) {
// Retain ranking information from previous record
@@ -2358,7 +2328,7 @@
handleGroupedNotificationLocked(r, old, callingUid, callingPid);
boolean ignoreNotification =
removeUnusedGroupedNotificationLocked(r, old, callingUid, callingPid);
- Slog.d(TAG, "ignoreNotification is " + ignoreNotification);
+ if (DBG) Slog.d(TAG, "ignoreNotification is " + ignoreNotification);
// This conditional is a dirty hack to limit the logging done on
// behalf of the download manager without affecting other apps.
@@ -2381,11 +2351,9 @@
mRankingHelper.extractSignals(r);
- // why is this here?
- savePolicyFile();
final boolean isPackageSuspended = isPackageSuspendedForUser(pkg, callingUid);
- // blocked apps/topics
+ // blocked apps
if (r.getImportance() == NotificationListenerService.Ranking.IMPORTANCE_NONE
|| !noteNotificationOp(pkg, callingUid) || isPackageSuspended) {
if (!isSystemNotification) {
@@ -2556,7 +2524,7 @@
final Notification notification = record.sbn.getNotification();
// Should this notification make noise, vibe, or use the LED?
- final boolean aboveThreshold = record.getImportance() >= IMPORTANCE_HIGH;
+ final boolean aboveThreshold = record.getImportance() >= IMPORTANCE_DEFAULT;
final boolean canInterrupt = aboveThreshold && !record.isIntercepted();
if (DBG || record.isIntercepted())
Slog.v(TAG,
@@ -3182,11 +3150,11 @@
}
/**
- * Cancels all notifications from a given package or topic that have all of the
+ * Cancels all notifications from a given package that have all of the
* {@code mustHaveFlags}.
*/
boolean cancelAllNotificationsInt(int callingUid, int callingPid, String pkg, int mustHaveFlags,
- int mustNotHaveFlags, boolean doit, int userId, int reason, Notification.Topic topic,
+ int mustNotHaveFlags, boolean doit, int userId, int reason,
ManagedServiceInfo listener) {
String listenerName = listener == null ? null : listener.component.toShortString();
EventLogTags.writeNotificationCancelAll(callingUid, callingPid,
@@ -3214,10 +3182,6 @@
if (pkg != null && !r.sbn.getPackageName().equals(pkg)) {
continue;
}
- if (topic != null
- && !topic.getId().equals(r.getNotification().getTopic().getId())) {
- continue;
- }
if (canceledNotifications == null) {
canceledNotifications = new ArrayList<>();
}
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 2ca5534..fd893fa 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -15,6 +15,7 @@
*/
package com.android.server.notification;
+import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_MIN;
import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_DEFAULT;
import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
@@ -33,9 +34,10 @@
import android.os.UserHandle;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
+import android.util.Log;
+import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.logging.MetricsLogger;
import com.android.server.EventLogTags;
import java.io.PrintWriter;
@@ -56,6 +58,8 @@
* {@hide}
*/
public final class NotificationRecord {
+ static final String TAG = "NotificationRecord";
+ static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
final StatusBarNotification sbn;
final int mOriginalFlags;
private final Context mContext;
@@ -92,12 +96,12 @@
private int mAuthoritativeRank;
private String mGlobalSortKey;
private int mPackageVisibility;
- private int mTopicImportance = IMPORTANCE_UNSPECIFIED;
+ private int mUserImportance = IMPORTANCE_UNSPECIFIED;
private int mImportance = IMPORTANCE_UNSPECIFIED;
private CharSequence mImportanceExplanation = null;
private int mSuppressedVisualEffects = 0;
- private String mTopicExplanation;
+ private String mUserExplanation;
private String mPeopleExplanation;
@VisibleForTesting
@@ -124,6 +128,8 @@
switch (n.priority) {
case Notification.PRIORITY_MIN:
+ importance = IMPORTANCE_MIN;
+ break;
case Notification.PRIORITY_LOW:
importance = IMPORTANCE_LOW;
break;
@@ -144,25 +150,15 @@
|| n.sound != null
|| n.vibrate != null;
stats.isNoisy = isNoisy;
- if (!isNoisy && importance > IMPORTANCE_DEFAULT) {
- importance = IMPORTANCE_DEFAULT;
+
+ if (!isNoisy && importance > IMPORTANCE_LOW) {
+ importance = IMPORTANCE_LOW;
}
- try {
- final ApplicationInfo applicationInfo =
- mContext.getPackageManager().getApplicationInfoAsUser(sbn.getPackageName(),
- 0, sbn.getUser().getIdentifier());
- if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.N) {
- if (isNoisy) {
- if (importance >= IMPORTANCE_HIGH) {
- importance = IMPORTANCE_MAX;
- } else {
- importance = IMPORTANCE_HIGH;
- }
- }
+ if (isNoisy) {
+ if (importance < IMPORTANCE_DEFAULT) {
+ importance = IMPORTANCE_DEFAULT;
}
- } catch (NameNotFoundException e) {
- // oh well.
}
if (n.fullScreenIntent != null) {
@@ -183,7 +179,7 @@
mRankingTimeMs = calculateRankingTimeMs(previous.getRankingTimeMs());
mCreationTimeMs = previous.mCreationTimeMs;
mVisibleSinceMs = previous.mVisibleSinceMs;
- mTopicImportance = previous.mTopicImportance;
+ mUserImportance = previous.mUserImportance;
mImportance = previous.mImportance;
mImportanceExplanation = previous.mImportanceExplanation;
// Don't copy mGlobalSortKey, recompute it.
@@ -228,12 +224,14 @@
final int N = notification.actions.length;
for (int i=0; i<N; i++) {
final Notification.Action action = notification.actions[i];
- pw.println(String.format("%s [%d] \"%s\" -> %s",
- prefix,
- i,
- action.title,
- action.actionIntent.toString()
- ));
+ if (action != null) {
+ pw.println(String.format("%s [%d] \"%s\" -> %s",
+ prefix,
+ i,
+ action.title,
+ action.actionIntent == null ? "null" : action.actionIntent.toString()
+ ));
+ }
}
pw.println(prefix + " }");
}
@@ -275,8 +273,8 @@
pw.println(prefix + " mRecentlyIntrusive=" + mRecentlyIntrusive);
pw.println(prefix + " mPackagePriority=" + mPackagePriority);
pw.println(prefix + " mPackageVisibility=" + mPackageVisibility);
- pw.println(prefix + " mTopicImportance="
- + NotificationListenerService.Ranking.importanceToString(mTopicImportance));
+ pw.println(prefix + " mUserImportance="
+ + NotificationListenerService.Ranking.importanceToString(mUserImportance));
pw.println(prefix + " mImportance="
+ NotificationListenerService.Ranking.importanceToString(mImportance));
pw.println(prefix + " mImportanceExplanation=" + mImportanceExplanation);
@@ -357,17 +355,17 @@
return mPackageVisibility;
}
- public void setTopicImportance(int importance) {
- mTopicImportance = importance;
- applyTopicImportance();
+ public void setUserImportance(int importance) {
+ mUserImportance = importance;
+ applyUserImportance();
}
- private String getTopicExplanation() {
- if (mTopicExplanation == null) {
- mTopicExplanation =
- mContext.getString(com.android.internal.R.string.importance_from_topic);
+ private String getUserExplanation() {
+ if (mUserExplanation == null) {
+ mUserExplanation =
+ mContext.getString(com.android.internal.R.string.importance_from_user);
}
- return mTopicExplanation;
+ return mUserExplanation;
}
private String getPeopleExplanation() {
@@ -378,15 +376,15 @@
return mPeopleExplanation;
}
- private void applyTopicImportance() {
- if (mTopicImportance != NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED) {
- mImportance = mTopicImportance;
- mImportanceExplanation = getTopicExplanation();
+ private void applyUserImportance() {
+ if (mUserImportance != NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED) {
+ mImportance = mUserImportance;
+ mImportanceExplanation = getUserExplanation();
}
}
- public int getTopicImportance() {
- return mTopicImportance;
+ public int getUserImportance() {
+ return mUserImportance;
}
public void setImportance(int importance, CharSequence explanation) {
@@ -394,7 +392,7 @@
mImportance = importance;
mImportanceExplanation = explanation;
}
- applyTopicImportance();
+ applyUserImportance();
}
public int getImportance() {
@@ -529,6 +527,6 @@
}
public boolean isImportanceFromUser() {
- return mImportance == mTopicImportance;
+ return mImportance == mUserImportance;
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java
index 0272850..538f951 100644
--- a/services/core/java/com/android/server/notification/NotificationUsageStats.java
+++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java
@@ -597,8 +597,9 @@
private static class ImportanceHistogram {
// TODO define these somewhere else
- private static final int NUM_IMPORTANCES = 5;
- private static final String[] IMPORTANCE_NAMES = {"none", "low", "default", "high", "max"};
+ private static final int NUM_IMPORTANCES = 6;
+ private static final String[] IMPORTANCE_NAMES =
+ {"none", "min", "low", "default", "high", "max"};
private final Context mContext;
private final String[] mCounterNames;
private final String mPrefix;
diff --git a/services/core/java/com/android/server/notification/TopicPriorityExtractor.java b/services/core/java/com/android/server/notification/PriorityExtractor.java
similarity index 84%
rename from services/core/java/com/android/server/notification/TopicPriorityExtractor.java
rename to services/core/java/com/android/server/notification/PriorityExtractor.java
index 1df5c2b..6c76476 100644
--- a/services/core/java/com/android/server/notification/TopicPriorityExtractor.java
+++ b/services/core/java/com/android/server/notification/PriorityExtractor.java
@@ -21,7 +21,7 @@
/**
* Determines if the given notification can bypass Do Not Disturb.
*/
-public class TopicPriorityExtractor implements NotificationSignalExtractor {
+public class PriorityExtractor implements NotificationSignalExtractor {
private static final String TAG = "ImportantTopicExtractor";
private static final boolean DBG = false;
@@ -42,9 +42,8 @@
return null;
}
- final int packagePriority = mConfig.getPriority(record.sbn.getPackageName(),
- record.sbn.getUid(), record.sbn.getNotification().getTopic());
- record.setPackagePriority(packagePriority);
+ record.setPackagePriority(
+ mConfig.getPriority(record.sbn.getPackageName(), record.sbn.getUid()));
return null;
}
diff --git a/services/core/java/com/android/server/notification/RankingConfig.java b/services/core/java/com/android/server/notification/RankingConfig.java
index 9773474..b5cc2ef 100644
--- a/services/core/java/com/android/server/notification/RankingConfig.java
+++ b/services/core/java/com/android/server/notification/RankingConfig.java
@@ -15,30 +15,17 @@
*/
package com.android.server.notification;
-import android.app.Notification;
-
-import java.util.List;
-
public interface RankingConfig {
- List<Notification.Topic> getTopics(String packageName, int uid);
+ int getPriority(String packageName, int uid);
- int getPriority(String packageName, int uid, Notification.Topic topic);
+ void setPriority(String packageName, int uid, int priority);
- void setPriority(String packageName, int uid, Notification.Topic topic, int priority);
+ int getVisibilityOverride(String packageName, int uid);
- int getVisibilityOverride(String packageName, int uid, Notification.Topic topic);
+ void setVisibilityOverride(String packageName, int uid, int visibility);
- void setVisibilityOverride(String packageName, int uid, Notification.Topic topic,
- int visibility);
+ void setImportance(String packageName, int uid, int importance);
- void setImportance(String packageName, int uid, Notification.Topic topic, int importance);
-
- int getImportance(String packageName, int uid, Notification.Topic topic);
-
- boolean doesUserUseTopics(String packageName, int uid);
-
- boolean hasBannedTopics(String packageName, int uid);
-
- int getImportance(String packageName, int uid, String topicId);
+ int getImportance(String packageName, int uid);
}
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 91eab10..fd96a78 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -20,14 +20,11 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.UserHandle;
-import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.Ranking;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Slog;
-import com.android.internal.R;
-
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -36,8 +33,6 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.List;
-import java.util.Map;
public class RankingHelper implements RankingConfig {
private static final String TAG = "RankingHelper";
@@ -47,7 +42,6 @@
private static final String TAG_RANKING = "ranking";
private static final String TAG_PACKAGE = "package";
private static final String ATT_VERSION = "version";
- private static final String TAG_TOPIC = "topic";
private static final String ATT_NAME = "name";
private static final String ATT_UID = "uid";
@@ -141,8 +135,6 @@
if (type == XmlPullParser.START_TAG) {
if (TAG_PACKAGE.equals(tag)) {
int uid = safeInt(parser, ATT_UID, Record.UNKNOWN_UID);
- int priority = safeInt(parser, ATT_PRIORITY, DEFAULT_PRIORITY);
- int vis = safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY);
String name = parser.getAttributeValue(null, ATT_NAME);
if (!TextUtils.isEmpty(name)) {
@@ -165,16 +157,8 @@
r = getOrCreateRecord(name, uid);
}
r.importance = safeInt(parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE);
- r.priority = priority;
- r.visibility = vis;
-
- // Migrate package level settings to the default topic.
- // Might be overwritten by parseTopics.
- Topic defaultTopic = r.topics.get(Notification.TOPIC_DEFAULT);
- defaultTopic.priority = priority;
- defaultTopic.visibility = vis;
-
- parseTopics(r, parser);
+ r.priority = safeInt(parser, ATT_PRIORITY, DEFAULT_PRIORITY);
+ r.visibility = safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY);
}
}
}
@@ -182,42 +166,6 @@
throw new IllegalStateException("Failed to reach END_DOCUMENT");
}
- public void parseTopics(Record r, XmlPullParser parser)
- throws XmlPullParserException, IOException {
- final int innerDepth = parser.getDepth();
- int type;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
- continue;
- }
-
- String tagName = parser.getName();
- if (TAG_TOPIC.equals(tagName)) {
- int priority = safeInt(parser, ATT_PRIORITY, DEFAULT_PRIORITY);
- int vis = safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY);
- int importance = safeInt(parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE);
- String id = parser.getAttributeValue(null, ATT_TOPIC_ID);
- CharSequence label = parser.getAttributeValue(null, ATT_TOPIC_LABEL);
-
- if (!TextUtils.isEmpty(id)) {
- Topic topic = new Topic(new Notification.Topic(id, label));
-
- if (priority != DEFAULT_PRIORITY) {
- topic.priority = priority;
- }
- if (vis != DEFAULT_VISIBILITY) {
- topic.visibility = vis;
- }
- if (importance != DEFAULT_IMPORTANCE) {
- topic.importance = importance;
- }
- r.topics.put(id, topic);
- }
- }
- }
- }
-
private static String recordKey(String pkg, int uid) {
return pkg + "|" + uid;
}
@@ -229,7 +177,6 @@
r = new Record();
r.pkg = pkg;
r.uid = uid;
- r.topics.put(Notification.TOPIC_DEFAULT, new Topic(createDefaultTopic()));
mRecords.put(key, r);
}
return r;
@@ -246,46 +193,31 @@
if (forBackup && UserHandle.getUserId(r.uid) != UserHandle.USER_SYSTEM) {
continue;
}
- out.startTag(null, TAG_PACKAGE);
- out.attribute(null, ATT_NAME, r.pkg);
- if (r.importance != DEFAULT_IMPORTANCE) {
- out.attribute(null, ATT_IMPORTANCE, Integer.toString(r.importance));
- }
- if (r.priority != DEFAULT_PRIORITY) {
- out.attribute(null, ATT_PRIORITY, Integer.toString(r.priority));
- }
- if (r.visibility != DEFAULT_VISIBILITY) {
- out.attribute(null, ATT_VISIBILITY, Integer.toString(r.visibility));
- }
+ final boolean hasNonDefaultSettings = r.importance != DEFAULT_IMPORTANCE
+ || r.priority != DEFAULT_PRIORITY || r.visibility != DEFAULT_VISIBILITY;
+ if (hasNonDefaultSettings) {
+ out.startTag(null, TAG_PACKAGE);
+ out.attribute(null, ATT_NAME, r.pkg);
+ if (r.importance != DEFAULT_IMPORTANCE) {
+ out.attribute(null, ATT_IMPORTANCE, Integer.toString(r.importance));
+ }
+ if (r.priority != DEFAULT_PRIORITY) {
+ out.attribute(null, ATT_PRIORITY, Integer.toString(r.priority));
+ }
+ if (r.visibility != DEFAULT_VISIBILITY) {
+ out.attribute(null, ATT_VISIBILITY, Integer.toString(r.visibility));
+ }
- if (!forBackup) {
- out.attribute(null, ATT_UID, Integer.toString(r.uid));
- }
+ if (!forBackup) {
+ out.attribute(null, ATT_UID, Integer.toString(r.uid));
+ }
- writeTopicsXml(out, r);
- out.endTag(null, TAG_PACKAGE);
+ out.endTag(null, TAG_PACKAGE);
+ }
}
out.endTag(null, TAG_RANKING);
}
- public void writeTopicsXml(XmlSerializer out, Record r) throws IOException {
- for (Topic t : r.topics.values()) {
- out.startTag(null, TAG_TOPIC);
- out.attribute(null, ATT_TOPIC_ID, t.topic.getId());
- out.attribute(null, ATT_TOPIC_LABEL, t.topic.getLabel().toString());
- if (t.priority != DEFAULT_PRIORITY) {
- out.attribute(null, ATT_PRIORITY, Integer.toString(t.priority));
- }
- if (t.visibility != DEFAULT_VISIBILITY) {
- out.attribute(null, ATT_VISIBILITY, Integer.toString(t.visibility));
- }
- if (t.importance != DEFAULT_IMPORTANCE) {
- out.attribute(null, ATT_IMPORTANCE, Integer.toString(t.importance));
- }
- out.endTag(null, TAG_TOPIC);
- }
- }
-
private void updateConfig() {
final int N = mSignalExtractors.length;
for (int i = 0; i < N; i++) {
@@ -370,189 +302,62 @@
}
}
- private static boolean safeBool(XmlPullParser parser, String att, boolean defValue) {
- final String val = parser.getAttributeValue(null, att);
- return tryParseBool(val, defValue);
- }
-
private static boolean tryParseBool(String value, boolean defValue) {
if (TextUtils.isEmpty(value)) return defValue;
return Boolean.valueOf(value);
}
+ /**
+ * Gets priority.
+ */
@Override
- public List<Notification.Topic> getTopics(String packageName, int uid) {
- final Record r = getOrCreateRecord(packageName, uid);
- List<Notification.Topic> topics = new ArrayList<>();
- for (Topic t : r.topics.values()) {
- topics.add(t.topic);
- }
- return topics;
- }
-
- @Override
- public boolean hasBannedTopics(String packageName, int uid) {
- final Record r = getOrCreateRecord(packageName, uid);
- for (Topic t : r.topics.values()) {
- if (t.importance == Ranking.IMPORTANCE_NONE) {
- return true;
- }
- }
- return false;
+ public int getPriority(String packageName, int uid) {
+ return getOrCreateRecord(packageName, uid).priority;
}
/**
- * Gets priority. If a topic is given, returns the priority of that topic. Otherwise, the
- * priority of the app.
+ * Sets priority.
*/
@Override
- public int getPriority(String packageName, int uid, Notification.Topic topic) {
- final Record r = getOrCreateRecord(packageName, uid);
- if (topic == null) {
- return r.priority;
- }
- return getOrCreateTopic(r, topic).priority;
- }
-
- /**
- * Sets priority. If a topic is given, sets the priority of that topic. If not,
- * sets the default priority for all new topics that appear in the future, and resets
- * the priority of all current topics.
- */
- @Override
- public void setPriority(String packageName, int uid, Notification.Topic topic,
- int priority) {
- final Record r = getOrCreateRecord(packageName, uid);
- if (topic == null) {
- r.priority = priority;
- for (Topic t : r.topics.values()) {
- t.priority = priority;
- }
- } else {
- getOrCreateTopic(r, topic).priority = priority;
- }
+ public void setPriority(String packageName, int uid, int priority) {
+ getOrCreateRecord(packageName, uid).priority = priority;
updateConfig();
}
/**
- * Gets visual override. If a topic is given, returns the override of that topic. Otherwise, the
- * override of the app.
+ * Gets visual override.
*/
@Override
- public int getVisibilityOverride(String packageName, int uid, Notification.Topic topic) {
- final Record r = getOrCreateRecord(packageName, uid);
- if (topic == null) {
- return r.visibility;
- }
- return getOrCreateTopic(r, topic).visibility;
+ public int getVisibilityOverride(String packageName, int uid) {
+ return getOrCreateRecord(packageName, uid).visibility;
}
/**
- * Sets visibility override. If a topic is given, sets the override of that topic. If not,
- * sets the default override for all new topics that appear in the future, and resets
- * the override of all current topics.
+ * Sets visibility override.
*/
@Override
- public void setVisibilityOverride(String pkgName, int uid, Notification.Topic topic,
- int visibility) {
- final Record r = getOrCreateRecord(pkgName, uid);
- if (topic == null) {
- r.visibility = visibility;
- for (Topic t : r.topics.values()) {
- t.visibility = visibility;
- }
- } else {
- getOrCreateTopic(r, topic).visibility = visibility;
- }
+ public void setVisibilityOverride(String pkgName, int uid, int visibility) {
+ getOrCreateRecord(pkgName, uid).visibility = visibility;
updateConfig();
}
/**
- * Gets the importance of a topic. Unlike {@link #getImportance(String, int, String)}, does not
- * create package or topic records if they don't exist.
+ * Gets importance.
*/
@Override
- public int getImportance(String packageName, int uid, String topicId) {
- final String key = recordKey(packageName, uid);
- Record r = mRecords.get(key);
- if (r == null) {
- return Ranking.IMPORTANCE_UNSPECIFIED;
- }
- Topic t = r.topics.get(topicId);
- if (t == null) {
- return Ranking.IMPORTANCE_UNSPECIFIED;
- }
- return t.importance;
+ public int getImportance(String packageName, int uid) {
+ return getOrCreateRecord(packageName, uid).importance;
}
/**
- * Gets importance. If a topic is given, returns the importance of that topic. Otherwise, the
- * importance of the app.
+ * Sets importance.
*/
@Override
- public int getImportance(String packageName, int uid, Notification.Topic topic) {
- final Record r = getOrCreateRecord(packageName, uid);
- if (topic == null) {
- return r.importance;
- }
- return getOrCreateTopic(r, topic).importance;
- }
-
- /**
- * Sets importance. If a topic is given, sets the importance of that topic. If not, sets the
- * default importance for all new topics that appear in the future, and resets
- * the importance of all current topics (unless the app is being blocked).
- */
- @Override
- public void setImportance(String pkgName, int uid, Notification.Topic topic,
- int importance) {
- final Record r = getOrCreateRecord(pkgName, uid);
- if (topic == null) {
- r.importance = importance;
- if (Ranking.IMPORTANCE_NONE != importance) {
- for (Topic t : r.topics.values()) {
- t.importance = importance;
- }
- }
- } else {
- getOrCreateTopic(r, topic).importance = importance;
- }
+ public void setImportance(String pkgName, int uid, int importance) {
+ getOrCreateRecord(pkgName, uid).importance = importance;
updateConfig();
}
- @Override
- public boolean doesUserUseTopics(String pkgName, int uid) {
- final Record r = getOrCreateRecord(pkgName, uid);
- for (Topic topic : r.topics.values()) {
- if (topic.importance != Ranking.IMPORTANCE_UNSPECIFIED
- && r.importance != topic.importance)
- return true;
- }
- return false;
- }
-
- private Topic getOrCreateTopic(Record r, Notification.Topic topic) {
- if (topic == null) {
- topic = createDefaultTopic();
- }
- Topic t = r.topics.get(topic.getId());
- if (t != null) {
- return t;
- } else {
- t = new Topic(topic);
- t.importance = r.importance;
- t.priority = r.priority;
- t.visibility = r.visibility;
- r.topics.put(topic.getId(), t);
- return t;
- }
- }
-
- private Notification.Topic createDefaultTopic() {
- return new Notification.Topic(Notification.TOPIC_DEFAULT,
- mContext.getString(R.string.default_notification_topic_label));
- }
-
public void dump(PrintWriter pw, String prefix, NotificationManagerService.DumpFilter filter) {
if (filter == null) {
final int N = mSignalExtractors.length;
@@ -600,25 +405,6 @@
pw.print(Ranking.importanceToString(r.visibility));
}
pw.println();
- for (Topic t : r.topics.values()) {
- pw.print(prefix);
- pw.print(" ");
- pw.print(" ");
- pw.print(t.topic.getId());
- if (t.priority != DEFAULT_PRIORITY) {
- pw.print(" priority=");
- pw.print(Notification.priorityToString(t.priority));
- }
- if (t.visibility != DEFAULT_VISIBILITY) {
- pw.print(" visibility=");
- pw.print(Notification.visibilityToString(t.visibility));
- }
- if (t.importance != DEFAULT_IMPORTANCE) {
- pw.print(" importance=");
- pw.print(Ranking.importanceToString(t.importance));
- }
- pw.println();
- }
}
}
}
@@ -657,17 +443,5 @@
int importance = DEFAULT_IMPORTANCE;
int priority = DEFAULT_PRIORITY;
int visibility = DEFAULT_VISIBILITY;
- Map<String, Topic> topics = new ArrayMap<>();
}
-
- private static class Topic {
- Notification.Topic topic;
- int priority = DEFAULT_PRIORITY;
- int visibility = DEFAULT_VISIBILITY;
- int importance = DEFAULT_IMPORTANCE;
-
- public Topic(Notification.Topic topic) {
- this.topic = topic;
- }
- }
}
diff --git a/services/core/java/com/android/server/notification/TopicVisibilityExtractor.java b/services/core/java/com/android/server/notification/VisibilityExtractor.java
similarity index 79%
rename from services/core/java/com/android/server/notification/TopicVisibilityExtractor.java
rename to services/core/java/com/android/server/notification/VisibilityExtractor.java
index eaa3ed3..2da2b2f 100644
--- a/services/core/java/com/android/server/notification/TopicVisibilityExtractor.java
+++ b/services/core/java/com/android/server/notification/VisibilityExtractor.java
@@ -21,8 +21,8 @@
/**
* Determines if the given notification can display sensitive content on the lockscreen.
*/
-public class TopicVisibilityExtractor implements NotificationSignalExtractor {
- private static final String TAG = "TopicVisibilityExtractor";
+public class VisibilityExtractor implements NotificationSignalExtractor {
+ private static final String TAG = "VisibilityExtractor";
private static final boolean DBG = false;
private RankingConfig mConfig;
@@ -42,10 +42,8 @@
return null;
}
- final int packageVisibility = mConfig.getVisibilityOverride(
- record.sbn.getPackageName(), record.sbn.getUid(),
- record.sbn.getNotification().getTopic());
- record.setPackageVisibilityOverride(packageVisibility);
+ record.setPackageVisibilityOverride(
+ mConfig.getVisibilityOverride(record.sbn.getPackageName(), record.sbn.getUid()));
return null;
}
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 383c1ab..5c5c8f8 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -238,13 +238,13 @@
return mZenMode;
}
- public List<AutomaticZenRule> getAutomaticZenRules() {
- List<AutomaticZenRule> rules = new ArrayList<>();
+ public List<ZenRule> getZenRules() {
+ List<ZenRule> rules = new ArrayList<>();
synchronized (mConfig) {
if (mConfig == null) return rules;
for (ZenRule rule : mConfig.automaticRules.values()) {
if (canManageAutomaticZenRule(rule)) {
- rules.add(createAutomaticZenRule(rule));
+ rules.add(rule);
}
}
}
@@ -264,18 +264,18 @@
return null;
}
- public AutomaticZenRule addAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason) {
- if (!TextUtils.isEmpty(automaticZenRule.getId())) {
- throw new IllegalArgumentException("Rule already exists");
- }
+ public String addAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason) {
if (!isSystemRule(automaticZenRule)) {
ServiceInfo owner = getServiceInfo(automaticZenRule.getOwner());
if (owner == null) {
throw new IllegalArgumentException("Owner is not a condition provider service");
}
- final int ruleInstanceLimit = owner.metaData.getInt(
- ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1);
+ int ruleInstanceLimit = -1;
+ if (owner.metaData != null) {
+ ruleInstanceLimit = owner.metaData.getInt(
+ ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1);
+ }
if (ruleInstanceLimit > 0 && ruleInstanceLimit
< (getCurrentInstanceCount(automaticZenRule.getOwner()) + 1)) {
throw new IllegalArgumentException("Rule instance limit exceeded");
@@ -293,14 +293,15 @@
populateZenRule(automaticZenRule, rule, true);
newConfig.automaticRules.put(rule.id, rule);
if (setConfigLocked(newConfig, reason, true)) {
- return createAutomaticZenRule(rule);
+ return rule.id;
} else {
return null;
}
}
}
- public boolean updateAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason) {
+ public boolean updateAutomaticZenRule(String ruleId, AutomaticZenRule automaticZenRule,
+ String reason) {
ZenModeConfig newConfig;
synchronized (mConfig) {
if (mConfig == null) return false;
@@ -309,7 +310,6 @@
+ " reason=" + reason);
}
newConfig = mConfig.copy();
- final String ruleId = automaticZenRule.getId();
ZenModeConfig.ZenRule rule;
if (ruleId == null) {
throw new IllegalArgumentException("Rule doesn't exist");
@@ -437,7 +437,7 @@
private AutomaticZenRule createAutomaticZenRule(ZenRule rule) {
return new AutomaticZenRule(rule.name, rule.component, rule.conditionId,
NotificationManager.zenModeToInterruptionFilter(rule.zenMode), rule.enabled,
- rule.id, rule.creationTime);
+ rule.creationTime);
}
public void setManualZenMode(int zenMode, Uri conditionId, String reason) {
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index 63c9408..9ec6da0 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -35,6 +35,7 @@
import android.provider.ContactsContract;
import android.provider.MediaStore;
import android.provider.Telephony.Sms.Intents;
+import android.telephony.TelephonyManager;
import android.security.Credentials;
import android.util.ArraySet;
import android.util.Log;
@@ -124,7 +125,6 @@
private final PackageManagerService mService;
- private PackagesProvider mImePackagesProvider;
private PackagesProvider mLocationPackagesProvider;
private PackagesProvider mVoiceInteractionPackagesProvider;
private PackagesProvider mSmsAppPackagesProvider;
@@ -136,10 +136,6 @@
mService = service;
}
- public void setImePackagesProviderLPr(PackagesProvider provider) {
- mImePackagesProvider = provider;
- }
-
public void setLocationPackagesProviderLPw(PackagesProvider provider) {
mLocationPackagesProvider = provider;
}
@@ -198,7 +194,6 @@
private void grantDefaultSystemHandlerPermissions(int userId) {
Log.i(TAG, "Granting permissions to default platform handlers for user " + userId);
- final PackagesProvider imePackagesProvider;
final PackagesProvider locationPackagesProvider;
final PackagesProvider voiceInteractionPackagesProvider;
final PackagesProvider smsAppPackagesProvider;
@@ -207,7 +202,6 @@
final SyncAdapterPackagesProvider syncAdapterPackagesProvider;
synchronized (mService.mPackages) {
- imePackagesProvider = mImePackagesProvider;
locationPackagesProvider = mLocationPackagesProvider;
voiceInteractionPackagesProvider = mVoiceInteractionPackagesProvider;
smsAppPackagesProvider = mSmsAppPackagesProvider;
@@ -216,8 +210,6 @@
syncAdapterPackagesProvider = mSyncAdapterPackagesProvider;
}
- String[] imePackageNames = (imePackagesProvider != null)
- ? imePackagesProvider.getPackages(userId) : null;
String[] voiceInteractPackageNames = (voiceInteractionPackagesProvider != null)
? voiceInteractionPackagesProvider.getPackages(userId) : null;
String[] locationPackageNames = (locationPackagesProvider != null)
@@ -500,17 +492,6 @@
grantRuntimePermissionsLPw(browserPackage, LOCATION_PERMISSIONS, userId);
}
- // IME
- if (imePackageNames != null) {
- for (String imePackageName : imePackageNames) {
- PackageParser.Package imePackage = getSystemPackageLPr(imePackageName);
- if (imePackage != null
- && doesPackageSupportRuntimePermissions(imePackage)) {
- grantRuntimePermissionsLPw(imePackage, CONTACTS_PERMISSIONS, userId);
- }
- }
- }
-
// Voice interaction
if (voiceInteractPackageNames != null) {
for (String voiceInteractPackageName : voiceInteractPackageNames) {
@@ -604,6 +585,16 @@
grantRuntimePermissionsLPw(printSpoolerPackage, LOCATION_PERMISSIONS, true, userId);
}
+ // EmergencyInfo
+ Intent emergencyInfoIntent = new Intent(TelephonyManager.ACTION_EMERGENCY_ASSISTANCE);
+ PackageParser.Package emergencyInfoPckg = getDefaultSystemHandlerActivityPackageLPr(
+ emergencyInfoIntent, userId);
+ if (emergencyInfoPckg != null
+ && doesPackageSupportRuntimePermissions(emergencyInfoPckg)) {
+ grantRuntimePermissionsLPw(emergencyInfoPckg, CONTACTS_PERMISSIONS, true, userId);
+ grantRuntimePermissionsLPw(emergencyInfoPckg, PHONE_PERMISSIONS, true, userId);
+ }
+
mService.mSettings.onDefaultRuntimePermissionsGrantedLPr(userId);
}
}
@@ -723,7 +714,8 @@
private PackageParser.Package getDefaultSystemHandlerServicePackageLPr(
Intent intent, int userId) {
List<ResolveInfo> handlers = mService.queryIntentServices(intent,
- intent.resolveType(mService.mContext.getContentResolver()), DEFAULT_FLAGS, userId);
+ intent.resolveType(mService.mContext.getContentResolver()), DEFAULT_FLAGS, userId)
+ .getList();
if (handlers == null) {
return null;
}
@@ -797,7 +789,7 @@
}
private void grantRuntimePermissionsLPw(PackageParser.Package pkg, Set<String> permissions,
- boolean systemFixed, boolean overrideUserChoice, int userId) {
+ boolean systemFixed, boolean isDefaultPhoneOrSms, int userId) {
if (pkg.requestedPermissions.isEmpty()) {
return;
}
@@ -805,7 +797,13 @@
List<String> requestedPermissions = pkg.requestedPermissions;
Set<String> grantablePermissions = null;
- if (pkg.isUpdatedSystemApp()) {
+ // If this is the default Phone or SMS app we grant permissions regardless
+ // whether the version on the system image declares the permission as used since
+ // selecting the app as the default Phone or SMS the user makes a deliberate
+ // choice to grant this app the permissions needed to function. For all other
+ // apps, (default grants on first boot and user creation) we don't grant default
+ // permissions if the version on the system image does not declare them.
+ if (!isDefaultPhoneOrSms && pkg.isUpdatedSystemApp()) {
PackageSetting sysPs = mService.mSettings.getDisabledSystemPkgLPr(pkg.packageName);
if (sysPs != null) {
if (sysPs.pkg.requestedPermissions.isEmpty()) {
@@ -837,7 +835,7 @@
// Unless the caller wants to override user choices. The override is
// to make sure we can grant the needed permission to the default
// sms and phone apps after the user chooses this in the UI.
- if (flags == 0 || overrideUserChoice) {
+ if (flags == 0 || isDefaultPhoneOrSms) {
// Never clobber policy or system.
final int fixedFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
| PackageManager.FLAG_PERMISSION_POLICY_FIXED;
diff --git a/services/core/java/com/android/server/pm/EphemeralApplicationRegistry.java b/services/core/java/com/android/server/pm/EphemeralApplicationRegistry.java
index 8786350..389e0a1 100644
--- a/services/core/java/com/android/server/pm/EphemeralApplicationRegistry.java
+++ b/services/core/java/com/android/server/pm/EphemeralApplicationRegistry.java
@@ -210,6 +210,9 @@
}
public void onPackageUninstalledLPw(PackageParser.Package pkg) {
+ if (pkg == null) {
+ return;
+ }
PackageSetting ps = (PackageSetting) pkg.mExtras;
if (ps == null) {
return;
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 1476e6e..93dcc72 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -203,6 +203,11 @@
mInstaller.execute("linkfile", relativePath, fromBase, toBase);
}
+ public void moveAb(String apkPath, String instructionSet, String outputPath)
+ throws InstallerException {
+ mInstaller.execute("move_ab", apkPath, instructionSet, outputPath);
+ }
+
private static void assertValidInstructionSet(String instructionSet)
throws InstallerException {
for (String abi : Build.SUPPORTED_ABIS) {
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 94b3b2d..67aeed1 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -16,36 +16,28 @@
package com.android.server.pm;
-import android.app.AppGlobals;
+import static com.android.server.pm.Installer.DEXOPT_OTA;
+import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
+import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
+
import android.content.Context;
-import android.content.Intent;
import android.content.pm.IOtaDexopt;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.Package;
-import android.content.pm.ResolveInfo;
import android.os.Environment;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
-import android.os.UserHandle;
import android.os.storage.StorageManager;
-import android.util.ArraySet;
import android.util.Log;
+import android.util.Slog;
-import dalvik.system.DexFile;
+import com.android.internal.os.InstallerConnection.InstallerException;
import java.io.File;
import java.io.FileDescriptor;
-import java.util.ArrayList;
import java.util.Collection;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
import java.util.List;
-import java.util.Set;
-
-import static com.android.server.pm.Installer.DEXOPT_OTA;
/**
* A service for A/B OTA dexopting.
@@ -70,6 +62,9 @@
// Use the package manager install and install lock here for the OTA dex optimizer.
mPackageDexOptimizer = new OTADexoptPackageDexOptimizer(packageManagerService.mInstaller,
packageManagerService.mInstallLock, context);
+
+ // Now it's time to check whether we need to move any A/B artifacts.
+ moveAbArtifacts(packageManagerService.mInstaller);
}
public static OtaDexoptService main(Context context,
@@ -150,20 +145,50 @@
false /* extractOnly */);
}
- private ArraySet<String> getPackageNamesForIntent(Intent intent, int userId) {
- List<ResolveInfo> ris = null;
- try {
- ris = AppGlobals.getPackageManager().queryIntentReceivers(
- intent, null, 0, userId);
- } catch (RemoteException e) {
+ private void moveAbArtifacts(Installer installer) {
+ if (mDexoptPackages != null) {
+ throw new IllegalStateException("Should not be ota-dexopting when trying to move.");
}
- ArraySet<String> pkgNames = new ArraySet<String>(ris == null ? 0 : ris.size());
- if (ris != null) {
- for (ResolveInfo ri : ris) {
- pkgNames.add(ri.activityInfo.packageName);
+
+ // Look into all packages.
+ Collection<PackageParser.Package> pkgs = mPackageManagerService.getPackages();
+ for (PackageParser.Package pkg : pkgs) {
+ if (pkg == null) {
+ continue;
+ }
+
+ // Does the package have code? If not, there won't be any artifacts.
+ if (!PackageDexOptimizer.canOptimizePackage(pkg)) {
+ continue;
+ }
+ if (pkg.codePath == null) {
+ Slog.w(TAG, "Package " + pkg + " can be optimized but has null codePath");
+ continue;
+ }
+
+ // If the path is in /system or /vendor, ignore. It will have been ota-dexopted into
+ // /data/ota and moved into the dalvik-cache already.
+ if (pkg.codePath.startsWith("/system") || pkg.codePath.startsWith("/vendor")) {
+ continue;
+ }
+
+ final String[] instructionSets = getAppDexInstructionSets(pkg.applicationInfo);
+ final List<String> paths = pkg.getAllCodePathsExcludingResourceOnly();
+ final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
+ for (String dexCodeInstructionSet : dexCodeInstructionSets) {
+ for (String path : paths) {
+ String oatDir = PackageDexOptimizer.getOatDir(new File(pkg.codePath)).
+ getAbsolutePath();
+
+ // TODO: Check first whether there is an artifact, to save the roundtrip time.
+
+ try {
+ installer.moveAb(path, dexCodeInstructionSet, oatDir);
+ } catch (InstallerException e) {
+ }
+ }
}
}
- return pkgNames;
}
private static class OTADexoptPackageDexOptimizer extends
@@ -180,10 +205,5 @@
return dexoptFlags | DEXOPT_OTA;
}
- @Override
- protected void recordSuccessfulDexopt(Package pkg, String instructionSet) {
- // Never record the dexopt, as it's in the B partition.
- }
-
}
}
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index a3af561..c9613b4 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -21,6 +21,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.Package;
+import android.os.Environment;
import android.os.PowerManager;
import android.os.UserHandle;
import android.os.WorkSource;
@@ -112,15 +113,6 @@
}
/**
- * Determine whether the package should be skipped for the given instruction set. A return
- * value of true means the package will be skipped. A return value of false means that the
- * package will be further investigated, and potentially compiled.
- */
- protected boolean shouldSkipBasedOnISA(PackageParser.Package pkg, String instructionSet) {
- return pkg.mDexOptPerformed.contains(instructionSet);
- }
-
- /**
* Adjust the given dexopt-needed value. Can be overridden to influence the decision to
* optimize or not (and in what way).
*/
@@ -135,13 +127,6 @@
return dexoptFlags;
}
- /**
- * Update the package status after a successful compilation.
- */
- protected void recordSuccessfulDexopt(PackageParser.Package pkg, String instructionSet) {
- pkg.mDexOptPerformed.add(instructionSet);
- }
-
private int performDexOptLI(PackageParser.Package pkg, String[] targetInstructionSets,
boolean useProfiles, boolean extractOnly) {
final String[] instructionSets = targetInstructionSets != null ?
@@ -158,44 +143,52 @@
boolean performedDexOpt = false;
final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
for (String dexCodeInstructionSet : dexCodeInstructionSets) {
- if (!useProfiles && shouldSkipBasedOnISA(pkg, dexCodeInstructionSet)) {
- // Skip only if we do not use profiles since they might trigger a recompilation.
- continue;
- }
-
for (String path : paths) {
+ if (useProfiles && isUsedByOtherApps(path)) {
+ // We cannot use profile guided compilation if the apk was used by another app.
+ useProfiles = false;
+ }
int dexoptNeeded;
try {
- dexoptNeeded = DexFile.getDexOptNeeded(path, pkg.packageName,
- dexCodeInstructionSet, /* defer */false);
+ int compilationTypeMask = 0;
+ if (extractOnly) {
+ // For extract only, any type of compilation is good.
+ compilationTypeMask = DexFile.COMPILATION_TYPE_FULL
+ | DexFile.COMPILATION_TYPE_PROFILE_GUIDE
+ | DexFile.COMPILATION_TYPE_EXTRACT_ONLY;
+ } else {
+ // Branch taken for profile guide and full compilation.
+ // Profile guide compilation should only recompile a previous
+ // profile compiled/extract only file and should not be attempted if the
+ // apk is already fully compiled. So test against a full compilation type.
+ compilationTypeMask = DexFile.COMPILATION_TYPE_FULL;
+ }
+ dexoptNeeded = DexFile.getDexOptNeeded(path,
+ dexCodeInstructionSet, compilationTypeMask);
} catch (IOException ioe) {
Slog.w(TAG, "IOException reading apk: " + path, ioe);
return DEX_OPT_FAILED;
}
dexoptNeeded = adjustDexoptNeeded(dexoptNeeded);
- if (dexoptNeeded == DexFile.NO_DEXOPT_NEEDED) {
- if (useProfiles) {
- // Profiles may trigger re-compilation. The final decision is taken in
- // installd.
- dexoptNeeded = DexFile.DEX2OAT_NEEDED;
- } else {
- // No dexopt needed and we don't use profiles. Nothing to do.
- continue;
- }
- }
final String dexoptType;
String oatDir = null;
- if (dexoptNeeded == DexFile.DEX2OAT_NEEDED) {
- dexoptType = "dex2oat";
- oatDir = createOatDirIfSupported(pkg, dexCodeInstructionSet);
- } else if (dexoptNeeded == DexFile.PATCHOAT_NEEDED) {
- dexoptType = "patchoat";
- } else if (dexoptNeeded == DexFile.SELF_PATCHOAT_NEEDED) {
- dexoptType = "self patchoat";
- } else {
- throw new IllegalStateException("Invalid dexopt needed: " + dexoptNeeded);
+ switch (dexoptNeeded) {
+ case DexFile.NO_DEXOPT_NEEDED:
+ continue;
+ case DexFile.DEX2OAT_NEEDED:
+ dexoptType = "dex2oat";
+ oatDir = createOatDirIfSupported(pkg, dexCodeInstructionSet);
+ break;
+ case DexFile.PATCHOAT_NEEDED:
+ dexoptType = "patchoat";
+ break;
+ case DexFile.SELF_PATCHOAT_NEEDED:
+ dexoptType = "self patchoat";
+ break;
+ default:
+ throw new IllegalStateException("Invalid dexopt:" + dexoptNeeded);
}
@@ -204,8 +197,10 @@
+ " vmSafeMode=" + vmSafeMode + " debuggable=" + debuggable
+ " extractOnly=" + extractOnly + " oatDir = " + oatDir);
final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
+ // Profile guide compiled oat files should not be public.
+ final boolean isPublic = !pkg.isForwardLocked() && !useProfiles;
final int dexFlags = adjustDexoptFlags(
- (!pkg.isForwardLocked() ? DEXOPT_PUBLIC : 0)
+ ( isPublic ? DEXOPT_PUBLIC : 0)
| (vmSafeMode ? DEXOPT_SAFEMODE : 0)
| (debuggable ? DEXOPT_DEBUGGABLE : 0)
| (extractOnly ? DEXOPT_EXTRACTONLY : 0)
@@ -219,15 +214,6 @@
Slog.w(TAG, "Failed to dexopt", e);
}
}
-
- if (!extractOnly) {
- // At this point we haven't failed dexopt and we haven't deferred dexopt. We must
- // either have either succeeded dexopt, or have had getDexOptNeeded tell us
- // it isn't required. We therefore mark that this package doesn't need dexopt unless
- // it's forced. performedDexOpt will tell us whether we performed dex-opt or skipped
- // it.
- recordSuccessfulDexopt(pkg, dexCodeInstructionSet);
- }
}
// If we've gotten here, we're sure that no error occurred and that we haven't
@@ -275,6 +261,25 @@
mSystemReady = true;
}
+ private boolean isUsedByOtherApps(String apkPath) {
+ try {
+ apkPath = new File(apkPath).getCanonicalPath();
+ } catch (IOException e) {
+ // Log an error but continue without it.
+ Slog.w(TAG, "Failed to get canonical path", e);
+ }
+ String useMarker = apkPath.replace('/', '@');
+ final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
+ for (int i = 0; i < currentUserIds.length; i++) {
+ File profileDir = Environment.getDataProfilesDeForeignDexDirectory(currentUserIds[i]);
+ File foreignUseMark = new File(profileDir, useMarker);
+ if (foreignUseMark.exists()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* A specialized PackageDexOptimizer that overrides already-installed checks, forcing a
* dexopt path.
@@ -291,12 +296,6 @@
}
@Override
- protected boolean shouldSkipBasedOnISA(Package pkg, String instructionSet) {
- // Forced compilation, never skip.
- return false;
- }
-
- @Override
protected int adjustDexoptNeeded(int dexoptNeeded) {
// Ensure compilation, no matter the current state.
// TODO: The return value is wrong when patchoat is needed.
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index bf0073a..8d4c9e5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -62,7 +62,9 @@
import static android.content.pm.PackageManager.MATCH_ALL;
import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
+import static android.content.pm.PackageManager.MATCH_ENCRYPTION_AWARE;
import static android.content.pm.PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
+import static android.content.pm.PackageManager.MATCH_ENCRYPTION_UNAWARE;
import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
import static android.content.pm.PackageManager.MOVE_FAILED_DEVICE_ADMIN;
@@ -101,6 +103,7 @@
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
+import android.app.admin.DevicePolicyManagerInternal;
import android.app.admin.IDevicePolicyManager;
import android.app.backup.IBackupManager;
import android.content.BroadcastReceiver;
@@ -153,7 +156,6 @@
import android.content.pm.ServiceInfo;
import android.content.pm.Signature;
import android.content.pm.UserInfo;
-import android.content.pm.VerificationParams;
import android.content.pm.VerifierDeviceIdentity;
import android.content.pm.VerifierInfo;
import android.content.res.Resources;
@@ -358,6 +360,7 @@
static final int SCAN_MOVE = 1<<13;
static final int SCAN_INITIAL = 1<<14;
static final int SCAN_CHECK_ONLY = 1<<15;
+ static final int SCAN_DONT_KILL_APP = 1<<17;
static final int REMOVE_CHATTY = 1<<16;
@@ -497,6 +500,9 @@
final ArrayMap<String, PackageParser.Package> mPackages =
new ArrayMap<String, PackageParser.Package>();
+ final ArrayMap<String, Set<String>> mKnownCodebase =
+ new ArrayMap<String, Set<String>>();
+
// Tracks available target package names -> overlay package paths.
final ArrayMap<String, ArrayMap<String, PackageParser.Package>> mOverlays =
new ArrayMap<String, ArrayMap<String, PackageParser.Package>>();
@@ -637,9 +643,6 @@
// List of packages names to keep cached, even if they are uninstalled for all users
private List<String> mKeepUninstalledPackages;
- private boolean mUseJitProfiles =
- SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
-
private static class IFVerificationParams {
PackageParser.Package pkg;
boolean replacing;
@@ -1426,19 +1429,21 @@
final boolean grantPermissions = (args.installFlags
& PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0;
+ final boolean killApp = (args.installFlags
+ & PackageManager.INSTALL_DONT_KILL_APP) == 0;
final String[] grantedPermissions = args.installGrantPermissions;
// Handle the parent package
- handlePackagePostInstall(parentRes, grantPermissions, grantedPermissions,
- args.observer);
+ handlePackagePostInstall(parentRes, grantPermissions, killApp,
+ grantedPermissions, args.observer);
// Handle the child packages
final int childCount = (parentRes.addedChildPackages != null)
? parentRes.addedChildPackages.size() : 0;
for (int i = 0; i < childCount; i++) {
PackageInstalledInfo childRes = parentRes.addedChildPackages.valueAt(i);
- handlePackagePostInstall(childRes, grantPermissions, grantedPermissions,
- args.observer);
+ handlePackagePostInstall(childRes, grantPermissions, killApp,
+ grantedPermissions, args.observer);
}
// Log tracing if needed
@@ -1633,11 +1638,12 @@
}
private void handlePackagePostInstall(PackageInstalledInfo res, boolean grantPermissions,
- String[] grantedPermissions, IPackageInstallObserver2 installObserver) {
+ boolean killApp, String[] grantedPermissions,
+ IPackageInstallObserver2 installObserver) {
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
// Send the removed broadcasts
if (res.removedInfo != null) {
- res.removedInfo.sendPackageRemovedBroadcasts();
+ res.removedInfo.sendPackageRemovedBroadcasts(killApp);
}
// Now that we successfully installed the package, grant runtime
@@ -2159,10 +2165,12 @@
}
try {
- int dexoptNeeded = DexFile.getDexOptNeeded(lib, null, dexCodeInstructionSet, false);
+ // Shared libraries do not have profiles so we perform a full
+ // AOT compilation (if needed).
+ int dexoptNeeded = DexFile.getDexOptNeeded(
+ lib, dexCodeInstructionSet,
+ DexFile.COMPILATION_TYPE_FULL);
if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
- // Shared libraries do not have profiles so we perform a full
- // AOT compilation.
mInstaller.dexopt(lib, Process.SYSTEM_UID, dexCodeInstructionSet,
dexoptNeeded, DEXOPT_PUBLIC /*dexFlags*/,
StorageManager.UUID_PRIVATE_INTERNAL,
@@ -2449,33 +2457,6 @@
reconcileAppsData(StorageManager.UUID_PRIVATE_INTERNAL, UserHandle.USER_SYSTEM,
storageFlags);
- if (!StorageManager.isFileBasedEncryptionEnabled()
- && PackageManager.APPLY_FORCE_DEVICE_ENCRYPTED) {
- // When upgrading a non-FBE device, we might need to shuffle
- // around the default storage location of system apps
- final List<UserInfo> users = sUserManager.getUsers(true);
- for (PackageSetting ps : mSettings.mPackages.values()) {
- if (ps.pkg == null || !ps.isSystem()) continue;
- final int storageTarget = ps.pkg.applicationInfo.isForceDeviceEncrypted()
- ? StorageManager.FLAG_STORAGE_DE : StorageManager.FLAG_STORAGE_CE;
- for (UserInfo user : users) {
- if (ps.getInstalled(user.id)) {
- try {
- mInstaller.migrateAppData(StorageManager.UUID_PRIVATE_INTERNAL,
- ps.name, user.id, storageTarget);
- } catch (InstallerException e) {
- logCriticalInfo(Log.WARN,
- "Failed to migrate " + ps.name + ": " + e.getMessage());
- }
- // We may have just shuffled around app data
- // directories, so prepare it one more time
- prepareAppData(StorageManager.UUID_PRIVATE_INTERNAL, user.id,
- storageFlags, ps.pkg, false);
- }
- }
- }
- }
-
// If this is first boot after an OTA, and a normal boot, then
// we need to clear code cache directories.
if (mIsUpgrade && !onlyCore) {
@@ -2583,7 +2564,7 @@
private @Nullable String getRequiredButNotReallyRequiredVerifierLPr() {
final Intent intent = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
- final List<ResolveInfo> matches = queryIntentReceivers(intent, PACKAGE_MIME_TYPE,
+ final List<ResolveInfo> matches = queryIntentReceiversInternal(intent, PACKAGE_MIME_TYPE,
MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM);
if (matches.size() == 1) {
return matches.get(0).getComponentInfo().packageName;
@@ -2598,7 +2579,7 @@
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE);
- final List<ResolveInfo> matches = queryIntentActivities(intent, PACKAGE_MIME_TYPE,
+ final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE,
MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM);
if (matches.size() == 1) {
return matches.get(0).getComponentInfo().packageName;
@@ -2610,7 +2591,7 @@
private @NonNull ComponentName getIntentFilterVerifierComponentNameLPr() {
final Intent intent = new Intent(Intent.ACTION_INTENT_FILTER_NEEDS_VERIFICATION);
- final List<ResolveInfo> matches = queryIntentReceivers(intent, PACKAGE_MIME_TYPE,
+ final List<ResolveInfo> matches = queryIntentReceiversInternal(intent, PACKAGE_MIME_TYPE,
MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM);
ResolveInfo best = null;
final int N = matches.size();
@@ -2645,7 +2626,7 @@
}
final Intent resolverIntent = new Intent(Intent.ACTION_RESOLVE_EPHEMERAL_PACKAGE);
- final List<ResolveInfo> resolvers = queryIntentServices(resolverIntent, null,
+ final List<ResolveInfo> resolvers = queryIntentServicesInternal(resolverIntent, null,
MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM);
final int N = resolvers.size();
@@ -2690,7 +2671,7 @@
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE);
- final List<ResolveInfo> matches = queryIntentActivities(intent, PACKAGE_MIME_TYPE,
+ final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE,
MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM);
if (matches.size() == 0) {
return null;
@@ -2785,7 +2766,7 @@
private List<String> resolveAllBrowserApps(int userId) {
// Resolve the canonical browser intent and check that the handleAllWebDataURI boolean is set
- List<ResolveInfo> list = queryIntentActivities(sBrowserIntent, null,
+ List<ResolveInfo> list = queryIntentActivitiesInternal(sBrowserIntent, null,
PackageManager.MATCH_ALL, userId);
final int count = list.size();
@@ -2805,7 +2786,7 @@
}
private boolean packageIsBrowser(String packageName, int userId) {
- List<ResolveInfo> list = queryIntentActivities(sBrowserIntent, null,
+ List<ResolveInfo> list = queryIntentActivitiesInternal(sBrowserIntent, null,
PackageManager.MATCH_ALL, userId);
final int N = list.size();
for (int i = 0; i < N; i++) {
@@ -2915,7 +2896,8 @@
@Override
public boolean isPackageAvailable(String packageName, int userId) {
if (!sUserManager.exists(userId)) return false;
- enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "is package available");
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ false /* requireFullPermission */, false /* checkShell */, "is package available");
synchronized (mPackages) {
PackageParser.Package p = mPackages.get(packageName);
if (p != null) {
@@ -2935,7 +2917,8 @@
public PackageInfo getPackageInfo(String packageName, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
flags = updateFlagsForPackage(flags, userId, packageName);
- enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get package info");
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ false /* requireFullPermission */, false /* checkShell */, "get package info");
// reader
synchronized (mPackages) {
PackageParser.Package p = mPackages.get(packageName);
@@ -2981,7 +2964,8 @@
public int getPackageUid(String packageName, int flags, int userId) {
if (!sUserManager.exists(userId)) return -1;
flags = updateFlagsForPackage(flags, userId, packageName);
- enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get package uid");
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ false /* requireFullPermission */, false /* checkShell */, "get package uid");
// reader
synchronized (mPackages) {
@@ -3004,7 +2988,8 @@
public int[] getPackageGids(String packageName, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
flags = updateFlagsForPackage(flags, userId, packageName);
- enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false,
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ false /* requireFullPermission */, false /* checkShell */,
"getPackageGids");
// reader
@@ -3050,9 +3035,15 @@
}
@Override
- public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
+ public @Nullable ParceledListSlice<PermissionInfo> queryPermissionsByGroup(String group,
+ int flags) {
// reader
synchronized (mPackages) {
+ if (group != null && !mPermissionGroups.containsKey(group)) {
+ // This is thrown as NameNotFoundException
+ return null;
+ }
+
ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
for (BasePermission p : mSettings.mPermissions.values()) {
if (group == null) {
@@ -3065,11 +3056,7 @@
}
}
}
-
- if (out.size() > 0) {
- return out;
- }
- return mPermissionGroups.containsKey(group) ? out : null;
+ return new ParceledListSlice<>(out);
}
}
@@ -3083,7 +3070,7 @@
}
@Override
- public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
+ public @NonNull ParceledListSlice<PermissionGroupInfo> getAllPermissionGroups(int flags) {
// reader
synchronized (mPackages) {
final int N = mPermissionGroups.size();
@@ -3092,7 +3079,7 @@
for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
}
- return out;
+ return new ParceledListSlice<>(out);
}
}
@@ -3144,7 +3131,8 @@
public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
flags = updateFlagsForApplication(flags, userId, packageName);
- enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get application info");
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ false /* requireFullPermission */, false /* checkShell */, "get application info");
// writer
synchronized (mPackages) {
PackageParser.Package p = mPackages.get(packageName);
@@ -3359,7 +3347,8 @@
public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
flags = updateFlagsForComponent(flags, userId, component);
- enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get activity info");
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ false /* requireFullPermission */, false /* checkShell */, "get activity info");
synchronized (mPackages) {
PackageParser.Activity a = mActivities.mActivities.get(component);
@@ -3404,7 +3393,8 @@
public ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
flags = updateFlagsForComponent(flags, userId, component);
- enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get receiver info");
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ false /* requireFullPermission */, false /* checkShell */, "get receiver info");
synchronized (mPackages) {
PackageParser.Activity a = mReceivers.mActivities.get(component);
if (DEBUG_PACKAGE_INFO) Log.v(
@@ -3423,7 +3413,8 @@
public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
flags = updateFlagsForComponent(flags, userId, component);
- enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get service info");
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ false /* requireFullPermission */, false /* checkShell */, "get service info");
synchronized (mPackages) {
PackageParser.Service s = mServices.mServices.get(component);
if (DEBUG_PACKAGE_INFO) Log.v(
@@ -3442,7 +3433,8 @@
public ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
flags = updateFlagsForComponent(flags, userId, component);
- enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get provider info");
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ false /* requireFullPermission */, false /* checkShell */, "get provider info");
synchronized (mPackages) {
PackageParser.Provider p = mProviders.mProviders.get(component);
if (DEBUG_PACKAGE_INFO) Log.v(
@@ -3485,22 +3477,17 @@
}
@Override
- public FeatureInfo[] getSystemAvailableFeatures() {
- Collection<FeatureInfo> featSet;
+ public @NonNull ParceledListSlice<FeatureInfo> getSystemAvailableFeatures() {
synchronized (mPackages) {
- featSet = mAvailableFeatures.values();
- int size = featSet.size();
- if (size > 0) {
- FeatureInfo[] features = new FeatureInfo[size+1];
- featSet.toArray(features);
- FeatureInfo fi = new FeatureInfo();
- fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
- FeatureInfo.GL_ES_VERSION_UNDEFINED);
- features[size] = fi;
- return features;
- }
+ final ArrayList<FeatureInfo> res = new ArrayList<>(mAvailableFeatures.values());
+
+ final FeatureInfo fi = new FeatureInfo();
+ fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
+ FeatureInfo.GL_ES_VERSION_UNDEFINED);
+ res.add(fi);
+
+ return new ParceledListSlice<>(res);
}
- return null;
}
@Override
@@ -3834,7 +3821,8 @@
android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
"grantRuntimePermission");
- enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ true /* requireFullPermission */, true /* checkShell */,
"grantRuntimePermission");
final int uid;
@@ -3945,7 +3933,8 @@
android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
"revokeRuntimePermission");
- enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ true /* requireFullPermission */, true /* checkShell */,
"revokeRuntimePermission");
final int appId;
@@ -4049,7 +4038,8 @@
enforceGrantRevokeRuntimePermissionPermissions("getPermissionFlags");
- enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ true /* requireFullPermission */, false /* checkShell */,
"getPermissionFlags");
synchronized (mPackages) {
@@ -4082,7 +4072,8 @@
enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlags");
- enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ true /* requireFullPermission */, true /* checkShell */,
"updatePermissionFlags");
// Only the system can change these flags and nothing else.
@@ -4139,7 +4130,8 @@
enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlagsForAllApps");
- enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ true /* requireFullPermission */, true /* checkShell */,
"updatePermissionFlagsForAllApps");
// Only the system can change system fixed flags.
@@ -4245,7 +4237,8 @@
// TODO: remove these terrible hacks
if (actionName.startsWith("android.net.netmon.lingerExpired")
|| actionName.startsWith("com.android.server.sip.SipWakeupTimer")
- || actionName.startsWith("com.android.internal.telephony.data-reconnect")) {
+ || actionName.startsWith("com.android.internal.telephony.data-reconnect")
+ || actionName.startsWith("android.net.netmon.launchCaptivePortalApp")) {
return true;
}
}
@@ -4572,8 +4565,10 @@
int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
flags = updateFlagsForResolve(flags, userId, intent);
- enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "resolve intent");
- List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ false /* requireFullPermission */, false /* checkShell */, "resolve intent");
+ final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags,
+ userId);
final ResolveInfo bestChoice =
chooseBestActivity(intent, resolvedType, flags, query, userId);
@@ -4605,7 +4600,8 @@
filter.dump(new PrintStreamPrinter(System.out), " ");
}
intent.setComponent(null);
- List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
+ final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags,
+ userId);
// Find any earlier preferred or last chosen entries and nuke them
findPreferredActivity(intent, resolvedType,
flags, query, 0, false, true, false, userId);
@@ -4618,7 +4614,8 @@
public ResolveInfo getLastChosenActivity(Intent intent, String resolvedType, int flags) {
final int userId = UserHandle.getCallingUserId();
if (DEBUG_PREFERRED) Log.v(TAG, "Querying last chosen activity for " + intent);
- List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
+ final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags,
+ userId);
return findPreferredActivity(intent, resolvedType, flags, query, 0,
false, false, false, userId);
}
@@ -5001,8 +4998,9 @@
// cross-profile app linking works only towards the parent.
final UserInfo parent = getProfileParent(sourceUserId);
synchronized(mPackages) {
+ int flags = updateFlagsForResolve(0, parent.id, intent);
CrossProfileDomainInfo xpDomainInfo = getCrossProfileDomainPreferredLpr(
- intent, resolvedType, 0, sourceUserId, parent.id);
+ intent, resolvedType, flags, sourceUserId, parent.id);
return xpDomainInfo != null;
}
}
@@ -5028,11 +5026,19 @@
}
@Override
- public List<ResolveInfo> queryIntentActivities(Intent intent,
+ public @NonNull ParceledListSlice<ResolveInfo> queryIntentActivities(Intent intent,
+ String resolvedType, int flags, int userId) {
+ return new ParceledListSlice<>(
+ queryIntentActivitiesInternal(intent, resolvedType, flags, userId));
+ }
+
+ private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
flags = updateFlagsForResolve(flags, userId, intent);
- enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "query intent activities");
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ false /* requireFullPermission */, false /* checkShell */,
+ "query intent activities");
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
@@ -5517,16 +5523,24 @@
}
@Override
- public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
+ public @NonNull ParceledListSlice<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
+ Intent[] specifics, String[] specificTypes, Intent intent,
+ String resolvedType, int flags, int userId) {
+ return new ParceledListSlice<>(queryIntentActivityOptionsInternal(caller, specifics,
+ specificTypes, intent, resolvedType, flags, userId));
+ }
+
+ private @NonNull List<ResolveInfo> queryIntentActivityOptionsInternal(ComponentName caller,
Intent[] specifics, String[] specificTypes, Intent intent,
String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
flags = updateFlagsForResolve(flags, userId, intent);
- enforceCrossUserPermission(Binder.getCallingUid(), userId, false,
- false, "query intent activity options");
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ false /* requireFullPermission */, false /* checkShell */,
+ "query intent activity options");
final String resultsAction = intent.getAction();
- List<ResolveInfo> results = queryIntentActivities(intent, resolvedType, flags
+ final List<ResolveInfo> results = queryIntentActivitiesInternal(intent, resolvedType, flags
| PackageManager.GET_RESOLVED_FILTER, userId);
if (DEBUG_INTENT_MATCHING) {
@@ -5691,8 +5705,14 @@
}
@Override
- public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int flags,
- int userId) {
+ public @NonNull ParceledListSlice<ResolveInfo> queryIntentReceivers(Intent intent,
+ String resolvedType, int flags, int userId) {
+ return new ParceledListSlice<>(
+ queryIntentReceiversInternal(intent, resolvedType, flags, userId));
+ }
+
+ private @NonNull List<ResolveInfo> queryIntentReceiversInternal(Intent intent,
+ String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
flags = updateFlagsForResolve(flags, userId, intent);
ComponentName comp = intent.getComponent();
@@ -5724,7 +5744,7 @@
return mReceivers.queryIntentForPackage(intent, resolvedType, flags, pkg.receivers,
userId);
}
- return null;
+ return Collections.emptyList();
}
}
@@ -5732,7 +5752,7 @@
public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
flags = updateFlagsForResolve(flags, userId, intent);
- List<ResolveInfo> query = queryIntentServices(intent, resolvedType, flags, userId);
+ List<ResolveInfo> query = queryIntentServicesInternal(intent, resolvedType, flags, userId);
if (query != null) {
if (query.size() >= 1) {
// If there is more than one service with the same priority,
@@ -5744,8 +5764,14 @@
}
@Override
- public List<ResolveInfo> queryIntentServices(Intent intent, String resolvedType, int flags,
- int userId) {
+ public @NonNull ParceledListSlice<ResolveInfo> queryIntentServices(Intent intent,
+ String resolvedType, int flags, int userId) {
+ return new ParceledListSlice<>(
+ queryIntentServicesInternal(intent, resolvedType, flags, userId));
+ }
+
+ private @NonNull List<ResolveInfo> queryIntentServicesInternal(Intent intent,
+ String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
flags = updateFlagsForResolve(flags, userId, intent);
ComponentName comp = intent.getComponent();
@@ -5777,12 +5803,18 @@
return mServices.queryIntentForPackage(intent, resolvedType, flags, pkg.services,
userId);
}
- return null;
+ return Collections.emptyList();
}
}
@Override
- public List<ResolveInfo> queryIntentContentProviders(
+ public @NonNull ParceledListSlice<ResolveInfo> queryIntentContentProviders(Intent intent,
+ String resolvedType, int flags, int userId) {
+ return new ParceledListSlice<>(
+ queryIntentContentProvidersInternal(intent, resolvedType, flags, userId));
+ }
+
+ private @NonNull List<ResolveInfo> queryIntentContentProvidersInternal(
Intent intent, String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
flags = updateFlagsForResolve(flags, userId, intent);
@@ -5815,7 +5847,7 @@
return mProviders.queryIntentForPackage(
intent, resolvedType, flags, pkg.providers, userId);
}
- return null;
+ return Collections.emptyList();
}
}
@@ -5824,7 +5856,9 @@
if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
flags = updateFlagsForPackage(flags, userId, null);
final boolean listUninstalled = (flags & MATCH_UNINSTALLED_PACKAGES) != 0;
- enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "get installed packages");
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ true /* requireFullPermission */, false /* checkShell */,
+ "get installed packages");
// writer
synchronized (mPackages) {
@@ -5976,7 +6010,8 @@
mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_EPHEMERAL_APPS,
"getEphemeralApplications");
- enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ true /* requireFullPermission */, false /* checkShell */,
"getEphemeralApplications");
synchronized (mPackages) {
List<EphemeralApplicationInfo> ephemeralApps = mEphemeralApplicationRegistry
@@ -5990,7 +6025,8 @@
@Override
public boolean isEphemeralApplication(String packageName, int userId) {
- enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ true /* requireFullPermission */, false /* checkShell */,
"isEphemeral");
if (DISABLE_EPHEMERAL_APPS) {
return false;
@@ -6014,7 +6050,8 @@
return null;
}
- enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ true /* requireFullPermission */, false /* checkShell */,
"getCookie");
if (!isCallerSameApp(packageName)) {
return null;
@@ -6031,7 +6068,8 @@
return true;
}
- enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ true /* requireFullPermission */, true /* checkShell */,
"setCookie");
if (!isCallerSameApp(packageName)) {
return false;
@@ -6050,7 +6088,8 @@
mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_EPHEMERAL_APPS,
"getEphemeralApplicationIcon");
- enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ true /* requireFullPermission */, false /* checkShell */,
"getEphemeralApplicationIcon");
synchronized (mPackages) {
return mEphemeralApplicationRegistry.getEphemeralApplicationIconLPw(
@@ -6064,7 +6103,12 @@
&& UserHandle.getAppId(Binder.getCallingUid()) == pkg.applicationInfo.uid;
}
- public List<ApplicationInfo> getPersistentApplications(int flags) {
+ @Override
+ public @NonNull ParceledListSlice<ApplicationInfo> getPersistentApplications(int flags) {
+ return new ParceledListSlice<>(getPersistentApplicationsInternal(flags));
+ }
+
+ private @NonNull List<ApplicationInfo> getPersistentApplicationsInternal(int flags) {
final ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
// reader
@@ -6073,9 +6117,16 @@
final int userId = UserHandle.getCallingUserId();
while (i.hasNext()) {
final PackageParser.Package p = i.next();
- if (p.applicationInfo != null
- && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
- && (!mSafeMode || isSystemApp(p))) {
+ if (p.applicationInfo == null) continue;
+
+ final boolean matchesUnaware = ((flags & MATCH_ENCRYPTION_UNAWARE) != 0)
+ && !p.applicationInfo.isEncryptionAware();
+ final boolean matchesAware = ((flags & MATCH_ENCRYPTION_AWARE) != 0)
+ && p.applicationInfo.isEncryptionAware();
+
+ if ((p.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0
+ && (!mSafeMode || isSystemApp(p))
+ && (matchesUnaware || matchesAware)) {
PackageSetting ps = mSettings.mPackages.get(p.packageName);
if (ps != null) {
ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
@@ -6139,11 +6190,11 @@
}
@Override
- public ParceledListSlice<ProviderInfo> queryContentProviders(String processName,
+ public @NonNull ParceledListSlice<ProviderInfo> queryContentProviders(String processName,
int uid, int flags) {
final int userId = processName != null ? UserHandle.getUserId(uid)
: UserHandle.getCallingUserId();
- if (!sUserManager.exists(userId)) return null;
+ if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
flags = updateFlagsForComponent(flags, userId, processName);
ArrayList<ProviderInfo> finalList = null;
@@ -6175,7 +6226,7 @@
return new ParceledListSlice<ProviderInfo>(finalList);
}
- return null;
+ return ParceledListSlice.emptyList();
}
@Override
@@ -6188,10 +6239,14 @@
}
@Override
- public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
+ public @NonNull ParceledListSlice<InstrumentationInfo> queryInstrumentation(
+ String targetPackage, int flags) {
+ return new ParceledListSlice<>(queryInstrumentationInternal(targetPackage, flags));
+ }
+
+ private @NonNull List<InstrumentationInfo> queryInstrumentationInternal(String targetPackage,
int flags) {
- ArrayList<InstrumentationInfo> finalList =
- new ArrayList<InstrumentationInfo>();
+ ArrayList<InstrumentationInfo> finalList = new ArrayList<InstrumentationInfo>();
// reader
synchronized (mPackages) {
@@ -6829,17 +6884,37 @@
// Extract pacakges only if profile-guided compilation is enabled because
// otherwise BackgroundDexOptService will not dexopt them later.
- if (mUseJitProfiles) {
- List<PackageParser.Package> pkgs;
- synchronized (mPackages) {
- pkgs = PackageManagerServiceUtils.getPackagesForDexopt(mPackages.values(), this);
+ if (!isUpgrade()) {
+ return;
+ }
+
+ List<PackageParser.Package> pkgs;
+ synchronized (mPackages) {
+ pkgs = PackageManagerServiceUtils.getPackagesForDexopt(mPackages.values(), this);
+ }
+
+ int curr = 0;
+ int total = pkgs.size();
+ for (PackageParser.Package pkg : pkgs) {
+ curr++;
+
+ if (DEBUG_DEXOPT) {
+ Log.i(TAG, "Extracting app " + curr + " of " + total + ": " + pkg.packageName);
}
- for (PackageParser.Package pkg : pkgs) {
- if (PackageDexOptimizer.canOptimizePackage(pkg)) {
- performDexOpt(pkg.packageName, null /* instructionSet */,
- false /* useProfiles */, true /* extractOnly */, false /* force */);
+
+ if (!isFirstBoot()) {
+ try {
+ ActivityManagerNative.getDefault().showBootMessage(
+ mContext.getResources().getString(R.string.android_upgrading_apk,
+ curr, total), true);
+ } catch (RemoteException e) {
}
}
+
+ if (PackageDexOptimizer.canOptimizePackage(pkg)) {
+ performDexOpt(pkg.packageName, null /* instructionSet */,
+ false /* useProfiles */, true /* extractOnly */, false /* force */);
+ }
}
}
@@ -6891,10 +6966,6 @@
targetInstructionSet = instructionSet != null ? instructionSet :
getPrimaryInstructionSet(p.applicationInfo);
- if (!force && !useProfiles && p.mDexOptPerformed.contains(targetInstructionSet)) {
- // Skip only if we do not use profiles since they might trigger a recompilation.
- return false;
- }
}
long callingId = Binder.clearCallingIdentity();
try {
@@ -7875,13 +7946,17 @@
// Request the ActivityManager to kill the process(only for existing packages)
// so that we do not end up in a confused state while the user is still using the older
// version of the application while the new one gets installed.
- if ((scanFlags & SCAN_REPLACING) != 0) {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "killApplication");
+ final boolean isReplacing = (scanFlags & SCAN_REPLACING) != 0;
+ final boolean killApp = (scanFlags & SCAN_DONT_KILL_APP) == 0;
+ if (killApp) {
+ if (isReplacing) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "killApplication");
- killApplication(pkg.applicationInfo.packageName,
- pkg.applicationInfo.uid, "replace pkg");
+ killApplication(pkg.applicationInfo.packageName,
+ pkg.applicationInfo.uid, "replace pkg");
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
}
// Also need to kill any apps that are dependent on the library.
@@ -10382,21 +10457,13 @@
}
@Override
- public void installPackage(String originPath, IPackageInstallObserver2 observer,
- int installFlags, String installerPackageName, VerificationParams verificationParams,
- String packageAbiOverride) {
- installPackageAsUser(originPath, observer, installFlags, installerPackageName,
- verificationParams, packageAbiOverride, UserHandle.getCallingUserId());
- }
-
- @Override
public void installPackageAsUser(String originPath, IPackageInstallObserver2 observer,
- int installFlags, String installerPackageName, VerificationParams verificationParams,
- String packageAbiOverride, int userId) {
+ int installFlags, String installerPackageName, int userId) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);
final int callingUid = Binder.getCallingUid();
- enforceCrossUserPermission(callingUid, userId, true, true, "installPackageAsUser");
+ enforceCrossUserPermission(callingUid, userId,
+ true /* requireFullPermission */, true /* checkShell */, "installPackageAsUser");
if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
try {
@@ -10435,14 +10502,15 @@
+ "to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag");
}
- verificationParams.setInstallerUid(callingUid);
-
final File originFile = new File(originPath);
final OriginInfo origin = OriginInfo.fromUntrustedFile(originFile);
final Message msg = mHandler.obtainMessage(INIT_COPY);
- final InstallParams params = new InstallParams(origin, null, observer, installFlags,
- installerPackageName, null, verificationParams, user, packageAbiOverride, null);
+ final VerificationInfo verificationInfo = new VerificationInfo(
+ null /*originatingUri*/, null /*referrer*/, -1 /*originatingUid*/, callingUid);
+ final InstallParams params = new InstallParams(origin, null /*moveInfo*/, observer,
+ installFlags, installerPackageName, null /*volumeUuid*/, verificationInfo, user,
+ null /*packageAbiOverride*/, null /*grantedPermissions*/);
params.setTraceMethod("installAsUser").setTraceCookie(System.identityHashCode(params));
msg.obj = params;
@@ -10462,10 +10530,9 @@
Slog.d(TAG, "Ephemeral install of " + packageName);
}
}
- final VerificationParams verifParams = new VerificationParams(
- null, sessionParams.originatingUri, sessionParams.referrerUri,
- sessionParams.originatingUid);
- verifParams.setInstallerUid(installerUid);
+ final VerificationInfo verificationInfo = new VerificationInfo(
+ sessionParams.originatingUri, sessionParams.referrerUri,
+ sessionParams.originatingUid, installerUid);
final OriginInfo origin;
if (stagedDir != null) {
@@ -10477,7 +10544,7 @@
final Message msg = mHandler.obtainMessage(INIT_COPY);
final InstallParams params = new InstallParams(origin, null, observer,
sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid,
- verifParams, user, sessionParams.abiOverride,
+ verificationInfo, user, sessionParams.abiOverride,
sessionParams.grantedRuntimePermissions);
params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
msg.obj = params;
@@ -10527,7 +10594,8 @@
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
PackageSetting pkgSetting;
final int uid = Binder.getCallingUid();
- enforceCrossUserPermission(uid, userId, true, true,
+ enforceCrossUserPermission(uid, userId,
+ true /* requireFullPermission */, true /* checkShell */,
"setApplicationHiddenSetting for user " + userId);
if (hidden && isPackageDeviceAdmin(packageName, userId)) {
@@ -10577,7 +10645,7 @@
info.removedPackage = packageName;
info.removedUsers = new int[] {userId};
info.uid = UserHandle.getUid(userId, pkgSetting.appId);
- info.sendPackageRemovedBroadcasts();
+ info.sendPackageRemovedBroadcasts(true /*killApp*/);
}
private void sendPackagesSuspendedForUser(String[] pkgList, int userId, boolean suspended) {
@@ -10600,8 +10668,9 @@
@Override
public boolean getApplicationHiddenSettingAsUser(String packageName, int userId) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
- enforceCrossUserPermission(Binder.getCallingUid(), userId, true,
- false, "getApplicationHidden for user " + userId);
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ true /* requireFullPermission */, false /* checkShell */,
+ "getApplicationHidden for user " + userId);
PackageSetting pkgSetting;
long callingId = Binder.clearCallingIdentity();
try {
@@ -10627,8 +10696,9 @@
null);
PackageSetting pkgSetting;
final int uid = Binder.getCallingUid();
- enforceCrossUserPermission(uid, userId, true, true, "installExistingPackage for user "
- + userId);
+ enforceCrossUserPermission(uid, userId,
+ true /* requireFullPermission */, true /* checkShell */,
+ "installExistingPackage for user " + userId);
if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
return PackageManager.INSTALL_FAILED_USER_RESTRICTED;
}
@@ -10647,14 +10717,14 @@
pkgSetting.setInstalled(true, userId);
pkgSetting.setHidden(false, userId);
mSettings.writePackageRestrictionsLPr(userId);
- if (pkgSetting.pkg != null) {
- prepareAppDataAfterInstall(pkgSetting.pkg);
- }
installed = true;
}
}
if (installed) {
+ if (pkgSetting.pkg != null) {
+ prepareAppDataAfterInstall(pkgSetting.pkg);
+ }
sendPackageAddedForUser(packageName, pkgSetting, userId);
}
} finally {
@@ -10677,7 +10747,8 @@
public String[] setPackagesSuspendedAsUser(String[] packageNames, boolean suspended,
int userId) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
- enforceCrossUserPermission(Binder.getCallingUid(), userId, true, true,
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ true /* requireFullPermission */, true /* checkShell */,
"setPackagesSuspended for user " + userId);
if (ArrayUtils.isEmpty(packageNames)) {
@@ -10705,7 +10776,7 @@
}
appId = pkgSetting.appId;
if (pkgSetting.getSuspended(userId) != suspended) {
- if (!canSuspendPackageForUser(packageName, userId)) {
+ if (!canSuspendPackageForUserLocked(packageName, userId)) {
unactionedPackages.add(packageName);
continue;
}
@@ -10735,8 +10806,9 @@
@Override
public boolean isPackageSuspendedForUser(String packageName, int userId) {
- enforceCrossUserPermission(Binder.getCallingUid(), userId, true,
- false, "isPackageSuspendedForUser for user " + userId);
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ true /* requireFullPermission */, false /* checkShell */,
+ "isPackageSuspendedForUser for user " + userId);
synchronized (mPackages) {
final PackageSetting pkgSetting = mSettings.mPackages.get(packageName);
return pkgSetting != null && pkgSetting.getSuspended(userId);
@@ -10744,7 +10816,7 @@
}
// TODO: investigate and add more restrictions for suspending crucial packages.
- private boolean canSuspendPackageForUser(String packageName, int userId) {
+ private boolean canSuspendPackageForUserLocked(String packageName, int userId) {
if (isPackageDeviceAdmin(packageName, userId)) {
Slog.w(TAG, "Not suspending/un-suspending package \"" + packageName
+ "\": has active device admin");
@@ -10758,6 +10830,13 @@
return false;
}
+ final PackageParser.Package pkg = mPackages.get(packageName);
+ if (pkg != null && isPrivilegedApp(pkg)) {
+ Slog.w(TAG, "Not suspending/un-suspending package \"" + packageName
+ + "\" because it is a privileged app");
+ return false;
+ }
+
return true;
}
@@ -11042,21 +11121,22 @@
}
@Override
- public List<IntentFilterVerificationInfo> getIntentFilterVerifications(String packageName) {
+ public @NonNull ParceledListSlice<IntentFilterVerificationInfo> getIntentFilterVerifications(
+ String packageName) {
synchronized (mPackages) {
- return mSettings.getIntentFilterVerificationsLPr(packageName);
+ return new ParceledListSlice<>(mSettings.getIntentFilterVerificationsLPr(packageName));
}
}
@Override
- public List<IntentFilter> getAllIntentFilters(String packageName) {
+ public @NonNull ParceledListSlice<IntentFilter> getAllIntentFilters(String packageName) {
if (TextUtils.isEmpty(packageName)) {
- return Collections.<IntentFilter>emptyList();
+ return ParceledListSlice.emptyList();
}
synchronized (mPackages) {
PackageParser.Package pkg = mPackages.get(packageName);
if (pkg == null || pkg.activities == null) {
- return Collections.<IntentFilter>emptyList();
+ return ParceledListSlice.emptyList();
}
final int count = pkg.activities.size();
ArrayList<IntentFilter> result = new ArrayList<>();
@@ -11066,7 +11146,7 @@
result.addAll(activity.intents);
}
}
- return result;
+ return new ParceledListSlice<>(result);
}
}
@@ -11505,6 +11585,30 @@
}
}
+ static class VerificationInfo {
+ /** A constant used to indicate that a uid value is not present. */
+ public static final int NO_UID = -1;
+
+ /** URI referencing where the package was downloaded from. */
+ final Uri originatingUri;
+
+ /** HTTP referrer URI associated with the originatingURI. */
+ final Uri referrer;
+
+ /** UID of the application that the install request originated from. */
+ final int originatingUid;
+
+ /** UID of application requesting the install */
+ final int installerUid;
+
+ VerificationInfo(Uri originatingUri, Uri referrer, int originatingUid, int installerUid) {
+ this.originatingUri = originatingUri;
+ this.referrer = referrer;
+ this.originatingUid = originatingUid;
+ this.installerUid = installerUid;
+ }
+ }
+
class InstallParams extends HandlerParams {
final OriginInfo origin;
final MoveInfo move;
@@ -11512,15 +11616,15 @@
int installFlags;
final String installerPackageName;
final String volumeUuid;
- final VerificationParams verificationParams;
private InstallArgs mArgs;
private int mRet;
final String packageAbiOverride;
final String[] grantedRuntimePermissions;
+ final VerificationInfo verificationInfo;
InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer,
int installFlags, String installerPackageName, String volumeUuid,
- VerificationParams verificationParams, UserHandle user, String packageAbiOverride,
+ VerificationInfo verificationInfo, UserHandle user, String packageAbiOverride,
String[] grantedPermissions) {
super(user);
this.origin = origin;
@@ -11529,7 +11633,7 @@
this.installFlags = installFlags;
this.installerPackageName = installerPackageName;
this.volumeUuid = volumeUuid;
- this.verificationParams = verificationParams;
+ this.verificationInfo = verificationInfo;
this.packageAbiOverride = packageAbiOverride;
this.grantedRuntimePermissions = grantedPermissions;
}
@@ -11546,20 +11650,41 @@
boolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0;
// reader
synchronized (mPackages) {
- PackageParser.Package pkg = mPackages.get(packageName);
- if (pkg != null) {
- if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
- // Check for downgrading.
- if ((installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) == 0) {
- try {
- checkDowngrade(pkg, pkgLite);
- } catch (PackageManagerException e) {
- Slog.w(TAG, "Downgrade detected: " + e.getMessage());
- return PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE;
- }
+ // Currently installed package which the new package is attempting to replace or
+ // null if no such package is installed.
+ PackageParser.Package installedPkg = mPackages.get(packageName);
+ // Package which currently owns the data which the new package will own if installed.
+ // If an app is unstalled while keeping data (e.g., adb uninstall -k), installedPkg
+ // will be null whereas dataOwnerPkg will contain information about the package
+ // which was uninstalled while keeping its data.
+ PackageParser.Package dataOwnerPkg = installedPkg;
+ if (dataOwnerPkg == null) {
+ PackageSetting ps = mSettings.mPackages.get(packageName);
+ if (ps != null) {
+ dataOwnerPkg = ps.pkg;
+ }
+ }
+
+ if (dataOwnerPkg != null) {
+ // If installed, the package will get access to data left on the device by its
+ // predecessor. As a security measure, this is permited only if this is not a
+ // version downgrade or if the predecessor package is marked as debuggable and
+ // a downgrade is explicitly requested.
+ if (((dataOwnerPkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0)
+ || ((installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) == 0)) {
+ try {
+ checkDowngrade(dataOwnerPkg, pkgLite);
+ } catch (PackageManagerException e) {
+ Slog.w(TAG, "Downgrade detected: " + e.getMessage());
+ return PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE;
}
+ }
+ }
+
+ if (installedPkg != null) {
+ if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
// Check for updated system application.
- if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ if ((installedPkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
if (onSd) {
Slog.w(TAG, "Cannot install update to system app on sdcard");
return PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION;
@@ -11578,7 +11703,7 @@
// App explictly prefers external. Let policy decide
} else {
// Prefer previous location
- if (isExternal(pkg)) {
+ if (isExternal(installedPkg)) {
return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
}
return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
@@ -11747,7 +11872,7 @@
verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
// Query all live verifiers based on current user state
- final List<ResolveInfo> receivers = queryIntentReceivers(verification,
+ final List<ResolveInfo> receivers = queryIntentReceiversInternal(verification,
PACKAGE_MIME_TYPE, 0, verifierUser.getIdentifier());
if (DEBUG_VERIFY) {
@@ -11772,26 +11897,22 @@
verification.putExtra(PackageManager.EXTRA_VERIFICATION_VERSION_CODE,
pkgLite.versionCode);
- if (verificationParams != null) {
- if (verificationParams.getVerificationURI() != null) {
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI,
- verificationParams.getVerificationURI());
- }
- if (verificationParams.getOriginatingURI() != null) {
+ if (verificationInfo != null) {
+ if (verificationInfo.originatingUri != null) {
verification.putExtra(Intent.EXTRA_ORIGINATING_URI,
- verificationParams.getOriginatingURI());
+ verificationInfo.originatingUri);
}
- if (verificationParams.getReferrer() != null) {
+ if (verificationInfo.referrer != null) {
verification.putExtra(Intent.EXTRA_REFERRER,
- verificationParams.getReferrer());
+ verificationInfo.referrer);
}
- if (verificationParams.getOriginatingUid() >= 0) {
+ if (verificationInfo.originatingUid >= 0) {
verification.putExtra(Intent.EXTRA_ORIGINATING_UID,
- verificationParams.getOriginatingUid());
+ verificationInfo.originatingUid);
}
- if (verificationParams.getInstallerUid() >= 0) {
+ if (verificationInfo.installerUid >= 0) {
verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID,
- verificationParams.getInstallerUid());
+ verificationInfo.installerUid);
}
}
@@ -13008,6 +13129,15 @@
}
}
+ public List<String> getPreviousCodePaths(String packageName) {
+ final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final List<String> result = new ArrayList<String>();
+ if (ps != null && ps.oldCodePaths != null) {
+ result.addAll(ps.oldCodePaths);
+ }
+ return result;
+ }
+
private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
PackageParser.Package pkg, int parseFlags, int scanFlags, UserHandle user,
int[] allUsers, String installerPackageName, PackageInstalledInfo res) {
@@ -13017,12 +13147,16 @@
String pkgName = deletedPackage.packageName;
boolean deletedPkg = true;
boolean addedPkg = false;
+ boolean updatedSettings = false;
+ final boolean killApp = (scanFlags & SCAN_DONT_KILL_APP) == 0;
+ final int deleteFlags = PackageManager.DELETE_KEEP_DATA
+ | (killApp ? 0 : PackageManager.DELETE_DONT_KILL_APP);
final long origUpdateTime = (pkg.mExtras != null)
? ((PackageSetting)pkg.mExtras).lastUpdateTime : 0;
// First delete the existing package while retaining the data directory
- if (!deletePackageLI(pkgName, null, true, allUsers, PackageManager.DELETE_KEEP_DATA,
+ if (!deletePackageLI(pkgName, null, true, allUsers, deleteFlags,
res.removedInfo, true, pkg)) {
// If the existing package wasn't successfully deleted
res.setError(INSTALL_FAILED_REPLACE_COULDNT_DELETE, "replaceNonSystemPackageLI");
@@ -13048,6 +13182,27 @@
final PackageParser.Package newPackage = scanPackageTracedLI(pkg, parseFlags,
scanFlags | SCAN_UPDATE_TIME, System.currentTimeMillis(), user);
updateSettingsLI(newPackage, installerPackageName, allUsers, res, user);
+
+ // Update the in-memory copy of the previous code paths.
+ PackageSetting ps = mSettings.mPackages.get(pkgName);
+ if (!killApp) {
+ if (ps.oldCodePaths == null) {
+ ps.oldCodePaths = new ArraySet<>();
+ }
+ Collections.addAll(ps.oldCodePaths, deletedPackage.baseCodePath);
+ if (deletedPackage.splitCodePaths != null) {
+ Collections.addAll(ps.oldCodePaths, deletedPackage.splitCodePaths);
+ }
+ } else {
+ ps.oldCodePaths = null;
+ }
+ if (ps.childPackageNames != null) {
+ for (int i = ps.childPackageNames.size() - 1; i >= 0; --i) {
+ final String childPkgName = ps.childPackageNames.get(i);
+ final PackageSetting childPs = mSettings.mPackages.get(childPkgName);
+ childPs.oldCodePaths = ps.oldCodePaths;
+ }
+ }
prepareAppDataAfterInstall(newPackage);
addedPkg = true;
} catch (PackageManagerException e) {
@@ -13060,7 +13215,7 @@
// Revert all internal state mutations and added folders for the failed install
if (addedPkg) {
- deletePackageLI(pkgName, null, true, allUsers, PackageManager.DELETE_KEEP_DATA,
+ deletePackageLI(pkgName, null, true, allUsers, deleteFlags,
res.removedInfo, true, null);
}
@@ -13281,18 +13436,21 @@
return null;
}
- private void removeNativeBinariesLI(PackageParser.Package pkg) {
+ private void removeNativeBinariesLI(PackageSetting ps) {
// Remove the lib path for the parent package
- PackageSetting ps = (PackageSetting) pkg.mExtras;
if (ps != null) {
NativeLibraryHelper.removeNativeBinariesLI(ps.legacyNativeLibraryPathString);
- }
- // Remove the lib path for the child packages
- final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
- for (int i = 0; i < childCount; i++) {
- ps = (PackageSetting) pkg.childPackages.get(i).mExtras;
- if (ps != null) {
- NativeLibraryHelper.removeNativeBinariesLI(ps.legacyNativeLibraryPathString);
+ // Remove the lib path for the child packages
+ final int childCount = (ps.childPackageNames != null) ? ps.childPackageNames.size() : 0;
+ for (int i = 0; i < childCount; i++) {
+ PackageSetting childPs = null;
+ synchronized (mPackages) {
+ childPs = mSettings.peekPackageLPr(ps.childPackageNames.get(i));
+ }
+ if (childPs != null) {
+ NativeLibraryHelper.removeNativeBinariesLI(childPs
+ .legacyNativeLibraryPathString);
+ }
}
}
}
@@ -13510,6 +13668,9 @@
// moving a complete application; perform an initial scan on the new install location
scanFlags |= SCAN_INITIAL;
}
+ if ((installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0) {
+ scanFlags |= SCAN_DONT_KILL_APP;
+ }
// Result object to be returned
res.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
@@ -13776,21 +13937,17 @@
return;
}
- // Extract package to save the VM unzipping the APK in memory during
- // launch. Only do this if profile-guided compilation is enabled because
- // otherwise BackgroundDexOptService will not dexopt the package later.
- if (mUseJitProfiles) {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
- // Do not run PackageDexOptimizer through the local performDexOpt
- // method because `pkg` is not in `mPackages` yet.
- int result = mPackageDexOptimizer.performDexOpt(pkg, null /* instructionSets */,
- false /* useProfiles */, true /* extractOnly */);
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
- String msg = "Extracking package failed for " + pkgName;
- res.setError(INSTALL_FAILED_DEXOPT, msg);
- return;
- }
+
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
+ // Do not run PackageDexOptimizer through the local performDexOpt
+ // method because `pkg` is not in `mPackages` yet.
+ int result = mPackageDexOptimizer.performDexOpt(pkg, null /* instructionSets */,
+ false /* useProfiles */, true /* extractOnly */);
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
+ String msg = "Extracking package failed for " + pkgName;
+ res.setError(INSTALL_FAILED_DEXOPT, msg);
+ return;
}
}
@@ -14077,25 +14234,48 @@
return;
}
- for (int currentUserId : users) {
- if (getBlockUninstallForUser(packageName, currentUserId)) {
- try {
- observer.onPackageDeleted(packageName,
- PackageManager.DELETE_FAILED_OWNER_BLOCKED, null);
- } catch (RemoteException re) {
- }
- return;
+ if (!deleteAllUsers && getBlockUninstallForUser(packageName, userId)) {
+ try {
+ observer.onPackageDeleted(packageName,
+ PackageManager.DELETE_FAILED_OWNER_BLOCKED, null);
+ } catch (RemoteException re) {
}
+ return;
}
if (DEBUG_REMOVE) {
- Slog.d(TAG, "deletePackageAsUser: pkg=" + packageName + " user=" + userId);
+ Slog.d(TAG, "deletePackageAsUser: pkg=" + packageName + " user=" + userId
+ + " deleteAllUsers: " + deleteAllUsers );
}
// Queue up an async operation since the package deletion may take a little while.
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
- final int returnCode = deletePackageX(packageName, userId, flags);
+ int returnCode;
+ if (!deleteAllUsers) {
+ returnCode = deletePackageX(packageName, userId, flags);
+ } else {
+ int[] blockUninstallUserIds = getBlockUninstallForUsers(packageName, users);
+ // If nobody is blocking uninstall, proceed with delete for all users
+ if (ArrayUtils.isEmpty(blockUninstallUserIds)) {
+ returnCode = deletePackageX(packageName, userId, flags);
+ } else {
+ // Otherwise uninstall individually for users with blockUninstalls=false
+ final int userFlags = flags & ~PackageManager.DELETE_ALL_USERS;
+ for (int userId : users) {
+ if (!ArrayUtils.contains(blockUninstallUserIds, userId)) {
+ returnCode = deletePackageX(packageName, userId, userFlags);
+ if (returnCode != PackageManager.DELETE_SUCCEEDED) {
+ Slog.w(TAG, "Package delete failed for user " + userId
+ + ", returnCode " + returnCode);
+ }
+ }
+ }
+ // The app has only been marked uninstalled for certain users.
+ // We still need to report that delete was blocked
+ returnCode = PackageManager.DELETE_FAILED_OWNER_BLOCKED;
+ }
+ }
try {
observer.onPackageDeleted(packageName, returnCode, null);
} catch (RemoteException e) {
@@ -14105,6 +14285,16 @@
});
}
+ private int[] getBlockUninstallForUsers(String packageName, int[] userIds) {
+ int[] result = EMPTY_INT_ARRAY;
+ for (int userId : userIds) {
+ if (getBlockUninstallForUser(packageName, userId)) {
+ result = ArrayUtils.appendInt(result, userId);
+ }
+ }
+ return result;
+ }
+
@Override
public boolean isPackageDeviceAdminOnAnyUser(String packageName) {
return isPackageDeviceAdmin(packageName, UserHandle.USER_ALL);
@@ -14201,7 +14391,8 @@
}
if (res) {
- info.sendPackageRemovedBroadcasts();
+ final boolean killApp = (flags & PackageManager.INSTALL_DONT_KILL_APP) == 0;
+ info.sendPackageRemovedBroadcasts(killApp);
info.sendSystemPackageUpdatedBroadcasts();
info.sendSystemPackageAppearedBroadcasts();
}
@@ -14233,12 +14424,12 @@
ArrayMap<String, PackageRemovedInfo> removedChildPackages;
ArrayMap<String, PackageInstalledInfo> appearedChildPackages;
- void sendPackageRemovedBroadcasts() {
- sendPackageRemovedBroadcastInternal();
+ void sendPackageRemovedBroadcasts(boolean killApp) {
+ sendPackageRemovedBroadcastInternal(killApp);
final int childCount = removedChildPackages != null ? removedChildPackages.size() : 0;
for (int i = 0; i < childCount; i++) {
PackageRemovedInfo childInfo = removedChildPackages.valueAt(i);
- childInfo.sendPackageRemovedBroadcastInternal();
+ childInfo.sendPackageRemovedBroadcastInternal(killApp);
}
}
@@ -14280,10 +14471,11 @@
null, 0, removedPackage, null, null);
}
- private void sendPackageRemovedBroadcastInternal() {
+ private void sendPackageRemovedBroadcastInternal(boolean killApp) {
Bundle extras = new Bundle(2);
extras.putInt(Intent.EXTRA_UID, removedAppId >= 0 ? removedAppId : uid);
extras.putBoolean(Intent.EXTRA_DATA_REMOVED, dataRemoved);
+ extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, !killApp);
if (isUpdate || isRemovedPackageSystemUpdate) {
extras.putBoolean(Intent.EXTRA_REPLACING, true);
}
@@ -14415,7 +14607,7 @@
private boolean deleteSystemPackageLI(PackageParser.Package deletedPkg,
PackageSetting deletedPs, int[] allUserHandles, int flags, PackageRemovedInfo outInfo,
boolean writeSettings) {
- if (deletedPkg.parentPackage != null) {
+ if (deletedPs.parentPackageName != null) {
Slog.w(TAG, "Attempt to delete child system package " + deletedPkg.packageName);
return false;
}
@@ -14428,7 +14620,7 @@
// the system pkg from system partition
// reader
synchronized (mPackages) {
- disabledPs = mSettings.getDisabledSystemPkgLPr(deletedPkg.packageName);
+ disabledPs = mSettings.getDisabledSystemPkgLPr(deletedPs.name);
}
if (DEBUG_REMOVE) Slog.d(TAG, "deleteSystemPackageLI: newPs=" + deletedPkg.packageName
@@ -14454,10 +14646,10 @@
// Delete the updated package
outInfo.isRemovedPackageSystemUpdate = true;
if (outInfo.removedChildPackages != null) {
- final int childCount = (deletedPkg.childPackages != null)
- ? deletedPkg.childPackages.size() : 0;
+ final int childCount = (deletedPs.childPackageNames != null)
+ ? deletedPs.childPackageNames.size() : 0;
for (int i = 0; i < childCount; i++) {
- String childPackageName = deletedPkg.childPackages.get(i).packageName;
+ String childPackageName = deletedPs.childPackageNames.get(i);
if (disabledPs.childPackageNames != null && disabledPs.childPackageNames
.contains(childPackageName)) {
PackageRemovedInfo childInfo = outInfo.removedChildPackages.get(
@@ -14477,7 +14669,7 @@
flags |= PackageManager.DELETE_KEEP_DATA;
}
- boolean ret = deleteInstalledPackageLI(deletedPkg, true, flags, allUserHandles,
+ boolean ret = deleteInstalledPackageLI(deletedPs, true, flags, allUserHandles,
outInfo, writeSettings, disabledPs.pkg);
if (!ret) {
return false;
@@ -14488,7 +14680,7 @@
// Reinstate the old system package
enableSystemPackageLPw(disabledPs.pkg);
// Remove any native libraries from the upgraded package.
- removeNativeBinariesLI(deletedPkg);
+ removeNativeBinariesLI(deletedPs);
}
// Install the system package
@@ -14545,29 +14737,18 @@
return true;
}
- private boolean deleteInstalledPackageLI(PackageParser.Package pkg,
+ private boolean deleteInstalledPackageLI(PackageSetting ps,
boolean deleteCodeAndResources, int flags, int[] allUserHandles,
PackageRemovedInfo outInfo, boolean writeSettings,
PackageParser.Package replacingPackage) {
- PackageSetting ps = null;
-
synchronized (mPackages) {
- pkg = mPackages.get(pkg.packageName);
- if (pkg == null) {
- return false;
- }
-
- ps = mSettings.mPackages.get(pkg.packageName);
- if (ps == null) {
- return false;
- }
-
if (outInfo != null) {
outInfo.uid = ps.appId;
}
if (outInfo != null && outInfo.removedChildPackages != null) {
- final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
+ final int childCount = (ps.childPackageNames != null)
+ ? ps.childPackageNames.size() : 0;
for (int i = 0; i < childCount; i++) {
String childPackageName = ps.childPackageNames.get(i);
PackageSetting childPs = mSettings.mPackages.get(childPackageName);
@@ -14587,11 +14768,11 @@
removePackageDataLI(ps, allUserHandles, outInfo, flags, writeSettings);
// Delete the child packages data
- final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
+ final int childCount = (ps.childPackageNames != null) ? ps.childPackageNames.size() : 0;
for (int i = 0; i < childCount; i++) {
PackageSetting childPs;
synchronized (mPackages) {
- childPs = mSettings.peekPackageLPr(pkg.childPackages.get(i).packageName);
+ childPs = mSettings.peekPackageLPr(ps.childPackageNames.get(i));
}
if (childPs != null) {
PackageRemovedInfo childOutInfo = (outInfo != null
@@ -14607,7 +14788,7 @@
}
// Delete application code and resources only for parent packages
- if (ps.pkg.parentPackage == null) {
+ if (ps.parentPackageName == null) {
if (deleteCodeAndResources && (outInfo != null)) {
outInfo.args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, getAppDexInstructionSets(ps));
@@ -14698,7 +14879,7 @@
return false;
}
- if (ps.pkg.parentPackage != null && (!isSystemApp(ps)
+ if (ps.parentPackageName != null && (!isSystemApp(ps)
|| (flags & PackageManager.DELETE_SYSTEM_APP) != 0)) {
if (DEBUG_REMOVE) {
Slog.d(TAG, "Uninstalled child package:" + packageName + " for user:"
@@ -14785,8 +14966,11 @@
} else {
if (DEBUG_REMOVE) Slog.d(TAG, "Removing non-system package: " + ps.name);
// Kill application pre-emptively especially for apps on sd.
- killApplication(packageName, ps.appId, "uninstall pkg");
- ret = deleteInstalledPackageLI(ps.pkg, deleteCodeAndResources, flags, allUserHandles,
+ final boolean killApp = (flags & PackageManager.DELETE_DONT_KILL_APP) == 0;
+ if (killApp) {
+ killApplication(packageName, ps.appId, "uninstall pkg");
+ }
+ ret = deleteInstalledPackageLI(ps, deleteCodeAndResources, flags, allUserHandles,
outInfo, writeSettings, replacingPackage);
}
@@ -14967,7 +15151,15 @@
final IPackageDataObserver observer, final int userId) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CLEAR_APP_USER_DATA, null);
- enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "clear application data");
+
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ true /* requireFullPermission */, false /* checkShell */, "clear application data");
+
+ final DevicePolicyManagerInternal dpmi = LocalServices
+ .getService(DevicePolicyManagerInternal.class);
+ if (dpmi != null && dpmi.hasDeviceOwnerOrProfileOwner(packageName, userId)) {
+ throw new SecurityException("Cannot clear data for a device owner or a profile owner");
+ }
// Queue up an async operation since the package deletion may take a little while.
mHandler.post(new Runnable() {
public void run() {
@@ -14979,8 +15171,8 @@
clearExternalStorageDataSync(packageName, userId, true);
if (succeeded) {
// invoke DeviceStorageMonitor's update method to clear any notifications
- DeviceStorageMonitorInternal
- dsm = LocalServices.getService(DeviceStorageMonitorInternal.class);
+ DeviceStorageMonitorInternal dsm = LocalServices
+ .getService(DeviceStorageMonitorInternal.class);
if (dsm != null) {
dsm.checkMemory();
}
@@ -15379,22 +15571,6 @@
return true;
}
-
- @Override
- public void addPackageToPreferred(String packageName) {
- Slog.w(TAG, "addPackageToPreferred: this is now a no-op");
- }
-
- @Override
- public void removePackageFromPreferred(String packageName) {
- Slog.w(TAG, "removePackageFromPreferred: this is now a no-op");
- }
-
- @Override
- public List<PackageInfo> getPreferredPackages(int flags) {
- return new ArrayList<PackageInfo>();
- }
-
private int getUidTargetSdkVersionLockedLPr(int uid) {
Object obj = mSettings.getUserIdLPr(uid);
if (obj instanceof SharedUserSetting) {
@@ -15430,7 +15606,8 @@
String opname) {
// writer
int callingUid = Binder.getCallingUid();
- enforceCrossUserPermission(callingUid, userId, true, false, "add preferred activity");
+ enforceCrossUserPermission(callingUid, userId,
+ true /* requireFullPermission */, false /* checkShell */, "add preferred activity");
if (filter.countActions() == 0) {
Slog.w(TAG, "Cannot set a preferred activity with no filter actions");
return;
@@ -15475,7 +15652,9 @@
}
final int callingUid = Binder.getCallingUid();
- enforceCrossUserPermission(callingUid, userId, true, false, "replace preferred activity");
+ enforceCrossUserPermission(callingUid, userId,
+ true /* requireFullPermission */, false /* checkShell */,
+ "replace preferred activity");
synchronized (mPackages) {
if (mContext.checkCallingOrSelfPermission(
android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
@@ -16244,7 +16423,7 @@
intent.addCategory(Intent.CATEGORY_HOME);
final int callingUserId = UserHandle.getCallingUserId();
- List<ResolveInfo> list = queryIntentActivities(intent, null,
+ List<ResolveInfo> list = queryIntentActivitiesInternal(intent, null,
PackageManager.GET_META_DATA, callingUserId);
ResolveInfo preferred = findPreferredActivity(intent, null, 0, list, 0,
true, false, false, callingUserId);
@@ -16293,7 +16472,8 @@
final int uid = Binder.getCallingUid();
final int permission = mContext.checkCallingOrSelfPermission(
android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
- enforceCrossUserPermission(uid, userId, false, true, "set enabled");
+ enforceCrossUserPermission(uid, userId,
+ false /* requireFullPermission */, true /* checkShell */, "set enabled");
final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
boolean sendNow = false;
boolean isApp = (className == null);
@@ -16432,7 +16612,8 @@
final int permission = mContext.checkCallingOrSelfPermission(
android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
- enforceCrossUserPermission(uid, userId, true, true, "stop package");
+ enforceCrossUserPermission(uid, userId,
+ true /* requireFullPermission */, true /* checkShell */, "stop package");
// writer
synchronized (mPackages) {
if (mSettings.setPackageStoppedStateLPw(this, packageName, stopped,
@@ -16454,7 +16635,8 @@
public int getApplicationEnabledSetting(String packageName, int userId) {
if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
int uid = Binder.getCallingUid();
- enforceCrossUserPermission(uid, userId, false, false, "get enabled");
+ enforceCrossUserPermission(uid, userId,
+ false /* requireFullPermission */, false /* checkShell */, "get enabled");
// reader
synchronized (mPackages) {
return mSettings.getApplicationEnabledSettingLPr(packageName, userId);
@@ -16465,7 +16647,8 @@
public int getComponentEnabledSetting(ComponentName componentName, int userId) {
if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
int uid = Binder.getCallingUid();
- enforceCrossUserPermission(uid, userId, false, false, "get component enabled");
+ enforceCrossUserPermission(uid, userId,
+ false /* requireFullPermission */, false /* checkShell */, "get component enabled");
// reader
synchronized (mPackages) {
return mSettings.getComponentEnabledSettingLPr(componentName, userId);
@@ -17236,8 +17419,9 @@
}
private String dumpDomainString(String packageName) {
- List<IntentFilterVerificationInfo> iviList = getIntentFilterVerifications(packageName);
- List<IntentFilter> filters = getAllIntentFilters(packageName);
+ List<IntentFilterVerificationInfo> iviList = getIntentFilterVerifications(packageName)
+ .getList();
+ List<IntentFilter> filters = getAllIntentFilters(packageName).getList();
ArraySet<String> result = new ArraySet<>();
if (iviList.size() > 0) {
@@ -17972,6 +18156,13 @@
if (ps.getInstalled(userId)) {
prepareAppData(volumeUuid, userId, flags, ps.pkg, restoreconNeeded);
+
+ if (maybeMigrateAppData(volumeUuid, userId, ps.pkg)) {
+ // We may have just shuffled around app data directories, so
+ // prepare them one more time
+ prepareAppData(volumeUuid, userId, flags, ps.pkg, restoreconNeeded);
+ }
+
preparedCount++;
}
}
@@ -17998,6 +18189,8 @@
* correct for all installed apps. If there is an ownership mismatch, it
* will try recovering system apps by wiping data; third-party app data is
* left intact.
+ * <p>
+ * <em>Note: To avoid a deadlock, do not call this method with {@code mPackages} lock held</em>
*/
private void prepareAppDataAfterInstall(PackageParser.Package pkg) {
prepareAppDataAfterInstallInternal(pkg);
@@ -18012,6 +18205,7 @@
final PackageSetting ps;
synchronized (mPackages) {
ps = mSettings.mPackages.get(pkg.packageName);
+ mSettings.writeKernelMappingLPr(ps);
}
final UserManager um = mContext.getSystemService(UserManager.class);
@@ -18096,6 +18290,30 @@
}
}
+ /**
+ * For system apps on non-FBE devices, this method migrates any existing
+ * CE/DE data to match the {@code forceDeviceEncrypted} flag requested by
+ * the app.
+ */
+ private boolean maybeMigrateAppData(String volumeUuid, int userId, PackageParser.Package pkg) {
+ if (pkg.isSystemApp() && !StorageManager.isFileBasedEncryptionEnabled()
+ && PackageManager.APPLY_FORCE_DEVICE_ENCRYPTED) {
+ final int storageTarget = pkg.applicationInfo.isForceDeviceEncrypted()
+ ? StorageManager.FLAG_STORAGE_DE : StorageManager.FLAG_STORAGE_CE;
+ synchronized (mInstallLock) {
+ try {
+ mInstaller.migrateAppData(volumeUuid, pkg.packageName, userId, storageTarget);
+ } catch (InstallerException e) {
+ logCriticalInfo(Log.WARN,
+ "Failed to migrate " + pkg.packageName + ": " + e.getMessage());
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
private void unfreezePackage(String packageName) {
synchronized (mPackages) {
final PackageSetting ps = mSettings.mPackages.get(packageName);
@@ -18336,7 +18554,8 @@
final Message msg = mHandler.obtainMessage(INIT_COPY);
final OriginInfo origin = OriginInfo.fromExistingFile(codeFile);
final InstallParams params = new InstallParams(origin, move, installObserver, installFlags,
- installerPackageName, volumeUuid, null, user, packageAbiOverride, null);
+ installerPackageName, volumeUuid, null /*verificationInfo*/, user,
+ packageAbiOverride, null);
params.setTraceMethod("movePackage").setTraceCookie(System.identityHashCode(params));
msg.obj = params;
@@ -18882,13 +19101,6 @@
}
@Override
- public void setImePackagesProvider(PackagesProvider provider) {
- synchronized (mPackages) {
- mDefaultPermissionPolicy.setImePackagesProviderLPr(provider);
- }
- }
-
- @Override
public void setVoiceInteractionPackagesProvider(PackagesProvider provider) {
synchronized (mPackages) {
mDefaultPermissionPolicy.setVoiceInteractionPackagesProviderLPw(provider);
@@ -18998,6 +19210,11 @@
return permissionsState.isPermissionReviewRequired(userId);
}
}
+
+ @Override
+ public ApplicationInfo getApplicationInfo(String packageName, int userId) {
+ return PackageManagerService.this.getApplicationInfo(packageName, 0 /*flags*/, userId);
+ }
}
@Override
@@ -19025,4 +19242,14 @@
boolean isHistoricalPackageUsageAvailable() {
return mPackageUsage.isHistoricalPackageUsageAvailable();
}
+
+ /**
+ * Return a <b>copy</b> of the collection of packages known to the package manager.
+ * @return A copy of the values of mPackages.
+ */
+ Collection<PackageParser.Package> getPackages() {
+ synchronized (mPackages) {
+ return new ArrayList<>(mPackages.values());
+ }
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index a3ac514..f79d6ee 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -16,13 +16,15 @@
package com.android.server.pm;
+import static com.android.server.pm.PackageManagerService.DEBUG_DEXOPT;
+import static com.android.server.pm.PackageManagerService.TAG;
+
import android.app.AppGlobals;
import android.content.Intent;
import android.content.pm.PackageParser;
-import android.content.pm.PackageParser.Package;
import android.content.pm.ResolveInfo;
-import android.os.UserHandle;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.ArraySet;
import android.util.Log;
@@ -35,9 +37,6 @@
import java.util.List;
import java.util.Set;
-import static com.android.server.pm.PackageManagerService.DEBUG_DEXOPT;
-import static com.android.server.pm.PackageManagerService.TAG;
-
/**
* Class containing helper methods for the PackageManagerService.
*
@@ -49,7 +48,8 @@
private static ArraySet<String> getPackageNamesForIntent(Intent intent, int userId) {
List<ResolveInfo> ris = null;
try {
- ris = AppGlobals.getPackageManager().queryIntentReceivers(intent, null, 0, userId);
+ ris = AppGlobals.getPackageManager().queryIntentReceivers(intent, null, 0, userId)
+ .getList();
} catch (RemoteException e) {
}
ArraySet<String> pkgNames = new ArraySet<String>();
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index abee007..ccbd823 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -317,11 +317,7 @@
private int runListFeatures() throws RemoteException {
final PrintWriter pw = getOutPrintWriter();
- final List<FeatureInfo> list = new ArrayList<FeatureInfo>();
- final FeatureInfo[] rawList = mInterface.getSystemAvailableFeatures();
- for (int i=0; i<rawList.length; i++) {
- list.add(rawList[i]);
- }
+ final List<FeatureInfo> list = mInterface.getSystemAvailableFeatures().getList();
// sort by name
Collections.sort(list, new Comparator<FeatureInfo>() {
@@ -380,7 +376,7 @@
}
final List<InstrumentationInfo> list =
- mInterface.queryInstrumentation(targetPackage, 0 /*flags*/);
+ mInterface.queryInstrumentation(targetPackage, 0 /*flags*/).getList();
// sort by target package
Collections.sort(list, new Comparator<InstrumentationInfo>() {
@@ -521,7 +517,7 @@
private int runListPermissionGroups() throws RemoteException {
final PrintWriter pw = getOutPrintWriter();
- final List<PermissionGroupInfo> pgs = mInterface.getAllPermissionGroups(0);
+ final List<PermissionGroupInfo> pgs = mInterface.getAllPermissionGroups(0).getList();
final int count = pgs.size();
for (int p = 0; p < count ; p++) {
@@ -568,7 +564,7 @@
final ArrayList<String> groupList = new ArrayList<String>();
if (groups) {
final List<PermissionGroupInfo> infos =
- mInterface.getAllPermissionGroups(0 /*flags*/);
+ mInterface.getAllPermissionGroups(0 /*flags*/).getList();
final int count = infos.size();
for (int i = 0; i < count; i++) {
groupList.add(infos.get(i).name);
@@ -718,7 +714,7 @@
}
try {
List<ResolveInfo> result = mInterface.queryIntentActivities(intent, null, 0,
- mTargetUser);
+ mTargetUser).getList();
PrintWriter pw = getOutPrintWriter();
if (result == null || result.size() <= 0) {
pw.println("No activities found");
@@ -745,7 +741,7 @@
}
try {
List<ResolveInfo> result = mInterface.queryIntentServices(intent, null, 0,
- mTargetUser);
+ mTargetUser).getList();
PrintWriter pw = getOutPrintWriter();
if (result == null || result.size() <= 0) {
pw.println("No services found");
@@ -772,7 +768,7 @@
}
try {
List<ResolveInfo> result = mInterface.queryIntentReceivers(intent, null, 0,
- mTargetUser);
+ mTargetUser).getList();
PrintWriter pw = getOutPrintWriter();
if (result == null || result.size() <= 0) {
pw.println("No receivers found");
@@ -1051,7 +1047,7 @@
prefix = " ";
}
List<PermissionInfo> ps =
- mInterface.queryPermissionsByGroup(groupList.get(i), 0 /*flags*/);
+ mInterface.queryPermissionsByGroup(groupList.get(i), 0 /*flags*/).getList();
final int count = ps.size();
boolean first = true;
for (int p = 0 ; p < count ; p++) {
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index e5eec7e..1434718 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -30,6 +30,7 @@
import java.io.File;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
/**
* Settings base class for pending and resolved classes.
@@ -118,7 +119,14 @@
* platform will refuse to launch packages in a frozen state.
*/
boolean frozen = false;
-
+ /**
+ * Non-persisted value. During an "upgrade without restart", we need the set
+ * of all previous code paths so we can surgically add the new APKs to the
+ * active classloader. If at any point an application is upgraded with a
+ * restart, this field will be cleared since the classloader would be created
+ * using the full set of code paths when the package's process is started.
+ */
+ Set<String> oldCodePaths;
PackageSettingBase origPackage;
/** Package name of the app that installed this package */
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 1872371..bf5a8f6 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -19,22 +19,16 @@
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
-import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
-import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
-import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
-import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;
-import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
-import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
-import static android.content.pm.PackageManager.MATCH_ENCRYPTION_AWARE;
-import static android.content.pm.PackageManager.MATCH_ENCRYPTION_UNAWARE;
-import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
import static android.os.Process.PACKAGE_INFO_GID;
import static android.os.Process.SYSTEM_UID;
+
import static com.android.server.pm.PackageManagerService.DEBUG_DOMAIN_VERIFICATION;
import android.annotation.NonNull;
@@ -88,7 +82,6 @@
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.JournaledFile;
-import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.server.backup.PreferredActivityBackupHelper;
import com.android.server.pm.PackageManagerService.DumpState;
@@ -170,6 +163,7 @@
private static final boolean DEBUG_STOPPED = false;
private static final boolean DEBUG_MU = false;
+ private static final boolean DEBUG_KERNEL = false;
private static final String RUNTIME_PERMISSIONS_FILE_NAME = "runtime-permissions.xml";
@@ -246,9 +240,13 @@
private final File mPackageListFilename;
private final File mStoppedPackagesFilename;
private final File mBackupStoppedPackagesFilename;
+ private final File mKernelMappingFilename;
- final ArrayMap<String, PackageSetting> mPackages =
- new ArrayMap<String, PackageSetting>();
+ /** Map from package name to settings */
+ final ArrayMap<String, PackageSetting> mPackages = new ArrayMap<>();
+
+ /** Map from package name to appId */
+ private final ArrayMap<String, Integer> mKernelMapping = new ArrayMap<>();
// List of replaced system applications
private final ArrayMap<String, PackageSetting> mDisabledSysPackages =
@@ -408,6 +406,9 @@
mPackageListFilename = new File(mSystemDir, "packages.list");
FileUtils.setPermissions(mPackageListFilename, 0640, SYSTEM_UID, PACKAGE_INFO_GID);
+ final File kernelDir = new File("/config/sdcardfs");
+ mKernelMappingFilename = kernelDir.exists() ? kernelDir : null;
+
// Deprecated: Needed for migration
mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
@@ -2342,6 +2343,7 @@
|FileUtils.S_IRGRP|FileUtils.S_IWGRP,
-1, -1);
+ writeKernelMappingLPr();
writePackageListLPr();
writeAllUsersPackageRestrictionsLPr();
writeAllRuntimePermissionsLPr();
@@ -2364,6 +2366,53 @@
//Debug.stopMethodTracing();
}
+ void writeKernelMappingLPr() {
+ if (mKernelMappingFilename == null) return;
+
+ final String[] known = mKernelMappingFilename.list();
+ final ArraySet<String> knownSet = new ArraySet<>(known.length);
+ for (String name : known) {
+ knownSet.add(name);
+ }
+
+ for (final PackageSetting ps : mPackages.values()) {
+ // Package is actively claimed
+ knownSet.remove(ps.name);
+ writeKernelMappingLPr(ps);
+ }
+
+ // Remove any unclaimed mappings
+ for (int i = 0; i < knownSet.size(); i++) {
+ final String name = knownSet.valueAt(i);
+ if (DEBUG_KERNEL) Slog.d(TAG, "Dropping mapping " + name);
+
+ mKernelMapping.remove(name);
+ new File(mKernelMappingFilename, name).delete();
+ }
+ }
+
+ void writeKernelMappingLPr(PackageSetting ps) {
+ if (mKernelMappingFilename == null) return;
+
+ final Integer cur = mKernelMapping.get(ps.name);
+ if (cur != null && cur.intValue() == ps.appId) {
+ // Ignore when mapping already matches
+ return;
+ }
+
+ if (DEBUG_KERNEL) Slog.d(TAG, "Mapping " + ps.name + " to " + ps.appId);
+
+ final File dir = new File(mKernelMappingFilename, ps.name);
+ dir.mkdir();
+
+ final File file = new File(dir, "appid");
+ try {
+ FileUtils.stringToFile(file, Integer.toString(ps.appId));
+ mKernelMapping.put(ps.name, ps.appId);
+ } catch (IOException ignored) {
+ }
+ }
+
void writePackageListLPr() {
writePackageListLPr(-1);
}
@@ -2395,7 +2444,9 @@
for (final PackageSetting pkg : mPackages.values()) {
if (pkg.pkg == null || pkg.pkg.applicationInfo == null
|| pkg.pkg.applicationInfo.dataDir == null) {
- Slog.w(TAG, "Skipping " + pkg + " due to missing metadata");
+ if (!"android".equals(pkg.name)) {
+ Slog.w(TAG, "Skipping " + pkg + " due to missing metadata");
+ }
continue;
}
@@ -2553,7 +2604,6 @@
if (pkg.volumeUuid != null) {
serializer.attribute(null, "volumeUuid", pkg.volumeUuid);
}
-
if (pkg.parentPackageName != null) {
serializer.attribute(null, "parentPackageName", pkg.parentPackageName);
}
@@ -2908,6 +2958,8 @@
mReadMessages.append("Read completed successfully: " + mPackages.size() + " packages, "
+ mSharedUsers.size() + " shared uids\n");
+ writeKernelMappingLPr();
+
return true;
}
@@ -2996,7 +3048,7 @@
tmpPa.dump(new LogPrinter(Log.DEBUG, TAG), " ");
}
Intent intent = new Intent();
- int flags = 0;
+ int flags = PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
intent.setAction(tmpPa.getAction(0));
for (int i=0; i<tmpPa.countCategories(); i++) {
String cat = tmpPa.getCategory(i);
@@ -4118,9 +4170,19 @@
};
static final Object[] PRIVATE_FLAG_DUMP_SPEC = new Object[] {
- ApplicationInfo.PRIVATE_FLAG_PRIVILEGED, "PRIVILEGED",
- ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK, "FORWARD_LOCK",
+ ApplicationInfo.PRIVATE_FLAG_HIDDEN, "HIDDEN",
ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE, "CANT_SAVE_STATE",
+ ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK, "FORWARD_LOCK",
+ ApplicationInfo.PRIVATE_FLAG_PRIVILEGED, "PRIVILEGED",
+ ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS, "HAS_DOMAIN_URLS",
+ ApplicationInfo.PRIVATE_FLAG_FORCE_DEVICE_ENCRYPTED, "FORCE_DEVICE_ENCRYPTED",
+ ApplicationInfo.PRIVATE_FLAG_ENCRYPTION_AWARE, "ENCRYPTION_AWARE",
+ ApplicationInfo.PRIVATE_FLAG_AUTOPLAY, "AUTOPLAY",
+ ApplicationInfo.PRIVATE_FLAG_PARTIALLY_ENCRYPTION_AWARE, "PARTIALLY_ENCRYPTION_AWARE",
+ ApplicationInfo.PRIVATE_FLAG_EPHEMERAL, "EPHEMERAL",
+ ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER, "REQUIRED_FOR_SYSTEM_USER",
+ ApplicationInfo.PRIVATE_FLAG_RESIZEABLE_ACTIVITIES, "RESIZEABLE_ACTIVITIES",
+ ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND, "BACKUP_IN_FOREGROUND",
};
void dumpVersionLPr(IndentingPrintWriter pw) {
@@ -4263,6 +4325,10 @@
}
pw.print(prefix); pw.print(" versionName="); pw.println(ps.pkg.mVersionName);
pw.print(prefix); pw.print(" splits="); dumpSplitNames(pw, ps.pkg); pw.println();
+ final int apkSigningVersion = PackageParser.getApkSigningVersion(ps.pkg);
+ if (apkSigningVersion != PackageParser.APK_SIGNING_UNKNOWN) {
+ pw.print(prefix); pw.print(" apkSigningVersion="); pw.println(apkSigningVersion);
+ }
pw.print(prefix); pw.print(" applicationInfo=");
pw.println(ps.pkg.applicationInfo.toString());
pw.print(prefix); pw.print(" flags="); printFlags(pw, ps.pkg.applicationInfo.flags,
@@ -4378,7 +4444,7 @@
if ((perm.info.flags&PermissionInfo.FLAG_COSTS_MONEY) != 0) {
pw.print(", COSTS_MONEY");
}
- if ((perm.info.flags&PermissionInfo.FLAG_HIDDEN) != 0) {
+ if ((perm.info.flags&PermissionInfo.FLAG_REMOVED) != 0) {
pw.print(", HIDDEN");
}
if ((perm.info.flags&PermissionInfo.FLAG_INSTALLED) != 0) {
@@ -4555,7 +4621,7 @@
if (p.perm != null) {
pw.print(" perm="); pw.println(p.perm);
if ((p.perm.info.flags & PermissionInfo.FLAG_INSTALLED) == 0
- || (p.perm.info.flags & PermissionInfo.FLAG_HIDDEN) != 0) {
+ || (p.perm.info.flags & PermissionInfo.FLAG_REMOVED) != 0) {
pw.print(" flags=0x"); pw.println(Integer.toHexString(p.perm.info.flags));
}
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 117c663..5490260 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -41,6 +41,7 @@
import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
+import android.os.IBinder;
import android.os.IUserManager;
import android.os.Message;
import android.os.ParcelFileDescriptor;
@@ -188,6 +189,8 @@
private final File mUsersDir;
private final File mUserListFile;
+ 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.
@@ -840,7 +843,7 @@
/**
* See {@link UserManagerInternal#setDevicePolicyUserRestrictions(int, Bundle, Bundle)}
*/
- void setDevicePolicyUserRestrictions(int userId, @NonNull Bundle local,
+ void setDevicePolicyUserRestrictionsInner(int userId, @NonNull Bundle local,
@Nullable Bundle global) {
Preconditions.checkNotNull(local);
boolean globalChanged = false;
@@ -1016,7 +1019,7 @@
if (mAppOpsService != null) { // We skip it until system-ready.
final long token = Binder.clearCallingIdentity();
try {
- mAppOpsService.setUserRestrictions(effective, userId);
+ mAppOpsService.setUserRestrictions(effective, mUserRestriconToken, userId);
} catch (RemoteException e) {
Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions");
} finally {
@@ -1833,6 +1836,11 @@
return null;
}
}
+ if (!UserManager.isSplitSystemUser() && (flags & UserInfo.FLAG_EPHEMERAL) != 0) {
+ Log.e(LOG_TAG,
+ "Ephemeral users are supported on split-system-user systems only.");
+ return null;
+ }
// In split system user mode, we assign the first human user the primary flag.
// And if there is no device owner, we also assign the admin flag to primary user.
if (UserManager.isSplitSystemUser()
@@ -2854,7 +2862,7 @@
@Override
public void setDevicePolicyUserRestrictions(int userId, @NonNull Bundle localRestrictions,
@Nullable Bundle globalRestrictions) {
- UserManagerService.this.setDevicePolicyUserRestrictions(userId, localRestrictions,
+ UserManagerService.this.setDevicePolicyUserRestrictionsInner(userId, localRestrictions,
globalRestrictions);
}
@@ -2974,6 +2982,22 @@
}
@Override
+ public void onEphemeralUserStop(int userId) {
+ synchronized (mUsersLock) {
+ UserInfo userInfo = getUserInfoLU(userId);
+ if (userInfo != null && userInfo.isEphemeral()) {
+ // Do not allow switching back to the ephemeral user again as the user is going
+ // to be deleted.
+ userInfo.flags |= UserInfo.FLAG_DISABLED;
+ if (userInfo.isGuest()) {
+ // Indicate that the guest will be deleted after it stops.
+ userInfo.guestToRemove = true;
+ }
+ }
+ }
+ }
+
+ @Override
public UserInfo createUserEvenWhenDisallowed(String name, int flags) {
UserInfo user = createUserInternalUnchecked(name, flags, UserHandle.USER_NULL);
// Keep this in sync with UserManager.createUser
diff --git a/services/core/java/com/android/server/policy/GlobalActions.java b/services/core/java/com/android/server/policy/GlobalActions.java
index a0f20aa..5ef518e 100644
--- a/services/core/java/com/android/server/policy/GlobalActions.java
+++ b/services/core/java/com/android/server/policy/GlobalActions.java
@@ -18,6 +18,8 @@
import com.android.internal.app.AlertController;
import com.android.internal.app.AlertController.AlertParams;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyProperties;
import com.android.internal.R;
@@ -388,6 +390,8 @@
public void run() {
try {
// Take an "interactive" bugreport.
+ MetricsLogger.action(mContext,
+ MetricsEvent.ACTION_BUGREPORT_FROM_POWER_MENU_INTERACTIVE);
ActivityManagerNative.getDefault().requestBugReport(
ActivityManager.BUGREPORT_OPTION_INTERACTIVE);
} catch (RemoteException e) {
@@ -405,6 +409,7 @@
}
try {
// Take a "full" bugreport.
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_BUGREPORT_FROM_POWER_MENU_FULL);
ActivityManagerNative.getDefault().requestBugReport(
ActivityManager.BUGREPORT_OPTION_FULL);
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index e88b72f..e51a2e1 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -25,6 +25,9 @@
import static android.content.pm.PackageManager.FEATURE_WATCH;
import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
+import static android.view.WindowManager.DOCKED_TOP;
+import static android.view.WindowManager.DOCKED_LEFT;
+import static android.view.WindowManager.DOCKED_RIGHT;
import static android.view.WindowManager.LayoutParams.*;
import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
@@ -33,6 +36,7 @@
import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED;
import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
+import android.Manifest;
import android.app.ActivityManager;
import android.app.ActivityManager.StackId;
import android.app.ActivityManagerInternal;
@@ -53,6 +57,7 @@
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.CompatibilityInfo;
@@ -72,6 +77,7 @@
import android.media.RingtoneManager;
import android.media.session.MediaSessionLegacyHelper;
import android.os.Binder;
+import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
import android.os.FactoryTest;
@@ -103,6 +109,7 @@
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.LongSparseArray;
import android.view.Display;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
@@ -131,6 +138,7 @@
import com.android.internal.R;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.policy.PhoneWindow;
+import com.android.internal.policy.IShortcutService;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.ScreenShapeHelper;
import com.android.internal.widget.PointerLocationView;
@@ -332,6 +340,8 @@
int[] mNavigationBarHeightForRotationInCarMode = new int[4];
int[] mNavigationBarWidthForRotationInCarMode = new int[4];
+ private LongSparseArray<IShortcutService> mShortcutKeyServices = new LongSparseArray<>();
+
// Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
// This is for car dock and this is updated from resource.
private boolean mEnableCarDockHomeCapture = true;
@@ -527,6 +537,7 @@
boolean mForceStatusBar;
boolean mForceStatusBarFromKeyguard;
private boolean mForceStatusBarTransparent;
+ boolean mForceNavBarOpaque;
boolean mHideLockScreen;
boolean mForcingShowNavBar;
int mForcingShowNavBarLayer;
@@ -572,6 +583,7 @@
boolean mConsumeSearchKeyUp;
boolean mAssistKeyLongPressed;
boolean mPendingMetaAction;
+ boolean mForceShowSystemBars;
// support for activating the lock screen while the screen is on
boolean mAllowLockscreenWhenOn;
@@ -1706,6 +1718,9 @@
if (mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
mShortPressWindowBehavior = SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE;
}
+
+ mForceNavBarOpaque = res.getBoolean(
+ com.android.internal.R.bool.config_forceNavBarAlwaysOpaque);
}
@Override
@@ -2035,7 +2050,7 @@
permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
}
if (permission != null) {
- if (permission == android.Manifest.permission.SYSTEM_ALERT_WINDOW) {
+ if (android.Manifest.permission.SYSTEM_ALERT_WINDOW.equals(permission)) {
final int callingUid = Binder.getCallingUid();
// system processes will be automatically allowed privilege to draw
if (callingUid == Process.SYSTEM_UID) {
@@ -2044,7 +2059,7 @@
// check if user has enabled this operation. SecurityException will be thrown if
// this app has not been allowed by the user
- final int mode = mAppOpsManager.checkOp(outAppOp[0], callingUid,
+ final int mode = mAppOpsManager.checkOpNoThrow(outAppOp[0], callingUid,
attrs.packageName);
switch (mode) {
case AppOpsManager.MODE_ALLOWED:
@@ -2053,6 +2068,17 @@
// actually be hidden in WindowManagerService
return WindowManagerGlobal.ADD_OKAY;
case AppOpsManager.MODE_ERRORED:
+ try {
+ ApplicationInfo appInfo = mContext.getPackageManager()
+ .getApplicationInfo(attrs.packageName,
+ UserHandle.getUserId(callingUid));
+ // Don't crash legacy apps
+ if (appInfo.targetSdkVersion < Build.VERSION_CODES.M) {
+ return WindowManagerGlobal.ADD_OKAY;
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ /* ignore */
+ }
return WindowManagerGlobal.ADD_PERMISSION_DENIED;
default:
// in the default mode, we will make a decision here based on
@@ -3095,7 +3121,9 @@
dispatchDirectAudioEvent(event);
return -1;
}
- } else if (KeyEvent.isMetaKey(keyCode)) {
+ }
+
+ if (KeyEvent.isMetaKey(keyCode)) {
if (down) {
mPendingMetaAction = true;
} else if (mPendingMetaAction) {
@@ -3210,6 +3238,35 @@
return -1;
}
+ if (down) {
+ long shortcutCode = (long) keyCode;
+ if (event.isCtrlPressed()) {
+ shortcutCode |= ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE;
+ }
+
+ if (event.isAltPressed()) {
+ shortcutCode |= ((long) KeyEvent.META_ALT_ON) << Integer.SIZE;
+ }
+
+ if (event.isShiftPressed()) {
+ shortcutCode |= ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE;
+ }
+
+ if (event.isMetaPressed()) {
+ shortcutCode |= ((long) KeyEvent.META_META_ON) << Integer.SIZE;
+ }
+
+ IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode);
+ if (shortcutService != null) {
+ try {
+ shortcutService.notifyShortcutKeyPressed(shortcutCode);
+ } catch (RemoteException e) {
+ mShortcutKeyServices.delete(shortcutCode);
+ }
+ return -1;
+ }
+ }
+
// Reserve all the META modifier combos for system behavior
if ((metaState & KeyEvent.META_META_ON) != 0) {
return -1;
@@ -3299,6 +3356,18 @@
return false;
}
+ public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService)
+ throws RemoteException {
+ synchronized (mLock) {
+ IShortcutService service = mShortcutKeyServices.get(shortcutCode);
+ if (service != null && service.asBinder().isBinderAlive()) {
+ throw new RemoteException("Key already exists.");
+ }
+
+ mShortcutKeyServices.put(shortcutCode, shortcutService);
+ }
+ }
+
private void launchAssistLongPressAction() {
performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
@@ -3604,7 +3673,7 @@
}
@Override
- public void getInsetHintLw(WindowManager.LayoutParams attrs, int displayRotation,
+ public boolean getInsetHintLw(WindowManager.LayoutParams attrs, int displayRotation,
Rect outContentInsets, Rect outStableInsets, Rect outOutsets) {
final int fl = PolicyControl.getWindowFlags(null, attrs);
final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs);
@@ -3659,10 +3728,11 @@
outStableInsets.set(mStableLeft, mStableTop,
availRight - mStableRight, availBottom - mStableBottom);
- return;
+ return mForceShowSystemBars;
}
outContentInsets.setEmpty();
outStableInsets.setEmpty();
+ return mForceShowSystemBars;
}
private boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) {
@@ -6075,9 +6145,20 @@
public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
Rect outInsets) {
outInsets.setEmpty();
+
+ // Navigation bar and status bar.
+ getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets);
if (mStatusBar != null) {
outInsets.top = mStatusBarHeight;
}
+ }
+
+ @Override
+ public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
+ Rect outInsets) {
+ outInsets.setEmpty();
+
+ // Only navigation bar
if (mNavigationBar != null) {
if (isNavigationBarOnBottom(displayWidth, displayHeight)) {
outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode);
@@ -6087,6 +6168,23 @@
}
}
+ @Override
+ public boolean isNavBarForcedShownLw(WindowState windowState) {
+ return mForceShowSystemBars
+ && !windowState.getFrameLw().equals(windowState.getDisplayFrameLw());
+ }
+
+ @Override
+ public boolean isDockSideAllowed(int dockSide) {
+
+ // We do not allow all dock sides at which the navigation bar touches the docked stack.
+ if (!mNavigationBarCanMove) {
+ return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT;
+ } else {
+ return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT;
+ }
+ }
+
void sendCloseSystemWindows() {
PhoneWindow.sendCloseSystemWindows(mContext, null);
}
@@ -6968,8 +7066,8 @@
// We need to force system bars when the docked stack is visible, when the freeform stack
// is visible but also when we are resizing for the transitions when docked stack
// visibility changes.
- final boolean forceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;
- final boolean forceOpaqueSystemBars = forceShowSystemBars && !mForceStatusBarFromKeyguard;
+ mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;
+ final boolean forceOpaqueSystemBars = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
// apply translucent bar vis flags
WindowState transWin = isStatusBarKeyguard() && !mHideLockScreen
@@ -6999,6 +7097,10 @@
| View.SYSTEM_UI_TRANSPARENT);
}
+ if (mForceNavBarOpaque) {
+ vis &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
+ }
+
if (mForceWindowDrawsStatusBarBackground) {
vis |= View.STATUS_BAR_TRANSPARENT;
vis &= ~View.STATUS_BAR_TRANSLUCENT;
@@ -7017,11 +7119,11 @@
(vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
final boolean transientStatusBarAllowed = mStatusBar != null
- && (statusBarHasFocus || (!forceShowSystemBars
+ && (statusBarHasFocus || (!mForceShowSystemBars
&& (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky))));
final boolean transientNavBarAllowed = mNavigationBar != null
- && !forceShowSystemBars && hideNavBarSysui && immersiveSticky;
+ && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky;
final long now = SystemClock.uptimeMillis();
final boolean pendingPanic = mPendingPanicGestureUptime != 0
@@ -7038,7 +7140,7 @@
&& !transientStatusBarAllowed && hideStatusBarSysui;
final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested()
&& !transientNavBarAllowed;
- if (denyTransientStatus || denyTransientNav || forceShowSystemBars) {
+ if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) {
// clear the clearable flags instead
clearClearableFlagsLw();
vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
diff --git a/services/core/java/com/android/server/policy/ShortcutManager.java b/services/core/java/com/android/server/policy/ShortcutManager.java
index 9284442..57ae523 100644
--- a/services/core/java/com/android/server/policy/ShortcutManager.java
+++ b/services/core/java/com/android/server/policy/ShortcutManager.java
@@ -138,14 +138,16 @@
ComponentName componentName = new ComponentName(packageName, className);
try {
info = packageManager.getActivityInfo(componentName,
- PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE);
+ PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+ | PackageManager.MATCH_UNINSTALLED_PACKAGES);
} catch (PackageManager.NameNotFoundException e) {
String[] packages = packageManager.canonicalToCurrentPackageNames(
new String[] { packageName });
componentName = new ComponentName(packages[0], className);
try {
info = packageManager.getActivityInfo(componentName,
- PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE);
+ PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+ | PackageManager.MATCH_UNINSTALLED_PACKAGES);
} catch (PackageManager.NameNotFoundException e1) {
Log.w(TAG, "Unable to add bookmark: " + packageName
+ "/" + className, e);
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index a1f24f7..6218c4e 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -49,6 +49,7 @@
import android.os.UserHandle;
import android.os.WorkSource;
import android.provider.Settings;
+import android.provider.Settings.Secure;
import android.service.dreams.DreamManagerInternal;
import android.util.EventLog;
import android.util.Slog;
@@ -59,6 +60,7 @@
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IBatteryStats;
import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.ArrayUtils;
import com.android.server.EventLogTags;
import com.android.server.ServiceThread;
import com.android.server.SystemService;
@@ -253,6 +255,9 @@
// True if boot completed occurred. We keep the screen on until this happens.
private boolean mBootCompleted;
+ // Runnables that should be triggered on boot completed
+ private Runnable[] mBootCompletedRunnables;
+
// True if auto-suspend mode is enabled.
// Refer to autosuspend.h.
private boolean mHalAutoSuspendModeEnabled;
@@ -468,6 +473,9 @@
private final ArrayList<PowerManagerInternal.LowPowerModeListener> mLowPowerModeListeners
= new ArrayList<PowerManagerInternal.LowPowerModeListener>();
+ // True if brightness should be affected by twilight.
+ private boolean mBrightnessUseTwilight;
+
private native void nativeInit();
private static native void nativeAcquireSuspendBlocker(String name);
@@ -521,6 +529,14 @@
userActivityNoUpdateLocked(
now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
updatePowerStateLocked();
+
+ if (!ArrayUtils.isEmpty(mBootCompletedRunnables)) {
+ Slog.d(TAG, "Posting " + mBootCompletedRunnables.length + " delayed runnables");
+ for (Runnable r : mBootCompletedRunnables) {
+ BackgroundThread.getHandler().post(r);
+ }
+ }
+ mBootCompletedRunnables = null;
}
}
}
@@ -620,6 +636,9 @@
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.DOUBLE_TAP_TO_WAKE),
false, mSettingsObserver, UserHandle.USER_ALL);
+ resolver.registerContentObserver(Settings.Secure.getUriFor(
+ Secure.BRIGHTNESS_USE_TWILIGHT),
+ false, mSettingsObserver, UserHandle.USER_ALL);
// Go.
readConfigurationLocked();
updateSettingsLocked();
@@ -726,6 +745,9 @@
Settings.System.SCREEN_BRIGHTNESS_MODE,
Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT);
+ mBrightnessUseTwilight = Settings.Secure.getIntForUser(resolver,
+ Secure.BRIGHTNESS_USE_TWILIGHT, 0, UserHandle.USER_CURRENT) != 0;
+
final boolean lowPowerModeEnabled = Settings.Global.getInt(resolver,
Settings.Global.LOW_POWER_MODE, 0) != 0;
final boolean autoLowPowerModeConfigured = Settings.Global.getInt(resolver,
@@ -740,6 +762,16 @@
mDirty |= DIRTY_SETTINGS;
}
+ private void postAfterBootCompleted(Runnable r) {
+ if (mBootCompleted) {
+ BackgroundThread.getHandler().post(r);
+ } else {
+ Slog.d(TAG, "Delaying runnable until system is booted");
+ mBootCompletedRunnables = ArrayUtils.appendElement(Runnable.class,
+ mBootCompletedRunnables, r);
+ }
+ }
+
void updateLowPowerModeLocked() {
if (mIsPowered && mLowPowerModeSetting) {
if (DEBUG_SPEW) {
@@ -757,7 +789,7 @@
if (mLowPowerModeEnabled != lowPowerModeEnabled) {
mLowPowerModeEnabled = lowPowerModeEnabled;
powerHintInternal(POWER_HINT_LOW_POWER, lowPowerModeEnabled ? 1 : 0);
- BackgroundThread.getHandler().post(new Runnable() {
+ postAfterBootCompleted(new Runnable() {
@Override
public void run() {
Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING)
@@ -1997,6 +2029,7 @@
mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
mDisplayPowerRequest.lowPowerMode = mLowPowerModeEnabled;
mDisplayPowerRequest.boostScreenBrightness = mScreenBrightnessBoostInProgress;
+ mDisplayPowerRequest.useTwilight = mBrightnessUseTwilight;
if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
@@ -2692,12 +2725,9 @@
if (reason == null) {
reason = "";
}
- if (reason.equals(PowerManager.REBOOT_RECOVERY)) {
- // If we are rebooting to go into recovery, instead of
- // setting sys.powerctl directly we'll start the
- // pre-recovery service which will do some preparation for
- // recovery and then reboot for us.
- SystemProperties.set("ctl.start", "pre-recovery");
+ if (reason.equals(PowerManager.REBOOT_RECOVERY)
+ || reason.equals(PowerManager.REBOOT_RECOVERY_UPDATE)) {
+ SystemProperties.set("sys.powerctl", "reboot,recovery");
} else {
SystemProperties.set("sys.powerctl", "reboot," + reason);
}
@@ -3410,7 +3440,8 @@
@Override // Binder call
public void reboot(boolean confirm, String reason, boolean wait) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
- if (PowerManager.REBOOT_RECOVERY.equals(reason)) {
+ if (PowerManager.REBOOT_RECOVERY.equals(reason)
+ || PowerManager.REBOOT_RECOVERY_UPDATE.equals(reason)) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
}
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index ac6a28e..bcafddc 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -32,8 +32,10 @@
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
+import android.os.FileUtils;
import android.os.Handler;
import android.os.PowerManager;
+import android.os.RecoverySystem;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -81,13 +83,9 @@
private static Object sIsStartedGuard = new Object();
private static boolean sIsStarted = false;
- // uncrypt status files
- private static final String UNCRYPT_STATUS_FILE = "/cache/recovery/uncrypt_status";
- private static final String UNCRYPT_PACKAGE_FILE = "/cache/recovery/uncrypt_file";
-
private static boolean mReboot;
private static boolean mRebootSafeMode;
- private static boolean mRebootUpdate;
+ private static boolean mRebootHasProgressBar;
private static String mReason;
// Provides shutdown assurance in case the system_server is killed
@@ -96,6 +94,9 @@
// Indicates whether we are rebooting into safe mode
public static final String REBOOT_SAFEMODE_PROPERTY = "persist.sys.safemode";
+ // Indicates whether we should stay in safe mode until ro.build.date.utc is newer than this
+ public static final String AUDIT_SAFEMODE_PROPERTY = "persist.sys.audit_safemode";
+
// static instance of this thread
private static final ShutdownThread sInstance = new ShutdownThread();
@@ -213,7 +214,7 @@
public static void reboot(final Context context, String reason, boolean confirm) {
mReboot = true;
mRebootSafeMode = false;
- mRebootUpdate = false;
+ mRebootHasProgressBar = false;
mReason = reason;
shutdownInner(context, confirm);
}
@@ -233,7 +234,7 @@
mReboot = true;
mRebootSafeMode = true;
- mRebootUpdate = false;
+ mRebootHasProgressBar = false;
mReason = null;
shutdownInner(context, confirm);
}
@@ -250,10 +251,19 @@
// Throw up a system dialog to indicate the device is rebooting / shutting down.
ProgressDialog pd = new ProgressDialog(context);
- // Path 1: Reboot to recovery and install the update
- // Condition: mReason == REBOOT_RECOVERY and mRebootUpdate == True
- // (mRebootUpdate is set by checking if /cache/recovery/uncrypt_file exists.)
- // UI: progress bar
+ // Path 1: Reboot to recovery for update
+ // Condition: mReason == REBOOT_RECOVERY_UPDATE
+ //
+ // Path 1a: uncrypt needed
+ // Condition: if /cache/recovery/uncrypt_file exists but
+ // /cache/recovery/block.map doesn't.
+ // UI: determinate progress bar (mRebootHasProgressBar == True)
+ //
+ // * Path 1a is expected to be removed once the GmsCore shipped on
+ // device always calls uncrypt prior to reboot.
+ //
+ // Path 1b: uncrypt already done
+ // UI: spinning circle only (no progress bar)
//
// Path 2: Reboot to recovery for factory reset
// Condition: mReason == REBOOT_RECOVERY
@@ -262,24 +272,31 @@
// Path 3: Regular reboot / shutdown
// Condition: Otherwise
// UI: spinning circle only (no progress bar)
- if (PowerManager.REBOOT_RECOVERY.equals(mReason)) {
- mRebootUpdate = new File(UNCRYPT_PACKAGE_FILE).exists();
- if (mRebootUpdate) {
- pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_update_title));
- pd.setMessage(context.getText(
- com.android.internal.R.string.reboot_to_update_prepare));
+ if (PowerManager.REBOOT_RECOVERY_UPDATE.equals(mReason)) {
+ // We need the progress bar if uncrypt will be invoked during the
+ // reboot, which might be time-consuming.
+ mRebootHasProgressBar = RecoverySystem.UNCRYPT_PACKAGE_FILE.exists()
+ && !(RecoverySystem.BLOCK_MAP_FILE.exists());
+ pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_update_title));
+ if (mRebootHasProgressBar) {
pd.setMax(100);
- pd.setProgressNumberFormat(null);
- pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setProgress(0);
pd.setIndeterminate(false);
- } else {
- // Factory reset path. Set the dialog message accordingly.
- pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_reset_title));
+ pd.setProgressNumberFormat(null);
+ pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setMessage(context.getText(
- com.android.internal.R.string.reboot_to_reset_message));
+ com.android.internal.R.string.reboot_to_update_prepare));
+ } else {
pd.setIndeterminate(true);
+ pd.setMessage(context.getText(
+ com.android.internal.R.string.reboot_to_update_reboot));
}
+ } else if (PowerManager.REBOOT_RECOVERY.equals(mReason)) {
+ // Factory reset path. Set the dialog message accordingly.
+ pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_reset_title));
+ pd.setMessage(context.getText(
+ com.android.internal.R.string.reboot_to_reset_message));
+ pd.setIndeterminate(true);
} else {
pd.setTitle(context.getText(com.android.internal.R.string.power_off));
pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
@@ -379,7 +396,7 @@
if (delay <= 0) {
Log.w(TAG, "Shutdown broadcast timed out");
break;
- } else if (mRebootUpdate) {
+ } else if (mRebootHasProgressBar) {
int status = (int)((MAX_BROADCAST_TIME - delay) * 1.0 *
BROADCAST_STOP_PERCENT / MAX_BROADCAST_TIME);
sInstance.setRebootProgress(status, null);
@@ -390,7 +407,7 @@
}
}
}
- if (mRebootUpdate) {
+ if (mRebootHasProgressBar) {
sInstance.setRebootProgress(BROADCAST_STOP_PERCENT, null);
}
@@ -404,7 +421,7 @@
} catch (RemoteException e) {
}
}
- if (mRebootUpdate) {
+ if (mRebootHasProgressBar) {
sInstance.setRebootProgress(ACTIVITY_MANAGER_STOP_PERCENT, null);
}
@@ -415,13 +432,13 @@
if (pm != null) {
pm.shutdown();
}
- if (mRebootUpdate) {
+ if (mRebootHasProgressBar) {
sInstance.setRebootProgress(PACKAGE_MANAGER_STOP_PERCENT, null);
}
// Shutdown radios.
shutdownRadios(MAX_RADIO_WAIT_TIME);
- if (mRebootUpdate) {
+ if (mRebootHasProgressBar) {
sInstance.setRebootProgress(RADIO_STOP_PERCENT, null);
}
@@ -455,7 +472,7 @@
if (delay <= 0) {
Log.w(TAG, "Shutdown wait timed out");
break;
- } else if (mRebootUpdate) {
+ } else if (mRebootHasProgressBar) {
int status = (int)((MAX_SHUTDOWN_WAIT_TIME - delay) * 1.0 *
(MOUNT_SERVICE_STOP_PERCENT - RADIO_STOP_PERCENT) /
MAX_SHUTDOWN_WAIT_TIME);
@@ -468,10 +485,11 @@
}
}
}
- if (mRebootUpdate) {
+ if (mRebootHasProgressBar) {
sInstance.setRebootProgress(MOUNT_SERVICE_STOP_PERCENT, null);
- // If it's to reboot to install update, invoke uncrypt via init service.
+ // If it's to reboot to install an update and uncrypt hasn't been
+ // done yet, trigger it now.
uncrypt();
}
@@ -549,7 +567,7 @@
long delay = endTime - SystemClock.elapsedRealtime();
while (delay > 0) {
- if (mRebootUpdate) {
+ if (mRebootHasProgressBar) {
int status = (int)((timeout - delay) * 1.0 *
(RADIO_STOP_PERCENT - PACKAGE_MANAGER_STOP_PERCENT) / timeout);
status += PACKAGE_MANAGER_STOP_PERCENT;
@@ -651,66 +669,40 @@
private void uncrypt() {
Log.i(TAG, "Calling uncrypt and monitoring the progress...");
+ final RecoverySystem.ProgressListener progressListener =
+ new RecoverySystem.ProgressListener() {
+ @Override
+ public void onProgress(int status) {
+ if (status >= 0 && status < 100) {
+ // Scale down to [MOUNT_SERVICE_STOP_PERCENT, 100).
+ status = (int)(status * (100.0 - MOUNT_SERVICE_STOP_PERCENT) / 100);
+ status += MOUNT_SERVICE_STOP_PERCENT;
+ CharSequence msg = mContext.getText(
+ com.android.internal.R.string.reboot_to_update_package);
+ sInstance.setRebootProgress(status, msg);
+ } else if (status == 100) {
+ CharSequence msg = mContext.getText(
+ com.android.internal.R.string.reboot_to_update_reboot);
+ sInstance.setRebootProgress(status, msg);
+ } else {
+ // Ignored
+ }
+ }
+ };
+
final boolean[] done = new boolean[1];
done[0] = false;
Thread t = new Thread() {
@Override
public void run() {
- // Create the status pipe file to communicate with /system/bin/uncrypt.
- new File(UNCRYPT_STATUS_FILE).delete();
+ RecoverySystem rs = (RecoverySystem) mContext.getSystemService(
+ Context.RECOVERY_SERVICE);
+ String filename = null;
try {
- Os.mkfifo(UNCRYPT_STATUS_FILE, 0600);
- } catch (ErrnoException e) {
- Log.w(TAG, "ErrnoException when creating named pipe \"" + UNCRYPT_STATUS_FILE +
- "\": " + e.getMessage());
- }
-
- SystemProperties.set("ctl.start", "uncrypt");
-
- // Read the status from the pipe.
- try (BufferedReader reader = new BufferedReader(
- new FileReader(UNCRYPT_STATUS_FILE))) {
-
- int lastStatus = Integer.MIN_VALUE;
- while (true) {
- String str = reader.readLine();
- try {
- int status = Integer.parseInt(str);
-
- // Avoid flooding the log with the same message.
- if (status == lastStatus && lastStatus != Integer.MIN_VALUE) {
- continue;
- }
- lastStatus = status;
-
- if (status >= 0 && status < 100) {
- // Update status
- Log.d(TAG, "uncrypt read status: " + status);
- // Scale down to [MOUNT_SERVICE_STOP_PERCENT, 100).
- status = (int)(status * (100.0 - MOUNT_SERVICE_STOP_PERCENT) / 100);
- status += MOUNT_SERVICE_STOP_PERCENT;
- CharSequence msg = mContext.getText(
- com.android.internal.R.string.reboot_to_update_package);
- sInstance.setRebootProgress(status, msg);
- } else if (status == 100) {
- Log.d(TAG, "uncrypt successfully finished.");
- CharSequence msg = mContext.getText(
- com.android.internal.R.string.reboot_to_update_reboot);
- sInstance.setRebootProgress(status, msg);
- break;
- } else {
- // Error in /system/bin/uncrypt. Or it's rebooting to recovery
- // to perform other operations (e.g. factory reset).
- Log.d(TAG, "uncrypt failed with status: " + status);
- break;
- }
- } catch (NumberFormatException unused) {
- Log.d(TAG, "uncrypt invalid status received: " + str);
- break;
- }
- }
- } catch (IOException unused) {
- Log.w(TAG, "IOException when reading \"" + UNCRYPT_STATUS_FILE + "\".");
+ filename = FileUtils.readTextFile(RecoverySystem.UNCRYPT_PACKAGE_FILE, 0, null);
+ rs.processPackage(mContext, new File(filename), progressListener);
+ } catch (IOException e) {
+ Log.e(TAG, "Error uncrypting file", e);
}
done[0] = true;
}
diff --git a/services/core/java/com/android/server/search/Searchables.java b/services/core/java/com/android/server/search/Searchables.java
index 0046fbb..6bacdfd 100644
--- a/services/core/java/com/android/server/search/Searchables.java
+++ b/services/core/java/com/android/server/search/Searchables.java
@@ -410,7 +410,7 @@
activities =
mPm.queryIntentActivities(intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
- flags, mUserId);
+ flags, mUserId).getList();
} catch (RemoteException re) {
// Local call
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index cbbcdae..6bda4ed 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -33,4 +33,5 @@
void topAppWindowChanged(boolean menuVisible);
void setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis, int mask,
Rect fullscreenBounds, Rect dockedBounds, String cause);
+ void toggleSplitScreen();
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 6eab8d4..d24e1af 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -204,6 +204,16 @@
StatusBarManagerService.this.setSystemUiVisibility(vis, fullscreenStackVis,
dockedStackVis, mask, fullscreenBounds, dockedBounds, cause);
}
+
+ @Override
+ public void toggleSplitScreen() {
+ enforceStatusBarService();
+ if (mBar != null) {
+ try {
+ mBar.toggleSplitScreen();
+ } catch (RemoteException ex) {}
+ }
+ }
};
// ================================================================================
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 4e96d71..bf281d6 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -24,6 +24,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.hardware.hdmi.HdmiHotplugEvent;
@@ -45,6 +46,7 @@
import android.media.tv.TvInputHardwareInfo;
import android.media.tv.TvInputInfo;
import android.media.tv.TvStreamConfig;
+import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
@@ -57,9 +59,13 @@
import android.view.KeyEvent;
import android.view.Surface;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.server.SystemService;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
@@ -549,6 +555,70 @@
return (float) mCurrentIndex / (float) mCurrentMaxIndex;
}
+ public void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
+ final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump TvInputHardwareManager from pid="
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
+ return;
+ }
+
+ synchronized (mLock) {
+ pw.println("TvInputHardwareManager Info:");
+ pw.increaseIndent();
+ pw.println("mConnections: deviceId -> Connection");
+ pw.increaseIndent();
+ for (int i = 0; i < mConnections.size(); i++) {
+ int deviceId = mConnections.keyAt(i);
+ Connection mConnection = mConnections.valueAt(i);
+ pw.println(deviceId + ": " + mConnection);
+
+ }
+ pw.decreaseIndent();
+
+ pw.println("mHardwareList:");
+ pw.increaseIndent();
+ for (TvInputHardwareInfo tvInputHardwareInfo : mHardwareList) {
+ pw.println(tvInputHardwareInfo);
+ }
+ pw.decreaseIndent();
+
+ pw.println("mHdmiDeviceList:");
+ pw.increaseIndent();
+ for (HdmiDeviceInfo hdmiDeviceInfo : mHdmiDeviceList) {
+ pw.println(hdmiDeviceInfo);
+ }
+ pw.decreaseIndent();
+
+ pw.println("mHardwareInputIdMap: deviceId -> inputId");
+ pw.increaseIndent();
+ for (int i = 0 ; i < mHardwareInputIdMap.size(); i++) {
+ int deviceId = mHardwareInputIdMap.keyAt(i);
+ String inputId = mHardwareInputIdMap.valueAt(i);
+ pw.println(deviceId + ": " + inputId);
+ }
+ pw.decreaseIndent();
+
+ pw.println("mHdmiInputIdMap: id -> inputId");
+ pw.increaseIndent();
+ for (int i = 0; i < mHdmiInputIdMap.size(); i++) {
+ int id = mHdmiInputIdMap.keyAt(i);
+ String inputId = mHdmiInputIdMap.valueAt(i);
+ pw.println(id + ": " + inputId);
+ }
+ pw.decreaseIndent();
+
+ pw.println("mInputMap: inputId -> inputInfo");
+ pw.increaseIndent();
+ for(Map.Entry<String, TvInputInfo> entry : mInputMap.entrySet()) {
+ pw.println(entry.getKey() + ": " + entry.getValue());
+ }
+ pw.decreaseIndent();
+ pw.decreaseIndent();
+ }
+ }
+
private class Connection implements IBinder.DeathRecipient {
private final TvInputHardwareInfo mHardwareInfo;
private TvInputInfo mInfo;
@@ -641,6 +711,17 @@
resetLocked(null, null, null, null, null);
}
}
+
+ public String toString() {
+ return "Connection{"
+ + " mHardwareInfo: " + mHardwareInfo
+ + ", mInfo: " + mInfo
+ + ", mCallback: " + mCallback
+ + ", mConfigs: " + Arrays.toString(mConfigs)
+ + ", mCallingUid: " + mCallingUid
+ + ", mResolvedUserId: " + mResolvedUserId
+ + " }";
+ }
}
private class TvInputHardwareImpl extends ITvInputHardware.Stub {
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 628c627..49aaa4a 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -1923,6 +1923,7 @@
pw.decreaseIndent();
}
}
+ mTvInputHardwareManager.dump(fd, writer, args);
}
}
@@ -2511,7 +2512,7 @@
// For the recording session only
@Override
- public void onTuned() {
+ public void onTuned(Uri channelUri) {
synchronized (mLock) {
if (DEBUG) {
Slog.d(TAG, "onTuned()");
@@ -2520,7 +2521,7 @@
return;
}
try {
- mSessionState.client.onTuned(mSessionState.seq);
+ mSessionState.client.onTuned(mSessionState.seq, channelUri);
} catch (RemoteException e) {
Slog.e(TAG, "error in onTuned", e);
}
diff --git a/services/core/java/com/android/server/twilight/TwilightManager.java b/services/core/java/com/android/server/twilight/TwilightManager.java
index b3de58b..56137a4 100644
--- a/services/core/java/com/android/server/twilight/TwilightManager.java
+++ b/services/core/java/com/android/server/twilight/TwilightManager.java
@@ -20,5 +20,6 @@
public interface TwilightManager {
void registerListener(TwilightListener listener, Handler handler);
+ void unregisterListener(TwilightListener listener);
TwilightState getCurrentState();
}
diff --git a/services/core/java/com/android/server/twilight/TwilightService.java b/services/core/java/com/android/server/twilight/TwilightService.java
index a71961c..6158c92 100644
--- a/services/core/java/com/android/server/twilight/TwilightService.java
+++ b/services/core/java/com/android/server/twilight/TwilightService.java
@@ -19,12 +19,15 @@
import com.android.server.SystemService;
import com.android.server.TwilightCalculator;
+import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.database.ContentObserver;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
@@ -33,6 +36,9 @@
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.provider.Settings.Secure;
import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.Slog;
@@ -54,6 +60,26 @@
static final String ACTION_UPDATE_TWILIGHT_STATE =
"com.android.server.action.UPDATE_TWILIGHT_STATE";
+ // The amount of time after or before sunrise over which to start adjusting
+ // twilight affected things. We want the change to happen gradually so that
+ // it is below the threshold of perceptibility and so that the adjustment has
+ // maximum effect well after dusk.
+ private static final long TWILIGHT_ADJUSTMENT_TIME = DateUtils.HOUR_IN_MILLIS * 2;
+
+ // Broadcast when twilight changes.
+ public static final String ACTION_TWILIGHT_CHANGED = "android.intent.action.TWILIGHT_CHANGED";
+
+ public static final String EXTRA_IS_NIGHT = "isNight";
+ public static final String EXTRA_AMOUNT = "amount";
+
+ // Amount of time the TwilightService will stay locked in an override state before switching
+ // back to auto.
+ private static final long RESET_TIME = DateUtils.HOUR_IN_MILLIS * 2;
+ private static final String EXTRA_RESET_USER = "user";
+
+ private static final String ACTION_RESET_TWILIGHT_AUTO =
+ "com.android.server.action.RESET_TWILIGHT_AUTO";
+
final Object mLock = new Object();
AlarmManager mAlarmManager;
@@ -65,6 +91,10 @@
TwilightState mTwilightState;
+ private int mCurrentUser;
+ private boolean mLocked;
+ private boolean mBootCompleted;
+
public TwilightService(Context context) {
super(context);
}
@@ -75,16 +105,95 @@
mLocationManager = (LocationManager) getContext().getSystemService(
Context.LOCATION_SERVICE);
mLocationHandler = new LocationHandler();
+ mCurrentUser = ActivityManager.getCurrentUser();
IntentFilter filter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
filter.addAction(ACTION_UPDATE_TWILIGHT_STATE);
- getContext().registerReceiver(mUpdateLocationReceiver, filter);
+ getContext().registerReceiver(mReceiver, filter);
publishLocalService(TwilightManager.class, mService);
}
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == PHASE_BOOT_COMPLETED) {
+ getContext().getContentResolver().registerContentObserver(
+ Secure.getUriFor(Secure.TWILIGHT_MODE), false, mContentObserver, mCurrentUser);
+ mContentObserver.onChange(true);
+ mBootCompleted = true;
+ sendBroadcast();
+ }
+ }
+
+ private void reregisterSettingObserver() {
+ final ContentResolver contentResolver = getContext().getContentResolver();
+ contentResolver.unregisterContentObserver(mContentObserver);
+ contentResolver.registerContentObserver(Secure.getUriFor(Secure.TWILIGHT_MODE), false,
+ mContentObserver, mCurrentUser);
+ mContentObserver.onChange(true);
+ }
+
+ private void setLockedState(TwilightState state) {
+ synchronized (mLock) {
+ // Make sure we aren't locked so we can set the state.
+ mLocked = false;
+ setTwilightState(state);
+ // Make sure we leave the state locked, so it cant be changed.
+ mLocked = true;
+ // TODO: Don't bother updating state when locked.
+ }
+ }
+
+ private void setTwilightState(TwilightState state) {
+ synchronized (mLock) {
+ if (mLocked) {
+ // State has been locked by secure setting, shouldn't be changed.
+ return;
+ }
+ if (!Objects.equal(mTwilightState, state)) {
+ if (DEBUG) {
+ Slog.d(TAG, "Twilight state changed: " + state);
+ }
+
+ mTwilightState = state;
+
+ final int listenerLen = mListeners.size();
+ for (int i = 0; i < listenerLen; i++) {
+ mListeners.get(i).postUpdate();
+ }
+ }
+ }
+ sendBroadcast();
+ }
+
+ private void sendBroadcast() {
+ synchronized (mLock) {
+ if (mTwilightState == null) {
+ return;
+ }
+ if (mBootCompleted) {
+ Intent intent = new Intent(ACTION_TWILIGHT_CHANGED);
+ intent.putExtra(EXTRA_IS_NIGHT, mTwilightState.isNight());
+ intent.putExtra(EXTRA_AMOUNT, mTwilightState.getAmount());
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+ }
+ }
+ }
+
+ private void scheduleReset() {
+ long resetTime = System.currentTimeMillis() + RESET_TIME;
+ Intent resetIntent = new Intent(ACTION_RESET_TWILIGHT_AUTO);
+ resetIntent.putExtra(EXTRA_RESET_USER, mCurrentUser);
+ PendingIntent pendingIntent = PendingIntent.getBroadcast(
+ getContext(), 0, resetIntent, 0);
+ mAlarmManager.cancel(pendingIntent);
+ mAlarmManager.setExact(AlarmManager.RTC, resetTime, pendingIntent);
+ }
+
private static class TwilightListenerRecord implements Runnable {
private final TwilightListener mListener;
private final Handler mHandler;
@@ -133,24 +242,22 @@
}
}
}
- };
- private void setTwilightState(TwilightState state) {
- synchronized (mLock) {
- if (!Objects.equal(mTwilightState, state)) {
- if (DEBUG) {
- Slog.d(TAG, "Twilight state changed: " + state);
+ @Override
+ public void unregisterListener(TwilightListener listener) {
+ synchronized (mLock) {
+ for (int i = 0; i < mListeners.size(); i++) {
+ if (mListeners.get(i).mListener == listener) {
+ mListeners.remove(i);
+ }
}
- mTwilightState = state;
-
- final int listenerLen = mListeners.size();
- for (int i = 0; i < listenerLen; i++) {
- mListeners.get(i).postUpdate();
+ if (mListeners.size() == 0) {
+ mLocationHandler.disableLocationUpdates();
}
}
}
- }
+ };
// The user has moved if the accuracy circles of the two locations don't overlap.
private static boolean hasMoved(Location from, Location to) {
@@ -183,6 +290,7 @@
private static final int MSG_GET_NEW_LOCATION_UPDATE = 2;
private static final int MSG_PROCESS_NEW_LOCATION = 3;
private static final int MSG_DO_TWILIGHT_UPDATE = 4;
+ private static final int MSG_DISABLE_LOCATION_UPDATES = 5;
private static final long LOCATION_UPDATE_MS = 24 * DateUtils.HOUR_IN_MILLIS;
private static final long MIN_LOCATION_UPDATE_MS = 30 * DateUtils.MINUTE_IN_MILLIS;
@@ -210,6 +318,10 @@
sendEmptyMessage(MSG_ENABLE_LOCATION_UPDATES);
}
+ public void disableLocationUpdates() {
+ sendEmptyMessage(MSG_DISABLE_LOCATION_UPDATES);
+ }
+
public void requestLocationUpdate() {
sendEmptyMessage(MSG_GET_NEW_LOCATION_UPDATE);
}
@@ -311,6 +423,11 @@
}
break;
+ case MSG_DISABLE_LOCATION_UPDATES:
+ mLocationManager.removeUpdates(mLocationListener);
+ removeMessages(MSG_ENABLE_LOCATION_UPDATES);
+ break;
+
case MSG_DO_TWILIGHT_UPDATE:
updateTwilightState();
break;
@@ -368,11 +485,6 @@
final long now = System.currentTimeMillis();
- // calculate yesterday's twilight
- mTwilightCalculator.calculateTwilight(now - DateUtils.DAY_IN_MILLIS,
- mLocation.getLatitude(), mLocation.getLongitude());
- final long yesterdaySunset = mTwilightCalculator.mSunset;
-
// calculate today's twilight
mTwilightCalculator.calculateTwilight(now,
mLocation.getLatitude(), mLocation.getLongitude());
@@ -385,9 +497,19 @@
mLocation.getLatitude(), mLocation.getLongitude());
final long tomorrowSunrise = mTwilightCalculator.mSunrise;
+ float amount = 0;
+ if (isNight) {
+ if (todaySunrise == -1 || todaySunset == -1) {
+ amount = 1;
+ } else if (now > todaySunset) {
+ amount = Math.min(1, (now - todaySunset) / (float) TWILIGHT_ADJUSTMENT_TIME);
+ } else {
+ amount = Math.max(0, 1
+ - (todaySunrise - now) / (float) TWILIGHT_ADJUSTMENT_TIME);
+ }
+ }
// set twilight state
- TwilightState state = new TwilightState(isNight, yesterdaySunset,
- todaySunrise, todaySunset, tomorrowSunrise);
+ TwilightState state = new TwilightState(isNight, amount);
if (DEBUG) {
Slog.d(TAG, "Updating twilight state: " + state);
}
@@ -402,12 +524,18 @@
// add some extra time to be on the safe side.
nextUpdate += DateUtils.MINUTE_IN_MILLIS;
- if (now > todaySunset) {
- nextUpdate += tomorrowSunrise;
- } else if (now > todaySunrise) {
- nextUpdate += todaySunset;
+ if (amount == 1 || amount == 0) {
+ if (now > todaySunset) {
+ nextUpdate += tomorrowSunrise;
+ } else if (now > todaySunrise) {
+ nextUpdate += todaySunset;
+ } else {
+ nextUpdate += todaySunrise;
+ }
} else {
- nextUpdate += todaySunrise;
+ // This is the update rate while transitioning.
+ // Leave at 10 min for now (one from above).
+ nextUpdate += 9 * DateUtils.MINUTE_IN_MILLIS;
}
}
@@ -423,9 +551,37 @@
}
}
- private final BroadcastReceiver mUpdateLocationReceiver = new BroadcastReceiver() {
+ private final ContentObserver mContentObserver = new ContentObserver(new Handler()) {
+ @Override
+ public void onChange(boolean selfChange) {
+ super.onChange(selfChange);
+ int value = Secure.getIntForUser(getContext().getContentResolver(),
+ Secure.TWILIGHT_MODE, Secure.TWILIGHT_MODE_LOCKED_OFF, mCurrentUser);
+ if (value == Secure.TWILIGHT_MODE_LOCKED_OFF) {
+ setLockedState(new TwilightState(false, 0));
+ } else if (value == Secure.TWILIGHT_MODE_LOCKED_ON) {
+ setLockedState(new TwilightState(true, 1));
+ } else if (value == Secure.TWILIGHT_MODE_AUTO_OVERRIDE_OFF) {
+ setLockedState(new TwilightState(false, 0));
+ scheduleReset();
+ } else if (value == Secure.TWILIGHT_MODE_AUTO_OVERRIDE_ON) {
+ setLockedState(new TwilightState(true, 1));
+ scheduleReset();
+ } else {
+ mLocked = false;
+ mLocationHandler.requestTwilightUpdate();
+ }
+ }
+ };
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
+ mCurrentUser = ActivityManager.getCurrentUser();
+ reregisterSettingObserver();
+ return;
+ }
if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(intent.getAction())
&& !intent.getBooleanExtra("state", false)) {
// Airplane mode is now off!
@@ -433,6 +589,12 @@
return;
}
+ if (ACTION_RESET_TWILIGHT_AUTO.equals(intent.getAction())) {
+ int user = intent.getIntExtra(EXTRA_RESET_USER, 0);
+ Settings.Secure.putIntForUser(getContext().getContentResolver(),
+ Secure.TWILIGHT_MODE, Secure.TWILIGHT_MODE_AUTO, user);
+ return;
+ }
// Time zone has changed or alarm expired.
mLocationHandler.requestTwilightUpdate();
}
diff --git a/services/core/java/com/android/server/twilight/TwilightState.java b/services/core/java/com/android/server/twilight/TwilightState.java
index 91e24d7..81abc13 100644
--- a/services/core/java/com/android/server/twilight/TwilightState.java
+++ b/services/core/java/com/android/server/twilight/TwilightState.java
@@ -25,20 +25,11 @@
*/
public class TwilightState {
private final boolean mIsNight;
- private final long mYesterdaySunset;
- private final long mTodaySunrise;
- private final long mTodaySunset;
- private final long mTomorrowSunrise;
+ private final float mAmount;
- TwilightState(boolean isNight,
- long yesterdaySunset,
- long todaySunrise, long todaySunset,
- long tomorrowSunrise) {
+ TwilightState(boolean isNight, float amount) {
mIsNight = isNight;
- mYesterdaySunset = yesterdaySunset;
- mTodaySunrise = todaySunrise;
- mTodaySunset = todaySunset;
- mTomorrowSunrise = tomorrowSunrise;
+ mAmount = amount;
}
/**
@@ -49,35 +40,11 @@
}
/**
- * Returns the time of yesterday's sunset in the System.currentTimeMillis() timebase,
- * or -1 if the sun never sets.
+ * For twilight affects that change gradually over time, this is the amount they
+ * should currently be in effect.
*/
- public long getYesterdaySunset() {
- return mYesterdaySunset;
- }
-
- /**
- * Returns the time of today's sunrise in the System.currentTimeMillis() timebase,
- * or -1 if the sun never rises.
- */
- public long getTodaySunrise() {
- return mTodaySunrise;
- }
-
- /**
- * Returns the time of today's sunset in the System.currentTimeMillis() timebase,
- * or -1 if the sun never sets.
- */
- public long getTodaySunset() {
- return mTodaySunset;
- }
-
- /**
- * Returns the time of tomorrow's sunrise in the System.currentTimeMillis() timebase,
- * or -1 if the sun never rises.
- */
- public long getTomorrowSunrise() {
- return mTomorrowSunrise;
+ public float getAmount() {
+ return mAmount;
}
@Override
@@ -88,10 +55,7 @@
public boolean equals(TwilightState other) {
return other != null
&& mIsNight == other.mIsNight
- && mYesterdaySunset == other.mYesterdaySunset
- && mTodaySunrise == other.mTodaySunrise
- && mTodaySunset == other.mTodaySunset
- && mTomorrowSunrise == other.mTomorrowSunrise;
+ && mAmount == other.mAmount;
}
@Override
@@ -103,10 +67,7 @@
public String toString() {
DateFormat f = DateFormat.getDateTimeInstance();
return "{TwilightState: isNight=" + mIsNight
- + ", mYesterdaySunset=" + f.format(new Date(mYesterdaySunset))
- + ", mTodaySunrise=" + f.format(new Date(mTodaySunrise))
- + ", mTodaySunset=" + f.format(new Date(mTodaySunset))
- + ", mTomorrowSunrise=" + f.format(new Date(mTomorrowSunrise))
+ + ", mAmount=" + mAmount
+ "}";
}
}
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 2f076d1..7611527 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -15,9 +15,12 @@
*/
package com.android.server.vr;
+import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.os.Binder;
+import android.os.IBinder;
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.Slog;
@@ -40,6 +43,9 @@
private static native void setVrModeNative(boolean enabled);
private final Object mLock = new Object();
+
+ private final IBinder mOverlayToken = new Binder();
+
private boolean mVrModeEnabled = false;
private ArraySet<VrStateListener> mListeners = new ArraySet<>();
@@ -97,11 +103,25 @@
// Log mode change event.
Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
setVrModeNative(mVrModeEnabled);
+ updateOverlayStateLocked();
onVrModeChangedLocked();
}
}
}
+ private void updateOverlayStateLocked() {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
+ if (appOpsManager != null) {
+ appOpsManager.setUserRestriction(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
+ mVrModeEnabled, mOverlayToken);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
private boolean getVrMode() {
synchronized (mLock) {
return mVrModeEnabled;
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 09c53ae..ccbdad2 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -16,6 +16,8 @@
package com.android.server.wallpaper;
+import static android.app.WallpaperManager.FLAG_SET_SYSTEM;
+import static android.app.WallpaperManager.FLAG_SET_LOCK;
import static android.os.ParcelFileDescriptor.*;
import android.app.ActivityManagerNative;
@@ -102,9 +104,9 @@
public class WallpaperManagerService extends IWallpaperManager.Stub {
static final String TAG = "WallpaperManagerService";
- static final boolean DEBUG = true;
+ static final boolean DEBUG = false;
- final Object mLock = new Object[0];
+ final Object mLock = new Object();
/**
* Minimum time between crashes of a wallpaper service for us to consider
@@ -114,8 +116,17 @@
static final int MAX_WALLPAPER_COMPONENT_LOG_LENGTH = 128;
static final String WALLPAPER = "wallpaper_orig";
static final String WALLPAPER_CROP = "wallpaper";
+ static final String WALLPAPER_LOCK_ORIG = "wallpaper_lock_orig";
+ static final String WALLPAPER_LOCK_CROP = "wallpaper_lock";
static final String WALLPAPER_INFO = "wallpaper_info.xml";
+ // All the various per-user state files we need to be aware of
+ static final String[] sPerUserFiles = new String[] {
+ WALLPAPER, WALLPAPER_CROP,
+ WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP,
+ WALLPAPER_INFO
+ };
+
/**
* Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks
* that the wallpaper has changed. The CREATE is triggered when there is no
@@ -124,22 +135,38 @@
*/
private class WallpaperObserver extends FileObserver {
+ final int mUserId;
final WallpaperData mWallpaper;
final File mWallpaperDir;
final File mWallpaperFile;
- final File mWallpaperCropFile;
+ final File mWallpaperLockFile;
final File mWallpaperInfoFile;
public WallpaperObserver(WallpaperData wallpaper) {
super(getWallpaperDir(wallpaper.userId).getAbsolutePath(),
CLOSE_WRITE | MOVED_TO | DELETE | DELETE_SELF);
+ mUserId = wallpaper.userId;
mWallpaperDir = getWallpaperDir(wallpaper.userId);
mWallpaper = wallpaper;
mWallpaperFile = new File(mWallpaperDir, WALLPAPER);
- mWallpaperCropFile = new File(mWallpaperDir, WALLPAPER_CROP);
+ mWallpaperLockFile = new File(mWallpaperDir, WALLPAPER_LOCK_ORIG);
mWallpaperInfoFile = new File(mWallpaperDir, WALLPAPER_INFO);
}
+ private WallpaperData dataForEvent(boolean sysChanged, boolean lockChanged) {
+ WallpaperData wallpaper = null;
+ synchronized (mLock) {
+ if (lockChanged) {
+ wallpaper = mLockWallpaperMap.get(mUserId);
+ }
+ if (wallpaper == null) {
+ // no lock-specific wallpaper exists, or sys case, handled together
+ wallpaper = mWallpaperMap.get(mUserId);
+ }
+ }
+ return (wallpaper != null) ? wallpaper : mWallpaper;
+ }
+
@Override
public void onEvent(int event, String path) {
if (path == null) {
@@ -148,38 +175,82 @@
final boolean written = (event == CLOSE_WRITE || event == MOVED_TO);
final File changedFile = new File(mWallpaperDir, path);
+ // System and system+lock changes happen on the system wallpaper input file;
+ // lock-only changes happen on the dedicated lock wallpaper input file
+ final boolean sysWallpaperChanged = (mWallpaperFile.equals(changedFile));
+ final boolean lockWallpaperChanged = (mWallpaperLockFile.equals(changedFile));
+ WallpaperData wallpaper = dataForEvent(sysWallpaperChanged, lockWallpaperChanged);
+
+ if (DEBUG) {
+ Slog.v(TAG, "Wallpaper file change: evt=" + event
+ + " path=" + path
+ + " sys=" + sysWallpaperChanged
+ + " lock=" + lockWallpaperChanged
+ + " imagePending=" + wallpaper.imageWallpaperPending
+ + " whichPending=0x" + Integer.toHexString(wallpaper.whichPending)
+ + " written=" + written);
+ }
synchronized (mLock) {
- if (mWallpaperFile.equals(changedFile)
- || mWallpaperInfoFile.equals(changedFile)) {
+ if (sysWallpaperChanged || mWallpaperInfoFile.equals(changedFile)) {
// changing the wallpaper means we'll need to back up the new one
long origId = Binder.clearCallingIdentity();
BackupManager bm = new BackupManager(mContext);
bm.dataChanged();
Binder.restoreCallingIdentity(origId);
}
- if (mWallpaperFile.equals(changedFile)) {
- notifyCallbacksLocked(mWallpaper);
- if (mWallpaper.wallpaperComponent == null
+ if (sysWallpaperChanged || lockWallpaperChanged) {
+ notifyCallbacksLocked(wallpaper);
+ if (wallpaper.wallpaperComponent == null
|| event != CLOSE_WRITE // includes the MOVED_TO case
- || mWallpaper.imageWallpaperPending) {
+ || wallpaper.imageWallpaperPending) {
if (written) {
// The image source has finished writing the source image,
// so we now produce the crop rect (in the background), and
// only publish the new displayable (sub)image as a result
// of that work.
- generateCrop(mWallpaper);
- mWallpaper.imageWallpaperPending = false;
- if (mWallpaper.setComplete != null) {
+ if (DEBUG) {
+ Slog.v(TAG, "Wallpaper written; generating crop");
+ }
+ generateCrop(wallpaper);
+ if (DEBUG) {
+ Slog.v(TAG, "Crop done; invoking completion callback");
+ }
+ wallpaper.imageWallpaperPending = false;
+ if (wallpaper.setComplete != null) {
try {
- mWallpaper.setComplete.onWallpaperChanged();
+ wallpaper.setComplete.onWallpaperChanged();
} catch (RemoteException e) {
// if this fails we don't really care; the setting app may just
// have crashed and that sort of thing is a fact of life.
}
}
- bindWallpaperComponentLocked(mImageWallpaper, true,
- false, mWallpaper, null);
- saveSettingsLocked(mWallpaper);
+ if (sysWallpaperChanged) {
+ // If this was the system wallpaper, rebind...
+ bindWallpaperComponentLocked(mImageWallpaper, true,
+ false, wallpaper, null);
+ }
+ if (lockWallpaperChanged
+ || (wallpaper.whichPending & FLAG_SET_LOCK) != 0) {
+ if (DEBUG) {
+ Slog.i(TAG, "Lock-relevant wallpaper changed");
+ }
+ // either a lock-only wallpaper commit or a system+lock event.
+ // if it's system-plus-lock we need to wipe the lock bookkeeping;
+ // we're falling back to displaying the system wallpaper there.
+ if (!lockWallpaperChanged) {
+ mLockWallpaperMap.remove(wallpaper.userId);
+ }
+ // and in any case, tell keyguard about it
+ final IWallpaperManagerCallback cb = mKeyguardListener;
+ if (cb != null) {
+ try {
+ cb.onWallpaperChanged();
+ } catch (RemoteException e) {
+ // Oh well it went away; no big deal
+ }
+ }
+ }
+ saveSettingsLocked(wallpaper.userId);
}
}
}
@@ -194,12 +265,21 @@
private void generateCrop(WallpaperData wallpaper) {
boolean success = false;
boolean needCrop = false;
+ boolean needScale = false;
+
+ if (DEBUG) {
+ Slog.v(TAG, "Generating crop for new wallpaper(s): 0x"
+ + Integer.toHexString(wallpaper.whichPending)
+ + " to " + wallpaper.cropFile.getName());
+ }
// Analyse the source; needed in multiple cases
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(wallpaper.wallpaperFile.getAbsolutePath(), options);
+ // We'll need to scale if the crop is sufficiently bigger than the display
+
// Legacy case uses an empty crop rect here, so we just preserve the
// source image verbatim
if (!wallpaper.cropHint.isEmpty()) {
@@ -211,7 +291,7 @@
&& options.outWidth >= wallpaper.cropHint.width());
}
- if (!needCrop) {
+ if (!needCrop && !needScale) {
// Simple case: the nominal crop is at least as big as the source image,
// so we take the whole thing and just copy the image file directly.
if (DEBUG) {
@@ -223,7 +303,7 @@
// TODO: fall back to default wallpaper in this case
}
} else {
- // Fancy case: the crop is a subrect of the source
+ // Fancy case: crop and/or scale
FileOutputStream f = null;
BufferedOutputStream bos = null;
try {
@@ -270,6 +350,7 @@
final MyPackageMonitor mMonitor;
final AppOpsManager mAppOpsManager;
WallpaperData mLastWallpaper;
+ IWallpaperManagerCallback mKeyguardListener;
/**
* ID of the current wallpaper, changed every time anything sets a wallpaper.
@@ -283,7 +364,8 @@
*/
final ComponentName mImageWallpaper;
- SparseArray<WallpaperData> mWallpaperMap = new SparseArray<WallpaperData>();
+ final SparseArray<WallpaperData> mWallpaperMap = new SparseArray<WallpaperData>();
+ final SparseArray<WallpaperData> mLockWallpaperMap = new SparseArray<WallpaperData>();
int mCurrentUserId;
@@ -291,15 +373,21 @@
int userId;
- final File wallpaperFile;
- final File cropFile;
+ final File wallpaperFile; // source image
+ final File cropFile; // eventual destination
/**
- * Client is currently writing a new image wallpaper.
+ * True while the client is writing a new wallpaper
*/
boolean imageWallpaperPending;
/**
+ * Which new wallpapers are being written; mirrors the 'which'
+ * selector bit field to setWallpaper().
+ */
+ int whichPending;
+
+ /**
* Callback once the set + crop is finished
*/
IWallpaperManagerCallback setComplete;
@@ -345,13 +433,14 @@
final Rect padding = new Rect(0, 0, 0, 0);
- WallpaperData(int userId) {
+ WallpaperData(int userId, String inputFileName, String cropFileName) {
this.userId = userId;
- wallpaperFile = new File(getWallpaperDir(userId), WALLPAPER);
- cropFile = new File(getWallpaperDir(userId), WALLPAPER_CROP);
+ final File wallpaperDir = getWallpaperDir(userId);
+ wallpaperFile = new File(wallpaperDir, inputFileName);
+ cropFile = new File(wallpaperDir, cropFileName);
}
- // Only called in single-threaded boot sequence mode
+ // Called during initialization of a given user's wallpaper bookkeeping
boolean ensureCropExists() {
// if the crop file is not present, copy over the source image to use verbatim
if (!cropFile.exists()) {
@@ -395,7 +484,7 @@
// when we have an engine, but I'm not sure about
// locking there and anyway we always need to be able to
// recover if there is something wrong.
- saveSettingsLocked(mWallpaper);
+ saveSettingsLocked(mWallpaper.userId);
}
}
}
@@ -419,7 +508,7 @@
&& mWallpaper.lastDiedTime + MIN_WALLPAPER_CRASH_TIME
> SystemClock.uptimeMillis()) {
Slog.w(TAG, "Reverting to built-in wallpaper!");
- clearWallpaperLocked(true, mWallpaper.userId, null);
+ clearWallpaperLocked(true, FLAG_SET_SYSTEM, mWallpaper.userId, null);
} else {
mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
}
@@ -498,7 +587,7 @@
if (!bindWallpaperComponentLocked(comp, false, false,
wallpaper, null)) {
Slog.w(TAG, "Wallpaper no longer available; reverting to default");
- clearWallpaperLocked(false, wallpaper.userId, null);
+ clearWallpaperLocked(false, FLAG_SET_SYSTEM, wallpaper.userId, null);
}
}
}
@@ -578,7 +667,7 @@
if (doit) {
Slog.w(TAG, "Wallpaper uninstalled, removing: "
+ wallpaper.wallpaperComponent);
- clearWallpaperLocked(false, wallpaper.userId, null);
+ clearWallpaperLocked(false, FLAG_SET_SYSTEM, wallpaper.userId, null);
}
}
}
@@ -598,7 +687,7 @@
} catch (NameNotFoundException e) {
Slog.w(TAG, "Wallpaper component gone, removing: "
+ wallpaper.wallpaperComponent);
- clearWallpaperLocked(false, wallpaper.userId, null);
+ clearWallpaperLocked(false, FLAG_SET_SYSTEM, wallpaper.userId, null);
}
}
if (wallpaper.nextWallpaperComponent != null
@@ -646,7 +735,7 @@
if (DEBUG) Slog.v(TAG, "systemReady");
WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM);
if (!wallpaper.ensureCropExists()) {
- clearWallpaperLocked(false, UserHandle.USER_SYSTEM, null);
+ clearWallpaperLocked(false, FLAG_SET_SYSTEM, UserHandle.USER_SYSTEM, null);
}
switchWallpaper(wallpaper, null);
wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
@@ -706,37 +795,38 @@
}
}
- void onStoppingUser(int userId) {
- if (userId < 1) return;
- synchronized (mLock) {
- WallpaperData wallpaper = mWallpaperMap.get(userId);
- if (wallpaper != null) {
- if (wallpaper.wallpaperObserver != null) {
- wallpaper.wallpaperObserver.stopWatching();
- wallpaper.wallpaperObserver = null;
- }
- mWallpaperMap.remove(userId);
+ void stopObserver(WallpaperData wallpaper) {
+ if (wallpaper != null) {
+ if (wallpaper.wallpaperObserver != null) {
+ wallpaper.wallpaperObserver.stopWatching();
+ wallpaper.wallpaperObserver = null;
}
}
}
+ void stopObserversLocked(int userId) {
+ stopObserver(mWallpaperMap.get(userId));
+ stopObserver(mLockWallpaperMap.get(userId));
+ mWallpaperMap.remove(userId);
+ mLockWallpaperMap.remove(userId);
+ }
+
void onRemoveUser(int userId) {
if (userId < 1) return;
+
+ final File wallpaperDir = getWallpaperDir(userId);
synchronized (mLock) {
- onStoppingUser(userId);
- File wallpaperFile = new File(getWallpaperDir(userId), WALLPAPER);
- wallpaperFile.delete();
- File cropFile = new File(getWallpaperDir(userId), WALLPAPER_CROP);
- cropFile.delete();
- File wallpaperInfoFile = new File(getWallpaperDir(userId), WALLPAPER_INFO);
- wallpaperInfoFile.delete();
+ stopObserversLocked(userId);
+ for (String filename : sPerUserFiles) {
+ new File(wallpaperDir, filename).delete();
+ }
}
}
void switchUser(int userId, IRemoteCallback reply) {
synchronized (mLock) {
mCurrentUserId = userId;
- WallpaperData wallpaper = getWallpaperSafeLocked(userId);
+ WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SET_SYSTEM);
// Not started watching yet, in case wallpaper data was loaded for other reasons.
if (wallpaper.wallpaperObserver == null) {
wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
@@ -759,32 +849,79 @@
e = e1;
}
Slog.w(TAG, "Failure starting previous wallpaper", e);
- clearWallpaperLocked(false, wallpaper.userId, reply);
+ clearWallpaperLocked(false, FLAG_SET_SYSTEM, wallpaper.userId, reply);
}
}
- public void clearWallpaper(String callingPackage) {
+ @Override
+ public void clearWallpaper(String callingPackage, int which, int userId) {
if (DEBUG) Slog.v(TAG, "clearWallpaper");
checkPermission(android.Manifest.permission.SET_WALLPAPER);
if (!isWallpaperSupported(callingPackage) || !isWallpaperSettingAllowed(callingPackage)) {
return;
}
+ if (userId != UserHandle.getCallingUserId()) {
+ // cross-user call
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ "WallpaperManagerService");
+ }
+
synchronized (mLock) {
- clearWallpaperLocked(false, UserHandle.getCallingUserId(), null);
+ clearWallpaperLocked(false, which, userId, null);
}
}
- void clearWallpaperLocked(boolean defaultFailed, int userId, IRemoteCallback reply) {
- WallpaperData wallpaper = mWallpaperMap.get(userId);
+ void clearWallpaperLocked(boolean defaultFailed, int which, int userId, IRemoteCallback reply) {
+ if (which != FLAG_SET_SYSTEM && which != FLAG_SET_LOCK) {
+ throw new IllegalArgumentException("Must specify exactly one kind of wallpaper to read");
+ }
+
+ WallpaperData wallpaper = null;
+ if (which == FLAG_SET_LOCK) {
+ wallpaper = mLockWallpaperMap.get(userId);
+ if (wallpaper == null) {
+ // It's already gone; we're done.
+ if (DEBUG) {
+ Slog.i(TAG, "Lock wallpaper already cleared");
+ }
+ return;
+ }
+ } else {
+ wallpaper = mWallpaperMap.get(userId);
+ if (wallpaper == null) {
+ // Might need to bring it in the first time to establish our rewrite
+ loadSettingsLocked(userId);
+ wallpaper = mWallpaperMap.get(userId);
+ }
+ }
if (wallpaper == null) {
return;
}
- if (wallpaper.wallpaperFile.exists()) {
- wallpaper.wallpaperFile.delete();
- wallpaper.cropFile.delete();
- }
+
final long ident = Binder.clearCallingIdentity();
try {
+ if (wallpaper.wallpaperFile.exists()) {
+ wallpaper.wallpaperFile.delete();
+ wallpaper.cropFile.delete();
+ if (which == FLAG_SET_LOCK) {
+ mLockWallpaperMap.remove(userId);
+ final IWallpaperManagerCallback cb = mKeyguardListener;
+ if (cb != null) {
+ if (DEBUG) {
+ Slog.i(TAG, "Notifying keyguard of lock wallpaper clear");
+ }
+ try {
+ cb.onWallpaperChanged();
+ } catch (RemoteException e) {
+ // Oh well it went away; no big deal
+ }
+ }
+ saveSettingsLocked(userId);
+ return;
+ }
+ }
+
RuntimeException e = null;
try {
wallpaper.imageWallpaperPending = false;
@@ -859,7 +996,7 @@
}
synchronized (mLock) {
int userId = UserHandle.getCallingUserId();
- WallpaperData wallpaper = getWallpaperSafeLocked(userId);
+ WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SET_SYSTEM);
if (width <= 0 || height <= 0) {
throw new IllegalArgumentException("width and height must be > 0");
}
@@ -871,7 +1008,7 @@
if (width != wallpaper.width || height != wallpaper.height) {
wallpaper.width = width;
wallpaper.height = height;
- saveSettingsLocked(wallpaper);
+ saveSettingsLocked(userId);
if (mCurrentUserId != userId) return; // Don't change the properties now
if (wallpaper.connection != null) {
if (wallpaper.connection.mEngine != null) {
@@ -921,14 +1058,14 @@
}
synchronized (mLock) {
int userId = UserHandle.getCallingUserId();
- WallpaperData wallpaper = getWallpaperSafeLocked(userId);
+ WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SET_SYSTEM);
if (padding.left < 0 || padding.top < 0 || padding.right < 0 || padding.bottom < 0) {
throw new IllegalArgumentException("padding must be positive: " + padding);
}
if (!padding.equals(wallpaper.padding)) {
wallpaper.padding.set(padding);
- saveSettingsLocked(wallpaper);
+ saveSettingsLocked(userId);
if (mCurrentUserId != userId) return; // Don't change the properties now
if (wallpaper.connection != null) {
if (wallpaper.connection.mEngine != null) {
@@ -948,28 +1085,41 @@
}
}
- public ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb,
- Bundle outParams) {
+ @Override
+ public ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb, final int which,
+ Bundle outParams, int wallpaperUserId) {
+ if (wallpaperUserId != UserHandle.getCallingUserId()) {
+ // cross-user call
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ "WallpaperManagerService");
+ }
+
+ if (which != FLAG_SET_SYSTEM && which != FLAG_SET_LOCK) {
+ throw new IllegalArgumentException("Must specify exactly one kind of wallpaper to read");
+ }
+
synchronized (mLock) {
- // This returns the current user's wallpaper, if called by a system service. Else it
- // returns the wallpaper for the calling user.
- int callingUid = Binder.getCallingUid();
- int wallpaperUserId = 0;
- if (callingUid == android.os.Process.SYSTEM_UID) {
- wallpaperUserId = mCurrentUserId;
- } else {
- wallpaperUserId = UserHandle.getUserId(callingUid);
- }
- WallpaperData wallpaper = mWallpaperMap.get(wallpaperUserId);
+ final SparseArray<WallpaperData> whichSet =
+ (which == FLAG_SET_LOCK) ? mLockWallpaperMap : mWallpaperMap;
+ WallpaperData wallpaper = whichSet.get(wallpaperUserId);
if (wallpaper == null) {
- return null;
+ // common case, this is the first lookup post-boot of the system or
+ // unified lock, so we bring up the saved state lazily now and recheck.
+ loadSettingsLocked(wallpaperUserId);
+ wallpaper = whichSet.get(wallpaperUserId);
+ if (wallpaper == null) {
+ return null;
+ }
}
try {
if (outParams != null) {
outParams.putInt("width", wallpaper.width);
outParams.putInt("height", wallpaper.height);
}
- wallpaper.callbacks.register(cb);
+ if (cb != null) {
+ wallpaper.callbacks.register(cb);
+ }
if (!wallpaper.cropFile.exists()) {
return null;
}
@@ -994,11 +1144,21 @@
}
@Override
+ public boolean setLockWallpaperCallback(IWallpaperManagerCallback cb) {
+ checkPermission(android.Manifest.permission.INTERNAL_SYSTEM_WINDOW);
+ synchronized (mLock) {
+ mKeyguardListener = cb;
+ }
+ return true;
+ }
+
+ @Override
public ParcelFileDescriptor setWallpaper(String name, String callingPackage,
Rect cropHint, Bundle extras, int which, IWallpaperManagerCallback completion) {
checkPermission(android.Manifest.permission.SET_WALLPAPER);
- if (which == 0) {
+ if ((which & (FLAG_SET_LOCK|FLAG_SET_SYSTEM)) == 0) {
+ Slog.e(TAG, "Must specify a valid wallpaper category to set");
return null;
}
@@ -1017,15 +1177,19 @@
}
}
+ final int userId = UserHandle.getCallingUserId();
+
synchronized (mLock) {
- if (DEBUG) Slog.v(TAG, "setWallpaper");
- int userId = UserHandle.getCallingUserId();
- WallpaperData wallpaper = getWallpaperSafeLocked(userId);
+ if (DEBUG) Slog.v(TAG, "setWallpaper which=0x" + Integer.toHexString(which));
+ WallpaperData wallpaper;
+
+ wallpaper = getWallpaperSafeLocked(userId, which);
final long ident = Binder.clearCallingIdentity();
try {
ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper, extras);
if (pfd != null) {
wallpaper.imageWallpaperPending = true;
+ wallpaper.whichPending = which;
wallpaper.setComplete = completion;
wallpaper.cropHint.set(cropHint);
}
@@ -1048,10 +1212,9 @@
FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
-1, -1);
}
- File file = new File(dir, WALLPAPER);
- ParcelFileDescriptor fd = ParcelFileDescriptor.open(file,
+ ParcelFileDescriptor fd = ParcelFileDescriptor.open(wallpaper.wallpaperFile,
MODE_CREATE|MODE_READ_WRITE|MODE_TRUNCATE);
- if (!SELinux.restorecon(file)) {
+ if (!SELinux.restorecon(wallpaper.wallpaperFile)) {
return null;
}
wallpaper.name = name;
@@ -1061,7 +1224,7 @@
}
if (DEBUG) {
Slog.v(TAG, "updateWallpaperBitmapLocked() : id=" + wallpaper.wallpaperId
- + " name=" + name);
+ + " name=" + name + " file=" + wallpaper.wallpaperFile.getName());
}
return fd;
} catch (FileNotFoundException e) {
@@ -1154,7 +1317,7 @@
List<ResolveInfo> ris =
mIPackageManager.queryIntentServices(intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
- PackageManager.GET_META_DATA, serviceUserId);
+ PackageManager.GET_META_DATA, serviceUserId).getList();
for (int i=0; i<ris.size(); i++) {
ServiceInfo rsi = ris.get(i).serviceInfo;
if (rsi.name.equals(si.name) &&
@@ -1338,50 +1501,33 @@
return new JournaledFile(new File(base), new File(base + ".tmp"));
}
- private void saveSettingsLocked(WallpaperData wallpaper) {
- JournaledFile journal = makeJournaledFile(wallpaper.userId);
- FileOutputStream stream = null;
+ private void saveSettingsLocked(int userId) {
+ JournaledFile journal = makeJournaledFile(userId);
+ FileOutputStream fstream = null;
+ BufferedOutputStream stream = null;
try {
- stream = new FileOutputStream(journal.chooseForWrite(), false);
XmlSerializer out = new FastXmlSerializer();
+ fstream = new FileOutputStream(journal.chooseForWrite(), false);
+ stream = new BufferedOutputStream(fstream);
out.setOutput(stream, StandardCharsets.UTF_8.name());
out.startDocument(null, true);
- out.startTag(null, "wp");
- out.attribute(null, "id", Integer.toString(wallpaper.wallpaperId));
- out.attribute(null, "width", Integer.toString(wallpaper.width));
- out.attribute(null, "height", Integer.toString(wallpaper.height));
+ WallpaperData wallpaper;
- out.attribute(null, "cropLeft", Integer.toString(wallpaper.cropHint.left));
- out.attribute(null, "cropTop", Integer.toString(wallpaper.cropHint.top));
- out.attribute(null, "cropRight", Integer.toString(wallpaper.cropHint.right));
- out.attribute(null, "cropBottom", Integer.toString(wallpaper.cropHint.bottom));
-
- if (wallpaper.padding.left != 0) {
- out.attribute(null, "paddingLeft", Integer.toString(wallpaper.padding.left));
+ wallpaper = mWallpaperMap.get(userId);
+ if (wallpaper != null) {
+ writeWallpaperAttributes(out, "wp", wallpaper);
}
- if (wallpaper.padding.top != 0) {
- out.attribute(null, "paddingTop", Integer.toString(wallpaper.padding.top));
+ wallpaper = mLockWallpaperMap.get(userId);
+ if (wallpaper != null) {
+ writeWallpaperAttributes(out, "kwp", wallpaper);
}
- if (wallpaper.padding.right != 0) {
- out.attribute(null, "paddingRight", Integer.toString(wallpaper.padding.right));
- }
- if (wallpaper.padding.bottom != 0) {
- out.attribute(null, "paddingBottom", Integer.toString(wallpaper.padding.bottom));
- }
-
- out.attribute(null, "name", wallpaper.name);
- if (wallpaper.wallpaperComponent != null
- && !wallpaper.wallpaperComponent.equals(mImageWallpaper)) {
- out.attribute(null, "component",
- wallpaper.wallpaperComponent.flattenToShortString());
- }
- out.endTag(null, "wp");
out.endDocument();
- stream.flush();
- FileUtils.sync(stream);
- stream.close();
+
+ stream.flush(); // also flushes fstream
+ FileUtils.sync(fstream);
+ stream.close(); // also closes fstream
journal.commit();
} catch (IOException e) {
IoUtils.closeQuietly(stream);
@@ -1389,6 +1535,40 @@
}
}
+ private void writeWallpaperAttributes(XmlSerializer out, String tag, WallpaperData wallpaper)
+ throws IllegalArgumentException, IllegalStateException, IOException {
+ out.startTag(null, tag);
+ out.attribute(null, "id", Integer.toString(wallpaper.wallpaperId));
+ out.attribute(null, "width", Integer.toString(wallpaper.width));
+ out.attribute(null, "height", Integer.toString(wallpaper.height));
+
+ out.attribute(null, "cropLeft", Integer.toString(wallpaper.cropHint.left));
+ out.attribute(null, "cropTop", Integer.toString(wallpaper.cropHint.top));
+ out.attribute(null, "cropRight", Integer.toString(wallpaper.cropHint.right));
+ out.attribute(null, "cropBottom", Integer.toString(wallpaper.cropHint.bottom));
+
+ if (wallpaper.padding.left != 0) {
+ out.attribute(null, "paddingLeft", Integer.toString(wallpaper.padding.left));
+ }
+ if (wallpaper.padding.top != 0) {
+ out.attribute(null, "paddingTop", Integer.toString(wallpaper.padding.top));
+ }
+ if (wallpaper.padding.right != 0) {
+ out.attribute(null, "paddingRight", Integer.toString(wallpaper.padding.right));
+ }
+ if (wallpaper.padding.bottom != 0) {
+ out.attribute(null, "paddingBottom", Integer.toString(wallpaper.padding.bottom));
+ }
+
+ out.attribute(null, "name", wallpaper.name);
+ if (wallpaper.wallpaperComponent != null
+ && !wallpaper.wallpaperComponent.equals(mImageWallpaper)) {
+ out.attribute(null, "component",
+ wallpaper.wallpaperComponent.flattenToShortString());
+ }
+ out.endTag(null, tag);
+ }
+
private void migrateFromOld() {
File oldWallpaper = new File(WallpaperBackupHelper.WALLPAPER_IMAGE_KEY);
File oldInfo = new File(WallpaperBackupHelper.WALLPAPER_INFO_KEY);
@@ -1417,11 +1597,36 @@
* want to update the data. The data is going to be applied when the user switch observer
* is eventually executed.
*/
- private WallpaperData getWallpaperSafeLocked(int userId) {
- WallpaperData wallpaper = mWallpaperMap.get(userId);
+ private WallpaperData getWallpaperSafeLocked(int userId, int which) {
+ // We're setting either just system (work with the system wallpaper),
+ // both (also work with the system wallpaper), or just the lock
+ // wallpaper (update against the existing lock wallpaper if any).
+ // Combined or just-system operations use the 'system' WallpaperData
+ // for this use; lock-only operations use the dedicated one.
+ final SparseArray<WallpaperData> whichSet =
+ (which == FLAG_SET_LOCK) ? mLockWallpaperMap : mWallpaperMap;
+ WallpaperData wallpaper = whichSet.get(userId);
if (wallpaper == null) {
+ // common case, this is the first lookup post-boot of the system or
+ // unified lock, so we bring up the saved state lazily now and recheck.
loadSettingsLocked(userId);
- wallpaper = mWallpaperMap.get(userId);
+ wallpaper = whichSet.get(userId);
+ // if it's still null here, this is a lock-only operation and there is not
+ // yet a lock-only wallpaper set for this user, so we need to establish
+ // it now.
+ if (wallpaper == null) {
+ if (which == FLAG_SET_LOCK) {
+ wallpaper = new WallpaperData(userId,
+ WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
+ mLockWallpaperMap.put(userId, wallpaper);
+ } else {
+ // sanity fallback: we're in bad shape, but establishing a known
+ // valid system+lock WallpaperData will keep us from dying.
+ Slog.wtf(TAG, "Didn't find wallpaper in non-lock case!");
+ wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
+ mWallpaperMap.put(userId, wallpaper);
+ }
+ }
}
return wallpaper;
}
@@ -1438,8 +1643,9 @@
}
WallpaperData wallpaper = mWallpaperMap.get(userId);
if (wallpaper == null) {
- wallpaper = new WallpaperData(userId);
+ wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
mWallpaperMap.put(userId, wallpaper);
+ wallpaper.ensureCropExists();
}
boolean success = false;
try {
@@ -1453,28 +1659,10 @@
if (type == XmlPullParser.START_TAG) {
String tag = parser.getName();
if ("wp".equals(tag)) {
- final String idString = parser.getAttributeValue(null, "id");
- if (idString != null) {
- final int id = wallpaper.wallpaperId = Integer.parseInt(idString);
- if (id > mWallpaperId) {
- mWallpaperId = id;
- }
- } else {
- wallpaper.wallpaperId = makeWallpaperIdLocked();
- }
+ // Common to system + lock wallpapers
+ parseWallpaperAttributes(parser, wallpaper);
- wallpaper.width = Integer.parseInt(parser.getAttributeValue(null, "width"));
- wallpaper.height = Integer.parseInt(parser
- .getAttributeValue(null, "height"));
- wallpaper.cropHint.left = getAttributeInt(parser, "cropLeft", 0);
- wallpaper.cropHint.top = getAttributeInt(parser, "cropTop", 0);
- wallpaper.cropHint.right = getAttributeInt(parser, "cropRight", 0);
- wallpaper.cropHint.bottom = getAttributeInt(parser, "cropBottom", 0);
- wallpaper.padding.left = getAttributeInt(parser, "paddingLeft", 0);
- wallpaper.padding.top = getAttributeInt(parser, "paddingTop", 0);
- wallpaper.padding.right = getAttributeInt(parser, "paddingRight", 0);
- wallpaper.padding.bottom = getAttributeInt(parser, "paddingBottom", 0);
- wallpaper.name = parser.getAttributeValue(null, "name");
+ // A system wallpaper might also be a live wallpaper
String comp = parser.getAttributeValue(null, "component");
wallpaper.nextWallpaperComponent = comp != null
? ComponentName.unflattenFromString(comp)
@@ -1493,6 +1681,15 @@
Slog.v(TAG, "mNextWallpaperComponent:"
+ wallpaper.nextWallpaperComponent);
}
+ } else if ("kwp".equals(tag)) {
+ // keyguard-specific wallpaper for this user
+ WallpaperData lockWallpaper = mLockWallpaperMap.get(userId);
+ if (lockWallpaper == null) {
+ lockWallpaper = new WallpaperData(userId,
+ WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
+ mLockWallpaperMap.put(userId, lockWallpaper);
+ }
+ parseWallpaperAttributes(parser, lockWallpaper);
}
}
} while (type != XmlPullParser.END_DOCUMENT);
@@ -1543,6 +1740,31 @@
}
}
+ private void parseWallpaperAttributes(XmlPullParser parser, WallpaperData wallpaper) {
+ final String idString = parser.getAttributeValue(null, "id");
+ if (idString != null) {
+ final int id = wallpaper.wallpaperId = Integer.parseInt(idString);
+ if (id > mWallpaperId) {
+ mWallpaperId = id;
+ }
+ } else {
+ wallpaper.wallpaperId = makeWallpaperIdLocked();
+ }
+
+ wallpaper.width = Integer.parseInt(parser.getAttributeValue(null, "width"));
+ wallpaper.height = Integer.parseInt(parser
+ .getAttributeValue(null, "height"));
+ wallpaper.cropHint.left = getAttributeInt(parser, "cropLeft", 0);
+ wallpaper.cropHint.top = getAttributeInt(parser, "cropTop", 0);
+ wallpaper.cropHint.right = getAttributeInt(parser, "cropRight", 0);
+ wallpaper.cropHint.bottom = getAttributeInt(parser, "cropBottom", 0);
+ wallpaper.padding.left = getAttributeInt(parser, "paddingLeft", 0);
+ wallpaper.padding.top = getAttributeInt(parser, "paddingTop", 0);
+ wallpaper.padding.right = getAttributeInt(parser, "paddingRight", 0);
+ wallpaper.padding.bottom = getAttributeInt(parser, "paddingBottom", 0);
+ wallpaper.name = parser.getAttributeValue(null, "name");
+ }
+
private int getMaximumSizeDimension() {
WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
Display d = wm.getDefaultDisplay();
@@ -1561,8 +1783,8 @@
WallpaperData wallpaper = null;
boolean success = false;
synchronized (mLock) {
- loadSettingsLocked(0);
- wallpaper = mWallpaperMap.get(0);
+ loadSettingsLocked(UserHandle.USER_SYSTEM);
+ wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM);
wallpaper.wallpaperId = makeWallpaperIdLocked(); // always bump id at restore
if (wallpaper.nextWallpaperComponent != null
&& !wallpaper.nextWallpaperComponent.equals(mImageWallpaper)) {
@@ -1596,11 +1818,11 @@
if (!success) {
Slog.e(TAG, "Failed to restore wallpaper: '" + wallpaper.name + "'");
wallpaper.name = "";
- getWallpaperDir(0).delete();
+ getWallpaperDir(UserHandle.USER_SYSTEM).delete();
}
synchronized (mLock) {
- saveSettingsLocked(wallpaper);
+ saveSettingsLocked(UserHandle.USER_SYSTEM);
}
}
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
index f3b120f..9c770e1 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
@@ -23,13 +23,18 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageDeleteObserver;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
+import android.content.pm.UserInfo;
import android.os.Binder;
+import android.os.PatternMatcher;
import android.os.Process;
import android.os.RemoteException;
+import android.os.ResultReceiver;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.util.AndroidRuntimeException;
@@ -41,6 +46,7 @@
import com.android.server.SystemService;
+import java.io.FileDescriptor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
@@ -102,12 +108,29 @@
return;
}
+ // Ensure that we only heed PACKAGE_CHANGED intents if they change an entire
+ // package, not just a component
+ if (intent.getAction().equals(Intent.ACTION_PACKAGE_CHANGED)) {
+ if (!WebViewFactory.entirePackageChanged(intent)) {
+ return;
+ }
+ }
+
+ if (intent.getAction().equals(Intent.ACTION_USER_ADDED)) {
+ int userId =
+ intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+ handleNewUser(userId);
+ return;
+ }
+
+ updateFallbackState(context, intent);
+
for (WebViewProviderInfo provider : WebViewFactory.getWebViewPackages()) {
String webviewPackage = "package:" + provider.packageName;
if (webviewPackage.equals(intent.getDataString())) {
boolean updateWebView = false;
- boolean removedOldPackage = false;
+ boolean removedOrChangedOldPackage = false;
String oldProviderName = null;
PackageInfo newPackage = null;
synchronized(WebViewUpdateService.this) {
@@ -125,7 +148,7 @@
|| mCurrentWebViewPackage == null;
// We removed the old package if we received an intent to remove
// or replace the old package.
- removedOldPackage =
+ removedOrChangedOldPackage =
provider.packageName.equals(oldProviderName);
if (updateWebView) {
onWebViewProviderChanged(newPackage);
@@ -135,7 +158,8 @@
"relro with " + e);
}
}
- if(updateWebView && !removedOldPackage && oldProviderName != null) {
+ if(updateWebView && !removedOrChangedOldPackage
+ && oldProviderName != null) {
// If the provider change is the result of adding or replacing a
// package that was not the previous provider then we must kill
// packages dependent on the old package ourselves. The framework
@@ -154,12 +178,167 @@
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addDataScheme("package");
+ // Make sure we only receive intents for WebView packages from our config file.
+ for (WebViewProviderInfo provider : WebViewFactory.getWebViewPackages()) {
+ filter.addDataSchemeSpecificPart(provider.packageName, PatternMatcher.PATTERN_LITERAL);
+ }
getContext().registerReceiver(mWebViewUpdatedReceiver, filter);
+ IntentFilter userAddedFilter = new IntentFilter();
+ userAddedFilter.addAction(Intent.ACTION_USER_ADDED);
+ getContext().registerReceiver(mWebViewUpdatedReceiver, userAddedFilter);
+
publishBinderService("webviewupdate", new BinderService());
}
+ private static boolean existsValidNonFallbackProvider(WebViewProviderInfo[] providers) {
+ for (WebViewProviderInfo provider : providers) {
+ if (provider.isAvailableByDefault() && provider.isEnabled()
+ && provider.isValidProvider() && !provider.isFallbackPackage()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static void enablePackageForUser(String packageName, boolean enable, int userId) {
+ try {
+ AppGlobals.getPackageManager().setApplicationEnabledSetting(
+ packageName,
+ enable ? PackageManager.COMPONENT_ENABLED_STATE_DEFAULT :
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER, 0,
+ userId, null);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Tried to disable " + packageName + " for user " + userId + ": " + e);
+ }
+ }
+
+ /**
+ * Called when a new user has been added to update the state of its fallback package.
+ */
+ void handleNewUser(int userId) {
+ if (!isFallbackLogicEnabled()) return;
+
+ WebViewProviderInfo[] webviewProviders = WebViewFactory.getWebViewPackages();
+ WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewProviders);
+ if (fallbackProvider == null) return;
+ boolean existsValidNonFallbackProvider =
+ existsValidNonFallbackProvider(webviewProviders);
+
+ enablePackageForUser(fallbackProvider.packageName, !existsValidNonFallbackProvider,
+ userId);
+ }
+
+ /**
+ * Handle the enabled-state of our fallback package, i.e. if there exists some non-fallback
+ * package that is valid (and available by default) then disable the fallback package,
+ * otherwise, enable the fallback package.
+ */
+ void updateFallbackState(final Context context, final Intent intent) {
+ if (!isFallbackLogicEnabled()) return;
+
+ WebViewProviderInfo[] webviewProviders = WebViewFactory.getWebViewPackages();
+
+ if (intent != null && (intent.getAction().equals(Intent.ACTION_PACKAGE_ADDED)
+ || intent.getAction().equals(Intent.ACTION_PACKAGE_CHANGED))) {
+ // A package was changed / updated / downgraded, early out if it is not one of the
+ // webview packages that are available by default.
+ String changedPackage = null;
+ for (WebViewProviderInfo provider : webviewProviders) {
+ String webviewPackage = "package:" + provider.packageName;
+ if (webviewPackage.equals(intent.getDataString())) {
+ if (provider.isAvailableByDefault()) {
+ changedPackage = provider.packageName;
+ }
+ break;
+ }
+ }
+ if (changedPackage == null) return;
+ }
+
+ // If there exists a valid and enabled non-fallback package - disable the fallback
+ // package, otherwise, enable it.
+ WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewProviders);
+ if (fallbackProvider == null) return;
+ boolean existsValidNonFallbackProvider = existsValidNonFallbackProvider(webviewProviders);
+
+ if (existsValidNonFallbackProvider
+ // During an OTA the primary user's WebView state might differ from other users', so
+ // ignore the state of that user during boot.
+ && (fallbackProvider.isEnabled() || intent == null)) {
+ // Uninstall and disable fallback package for all users.
+ context.getPackageManager().deletePackage(fallbackProvider.packageName,
+ new IPackageDeleteObserver.Stub() {
+ public void packageDeleted(String packageName, int returnCode) {
+ // Ignore returnCode since the deletion could fail, e.g. we might be trying
+ // to delete a non-updated system-package (and we should still disable the
+ // package)
+ UserManager userManager =
+ (UserManager)context.getSystemService(Context.USER_SERVICE);
+ // Disable the fallback package for all users.
+ for(UserInfo userInfo : userManager.getUsers()) {
+ enablePackageForUser(packageName, false, userInfo.id);
+ }
+ }
+ }, PackageManager.DELETE_SYSTEM_APP | PackageManager.DELETE_ALL_USERS);
+ } else if (!existsValidNonFallbackProvider
+ // During an OTA the primary user's WebView state might differ from other users', so
+ // ignore the state of that user during boot.
+ && (!fallbackProvider.isEnabled() || intent==null)) {
+ // Enable the fallback package for all users.
+ UserManager userManager =
+ (UserManager)context.getSystemService(Context.USER_SERVICE);
+ for(UserInfo userInfo : userManager.getUsers()) {
+ enablePackageForUser(fallbackProvider.packageName, true, userInfo.id);
+ }
+ }
+ }
+
+ private static boolean isFallbackLogicEnabled() {
+ // Note that this is enabled by default (i.e. if the setting hasn't been set).
+ return Settings.Global.getInt(AppGlobals.getInitialApplication().getContentResolver(),
+ Settings.Global.WEBVIEW_FALLBACK_LOGIC_ENABLED, 1) == 1;
+ }
+
+ private static void enableFallbackLogic(boolean enable) {
+ Settings.Global.putInt(AppGlobals.getInitialApplication().getContentResolver(),
+ Settings.Global.WEBVIEW_FALLBACK_LOGIC_ENABLED, enable ? 1 : 0);
+ }
+
+ /**
+ * Returns the only fallback provider, or null if there is none.
+ */
+ private static WebViewProviderInfo getFallbackProvider(WebViewProviderInfo[] webviewPackages) {
+ for (WebViewProviderInfo provider : webviewPackages) {
+ if (provider.isFallbackPackage()) {
+ return provider;
+ }
+ }
+ return null;
+ }
+
+ private static boolean containsAvailableNonFallbackProvider(
+ WebViewProviderInfo[] webviewPackages) {
+ for (WebViewProviderInfo provider : webviewPackages) {
+ if (provider.isAvailableByDefault() && provider.isEnabled()
+ && provider.isValidProvider() && !provider.isFallbackPackage()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean isFallbackPackage(String packageName) {
+ if (packageName == null || !isFallbackLogicEnabled()) return false;
+
+ WebViewProviderInfo[] webviewPackages = WebViewFactory.getWebViewPackages();
+ WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewPackages);
+ return (fallbackProvider != null
+ && packageName.equals(fallbackProvider.packageName));
+ }
+
/**
* Perform any WebView loading preparations that must happen at boot from the system server,
* after the package manager has started or after an update to the webview is installed.
@@ -167,6 +346,7 @@
* Currently, this means spawning the child processes which will create the relro files.
*/
public void prepareWebViewInSystemServer() {
+ updateFallbackState(getContext(), null);
try {
synchronized(this) {
updateValidWebViewPackages();
@@ -182,8 +362,10 @@
/**
* Change WebView provider and provider setting and kill packages using the old provider.
+ * Return the new provider (in case we are in the middle of creating relro files this new
+ * provider will not be in use directly, but will when the relros are done).
*/
- private void changeProviderAndSetting(String newProviderName) {
+ private String changeProviderAndSetting(String newProviderName) {
PackageInfo oldPackage = null;
PackageInfo newPackage = null;
synchronized(this) {
@@ -195,14 +377,14 @@
if (oldPackage != null && newPackage.packageName.equals(oldPackage.packageName)) {
// If we don't perform the user change, revert the settings change.
updateUserSetting(newPackage.packageName);
- return;
+ return newPackage.packageName;
}
} catch (WebViewFactory.MissingWebViewPackageException e) {
Slog.e(TAG, "Tried to change WebView provider but failed to fetch WebView package "
+ e);
// If we don't perform the user change but don't have an installed WebView package,
// we will have changed the setting and it will be used when a package is available.
- return;
+ return newProviderName;
}
onWebViewProviderChanged(newPackage);
}
@@ -214,7 +396,7 @@
}
} catch (RemoteException e) {
}
- return;
+ return newPackage.packageName;
}
/**
@@ -349,6 +531,14 @@
private class BinderService extends IWebViewUpdateService.Stub {
+ @Override
+ public void onShellCommand(FileDescriptor in, FileDescriptor out,
+ FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
+ (new WebViewUpdateServiceShellCommand(this)).exec(
+ this, in, out, err, args, resultReceiver);
+ }
+
+
/**
* The shared relro process calls this to notify us that it's done trying to create a relro
* file. This method gets called even if the relro creation has failed or the process
@@ -364,9 +554,14 @@
return;
}
- synchronized (WebViewUpdateService.this) {
- mNumRelroCreationsFinished++;
- checkIfRelrosDoneLocked();
+ long callingId = Binder.clearCallingIdentity();
+ try {
+ synchronized (WebViewUpdateService.this) {
+ mNumRelroCreationsFinished++;
+ checkIfRelrosDoneLocked();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(callingId);
}
}
@@ -423,7 +618,7 @@
* This is called from DeveloperSettings when the user changes WebView provider.
*/
@Override // Binder call
- public void changeProviderAndSetting(String newProvider) {
+ public String changeProviderAndSetting(String newProvider) {
if (getContext().checkCallingPermission(
android.Manifest.permission.WRITE_SECURE_SETTINGS)
!= PackageManager.PERMISSION_GRANTED) {
@@ -435,7 +630,7 @@
throw new SecurityException(msg);
}
- WebViewUpdateService.this.changeProviderAndSetting(newProvider);
+ return WebViewUpdateService.this.changeProviderAndSetting(newProvider);
}
@Override // Binder call
@@ -453,5 +648,26 @@
return WebViewUpdateService.this.mCurrentWebViewPackage.packageName;
}
}
+
+ @Override // Binder call
+ public boolean isFallbackPackage(String packageName) {
+ return WebViewUpdateService.isFallbackPackage(packageName);
+ }
+
+ @Override // Binder call
+ public void enableFallbackLogic(boolean enable) {
+ if (getContext().checkCallingPermission(
+ android.Manifest.permission.WRITE_SECURE_SETTINGS)
+ != PackageManager.PERMISSION_GRANTED) {
+ String msg = "Permission Denial: enableFallbackLogic() from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid()
+ + " requires " + android.Manifest.permission.WRITE_SECURE_SETTINGS;
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
+
+ WebViewUpdateService.enableFallbackLogic(enable);
+ }
}
}
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceShellCommand.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceShellCommand.java
new file mode 100644
index 0000000..a9461e8
--- /dev/null
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceShellCommand.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.webkit;
+
+import android.os.RemoteException;
+import android.os.ShellCommand;
+import android.webkit.IWebViewUpdateService;
+
+import java.io.PrintWriter;
+
+class WebViewUpdateServiceShellCommand extends ShellCommand {
+ final IWebViewUpdateService mInterface;
+
+ WebViewUpdateServiceShellCommand(IWebViewUpdateService service) {
+ mInterface = service;
+ }
+
+ @Override
+ public int onCommand(String cmd) {
+ if (cmd == null) {
+ return handleDefaultCommands(cmd);
+ }
+
+ final PrintWriter pw = getOutPrintWriter();
+ try {
+ // TODO(gsennton) add command for changing WebView provider
+ switch(cmd) {
+ case "enable-redundant-packages":
+ return enableFallbackLogic(false);
+ case "disable-redundant-packages":
+ return enableFallbackLogic(true);
+ default:
+ return handleDefaultCommands(cmd);
+ }
+ } catch (RemoteException e) {
+ pw.println("Remote exception: " + e);
+ }
+ return -1;
+ }
+
+ private int enableFallbackLogic(boolean enable) throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+ mInterface.enableFallbackLogic(enable);
+ pw.println("Success");
+ return 0;
+ }
+
+ @Override
+ public void onHelp() {
+ PrintWriter pw = getOutPrintWriter();
+ pw.println("WebView updater commands:");
+ pw.println(" help");
+ pw.println(" Print this help text.");
+ pw.println("");
+ pw.println(" enable-redundant-packages");
+ pw.println(" Allow a fallback package to be installed and enabled even when a");
+ pw.println(" more-preferred package is available. This command is useful when testing");
+ pw.println(" fallback packages.");
+ pw.println(" disable-redundant-packages");
+ pw.println(" Disallow installing and enabling fallback packages when a more-preferred");
+ pw.println(" package is available.");
+ pw.println();
+ }
+}
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index e6b649e7..2c15818 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -60,6 +60,7 @@
import com.android.internal.os.SomeArgs;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -1019,9 +1020,17 @@
boolean focusedWindowAdded = false;
final int visibleWindowCount = visibleWindows.size();
+ int skipRemainingWindowsForTaskId = -1;
+ HashSet<Integer> skipRemainingWindowsForTasks = new HashSet<>();
for (int i = visibleWindowCount - 1; i >= 0; i--) {
final WindowState windowState = visibleWindows.valueAt(i);
final int flags = windowState.mAttrs.flags;
+ final Task task = windowState.getTask();
+
+ // If the window is part of a task that we're finished with - ignore.
+ if (task != null && skipRemainingWindowsForTasks.contains(task.mTaskId)) {
+ continue;
+ }
// If the window is not touchable - ignore.
if ((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
@@ -1062,10 +1071,19 @@
break;
}
- // If a window is modal, no other below can be touched - done.
+ // If a window is modal it prevents other windows from being touched
if ((flags & (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL)) == 0) {
- break;
+ if (task != null) {
+ // If the window is associated with a particular task, we can skip the
+ // rest of the windows for that task.
+ skipRemainingWindowsForTasks.add(task.mTaskId);
+ continue;
+ } else {
+ // If the window is not associated with a particular task, then it is
+ // globally modal. In this case we can skip all remaining windows.
+ break;
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 1821487..5cb7099 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -46,13 +46,13 @@
import android.annotation.Nullable;
import android.content.Context;
-import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.os.Debug;
import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.RemoteException;
+import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
import android.view.AppTransitionAnimationSpec;
@@ -63,8 +63,6 @@
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
import android.view.animation.ClipRectAnimation;
-import android.view.animation.ClipRectLRAnimation;
-import android.view.animation.ClipRectTBAnimation;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
import android.view.animation.ScaleAnimation;
@@ -73,10 +71,11 @@
import com.android.internal.util.DumpUtils.Dump;
import com.android.server.AttributeCache;
import com.android.server.wm.WindowManagerService.H;
+import com.android.server.wm.animation.ClipRectLRAnimation;
+import com.android.server.wm.animation.ClipRectTBAnimation;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -135,6 +134,16 @@
private static final float RECENTS_THUMBNAIL_FADEOUT_FRACTION = 0.5f;
static final int DEFAULT_APP_TRANSITION_DURATION = 336;
+
+ /** Interpolator to be used for animations that respond directly to a touch */
+ static final Interpolator TOUCH_RESPONSE_INTERPOLATOR =
+ new PathInterpolator(0.3f, 0f, 0.1f, 1f);
+
+ /**
+ * Maximum duration for the clip reveal animation. This is used when there is a lot of movement
+ * involved, to make it more understandable.
+ */
+ private static final int MAX_CLIP_REVEAL_TRANSITION_DURATION = 420;
private static final int THUMBNAIL_APP_TRANSITION_DURATION = 336;
private static final int THUMBNAIL_APP_TRANSITION_ALPHA_DURATION = 336;
private static final long APP_TRANSITION_TIMEOUT_MS = 5000;
@@ -199,17 +208,17 @@
private final Interpolator mFastOutLinearInInterpolator;
private final Interpolator mClipHorizontalInterpolator = new PathInterpolator(0, 0, 0.4f, 1f);
- /** Interpolator to be used for animations that respond directly to a touch */
- private final Interpolator mTouchResponseInterpolator =
- new PathInterpolator(0.3f, 0f, 0.1f, 1f);
-
private final int mClipRevealTranslationY;
private int mCurrentUserId = 0;
+ private long mLastClipRevealTransitionDuration = DEFAULT_APP_TRANSITION_DURATION;
private final ArrayList<AppTransitionListener> mListeners = new ArrayList<>();
private final ExecutorService mDefaultExecutor = Executors.newSingleThreadExecutor();
+ private int mLastClipRevealMaxTranslation;
+ private boolean mLastHadClipReveal;
+
AppTransition(Context context, WindowManagerService service) {
mContext = context;
mService = service;
@@ -331,19 +340,25 @@
if (!isRunning()) {
mAppTransitionState = APP_STATE_IDLE;
notifyAppTransitionPendingLocked();
+ mLastHadClipReveal = false;
+ mLastClipRevealMaxTranslation = 0;
+ mLastClipRevealTransitionDuration = DEFAULT_APP_TRANSITION_DURATION;
return true;
}
return false;
}
- void goodToGo(AppWindowAnimator openingAppAnimator, AppWindowAnimator closingAppAnimator) {
+ void goodToGo(AppWindowAnimator topOpeningAppAnimator, AppWindowAnimator topClosingAppAnimator,
+ ArraySet<AppWindowToken> openingApps, ArraySet<AppWindowToken> closingApps) {
mNextAppTransition = TRANSIT_UNSET;
mAppTransitionState = APP_STATE_RUNNING;
notifyAppTransitionStartingLocked(
- openingAppAnimator != null ? openingAppAnimator.mAppToken.token : null,
- closingAppAnimator != null ? closingAppAnimator.mAppToken.token : null,
- openingAppAnimator != null ? openingAppAnimator.animation : null,
- closingAppAnimator != null ? closingAppAnimator.animation : null);
+ topOpeningAppAnimator != null ? topOpeningAppAnimator.mAppToken.token : null,
+ topClosingAppAnimator != null ? topClosingAppAnimator.mAppToken.token : null,
+ topOpeningAppAnimator != null ? topOpeningAppAnimator.animation : null,
+ topClosingAppAnimator != null ? topClosingAppAnimator.animation : null);
+ mService.getDefaultDisplayContentLocked().getDockedDividerController()
+ .notifyAppTransitionStarting(openingApps, closingApps);
}
void clear() {
@@ -632,50 +647,118 @@
bitmap, new Rect(left, top, left + width, top + height));
}
- private Animation createClipRevealAnimationLocked(int transit, boolean enter, Rect appFrame) {
+ /**
+ * @return the duration of the last clip reveal animation
+ */
+ long getLastClipRevealTransitionDuration() {
+ return mLastClipRevealTransitionDuration;
+ }
+
+ /**
+ * @return the maximum distance the app surface is traveling of the last clip reveal animation
+ */
+ int getLastClipRevealMaxTranslation() {
+ return mLastClipRevealMaxTranslation;
+ }
+
+ /**
+ * @return true if in the last app transition had a clip reveal animation, false otherwise
+ */
+ boolean hadClipRevealAnimation() {
+ return mLastHadClipReveal;
+ }
+
+ /**
+ * Calculates the duration for the clip reveal animation. If the clip is "cut off", meaning that
+ * the start rect is outside of the target rect, and there is a lot of movement going on.
+ *
+ * @param cutOff whether the start rect was not fully contained by the end rect
+ * @param translationX the total translation the surface moves in x direction
+ * @param translationY the total translation the surfaces moves in y direction
+ * @param displayFrame our display frame
+ *
+ * @return the duration of the clip reveal animation, in milliseconds
+ */
+ private long calculateClipRevealTransitionDuration(boolean cutOff, float translationX,
+ float translationY, Rect displayFrame) {
+ if (!cutOff) {
+ return DEFAULT_APP_TRANSITION_DURATION;
+ }
+ final float fraction = Math.max(Math.abs(translationX) / displayFrame.width(),
+ Math.abs(translationY) / displayFrame.height());
+ return (long) (DEFAULT_APP_TRANSITION_DURATION + fraction *
+ (MAX_CLIP_REVEAL_TRANSITION_DURATION - DEFAULT_APP_TRANSITION_DURATION));
+ }
+
+ private Animation createClipRevealAnimationLocked(int transit, boolean enter, Rect appFrame,
+ Rect displayFrame) {
final Animation anim;
if (enter) {
- // Reveal will expand and move faster in horizontal direction
-
final int appWidth = appFrame.width();
final int appHeight = appFrame.height();
+
// mTmpRect will contain an area around the launcher icon that was pressed. We will
// clip reveal from that area in the final area of the app.
getDefaultNextAppTransitionStartRect(mTmpRect);
float t = 0f;
if (appHeight > 0) {
- t = (float) mTmpRect.left / appHeight;
+ t = (float) mTmpRect.top / displayFrame.height();
}
- int translationY = mClipRevealTranslationY + (int)(appHeight / 7f * t);
-
+ int translationY = mClipRevealTranslationY + (int)(displayFrame.height() / 7f * t);
+ int translationX = 0;
+ int translationYCorrection = translationY;
int centerX = mTmpRect.centerX();
int centerY = mTmpRect.centerY();
int halfWidth = mTmpRect.width() / 2;
int halfHeight = mTmpRect.height() / 2;
+ int clipStartX = centerX - halfWidth - appFrame.left;
+ int clipStartY = centerY - halfHeight - appFrame.top;
+ boolean cutOff = false;
+
+ // If the starting rectangle is fully or partially outside of the target rectangle, we
+ // need to start the clipping at the edge and then achieve the rest with translation
+ // and extending the clip rect from that edge.
+ if (appFrame.top > centerY - halfHeight) {
+ translationY = (centerY - halfHeight) - appFrame.top;
+ translationYCorrection = 0;
+ clipStartY = 0;
+ cutOff = true;
+ }
+ if (appFrame.left > centerX - halfWidth) {
+ translationX = (centerX - halfWidth) - appFrame.left;
+ clipStartX = 0;
+ cutOff = true;
+ }
+ if (appFrame.right < centerX + halfWidth) {
+ translationX = (centerX + halfWidth) - appFrame.right;
+ clipStartX = appWidth - mTmpRect.width();
+ cutOff = true;
+ }
+ final long duration = calculateClipRevealTransitionDuration(cutOff, translationX,
+ translationY, displayFrame);
// Clip third of the from size of launch icon, expand to full width/height
Animation clipAnimLR = new ClipRectLRAnimation(
- centerX - halfWidth, centerX + halfWidth, 0, appWidth);
+ clipStartX, clipStartX + mTmpRect.width(), 0, appWidth);
clipAnimLR.setInterpolator(mClipHorizontalInterpolator);
- clipAnimLR.setDuration((long) (DEFAULT_APP_TRANSITION_DURATION / 2.5f));
+ clipAnimLR.setDuration((long) (duration / 2.5f));
- Animation clipAnimTB = new ClipRectTBAnimation(centerY - halfHeight - translationY,
- centerY + halfHeight/ 2 - translationY, 0, appHeight);
- clipAnimTB.setInterpolator(mTouchResponseInterpolator);
- clipAnimTB.setDuration(DEFAULT_APP_TRANSITION_DURATION);
+ TranslateAnimation translate = new TranslateAnimation(translationX, 0, translationY, 0);
+ translate.setInterpolator(cutOff ? TOUCH_RESPONSE_INTERPOLATOR
+ : mLinearOutSlowInInterpolator);
+ translate.setDuration(duration);
- // We might be animating entrance of a docked task, so we need the translate to account
- // for the app frame in which the window will reside. Every other calculation here
- // is performed as if the window started at 0,0.
- translationY -= appFrame.top;
- TranslateAnimation translate = new TranslateAnimation(-appFrame.left, 0, translationY,
- 0);
- translate.setInterpolator(mLinearOutSlowInInterpolator);
- translate.setDuration(DEFAULT_APP_TRANSITION_DURATION);
+ Animation clipAnimTB = new ClipRectTBAnimation(
+ clipStartY, clipStartY + mTmpRect.height(),
+ 0, appHeight,
+ translationYCorrection, 0,
+ mLinearOutSlowInInterpolator);
+ clipAnimTB.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
+ clipAnimTB.setDuration(duration);
// Quick fade-in from icon to app window
- final int alphaDuration = DEFAULT_APP_TRANSITION_DURATION / 4;
+ final long alphaDuration = duration / 4;
AlphaAnimation alpha = new AlphaAnimation(0.5f, 1);
alpha.setDuration(alphaDuration);
alpha.setInterpolator(mLinearOutSlowInInterpolator);
@@ -688,6 +771,13 @@
set.setZAdjustment(Animation.ZORDER_TOP);
set.initialize(appWidth, appHeight, appWidth, appHeight);
anim = set;
+ mLastHadClipReveal = true;
+ mLastClipRevealTransitionDuration = duration;
+
+ // If the start rect was full inside the target rect (cutOff == false), we don't need
+ // to store the translation, because it's only used if cutOff == true.
+ mLastClipRevealMaxTranslation = cutOff
+ ? Math.max(Math.abs(translationY), Math.abs(translationX)) : 0;
} else {
final long duration;
switch (transit) {
@@ -794,7 +884,7 @@
// Animation up from the thumbnail to the full screen
Animation scale = new ScaleAnimation(1f, scaleW, 1f, scaleW,
mTmpRect.left + (thumbWidth / 2f), mTmpRect.top + (thumbHeight / 2f));
- scale.setInterpolator(mTouchResponseInterpolator);
+ scale.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
Animation alpha = new AlphaAnimation(1f, 0f);
alpha.setInterpolator(mThumbnailFadeOutInterpolator);
@@ -802,7 +892,7 @@
final float toX = appRect.left + appRect.width() / 2 -
(mTmpRect.left + thumbWidth / 2);
Animation translate = new TranslateAnimation(0, toX, 0, toY);
- translate.setInterpolator(mTouchResponseInterpolator);
+ translate.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
translate.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
// This AnimationSet uses the Interpolators assigned above.
@@ -815,7 +905,7 @@
// Animation down from the full screen to the thumbnail
Animation scale = new ScaleAnimation(scaleW, 1f, scaleW, 1f,
mTmpRect.left + (thumbWidth / 2f), mTmpRect.top + (thumbHeight / 2f));
- scale.setInterpolator(mTouchResponseInterpolator);
+ scale.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
Animation alpha = new AlphaAnimation(0f, 1f);
alpha.setInterpolator(mThumbnailFadeInInterpolator);
@@ -823,7 +913,7 @@
final float toX = appRect.left + appRect.width() / 2 -
(mTmpRect.left + thumbWidth / 2);
Animation translate = new TranslateAnimation(toX, 0, toY, 0);
- translate.setInterpolator(mTouchResponseInterpolator);
+ translate.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
translate.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
// This AnimationSet uses the Interpolators assigned above.
@@ -835,7 +925,7 @@
}
return prepareThumbnailAnimationWithDuration(a, appWidth, appRect.height(), 0,
- mTouchResponseInterpolator);
+ TOUCH_RESPONSE_INTERPOLATOR);
}
/**
@@ -967,7 +1057,7 @@
int duration = Math.max(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION,
THUMBNAIL_APP_TRANSITION_DURATION);
return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, duration,
- mTouchResponseInterpolator);
+ TOUCH_RESPONSE_INTERPOLATOR);
}
private Animation createAspectScaledThumbnailEnterFreeformAnimationLocked(Rect frame,
@@ -1219,8 +1309,9 @@
* bigger.
*/
Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
- int orientation, Rect frame, Rect insets, @Nullable Rect surfaceInsets,
- boolean isVoiceInteraction, boolean freeform, int taskId) {
+ int orientation, Rect frame, Rect displayFrame, Rect insets,
+ @Nullable Rect surfaceInsets, boolean isVoiceInteraction, boolean freeform,
+ int taskId) {
Animation a;
if (isVoiceInteraction && (transit == TRANSIT_ACTIVITY_OPEN
|| transit == TRANSIT_TASK_OPEN
@@ -1265,7 +1356,7 @@
+ " transit=" + appTransitionToString(transit)
+ " Callers=" + Debug.getCallers(3));
} else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CLIP_REVEAL) {
- a = createClipRevealAnimationLocked(transit, enter, frame);
+ a = createClipRevealAnimationLocked(transit, enter, frame, displayFrame);
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
"applyAnimation:"
+ " anim=" + a + " nextAppTransition=ANIM_CLIP_REVEAL"
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index fa5ee72..a81fba0 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -153,6 +153,13 @@
} else {
mClearProlongedAnimation = true;
}
+
+ // Since we are finally starting our animation, we don't need the logic anymore to prevent
+ // the app from showing again if we just moved between stacks. See
+ // {@link WindowState#notifyMovedInStack}.
+ for (int i = mAppToken.allAppWindows.size() - 1; i >= 0; i--) {
+ mAppToken.allAppWindows.get(i).resetJustMovedInStack();
+ }
}
public void setDummyAnimation() {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 56ae8e0..2731f429 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -21,6 +21,7 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -159,6 +160,25 @@
}
}
+ void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
+ firstWindowDrawn = true;
+
+ // We now have a good window to show, remove dead placeholders
+ removeAllDeadWindows();
+
+ if (startingData != null) {
+ if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG, "Finish starting "
+ + win.mToken + ": first real window is shown, no animation");
+ // If this initial window is animating, stop it -- we will do an animation to reveal
+ // it from behind the starting window, so there is no need for it to also be doing its
+ // own stuff.
+ winAnimator.clearAnimation();
+ winAnimator.mService.mFinishedStarting.add(this);
+ winAnimator.mService.mH.sendEmptyMessage(H.FINISHED_STARTING);
+ }
+ updateReportedVisibilityLocked();
+ }
+
void updateReportedVisibilityLocked() {
if (appToken == null) {
return;
@@ -254,7 +274,7 @@
// In cases where there are multiple windows, we prefer the non-exiting window. This
// happens for example when replacing windows during an activity relaunch. When
// constructing the animation, we want the new window, not the exiting one.
- if (win.mExiting) {
+ if (win.mAnimatingExit) {
candidate = win;
} else {
return win;
@@ -307,11 +327,11 @@
// If the app already requested to remove its window, we don't modify
// its exiting state. Otherwise the stale window won't get removed on
// exit and could cause focus to be given to the wrong window.
- if (!(win.mRemoveOnExit && win.mExiting)) {
- win.mExiting = exiting;
+ if (!(win.mRemoveOnExit && win.mAnimatingExit)) {
+ win.mAnimatingExit = exiting;
}
// If we're no longer exiting, remove the window from destroying list
- if (!win.mExiting && win.mDestroying) {
+ if (!win.mAnimatingExit && win.mDestroying) {
win.mDestroying = false;
service.mDestroySurface.remove(win);
}
@@ -330,13 +350,18 @@
continue;
}
- if (!mAppStopped && !win.mClientRemoveRequested) {
+ if (!(mAppStopped || win.mWindowRemovalAllowed)) {
continue;
}
+ if (DEBUG_ADD_REMOVE) Slog.e(TAG_WM, "win=" + win
+ + " destroySurfaces: mAppStopped=" + mAppStopped
+ + " win.mWindowRemovalAllowed=" + win.mWindowRemovalAllowed
+ + " win.mRemoveOnExit=" + win.mRemoveOnExit);
+
win.destroyOrSaveSurface();
if (win.mRemoveOnExit) {
- win.mExiting = false;
+ win.mAnimatingExit = false;
service.removeWindowInnerLocked(win);
}
final DisplayContent displayContent = win.getDisplayContent();
@@ -352,11 +377,19 @@
}
}
- // The application has stopped, so destroy any surfaces which were keeping alive
- // in case they were still being used.
- void notifyAppStopped() {
- mAppStopped = true;
- destroySurfaces();
+ /**
+ * If the application has stopped it is okay to destroy any surfaces which were keeping alive
+ * in case they were still being used.
+ */
+ void notifyAppStopped(boolean stopped) {
+ if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: stopped=" + stopped + " " + this);
+ mAppStopped = stopped;
+
+ if (stopped) {
+ destroySurfaces();
+ // Remove any starting window that was added for this app if they are still around.
+ mTask.mService.scheduleRemoveStartingWindowLocked(this);
+ }
}
/**
@@ -393,7 +426,9 @@
int numDrawn = 0;
for (int i = windows.size() - 1; i >= 0; i--) {
WindowState w = windows.get(i);
- w.restoreSavedSurface();
+ if (w.hasSavedSurface()) {
+ w.restoreSavedSurface();
+ }
if (w != startingWindow && !w.mAppDied
&& (!mAppAnimator.freezingScreen || !w.mAppFreezing)) {
numInteresting++;
@@ -403,7 +438,7 @@
}
}
- allDrawn |= (numInteresting == numDrawn);
+ allDrawn |= (numInteresting > 0) && (numInteresting == numDrawn);
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.d(TAG,
"restoreSavedSurfaces: " + appWindowToken + " allDrawn=" + allDrawn);
@@ -447,7 +482,7 @@
winNdx = Math.min(winNdx - 1, allAppWindows.size() - 1)) {
WindowState win = allAppWindows.get(winNdx);
if (win.mAppDied) {
- if (DEBUG_WINDOW_MOVEMENT) {
+ if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) {
Slog.w(TAG, "removeAllDeadWindows: " + win);
}
// Set mDestroying, we don't want any animation or delayed removal here.
@@ -592,6 +627,9 @@
if (paused) {
pw.print(prefix); pw.print("paused="); pw.println(paused);
}
+ if (mAppStopped) {
+ pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
+ }
if (numInterestingWindows != 0 || numDrawnWindows != 0
|| allDrawn || mAppAnimator.allDrawn) {
pw.print(prefix); pw.print("numInterestingWindows=");
@@ -617,7 +655,7 @@
pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
pw.print(" startingView="); pw.print(startingView);
pw.print(" startingDisplayed="); pw.print(startingDisplayed);
- pw.print(" startingMoved"); pw.println(startingMoved);
+ pw.print(" startingMoved="); pw.println(startingMoved);
}
if (!mFrozenBounds.isEmpty()) {
pw.print(prefix); pw.print("mFrozenBounds="); pw.print(mFrozenBounds);
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index f0efebe..79d3d84 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -54,7 +54,8 @@
private final AnimateBoundsUser mTarget;
private final Rect mFrom;
private final Rect mTo;
- private final Rect mTmpRect;
+ private final Rect mTmpRect = new Rect();
+ private final Rect mTmpTaskBounds = new Rect();
private final boolean mMoveToFullScreen;
// True if this this animation was cancelled and will be replaced the another animation from
// the same {@link #AnimateBoundsUser} target.
@@ -63,17 +64,40 @@
// {@link #AnimateBoundsUser} target.
private final boolean mReplacement;
+ // Depending on whether we are animating from
+ // a smaller to a larger size
+ private final int mFrozenTaskWidth;
+ private final int mFrozenTaskHeight;
+
BoundsAnimator(AnimateBoundsUser target, Rect from, Rect to,
boolean moveToFullScreen, boolean replacement) {
super();
mTarget = target;
mFrom = from;
mTo = to;
- mTmpRect = new Rect();
mMoveToFullScreen = moveToFullScreen;
mReplacement = replacement;
addUpdateListener(this);
addListener(this);
+
+ // If we are animating from smaller to larger, we want to change the task bounds
+ // to their final size immediately so we can use scaling to make the window
+ // larger. Likewise if we are going from bigger to smaller, we want to wait until
+ // the end so we don't have to upscale from the smaller finished size.
+ if (animatingToLargerSize()) {
+ mFrozenTaskWidth = mTo.width();
+ mFrozenTaskHeight = mTo.height();
+ } else {
+ mFrozenTaskWidth = mFrom.width();
+ mFrozenTaskHeight = mFrom.height();
+ }
+ }
+
+ boolean animatingToLargerSize() {
+ if (mFrom.width() * mFrom.height() > mTo.width() * mTo.height()) {
+ return false;
+ }
+ return true;
}
@Override
@@ -87,7 +111,13 @@
if (DEBUG) Slog.d(TAG, "animateUpdate: mTarget=" + mTarget + " mBounds="
+ mTmpRect + " from=" + mFrom + " mTo=" + mTo + " value=" + value
+ " remains=" + remains);
- if (!mTarget.setSize(mTmpRect)) {
+
+ if (remains != 0) {
+ mTmpTaskBounds.set(mTmpRect.left, mTmpRect.top,
+ mTmpRect.left + mFrozenTaskWidth, mTmpRect.top + mFrozenTaskHeight);
+ }
+
+ if (!mTarget.setPinnedStackSize(mTmpRect, remains != 0 ? mTmpTaskBounds : null)) {
// Whoops, the target doesn't feel like animating anymore. Let's immediately finish
// any further animation.
animation.cancel();
@@ -99,6 +129,10 @@
public void onAnimationStart(Animator animation) {
if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget
+ " mReplacement=" + mReplacement);
+ if (animatingToLargerSize()) {
+ mTarget.setPinnedStackSize(mFrom, mTo);
+ }
+
if (!mReplacement) {
mTarget.onAnimationStart();
}
@@ -108,6 +142,7 @@
public void onAnimationEnd(Animator animation) {
if (DEBUG) Slog.d(TAG, "onAnimationEnd: mTarget=" + mTarget
+ " mMoveToFullScreen=" + mMoveToFullScreen + " mWillReplace=" + mWillReplace);
+
finishAnimation();
if (mMoveToFullScreen && !mWillReplace) {
mTarget.moveToFullscreen();
@@ -159,6 +194,12 @@
* from the hierarchy and is not valid anymore.
*/
boolean setSize(Rect bounds);
+ /**
+ * Behaves as setSize, but freezes the bounds of any tasks in the target at taskBounds,
+ * to allow for more flexibility during resizing. Only
+ * works for the pinned stack at the moment.
+ */
+ boolean setPinnedStackSize(Rect bounds, Rect taskBounds);
void onAnimationStart();
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 144d7ac..73cea52 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -127,7 +127,7 @@
isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY;
mService = service;
initializeDisplayBaseInfo();
- mDividerControllerLocked = new DockedStackDividerController(service.mContext, this);
+ mDividerControllerLocked = new DockedStackDividerController(service, this);
mDimLayerController = new DimLayerController(this);
}
@@ -606,12 +606,24 @@
return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mStacks;
}
+ /**
+ * @return The docked stack, but only if it is visible, and {@code null} otherwise.
+ */
TaskStack getDockedStackLocked() {
final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
return (stack != null && stack.isVisibleLocked()) ? stack : null;
}
/**
+ * Like {@link #getDockedStackLocked}, but also returns the docked stack if it's currently not
+ * visible, as long as it's not hidden because the current user doesn't have any tasks there.
+ */
+ TaskStack getDockedStackVisibleForUserLocked() {
+ final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
+ return (stack != null && stack.isVisibleForUserLocked()) ? stack : null;
+ }
+
+ /**
* Find the visible, touch-deliverable window under the given point
*/
WindowState getTouchableWinAtPointLocked(float xf, float yf) {
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 75c06ff..b6aa3f2 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -20,10 +20,13 @@
import android.graphics.Rect;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
+import android.util.ArraySet;
import android.util.Slog;
import android.view.DisplayInfo;
import android.view.IDockedStackListener;
import android.view.SurfaceControl;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
import com.android.server.wm.DimLayer.DimLayerUser;
@@ -35,6 +38,8 @@
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.AppTransition.DEFAULT_APP_TRANSITION_DURATION;
+import static com.android.server.wm.AppTransition.TOUCH_RESPONSE_INTERPOLATOR;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -45,25 +50,65 @@
private static final String TAG = TAG_WITH_CLASS_NAME ? "DockedStackDividerController" : TAG_WM;
+ /**
+ * The fraction during the maximize/clip reveal animation the divider meets the edge of the clip
+ * revealing surface at the earliest.
+ */
+ private static final float CLIP_REVEAL_MEET_EARLIEST = 0.6f;
+
+ /**
+ * The fraction during the maximize/clip reveal animation the divider meets the edge of the clip
+ * revealing surface at the latest.
+ */
+ private static final float CLIP_REVEAL_MEET_LAST = 1f;
+
+ /**
+ * If the app translates at least CLIP_REVEAL_MEET_FRACTION_MIN * minimize distance, we start
+ * meet somewhere between {@link #CLIP_REVEAL_MEET_LAST} and {@link #CLIP_REVEAL_MEET_EARLIEST}.
+ */
+ private static final float CLIP_REVEAL_MEET_FRACTION_MIN = 0.4f;
+
+ /**
+ * If the app translates equals or more than CLIP_REVEAL_MEET_FRACTION_MIN * minimize distance,
+ * we meet at {@link #CLIP_REVEAL_MEET_EARLIEST}.
+ */
+ private static final float CLIP_REVEAL_MEET_FRACTION_MAX = 0.8f;
+
+ private final WindowManagerService mService;
private final DisplayContent mDisplayContent;
private final int mDividerWindowWidth;
private final int mDividerInsets;
private boolean mResizing;
private WindowState mWindow;
private final Rect mTmpRect = new Rect();
+ private final Rect mTmpRect2 = new Rect();
private final Rect mLastRect = new Rect();
private boolean mLastVisibility = false;
private final RemoteCallbackList<IDockedStackListener> mDockedStackListeners
= new RemoteCallbackList<>();
private final DimLayer mDimLayer;
- DockedStackDividerController(Context context, DisplayContent displayContent) {
+ private boolean mMinimizedDock;
+ private boolean mAnimating;
+ private boolean mAnimationStarted;
+ private long mAnimationStartTime;
+ private float mAnimationStart;
+ private float mAnimationTarget;
+ private long mAnimationDuration;
+ private final Interpolator mMinimizedDockInterpolator;
+ private float mMaximizeMeetFraction;
+
+ DockedStackDividerController(WindowManagerService service, DisplayContent displayContent) {
+ mService = service;
mDisplayContent = displayContent;
+ final Context context = service.mContext;
mDividerWindowWidth = context.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.docked_stack_divider_thickness);
mDividerInsets = context.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.docked_stack_divider_insets);
mDimLayer = new DimLayer(displayContent.mService, this, displayContent.getDisplayId());
+ mMinimizedDockInterpolator = AnimationUtils.loadInterpolator(
+ context, android.R.interpolator.fast_out_slow_in);
}
boolean isResizing() {
@@ -180,6 +225,19 @@
mDockedStackListeners.finishBroadcast();
}
+ void notifyDockedStackMinimizedChanged(boolean minimizedDock, long animDuration) {
+ final int size = mDockedStackListeners.beginBroadcast();
+ for (int i = 0; i < size; ++i) {
+ final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
+ try {
+ listener.onDockedStackMinimizedChanged(minimizedDock, animDuration);
+ } catch (RemoteException e) {
+ Slog.e(TAG_WM, "Error delivering minimized dock changed event.", e);
+ }
+ }
+ mDockedStackListeners.finishBroadcast();
+ }
+
void registerDockedStackListener(IDockedStackListener listener) {
mDockedStackListeners.register(listener);
notifyDockedDividerVisibilityChanged(wasVisible());
@@ -207,6 +265,183 @@
SurfaceControl.closeTransaction();
}
+ /**
+ * Notifies the docked stack divider controller of a visibility change that happens without
+ * an animation.
+ */
+ void notifyAppVisibilityChanged(AppWindowToken wtoken, boolean visible) {
+ final Task task = wtoken.mTask;
+ if (!task.isHomeTask() || !task.isVisibleForUser()) {
+ return;
+ }
+
+ // If the stack is completely offscreen, this might just be an intermediate state when
+ // docking a task/launching recents at the same time, but home doesn't actually get
+ // visible after the state settles in.
+ if (isWithinDisplay(task)
+ && mDisplayContent.getDockedStackVisibleForUserLocked() != null) {
+ setMinimizedDockedStack(visible, false /* animate */);
+ }
+ }
+
+ void notifyAppTransitionStarting(ArraySet<AppWindowToken> openingApps,
+ ArraySet<AppWindowToken> closingApps) {
+ if (containsHomeTaskWithinDisplay(openingApps)) {
+ setMinimizedDockedStack(true /* minimized */, true /* animate */);
+ } else if (containsHomeTaskWithinDisplay(closingApps)) {
+ setMinimizedDockedStack(false /* minimized */, true /* animate */);
+ }
+ }
+
+ private boolean containsHomeTaskWithinDisplay(ArraySet<AppWindowToken> apps) {
+ for (int i = apps.size() - 1; i >= 0; i--) {
+ final Task task = apps.valueAt(i).mTask;
+ if (task != null && task.isHomeTask()) {
+ return isWithinDisplay(task);
+ }
+ }
+ return false;
+ }
+
+ private boolean isWithinDisplay(Task task) {
+ task.mStack.getBounds(mTmpRect);
+ mDisplayContent.getLogicalDisplayRect(mTmpRect2);
+ return mTmpRect.intersect(mTmpRect2);
+ }
+
+ /**
+ * Sets whether the docked stack is currently in a minimized state, i.e. all the tasks in the
+ * docked stack are heavily clipped so you can only see a minimal peek state.
+ *
+ * @param minimizedDock Whether the docked stack is currently minimized.
+ * @param animate Whether to animate the change.
+ */
+ private void setMinimizedDockedStack(boolean minimizedDock, boolean animate) {
+ if (minimizedDock == mMinimizedDock
+ || mDisplayContent.getDockedStackVisibleForUserLocked() == null) {
+ return;
+ }
+
+ mMinimizedDock = minimizedDock;
+ if (minimizedDock) {
+ if (animate) {
+ startAdjustAnimation(0f, 1f);
+ } else {
+ setMinimizedDockedStack(true);
+ }
+ } else {
+ if (animate) {
+ startAdjustAnimation(1f, 0f);
+ } else {
+ setMinimizedDockedStack(false);
+ }
+ }
+ }
+
+ private void startAdjustAnimation(float from, float to) {
+ mAnimating = true;
+ mAnimationStarted = false;
+ mAnimationStart = from;
+ mAnimationTarget = to;
+ }
+
+ private void setMinimizedDockedStack(boolean minimized) {
+ final TaskStack stack = mDisplayContent.getDockedStackVisibleForUserLocked();
+ if (stack == null) {
+ return;
+ }
+ if (stack.setAdjustedForMinimizedDock(minimized ? 1f : 0f)) {
+ mService.mWindowPlacerLocked.performSurfacePlacement();
+ }
+ notifyDockedStackMinimizedChanged(minimized, 0);
+ }
+
+ private boolean isAnimationMaximizing() {
+ return mAnimationTarget == 0f;
+ }
+
+ public boolean animate(long now) {
+ if (!mAnimating) {
+ return false;
+ }
+
+ final TaskStack stack = mDisplayContent.getDockedStackVisibleForUserLocked();
+ if (!mAnimationStarted) {
+ mAnimationStarted = true;
+ mAnimationStartTime = now;
+ final long transitionDuration = isAnimationMaximizing()
+ ? mService.mAppTransition.getLastClipRevealTransitionDuration()
+ : DEFAULT_APP_TRANSITION_DURATION;
+ mAnimationDuration = (long)
+ (transitionDuration * mService.getTransitionAnimationScaleLocked());
+ mMaximizeMeetFraction = getClipRevealMeetFraction(stack);
+ notifyDockedStackMinimizedChanged(mMinimizedDock,
+ (long) (mAnimationDuration * mMaximizeMeetFraction));
+ }
+ float t = Math.min(1f, (float) (now - mAnimationStartTime) / mAnimationDuration);
+ t = (isAnimationMaximizing() ? TOUCH_RESPONSE_INTERPOLATOR : mMinimizedDockInterpolator)
+ .getInterpolation(t);
+ if (stack != null) {
+ if (stack.setAdjustedForMinimizedDock(getMinimizeAmount(stack, t))) {
+ mService.mWindowPlacerLocked.performSurfacePlacement();
+ }
+ }
+ if (t >= 1.0f) {
+ mAnimating = false;
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Gets the amount how much to minimize a stack depending on the interpolated fraction t.
+ */
+ private float getMinimizeAmount(TaskStack stack, float t) {
+ final float naturalAmount = t * mAnimationTarget + (1 - t) * mAnimationStart;
+ if (isAnimationMaximizing()) {
+ return adjustMaximizeAmount(stack, t, naturalAmount);
+ } else {
+ return naturalAmount;
+ }
+ }
+
+ /**
+ * When maximizing the stack during a clip reveal transition, this adjusts the minimize amount
+ * during the transition such that the edge of the clip reveal rect is met earlier in the
+ * transition so we don't create a visible "hole", but only if both the clip reveal and the
+ * docked stack divider start from about the same portion on the screen.
+ */
+ private float adjustMaximizeAmount(TaskStack stack, float t, float naturalAmount) {
+ if (mMaximizeMeetFraction == 1f) {
+ return naturalAmount;
+ }
+ final int minimizeDistance = stack.getMinimizeDistance();
+ float startPrime = mService.mAppTransition.getLastClipRevealMaxTranslation()
+ / (float) minimizeDistance;
+ final float amountPrime = t * mAnimationTarget + (1 - t) * startPrime;
+ final float t2 = Math.min(t / mMaximizeMeetFraction, 1);
+ return amountPrime * t2 + naturalAmount * (1 - t2);
+ }
+
+ /**
+ * Retrieves the animation fraction at which the docked stack has to meet the clip reveal
+ * edge. See {@link #adjustMaximizeAmount}.
+ */
+ private float getClipRevealMeetFraction(TaskStack stack) {
+ if (!isAnimationMaximizing() || stack == null ||
+ !mService.mAppTransition.hadClipRevealAnimation()) {
+ return 1f;
+ }
+ final int minimizeDistance = stack.getMinimizeDistance();
+ final float fraction = Math.abs(mService.mAppTransition.getLastClipRevealMaxTranslation())
+ / (float) minimizeDistance;
+ final float t = Math.max(0, Math.min(1, (fraction - CLIP_REVEAL_MEET_FRACTION_MIN)
+ / (CLIP_REVEAL_MEET_FRACTION_MAX - CLIP_REVEAL_MEET_FRACTION_MIN)));
+ return CLIP_REVEAL_MEET_EARLIEST
+ + (1 - t) * (CLIP_REVEAL_MEET_LAST - CLIP_REVEAL_MEET_EARLIEST);
+ }
+
@Override
public boolean isFullscreen() {
return false;
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 25de75a..a589f89 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -369,7 +369,12 @@
if (DEBUG_TASK_POSITIONING) Slog.d(
TAG_WM, "startMovingTask: {" + startX + "," + startY + "}");
- return mService.startMovingTask(window, startX, startY);
+ long ident = Binder.clearCallingIdentity();
+ try {
+ return mService.startMovingTask(window, startX, startY);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
public void reportDropResult(IWindow window, boolean consumed) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index fe55e80..f097eb2 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -19,7 +19,9 @@
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.app.ActivityManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
@@ -134,12 +136,6 @@
mShowNonResizeableDockToast = false;
- if (isResizeable()) {
- Slog.wtf(TAG,
- "Trying to show non-resizeable toast when task is resizeable task=" + this);
- return;
- }
-
if (mResizeMode == RESIZE_MODE_UNRESIZEABLE) {
final String text =
mService.mContext.getString(R.string.dock_non_resizeble_failed_to_dock_text);
@@ -148,7 +144,7 @@
}
final int dockSide = mStack.getDockSide();
- if (!inCropWindowsResizeMode() || dockSide == DOCKED_INVALID) {
+ if (mResizeMode != RESIZE_MODE_FORCE_RESIZEABLE || dockSide == DOCKED_INVALID) {
return;
}
@@ -176,7 +172,7 @@
yOffset = mTmpRect2.bottom - mTmpRect.bottom;
}
final String text =
- mService.mContext.getString(R.string.dock_cropped_windows_text);
+ mService.mContext.getString(R.string.dock_forced_resizable);
mService.mH.obtainMessage(SHOW_NON_RESIZEABLE_DOCK_TOAST,
xOffset, yOffset, text).sendToTarget();
}
@@ -247,7 +243,15 @@
mStack.removeTask(this);
}
stack.positionTask(this, position, showForAllUsers());
- setBounds(bounds, config);
+ resizeLocked(bounds, config, false /* force */);
+
+ for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
+ final ArrayList<WindowState> windows = mAppTokens.get(activityNdx).allAppWindows;
+ for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
+ final WindowState win = windows.get(winNdx);
+ win.notifyMovedInStack();
+ }
+ }
}
boolean removeAppToken(AppWindowToken wtoken) {
@@ -272,7 +276,7 @@
}
/** Set the task bounds. Passing in null sets the bounds to fullscreen. */
- int setBounds(Rect bounds, Configuration config) {
+ private int setBounds(Rect bounds, Configuration config) {
if (config == null) {
config = Configuration.EMPTY;
}
@@ -357,6 +361,10 @@
return !mHomeTask && (isResizeable() || mResizeMode == RESIZE_MODE_CROP_WINDOWS);
}
+ boolean isHomeTask() {
+ return mHomeTask;
+ }
+
private boolean inCropWindowsResizeMode() {
return !mHomeTask && !isResizeable() && mResizeMode == RESIZE_MODE_CROP_WINDOWS;
}
@@ -594,13 +602,21 @@
void resizeWindows() {
final ArrayList<WindowState> resizingWindows = mService.mResizingWindows;
for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
- final ArrayList<WindowState> windows = mAppTokens.get(activityNdx).allAppWindows;
+ final AppWindowToken atoken = mAppTokens.get(activityNdx);
+
+ // Some windows won't go through the resizing process, if they don't have a surface, so
+ // destroy all saved surfaces here.
+ atoken.destroySavedSurfaces();
+ final ArrayList<WindowState> windows = atoken.allAppWindows;
for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
final WindowState win = windows.get(winNdx);
if (win.mHasSurface && !resizingWindows.contains(win)) {
if (DEBUG_RESIZE) Slog.d(TAG, "resizeWindows: Resizing " + win);
resizingWindows.add(win);
}
+ if (win.isGoneForLayoutLw()) {
+ win.mResizedWhileGone = true;
+ }
}
}
}
@@ -639,6 +655,19 @@
return (tokensCount != 0) && mAppTokens.get(tokensCount - 1).showForAllUsers;
}
+ boolean isVisibleForUser() {
+ for (int i = mAppTokens.size() - 1; i >= 0; i--) {
+ final AppWindowToken appToken = mAppTokens.get(i);
+ for (int j = appToken.allAppWindows.size() - 1; j >= 0; j--) {
+ WindowState window = appToken.allAppWindows.get(j);
+ if (!window.isHiddenFromUserLocked()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
boolean inHomeStack() {
return mStack != null && mStack.mStackId == HOME_STACK_ID;
}
@@ -657,6 +686,10 @@
&& mStack != null && StackId.isTaskResizeableByDockedStack(mStack.mStackId);
}
+ boolean isFloating() {
+ return StackId.tasksAreFloating(mStack.mStackId);
+ }
+
/**
* Whether the task should be treated as if it's docked. Returns true if the task
* is currently in docked workspace, or it's side-by-side to a docked task.
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 8409058..86327f7 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -75,9 +75,6 @@
/** Content limits relative to the DisplayContent this sits in. */
private Rect mBounds = new Rect();
- /** Screen content area excluding IM windows, etc. */
- private final Rect mContentBounds = new Rect();
-
/** Stack bounds adjusted to screen content area (taking into account IM windows, etc.) */
private final Rect mAdjustedBounds = new Rect();
@@ -98,14 +95,38 @@
/** Detach this stack from its display when animation completes. */
boolean mDeferDetach;
- private boolean mUpdateBoundsAfterRotation = false;
+
+ // Display rotation as of the last time the display information was updated for this stack.
+ private int mLastUpdateDisplayInfoRotation = -1;
+ // Display rotation as of the last time the configuration was updated for this stack.
+ private int mLastConfigChangedRotation = -1;
// Whether the stack and all its tasks is currently being drag-resized
private boolean mDragResizing;
+ private final Rect mLastContentBounds = new Rect();
+ private final Rect mTmpAdjustedBounds = new Rect();
+ private boolean mAdjustedForIme;
+ private WindowState mImeWin;
+ private float mMinimizeAmount;
+ private final int mDockedStackMinimizeThickness;
+
+ // If this is true, the task will be down or upscaled
+ // to perfectly fit the region it would have been cropped
+ // to.
+ private boolean mForceScaleToCrop = false;
+ // By default, movement animations are applied to all
+ // window movement. If this is true, animations will not
+ // be applied within this stack. This is useful for example
+ // if the windows are moving as the result of a stack animation,
+ // in which case a second window animation would cause jitter.
+ private boolean mFreezeMovementAnimations = false;
+
TaskStack(WindowManagerService service, int stackId) {
mService = service;
mStackId = stackId;
+ mDockedStackMinimizeThickness = service.mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.docked_stack_minimize_thickness);
EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId);
}
@@ -174,7 +195,27 @@
return mTmpRect.equals(bounds);
}
- void alignTasksToAdjustedBounds(final Rect adjustedBounds) {
+ /**
+ * Overrides the adjusted bounds, i.e. sets temporary layout bounds which are different from
+ * the normal task bounds.
+ *
+ * @param bounds The adjusted bounds.
+ * @param keepInsets Whether to keep the insets from the original bounds or to calculate new
+ * ones depending on the adjusted bounds.
+ */
+ private void setAdjustedBounds(Rect bounds, boolean keepInsets) {
+ if (mAdjustedBounds.equals(bounds)) {
+ return;
+ }
+
+ mAdjustedBounds.set(bounds);
+ final boolean adjusted = !mAdjustedBounds.isEmpty();
+ alignTasksToAdjustedBounds(adjusted ? mAdjustedBounds : mBounds,
+ adjusted && keepInsets ? mBounds : null);
+ mDisplayContent.layoutNeeded = true;
+ }
+
+ private void alignTasksToAdjustedBounds(Rect adjustedBounds, Rect tempInsetBounds) {
if (mFullscreen) {
return;
}
@@ -187,72 +228,15 @@
task.resizeLocked(null, null, false /* forced */);
task.getBounds(mTmpRect2);
task.scrollLocked(mTmpRect2);
- } else if (task.isResizeable()) {
+ } else if (task.isResizeable() && task.mOverrideConfig != Configuration.EMPTY) {
task.getBounds(mTmpRect2);
mTmpRect2.offsetTo(adjustedBounds.left, adjustedBounds.top);
+ task.setTempInsetBounds(tempInsetBounds);
task.resizeLocked(mTmpRect2, task.mOverrideConfig, false /* forced */);
}
}
}
- void adjustForIME(final WindowState imeWin) {
- final int dockedSide = getDockSide();
- final boolean dockedTopOrBottom = dockedSide == DOCKED_TOP || dockedSide == DOCKED_BOTTOM;
- final Rect adjustedBounds = mAdjustedBounds;
- if (imeWin == null || !dockedTopOrBottom) {
- // If mContentBounds is already empty, it means we're not applying
- // any adjustments, so nothing to do; otherwise clear any adjustments.
- if (!mContentBounds.isEmpty()) {
- mContentBounds.setEmpty();
- adjustedBounds.set(mBounds);
- alignTasksToAdjustedBounds(adjustedBounds);
- }
- return;
- }
-
- final Rect displayContentRect = mTmpRect;
- final Rect contentBounds = mTmpRect2;
-
- // Calculate the content bounds excluding the area occupied by IME
- mDisplayContent.getContentRect(displayContentRect);
- contentBounds.set(displayContentRect);
- int imeTop = Math.max(imeWin.getDisplayFrameLw().top, contentBounds.top);
- imeTop += imeWin.getGivenContentInsetsLw().top;
- if (contentBounds.bottom > imeTop) {
- contentBounds.bottom = imeTop;
- }
-
- // If content bounds not changing, nothing to do.
- if (mContentBounds.equals(contentBounds)) {
- return;
- }
-
- // Content bounds changed, need to apply adjustments depending on dock sides.
- mContentBounds.set(contentBounds);
- adjustedBounds.set(mBounds);
- final int yOffset = displayContentRect.bottom - contentBounds.bottom;
-
- if (dockedSide == DOCKED_TOP) {
- // If this stack is docked on top, we make it smaller so the bottom stack is not
- // occluded by IME. We shift its bottom up by the height of the IME (capped by
- // the display content rect). Note that we don't change the task bounds.
- adjustedBounds.bottom = Math.max(
- adjustedBounds.bottom - yOffset, displayContentRect.top);
- } else {
- // If this stack is docked on bottom, we shift it up so that it's not occluded by
- // IME. We try to move it up by the height of the IME window (although the best
- // we could do is to make the top stack fully collapsed).
- final int dividerWidth = mDisplayContent.mDividerControllerLocked.getContentWidth();
- adjustedBounds.top = Math.max(
- adjustedBounds.top - yOffset, displayContentRect.top + dividerWidth);
- adjustedBounds.bottom = adjustedBounds.top + mBounds.height();
-
- // We also move the member tasks together, taking care not to resize them.
- // Resizing might cause relaunch, and IME window may not come back after that.
- alignTasksToAdjustedBounds(adjustedBounds);
- }
- }
-
private boolean setBounds(Rect bounds) {
boolean oldFullscreen = mFullscreen;
int rotation = Surface.ROTATION_0;
@@ -281,14 +265,7 @@
mBounds.set(bounds);
mRotation = rotation;
- // Clear the adjusted content bounds as they're no longer valid.
- // If IME is still visible, these will be re-applied.
- // Note that we don't clear mContentBounds here, so that we know the last IME
- // adjust we applied.
- // If user starts dragging the dock divider while IME is visible, the new bounds
- // we received are based on the actual screen location of the divider. It already
- // accounted for the IME window, so we don't want to adjust again.
- mAdjustedBounds.set(mBounds);
+ updateAdjustedBounds();
return true;
}
@@ -314,10 +291,11 @@
public void getBounds(Rect out) {
if (useCurrentBounds()) {
- // If we're currently adjusting for IME, we use the adjusted bounds; otherwise,
- // no need to adjust the output bounds if fullscreen or the docked stack is visible
- // since it is already what we want to represent to the rest of the system.
- if (!mContentBounds.isEmpty()) {
+ // If we're currently adjusting for IME or minimized docked stack, we use the adjusted
+ // bounds; otherwise, no need to adjust the output bounds if fullscreen or the docked
+ // stack is visible since it is already what we want to represent to the rest of the
+ // system.
+ if (!mAdjustedBounds.isEmpty()) {
out.set(mAdjustedBounds);
} else {
out.set(mBounds);
@@ -338,49 +316,99 @@
}
void updateDisplayInfo(Rect bounds) {
- mUpdateBoundsAfterRotation = false;
- if (mDisplayContent != null) {
- for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
- mTasks.get(taskNdx).updateDisplayInfo(mDisplayContent);
- }
- if (bounds != null) {
- setBounds(bounds);
- } else if (mFullscreen) {
- setBounds(null);
- } else {
- mUpdateBoundsAfterRotation = true;
- mTmpRect2.set(mBounds);
- final int newRotation = mDisplayContent.getDisplayInfo().rotation;
- if (mRotation == newRotation) {
- setBounds(mTmpRect2);
- }
+ if (mDisplayContent == null) {
+ return;
+ }
- // If the rotation changes, we'll handle it in updateBoundsAfterRotation
- }
+ for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
+ mTasks.get(taskNdx).updateDisplayInfo(mDisplayContent);
+ }
+ if (bounds != null) {
+ setBounds(bounds);
+ return;
+ } else if (mFullscreen) {
+ setBounds(null);
+ return;
+ }
+
+ mTmpRect2.set(mBounds);
+ final int newRotation = mDisplayContent.getDisplayInfo().rotation;
+ if (mRotation == newRotation) {
+ setBounds(mTmpRect2);
+ } else {
+ mLastUpdateDisplayInfoRotation = newRotation;
+ updateBoundsAfterRotation();
}
}
- /**
- * Updates the bounds after rotating the screen. We can't handle it in
- * {@link #updateDisplayInfo} because at that point the configuration might not be fully updated
- * yet.
- */
+ void onConfigurationChanged() {
+ mLastConfigChangedRotation = getDisplayInfo().rotation;
+ updateBoundsAfterRotation();
+ }
+
void updateBoundsAfterRotation() {
- if (!mUpdateBoundsAfterRotation) {
+ if (mLastConfigChangedRotation != mLastUpdateDisplayInfoRotation) {
+ // We wait for the rotation values after configuration change and display info. update
+ // to be equal before updating the bounds due to rotation change otherwise things might
+ // get out of alignment...
return;
}
- mUpdateBoundsAfterRotation = false;
+
final int newRotation = getDisplayInfo().rotation;
+
+ if (mRotation == newRotation) {
+ // Nothing to do here if the rotation didn't change
+ return;
+ }
+
mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
if (mStackId == DOCKED_STACK_ID) {
+ repositionDockedStackAfterRotation(mTmpRect2);
snapDockedStackAfterRotation(mTmpRect2);
}
// Post message to inform activity manager of the bounds change simulating
// a one-way call. We do this to prevent a deadlock between window manager
// lock and activity manager lock been held.
- mService.mH.sendMessage(mService.mH.obtainMessage(
- RESIZE_STACK, mStackId, 0 /*allowResizeInDockedMode*/, mTmpRect2));
+ mService.mH.obtainMessage(
+ RESIZE_STACK, mStackId, 0 /*allowResizeInDockedMode*/, mTmpRect2).sendToTarget();
+ }
+
+ /**
+ * Some dock sides are not allowed by the policy. This method queries the policy and moves
+ * the docked stack around if needed.
+ *
+ * @param inOutBounds the bounds of the docked stack to adjust
+ */
+ private void repositionDockedStackAfterRotation(Rect inOutBounds) {
+ int dockSide = getDockSide(inOutBounds);
+ if (mService.mPolicy.isDockSideAllowed(dockSide)) {
+ return;
+ }
+ mDisplayContent.getLogicalDisplayRect(mTmpRect);
+ dockSide = DockedDividerUtils.invertDockSide(dockSide);
+ switch (dockSide) {
+ case DOCKED_LEFT:
+ int movement = inOutBounds.left;
+ inOutBounds.left -= movement;
+ inOutBounds.right -= movement;
+ break;
+ case DOCKED_RIGHT:
+ movement = mTmpRect.right - inOutBounds.right;
+ inOutBounds.left += movement;
+ inOutBounds.right += movement;
+ break;
+ case DOCKED_TOP:
+ movement = inOutBounds.top;
+ inOutBounds.top -= movement;
+ inOutBounds.bottom -= movement;
+ break;
+ case DOCKED_BOTTOM:
+ movement = mTmpRect.bottom - inOutBounds.bottom;
+ inOutBounds.top += movement;
+ inOutBounds.bottom += movement;
+ break;
+ }
}
/**
@@ -420,7 +448,7 @@
final ArrayList<WindowState> windows = activities.get(activityNdx).allAppWindows;
for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
final WindowStateAnimator winAnimator = windows.get(winNdx).mWinAnimator;
- if (winAnimator.isAnimating() || winAnimator.mWin.mExiting) {
+ if (winAnimator.isAnimating() || winAnimator.mWin.mAnimatingExit) {
return true;
}
}
@@ -691,7 +719,7 @@
outBounds.top = dockedBounds.bottom + dockDividerWidth;
}
}
- DockedDividerUtils.sanitizeStackBounds(outBounds);
+ DockedDividerUtils.sanitizeStackBounds(outBounds, !dockOnTopOrLeft);
}
/** Resizes all non-docked stacks in the system to either fullscreen or the appropriate size
@@ -802,6 +830,158 @@
mDisplayContent = null;
}
+ /**
+ * Adjusts the stack bounds if the IME is visible.
+ *
+ * @param imeWin The IME window.
+ */
+ void setAdjustedForIme(WindowState imeWin) {
+ mAdjustedForIme = true;
+ mImeWin = imeWin;
+ updateAdjustedBounds();
+ }
+
+ /**
+ * Resets the adjustment after it got adjusted for the IME.
+ */
+ void resetAdjustedForIme() {
+ mAdjustedForIme = false;
+ mImeWin = null;
+ updateAdjustedBounds();
+ }
+
+ /**
+ * Sets the amount how much we currently minimize our stack.
+ *
+ * @param minimizeAmount The amount, between 0 and 1.
+ * @return Whether the amount has changed and a layout is needed.
+ */
+ boolean setAdjustedForMinimizedDock(float minimizeAmount) {
+ if (minimizeAmount != mMinimizeAmount) {
+ mMinimizeAmount = minimizeAmount;
+ updateAdjustedBounds();
+ return isVisibleForUserLocked();
+ } else {
+ return false;
+ }
+ }
+
+ private boolean adjustForIME(final WindowState imeWin) {
+ final int dockedSide = getDockSide();
+ final boolean dockedTopOrBottom = dockedSide == DOCKED_TOP || dockedSide == DOCKED_BOTTOM;
+ final Rect adjustedBounds = mTmpAdjustedBounds;
+ if (imeWin == null || !dockedTopOrBottom) {
+ return false;
+ }
+
+ final Rect displayContentRect = mTmpRect;
+ final Rect contentBounds = mTmpRect2;
+
+ // Calculate the content bounds excluding the area occupied by IME
+ getDisplayContent().getContentRect(displayContentRect);
+ contentBounds.set(displayContentRect);
+ int imeTop = Math.max(imeWin.getDisplayFrameLw().top, contentBounds.top);
+ imeTop += imeWin.getGivenContentInsetsLw().top;
+ if (contentBounds.bottom > imeTop) {
+ contentBounds.bottom = imeTop;
+ }
+
+ // If content bounds not changing, nothing to do.
+ if (mLastContentBounds.equals(contentBounds)) {
+ return true;
+ }
+
+ // Content bounds changed, need to apply adjustments depending on dock sides.
+ mLastContentBounds.set(contentBounds);
+ adjustedBounds.set(mBounds);
+ final int yOffset = displayContentRect.bottom - contentBounds.bottom;
+
+ if (dockedSide == DOCKED_TOP) {
+ // If this stack is docked on top, we make it smaller so the bottom stack is not
+ // occluded by IME. We shift its bottom up by the height of the IME (capped by
+ // the display content rect). Note that we don't change the task bounds.
+ adjustedBounds.bottom = Math.max(
+ adjustedBounds.bottom - yOffset, displayContentRect.top);
+ } else {
+ // If this stack is docked on bottom, we shift it up so that it's not occluded by
+ // IME. We try to move it up by the height of the IME window (although the best
+ // we could do is to make the top stack fully collapsed).
+ final int dividerWidth = getDisplayContent().mDividerControllerLocked
+ .getContentWidth();
+ adjustedBounds.top = Math.max(
+ adjustedBounds.top - yOffset, displayContentRect.top + dividerWidth);
+ adjustedBounds.bottom = adjustedBounds.top + mBounds.height();
+ }
+ return true;
+ }
+
+ private boolean adjustForMinimizedDockedStack(float minimizeAmount) {
+ final int dockSide = getDockSide();
+ if (dockSide == DOCKED_INVALID && !mTmpAdjustedBounds.isEmpty()) {
+ return false;
+ }
+
+ if (dockSide == DOCKED_TOP) {
+ mService.getStableInsetsLocked(mTmpRect);
+ int topInset = mTmpRect.top;
+ mTmpAdjustedBounds.set(mBounds);
+ mTmpAdjustedBounds.bottom =
+ (int) (minimizeAmount * topInset + (1 - minimizeAmount) * mBounds.bottom);
+ } else if (dockSide == DOCKED_LEFT) {
+ mTmpAdjustedBounds.set(mBounds);
+ mTmpAdjustedBounds.right =
+ (int) (minimizeAmount * mDockedStackMinimizeThickness
+ + (1 - minimizeAmount) * mBounds.right);
+ } else if (dockSide == DOCKED_RIGHT) {
+ mTmpAdjustedBounds.set(mBounds);
+ mTmpAdjustedBounds.left =
+ (int) (minimizeAmount * (mBounds.right - mDockedStackMinimizeThickness)
+ + (1 - minimizeAmount) * mBounds.left);
+ }
+ return true;
+ }
+
+ /**
+ * @return the distance in pixels how much the stack gets minimized from it's original size
+ */
+ int getMinimizeDistance() {
+ final int dockSide = getDockSide();
+ if (dockSide == DOCKED_INVALID) {
+ return 0;
+ }
+
+ if (dockSide == DOCKED_TOP) {
+ mService.getStableInsetsLocked(mTmpRect);
+ int topInset = mTmpRect.top;
+ return mBounds.bottom - topInset;
+ } else if (dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT) {
+ return mBounds.width() - mDockedStackMinimizeThickness;
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Updates the adjustment depending on it's current state.
+ */
+ void updateAdjustedBounds() {
+ boolean adjust = false;
+ if (mMinimizeAmount != 0f) {
+ adjust = adjustForMinimizedDockedStack(mMinimizeAmount);
+ } else if (mAdjustedForIme) {
+ adjust = adjustForIME(mImeWin);
+ }
+ if (!adjust) {
+ mTmpAdjustedBounds.setEmpty();
+ mLastContentBounds.setEmpty();
+ }
+ setAdjustedBounds(mTmpAdjustedBounds, isAdjustedForMinimizedDockedStack());
+ }
+
+ boolean isAdjustedForMinimizedDockedStack() {
+ return mMinimizeAmount != 0f;
+ }
+
public void dump(String prefix, PrintWriter pw) {
pw.println(prefix + "mStackId=" + mStackId);
pw.println(prefix + "mDeferDetach=" + mDeferDetach);
@@ -906,13 +1086,28 @@
}
for (int i = mTasks.size() - 1; i >= 0; i--) {
- Task task = mTasks.get(i);
+ final Task task = mTasks.get(i);
for (int j = task.mAppTokens.size() - 1; j >= 0; j--) {
if (!task.mAppTokens.get(j).hidden) {
return true;
}
}
}
+
+ return false;
+ }
+
+ /**
+ * @return true if a the stack is visible for the current in user, ignoring any other visibility
+ * aspects, and false otherwise
+ */
+ boolean isVisibleForUserLocked() {
+ for (int i = mTasks.size() - 1; i >= 0; i--) {
+ final Task task = mTasks.get(i);
+ if (task.isVisibleForUser()) {
+ return true;
+ }
+ }
return false;
}
@@ -944,17 +1139,38 @@
return true;
}
+ public boolean setPinnedStackSize(Rect bounds, Rect tempTaskBounds) {
+ synchronized (mService.mWindowMap) {
+ if (mDisplayContent == null) {
+ return false;
+ }
+ if (mStackId != PINNED_STACK_ID) {
+ Slog.w(TAG_WM, "Attempt to use pinned stack resize animation helper on"
+ + "non pinned stack");
+ return false;
+ }
+ }
+ try {
+ mService.mActivityManager.resizePinnedStack(bounds, tempTaskBounds);
+ } catch (RemoteException e) {
+ // I don't believe you.
+ }
+ return true;
+ }
+
@Override // AnimatesBounds
public void onAnimationStart() {
synchronized (mService.mWindowMap) {
- setDragResizingLocked(true);
+ mFreezeMovementAnimations = true;
+ mForceScaleToCrop = true;
}
}
@Override // AnimatesBounds
public void onAnimationEnd() {
synchronized (mService.mWindowMap) {
- setDragResizingLocked(false);
+ mFreezeMovementAnimations = false;
+ mForceScaleToCrop = false;
mService.requestTraversal();
}
if (mStackId == PINNED_STACK_ID) {
@@ -979,4 +1195,12 @@
public void getFullScreenBounds(Rect bounds) {
getDisplayContent().getContentRect(bounds);
}
-}
\ No newline at end of file
+
+ public boolean getFreezeMovementAnimations() {
+ return mFreezeMovementAnimations;
+ }
+
+ public boolean getForceScaleToCrop() {
+ return mForceScaleToCrop;
+ }
+}
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index f8a4d33..85bddee 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -530,7 +530,7 @@
for (int i = windows.size() - 1; i >= 0; i--) {
final WindowState win = windows.get(i);
WindowStateAnimator winAnimator = win.mWinAnimator;
- if (winAnimator.mSurfaceController == null) {
+ if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) {
continue;
}
@@ -705,7 +705,8 @@
}
orAnimating(mService.getDisplayContentLocked(displayId).animateDimLayers());
-
+ orAnimating(mService.getDisplayContentLocked(displayId).getDockedDividerController()
+ .animate(mCurrentTime));
//TODO (multidisplay): Magnification is supported only for the default display.
if (mService.mAccessibilityController != null
&& displayId == Display.DEFAULT_DISPLAY) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
index 0979cd3..ccba88d 100644
--- a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
+++ b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
@@ -35,7 +35,7 @@
static final boolean DEBUG_RESIZE = false;
static final boolean DEBUG = false;
- static final boolean DEBUG_ADD_REMOVE = false;
+ static final boolean DEBUG_ADD_REMOVE = true;
static final boolean DEBUG_FOCUS = false;
static final boolean DEBUG_FOCUS_LIGHT = DEBUG_FOCUS || false;
static final boolean DEBUG_ANIM = false;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 7169375..b64aaa8 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -20,6 +20,7 @@
import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityManagerInternal;
import android.app.ActivityManagerNative;
import android.app.AppOpsManager;
import android.app.IActivityManager;
@@ -116,9 +117,10 @@
import android.view.animation.Animation;
import android.view.inputmethod.InputMethodManagerInternal;
import android.widget.Toast;
-import com.android.internal.R;
+
import com.android.internal.app.IAssistScreenshotReceiver;
import com.android.internal.os.IResultReceiver;
+import com.android.internal.policy.IShortcutService;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
@@ -192,6 +194,8 @@
import static android.view.WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static android.view.WindowManagerPolicy.TRANSIT_EXIT;
+import static android.view.WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_END;
import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
@@ -318,6 +322,8 @@
private static final float DRAG_SHADOW_ALPHA_TRANSPARENT = .7071f;
+ private static final String PROPERTY_BUILD_DATE_UTC = "ro.build.date.utc";
+
final private KeyguardDisableHandler mKeyguardDisableHandler;
final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -358,6 +364,7 @@
final WindowManagerPolicy mPolicy = new PhoneWindowManager();
final IActivityManager mActivityManager;
+ final ActivityManagerInternal mAmInternal;
final AppOpsManager mAppOps;
@@ -898,6 +905,7 @@
mAppTransition.registerListenerLocked(mActivityManagerAppTransitionNotifier);
mActivityManager = ActivityManagerNative.getDefault();
+ mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
AppOpsManager.OnOpChangedInternalListener opListener =
new AppOpsManager.OnOpChangedInternalListener() {
@@ -1354,7 +1362,7 @@
+ " policyVis=" + w.mPolicyVisibility
+ " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim
+ " attachHid=" + w.mAttachedHidden
- + " exiting=" + w.mExiting + " destroying=" + w.mDestroying);
+ + " exiting=" + w.mAnimatingExit + " destroying=" + w.mDestroying);
if (w.mAppToken != null) {
Slog.i(TAG_WM, " mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested);
}
@@ -1994,8 +2002,10 @@
prepareWindowReplacementTransition(atoken);
if (displayContent.isDefaultDisplay) {
- mPolicy.getInsetHintLw(win.mAttrs, mRotation, outContentInsets, outStableInsets,
- outOutsets);
+ if (mPolicy.getInsetHintLw(win.mAttrs, mRotation, outContentInsets, outStableInsets,
+ outOutsets)) {
+ res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR;
+ }
} else {
outContentInsets.setEmpty();
outStableInsets.setEmpty();
@@ -2057,7 +2067,7 @@
WindowState replacedWindow = null;
for (int i = atoken.windows.size() - 1; i >= 0 && replacedWindow == null; i--) {
WindowState candidate = atoken.windows.get(i);
- if (candidate.mExiting && candidate.mWillReplaceWindow
+ if (candidate.mAnimatingExit && candidate.mWillReplaceWindow
&& candidate.mAnimateReplacingWindow) {
replacedWindow = candidate;
}
@@ -2131,25 +2141,21 @@
if (win == null) {
return;
}
- // We set this here instead of removeWindowLocked because we only want it to be
- // true when the client has requested we remove the window. In other remove
- // cases, we have to wait for activity stop to safely remove the window (as the
- // client may still be using the surface). In this case though, the client has
- // just dismissed a window (for example a Dialog) and activity stop isn't
- // necessarily imminent, so we need to know not to wait for it after our
- // hanimation (if applicable) finishes.
- win.mClientRemoveRequested = true;
removeWindowLocked(win);
}
}
void removeWindowLocked(WindowState win) {
+ win.mWindowRemovalAllowed = true;
+ if (DEBUG_ADD_REMOVE) Slog.v(TAG,
+ "removeWindowLocked: " + win + " callers=" + Debug.getCallers(4));
+
final boolean startingWindow = win.mAttrs.type == TYPE_APPLICATION_STARTING;
if (startingWindow) {
if (DEBUG_STARTING_WINDOW) Slog.d(TAG_WM, "Starting window removed " + win);
}
- if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win==mCurrentFocus) Slog.v(
+ if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win == mCurrentFocus) Slog.v(
TAG_WM, "Remove " + win + " client="
+ Integer.toHexString(System.identityHashCode(win.mClient.asBinder()))
+ ", surfaceController=" + win.mWinAnimator.mSurfaceController + " Callers="
@@ -2159,23 +2165,25 @@
win.disposeInputChannel();
- if (DEBUG_APP_TRANSITIONS) Slog.v(
- TAG_WM, "Remove " + win + ": mSurfaceController=" + win.mWinAnimator.mSurfaceController
- + " mExiting=" + win.mExiting
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
+ "Remove " + win + ": mSurfaceController=" + win.mWinAnimator.mSurfaceController
+ + " mAnimatingExit=" + win.mAnimatingExit
+ + " mRemoveOnExit=" + win.mRemoveOnExit
+ + " mHasSurface=" + win.mHasSurface
+ + " surfaceShowing=" + win.mWinAnimator.getShown()
+ " isAnimating=" + win.mWinAnimator.isAnimating()
+ " app-animation="
+ (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null)
- + " mWillReplaceWindow="
- + win.mWillReplaceWindow
+ + " mWillReplaceWindow=" + win.mWillReplaceWindow
+ " inPendingTransaction="
+ (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false)
- + " mDisplayFrozen=" + mDisplayFrozen);
+ + " mDisplayFrozen=" + mDisplayFrozen
+ + " callers=" + Debug.getCallers(6));
// Visibility of the removed window. Will be used later to update orientation later on.
boolean wasVisible = false;
- // First, see if we need to run an animation. If we do, we have
- // to hold off on removing the window until the animation is done.
- // If the display is frozen, just remove immediately, since the
- // animation wouldn't be seen.
+ // First, see if we need to run an animation. If we do, we have to hold off on removing the
+ // window until the animation is done. If the display is frozen, just remove immediately,
+ // since the animation wouldn't be seen.
if (win.mHasSurface && okToDisplay()) {
final AppWindowToken appToken = win.mAppToken;
if (win.mWillReplaceWindow) {
@@ -2183,13 +2191,16 @@
// gets added, then we will get rid of this one.
if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Preserving " + win + " until the new one is "
+ "added");
- win.mExiting = true;
+ // TODO: We are overloading mAnimatingExit flag to prevent the window state from
+ // been removed. We probably need another falg to indicate that window removal
+ // should be deffered vs. overloading the flag that says we are playing an exit
+ // animation.
+ win.mAnimatingExit = true;
win.mReplacingRemoveRequested = true;
Binder.restoreCallingIdentity(origId);
return;
}
- // If we are not currently running the exit animation, we
- // need to see about starting one.
+ // If we are not currently running the exit animation, we need to see about starting one
wasVisible = win.isWinVisibleLw();
if (win.shouldKeepVisibleDeadAppWindow()) {
@@ -2209,14 +2220,13 @@
return;
}
+ final WindowStateAnimator winAnimator = win.mWinAnimator;
if (wasVisible) {
- final int transit = (!startingWindow)
- ? WindowManagerPolicy.TRANSIT_EXIT
- : WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
+ final int transit = (!startingWindow) ? TRANSIT_EXIT : TRANSIT_PREVIEW_DONE;
// Try starting an animation.
- if (win.mWinAnimator.applyAnimationLocked(transit, false)) {
- win.mExiting = true;
+ if (winAnimator.applyAnimationLocked(transit, false)) {
+ win.mAnimatingExit = true;
}
//TODO (multidisplay): Magnification is supported only for the default display.
if (mAccessibilityController != null
@@ -2224,15 +2234,20 @@
mAccessibilityController.onWindowTransitionLocked(win, transit);
}
}
- final boolean isAnimating = win.mWinAnimator.isAnimating()
- && !win.mWinAnimator.isDummyAnimation();
- // The starting window is the last window in this app token and it isn't animating.
- // Allow it to be removed now as there is no additional window or animation that will
- // trigger its removal.
- final boolean lastWinStartingNotAnimating = startingWindow && appToken!= null
- && appToken.allAppWindows.size() == 1 && !isAnimating;
- if (!lastWinStartingNotAnimating && win.mExiting) {
- // The exit animation is running... wait for it!
+ final boolean isAnimating =
+ winAnimator.isAnimating() && !winAnimator.isDummyAnimation();
+ final boolean lastWindowIsStartingWindow = startingWindow && appToken != null
+ && appToken.allAppWindows.size() == 1;
+ // We delay the removal of a window if it has a showing surface that can be used to run
+ // exit animation and it is marked as exiting.
+ // Also, If isn't the an animating starting window that is the last window in the app.
+ // We allow the removal of the non-animating starting window now as there is no
+ // additional window or animation that will trigger its removal.
+ if (winAnimator.getShown() && win.mAnimatingExit
+ && (!lastWindowIsStartingWindow || isAnimating)) {
+ // The exit animation is running or should run... wait for it!
+ if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
+ "Not removing " + win + " due to exit animation ");
win.mRemoveOnExit = true;
win.setDisplayLayoutNeeded();
final boolean focusChanged = updateFocusedWindowLocked(
@@ -2262,13 +2277,14 @@
void removeWindowInnerLocked(WindowState win) {
if (win.mRemoved) {
// Nothing to do.
+ if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
+ "removeWindowInnerLocked: " + win + " Already removed...");
return;
}
- for (int i=win.mChildWindows.size()-1; i>=0; i--) {
+ for (int i = win.mChildWindows.size() - 1; i >= 0; i--) {
WindowState cwin = win.mChildWindows.get(i);
- Slog.w(TAG_WM, "Force-removing child win " + cwin + " from container "
- + win);
+ Slog.w(TAG_WM, "Force-removing child win " + cwin + " from container " + win);
removeWindowInnerLocked(cwin);
}
@@ -2681,16 +2697,16 @@
final boolean usingSavedSurfaceBeforeVisible =
oldVisibility != View.VISIBLE && win.isAnimatingWithSavedSurface();
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
- if (winAnimator.hasSurface() && !win.mExiting
+ if (winAnimator.hasSurface() && !win.mAnimatingExit
&& usingSavedSurfaceBeforeVisible) {
Slog.d(TAG, "Ignoring layout to invisible when using saved surface " + win);
}
}
- if (winAnimator.hasSurface() && !win.mExiting
+ if (winAnimator.hasSurface() && !win.mAnimatingExit
&& !usingSavedSurfaceBeforeVisible) {
if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Relayout invis " + win
- + ": mExiting=" + win.mExiting);
+ + ": mAnimatingExit=" + win.mAnimatingExit);
// If we are not currently running the exit animation, we
// need to see about starting one.
// We don't want to animate visibility of windows which are pending
@@ -2753,6 +2769,12 @@
winAnimator.mReportSurfaceResized = false;
result |= WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED;
}
+ if (mPolicy.isNavBarForcedShownLw(win)) {
+ result |= WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR;
+ }
+ if (!win.isGoneForLayoutLw()) {
+ win.mResizedWhileGone = false;
+ }
outFrame.set(win.mCompatFrame);
outOverscanInsets.set(win.mOverscanInsets);
outContentInsets.set(win.mContentInsets);
@@ -2797,16 +2819,16 @@
}
if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) {
focusMayChange = isDefaultDisplay;
- win.mExiting = true;
+ win.mAnimatingExit = true;
} else if (win.mWinAnimator.isAnimating()) {
// Currently in a hide animation... turn this into
// an exit.
- win.mExiting = true;
+ win.mAnimatingExit = true;
} else if (mWallpaperControllerLocked.isWallpaperTarget(win)) {
// If the wallpaper is currently behind this
// window, we need to change both of them inside
// of a transaction to avoid artifacts.
- win.mExiting = true;
+ win.mAnimatingExit = true;
win.mWinAnimator.mAnimating = true;
} else {
if (mInputMethodWindow == win) {
@@ -2842,12 +2864,12 @@
private int relayoutVisibleWindow(Configuration outConfig, int result, WindowState win,
WindowStateAnimator winAnimator, int attrChanges, int oldVisibility) {
result |= !win.isVisibleLw() ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0;
- if (win.mExiting) {
- Slog.d(TAG, "relayoutVisibleWindow: " + win + " mExiting=true, mRemoveOnExit="
+ if (win.mAnimatingExit) {
+ Slog.d(TAG, "relayoutVisibleWindow: " + win + " mAnimatingExit=true, mRemoveOnExit="
+ win.mRemoveOnExit + ", mDestroying=" + win.mDestroying);
winAnimator.cancelExitAnimationForNextAnimationLocked();
- win.mExiting = false;
+ win.mAnimatingExit = false;
}
if (win.mDestroying) {
win.mDestroying = false;
@@ -2968,6 +2990,8 @@
// Determine the visible rect to calculate the thumbnail clip
final WindowState win = atoken.findMainWindow();
final Rect frame = new Rect(0, 0, width, height);
+ final Rect displayFrame = new Rect(0, 0,
+ displayInfo.logicalWidth, displayInfo.logicalHeight);
final Rect insets = new Rect();
Rect surfaceInsets = null;
final boolean freeform = win != null && win.inFreeformWorkspace();
@@ -2995,8 +3019,8 @@
+ " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
+ " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
Animation a = mAppTransition.loadAnimation(lp, transit, enter,
- mCurConfiguration.orientation, frame, insets, surfaceInsets, isVoiceInteraction,
- freeform, atoken.mTask.mTaskId);
+ mCurConfiguration.orientation, frame, displayFrame, insets, surfaceInsets,
+ isVoiceInteraction, freeform, atoken.mTask.mTaskId);
if (a != null) {
if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + atoken);
final int containingWidth = frame.width();
@@ -3542,23 +3566,20 @@
}
synchronized(mWindowMap) {
- final boolean orientationChanged = mCurConfiguration.orientation != config.orientation;
mCurConfiguration = new Configuration(config);
if (mWaitingForConfig) {
mWaitingForConfig = false;
mLastFinishedFreezeSource = "new-config";
}
- if (orientationChanged) {
- updateTaskStackBoundsAfterRotation();
- }
+ onConfigurationChanged();
mWindowPlacerLocked.performSurfacePlacement();
}
}
- private void updateTaskStackBoundsAfterRotation() {
+ private void onConfigurationChanged() {
for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; stackNdx--) {
final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
- stack.updateBoundsAfterRotation();
+ stack.onConfigurationChanged();
}
}
@@ -3732,7 +3753,8 @@
}
for (final WindowState win : mWindowMap.values()) {
final Task task = win.getTask();
- if (task != null && mTmpTaskIds.get(task.mTaskId, -1) != -1) {
+ if (task != null && mTmpTaskIds.get(task.mTaskId, -1) != -1
+ && task.inFreeformWorkspace()) {
final AppWindowToken appToken = win.mAppToken;
if (appToken != null && appToken.mAppAnimator != null) {
appToken.mAppAnimator.startProlongAnimation(scaleUp ?
@@ -4000,10 +4022,8 @@
public void removeAppStartingWindow(IBinder token) {
synchronized (mWindowMap) {
- AppWindowToken wtoken = mTokenMap.get(token).appWindowToken;
- if (wtoken.startingWindow != null) {
- scheduleRemoveStartingWindowLocked(wtoken);
- }
+ final AppWindowToken wtoken = mTokenMap.get(token).appWindowToken;
+ scheduleRemoveStartingWindowLocked(wtoken);
}
}
@@ -4153,11 +4173,15 @@
}
}
- if (visibilityChanged && visible && !delayed) {
- // The token was made immediately visible, there will be no entrance animation. We need
- // to inform the client the enter animation was finished.
- wtoken.mEnteringAnimation = true;
- mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(wtoken.token);
+ if (visibilityChanged && !delayed) {
+ if (visible) {
+ // The token was made immediately visible, there will be no entrance animation.
+ // We need to inform the client the enter animation was finished.
+ wtoken.mEnteringAnimation = true;
+ mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(wtoken.token);
+ }
+ getDefaultDisplayContentLocked().getDockedDividerController()
+ .notifyAppVisibilityChanged(wtoken, visible);
}
return delayed;
@@ -4173,7 +4197,7 @@
}
@Override
- public void notifyAppStopped(IBinder token) {
+ public void notifyAppStopped(IBinder token, boolean stopped) {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
"notifyAppStopped()")) {
throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
@@ -4186,7 +4210,7 @@
Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: " + token);
return;
}
- wtoken.notifyAppStopped();
+ wtoken.notifyAppStopped(stopped);
}
}
@@ -4223,7 +4247,10 @@
wtoken.appDied = false;
wtoken.removeAllWindows();
} else if (visible) {
+ if (DEBUG_ADD_REMOVE) Slog.v(
+ TAG_WM, "No longer Stopped: " + wtoken);
wtoken.mAppStopped = false;
+ wtoken.setWindowsExiting(false);
}
// If we are preparing an app transition, then delay changing
@@ -4241,7 +4268,6 @@
}
wtoken.inPendingTransaction = true;
if (visible) {
- wtoken.setWindowsExiting(false);
mOpeningApps.add(wtoken);
wtoken.startingMoved = false;
wtoken.mEnteringAnimation = true;
@@ -4478,17 +4504,30 @@
}
void scheduleRemoveStartingWindowLocked(AppWindowToken wtoken) {
+ if (wtoken == null) {
+ return;
+ }
if (mH.hasMessages(H.REMOVE_STARTING, wtoken)) {
// Already scheduled.
return;
}
- if (wtoken != null && wtoken.startingWindow != null) {
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, Debug.getCallers(1) +
- ": Schedule remove starting " + wtoken + (wtoken != null ?
- " startingWindow=" + wtoken.startingWindow : ""));
- Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken);
- mH.sendMessage(m);
+
+ if (wtoken.startingWindow == null) {
+ if (wtoken.startingData != null) {
+ // Starting window has not been added yet, but it is scheduled to be added.
+ // Go ahead and cancel the request.
+ if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
+ "Clearing startingData for token=" + wtoken);
+ wtoken.startingData = null;
+ }
+ return;
}
+
+ if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, Debug.getCallers(1) +
+ ": Schedule remove starting " + wtoken + (wtoken != null ?
+ " startingWindow=" + wtoken.startingWindow : ""));
+ Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken);
+ mH.sendMessage(m);
}
void dumpAppTokensLocked() {
@@ -7450,8 +7489,22 @@
|| volumeDownState > 0;
try {
if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) {
- mSafeMode = true;
- SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
+ int auditSafeMode = SystemProperties.getInt(ShutdownThread.AUDIT_SAFEMODE_PROPERTY, 0);
+
+ if (auditSafeMode == 0) {
+ mSafeMode = true;
+ SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
+ } else {
+ // stay in safe mode until we have updated to a newer build
+ int buildDate = SystemProperties.getInt(PROPERTY_BUILD_DATE_UTC, 0);
+
+ if (auditSafeMode >= buildDate) {
+ mSafeMode = true;
+ } else {
+ SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
+ SystemProperties.set(ShutdownThread.AUDIT_SAFEMODE_PROPERTY, "");
+ }
+ }
}
} catch (IllegalArgumentException e) {
}
@@ -7573,6 +7626,9 @@
public static final int WINDOW_REPLACEMENT_TIMEOUT = 46;
+ public static final int NOTIFY_APP_TRANSITION_STARTING = 47;
+ public static final int NOTIFY_STARTING_WINDOW_DRAWN = 48;
+
/**
* Used to denote that an integer field in a message will not be used.
*/
@@ -8124,14 +8180,14 @@
for (int i = stacks.size() - 1; i >= 0; --i) {
final TaskStack stack = stacks.get(i);
if (stack.isVisibleLocked()) {
- stack.adjustForIME(imeWin);
+ stack.setAdjustedForIme(imeWin);
}
}
} else {
final ArrayList<TaskStack> stacks = displayContent.getStacks();
for (int i = stacks.size() - 1; i >= 0; --i) {
final TaskStack stack = stacks.get(i);
- stack.adjustForIME(null);
+ stack.resetAdjustedForIme();
}
}
}
@@ -8156,7 +8212,7 @@
break;
case SHOW_NON_RESIZEABLE_DOCK_TOAST: {
final Toast toast = Toast.makeText(
- mContext, (String) msg.obj, Toast.LENGTH_LONG);
+ mContext, (String) msg.obj, Toast.LENGTH_SHORT);
final int gravity = toast.getGravity();
final int xOffset = toast.getXOffset() + msg.arg1;
final int yOffset = toast.getYOffset() + msg.arg2;
@@ -8170,6 +8226,13 @@
token.clearTimedoutReplacesLocked();
}
}
+ case NOTIFY_APP_TRANSITION_STARTING: {
+ mAmInternal.notifyAppTransitionStarting(msg.arg1);
+ }
+ break;
+ case NOTIFY_STARTING_WINDOW_DRAWN: {
+ mAmInternal.notifyStartingWindowDrawn();
+ }
break;
}
if (DEBUG_WINDOW_TRACE) {
@@ -8719,10 +8782,10 @@
i -= lastBelow;
if (i != numRemoved) {
displayContent.layoutNeeded = true;
- Slog.w(TAG_WM, "On display=" + displayContent.getDisplayId() + " Rebuild removed " +
- numRemoved + " windows but added " + i,
- new RuntimeException("here").fillInStackTrace());
- for (i=0; i<numRemoved; i++) {
+ Slog.w(TAG_WM, "On display=" + displayContent.getDisplayId() + " Rebuild removed "
+ + numRemoved + " windows but added " + i + " rebuildAppWindowListLocked() "
+ + " callers=" + Debug.getCallers(10));
+ for (i = 0; i < numRemoved; i++) {
WindowState ws = mRebuildTmp[i];
if (ws.mRebuilding) {
StringWriter sw = new StringWriter();
@@ -8984,11 +9047,10 @@
EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
winAnimator.mSession.mPid, operation);
- long callingIdentity = Binder.clearCallingIdentity();
+ final long callingIdentity = Binder.clearCallingIdentity();
try {
- // There was some problem... first, do a sanity check of the
- // window list to make sure we haven't left any dangling surfaces
- // around.
+ // There was some problem... first, do a sanity check of the window list to make sure
+ // we haven't left any dangling surfaces around.
Slog.i(TAG_WM, "Out of memory for surface! Looking for leaks...");
final int numDisplays = mDisplayContents.size();
@@ -8997,28 +9059,27 @@
final int numWindows = windows.size();
for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
final WindowState ws = windows.get(winNdx);
- WindowStateAnimator wsa = ws.mWinAnimator;
- if (wsa.mSurfaceController != null) {
- if (!mSessions.contains(wsa.mSession)) {
- Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): "
- + ws + " surface=" + wsa.mSurfaceController
- + " token=" + ws.mToken
- + " pid=" + ws.mSession.mPid
- + " uid=" + ws.mSession.mUid);
- wsa.destroySurface();
- ws.setHasSurface(false);
- mForceRemoves.add(ws);
- leakedSurface = true;
- } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
- Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
- + ws + " surface=" + wsa.mSurfaceController
- + " token=" + ws.mAppToken
- + " saved=" + ws.mAppToken.hasSavedSurface());
- if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", false);
- wsa.destroySurface();
- ws.setHasSurface(false);
- leakedSurface = true;
- }
+ final WindowStateAnimator wsa = ws.mWinAnimator;
+ if (wsa.mSurfaceController == null) {
+ continue;
+ }
+ if (!mSessions.contains(wsa.mSession)) {
+ Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): "
+ + ws + " surface=" + wsa.mSurfaceController
+ + " token=" + ws.mToken
+ + " pid=" + ws.mSession.mPid
+ + " uid=" + ws.mSession.mUid);
+ wsa.destroySurface();
+ mForceRemoves.add(ws);
+ leakedSurface = true;
+ } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
+ Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
+ + ws + " surface=" + wsa.mSurfaceController
+ + " token=" + ws.mAppToken
+ + " saved=" + ws.mAppToken.hasSavedSurface());
+ if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", false);
+ wsa.destroySurface();
+ leakedSurface = true;
}
}
}
@@ -9061,8 +9122,7 @@
if (surfaceController != null) {
if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
"RECOVER DESTROY", false);
- surfaceController.destroyInTransaction();
- winAnimator.mWin.setHasSurface(false);
+ winAnimator.destroySurface();
scheduleRemoveStartingWindowLocked(winAnimator.mWin.mAppToken);
}
@@ -10336,7 +10396,8 @@
@Override
public int getDockedStackSide() {
synchronized (mWindowMap) {
- TaskStack dockedStack = getDefaultDisplayContentLocked().getDockedStackLocked();
+ final TaskStack dockedStack = getDefaultDisplayContentLocked()
+ .getDockedStackVisibleForUserLocked();
return dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide();
}
}
@@ -10420,11 +10481,16 @@
}
}
- private void getStableInsetsLocked(Rect outInsets) {
+ void getStableInsetsLocked(Rect outInsets) {
final DisplayInfo di = getDefaultDisplayInfoLocked();
mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets);
}
+ private void getNonDecorInsetsLocked(Rect outInsets) {
+ final DisplayInfo di = getDefaultDisplayInfoLocked();
+ mPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets);
+ }
+
/**
* Intersects the specified {@code inOutBounds} with the display frame that excludes the stable
* inset areas.
@@ -10441,6 +10507,23 @@
}
}
+ /**
+ * Intersects the specified {@code inOutBounds} with the display frame that excludes
+ * areas that could never be removed in Honeycomb. See
+ * {@link WindowManagerPolicy#getNonDecorInsetsLw}.
+ *
+ * @param inOutBounds The inOutBounds to subtract the inset areas from.
+ */
+ public void subtractNonDecorInsets(Rect inOutBounds) {
+ synchronized (mWindowMap) {
+ getNonDecorInsetsLocked(mTmpRect2);
+ final DisplayInfo di = getDefaultDisplayInfoLocked();
+ mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight);
+ mTmpRect.inset(mTmpRect2);
+ inOutBounds.intersect(mTmpRect);
+ }
+ }
+
private MousePositionTracker mMousePositionTracker = new MousePositionTracker();
private static class MousePositionTracker implements PointerEventListener {
@@ -10527,6 +10610,16 @@
}
}
+ public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)
+ throws RemoteException {
+ if (!checkCallingPermission(Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS,
+ "registerShortcutKey")) {
+ throw new SecurityException(
+ "Requires REGISTER_WINDOW_MANAGER_LISTENERS permission");
+ }
+ mPolicy.registerShortcutKey(shortcutCode, shortcutKeyReceiver);
+ }
+
private final class LocalService extends WindowManagerInternal {
@Override
public void requestTraversalFromDisplayManager() {
@@ -10635,6 +10728,7 @@
@Override
public void waitForAllWindowsDrawn(Runnable callback, long timeout) {
+ boolean allWindowsDrawn = false;
synchronized (mWindowMap) {
mWaitingForDrawnCallback = callback;
final WindowList windows = getDefaultWindowListLocked();
@@ -10655,13 +10749,16 @@
}
}
mWindowPlacerLocked.requestTraversal();
+ mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
+ if (mWaitingForDrawn.isEmpty()) {
+ allWindowsDrawn = true;
+ } else {
+ mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
+ checkDrawnWindowsLocked();
+ }
}
- mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
- if (mWaitingForDrawn.isEmpty()) {
+ if (allWindowsDrawn) {
callback.run();
- } else {
- mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
- checkDrawnWindowsLocked();
}
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index bea333b..4ad021e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -184,6 +184,10 @@
private Configuration mConfiguration = Configuration.EMPTY;
private Configuration mOverrideConfig = Configuration.EMPTY;
+ // Represents the changes from our override configuration applied
+ // to the global configuration. This is the only form of configuration
+ // which is suitable for delivery to the client.
+ private Configuration mMergedConfiguration = new Configuration();
// Sticky answer to isConfigChanged(), remains true until new Configuration is assigned.
// Used only on {@link #TYPE_KEYGUARD}.
private boolean mConfigHasChanged;
@@ -358,7 +362,7 @@
boolean mLayoutNeeded;
/** Currently running an exit animation? */
- boolean mExiting;
+ boolean mAnimatingExit;
/** Currently on the mDestroySurface list? */
boolean mDestroying;
@@ -387,11 +391,11 @@
boolean mRemoved;
/**
- * Has the client requested we remove the window? In this case we know
- * that we can dispose of it when we wish without further synchronization
- * with the client
+ * It is save to remove the window and destroy the surface because the client requested removal
+ * or some other higher level component said so (e.g. activity manager).
+ * TODO: We should either have different booleans for the removal reason or use a bit-field.
*/
- boolean mClientRemoveRequested;
+ boolean mWindowRemovalAllowed;
/**
* Temp for keeping track of windows that have been removed when
@@ -434,9 +438,9 @@
// If not null, the window that will be used to replace the old one. This is being set when
// the window is added and unset when this window reports its first draw.
WindowState mReplacingWindow = null;
-
// Whether this window is being moved via the resize API
boolean mMovedByResize;
+
/**
* Wake lock for drawing.
* Even though it's slightly more expensive to do so, we will use a separate wake lock
@@ -448,6 +452,16 @@
final private Rect mTmpRect = new Rect();
+ /**
+ * See {@link #notifyMovedInStack}.
+ */
+ private boolean mJustMovedInStack;
+
+ /**
+ * Whether the window was resized by us while it was gone for layout.
+ */
+ boolean mResizedWhileGone = false;
+
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
WindowState attachedWindow, int appOp, int seq, WindowManager.LayoutParams a,
int viewVisibility, final DisplayContent displayContent) {
@@ -614,7 +628,7 @@
@Override
public void computeFrameLw(Rect pf, Rect df, Rect of, Rect cf, Rect vf, Rect dcf, Rect sf,
Rect osf) {
- if (mWillReplaceWindow && (mExiting || !mReplacingRemoveRequested)) {
+ if (mWillReplaceWindow && (mAnimatingExit || !mReplacingRemoveRequested)) {
// This window is being replaced and either already got information that it's being
// removed or we are still waiting for some information. Because of this we don't
// want to apply any more changes to it, so it remains in this state until new window
@@ -625,7 +639,7 @@
final Task task = getTask();
final boolean fullscreenTask = task == null || task.isFullscreen();
- final boolean freeformWorkspace = task != null && task.inFreeformWorkspace();
+ final boolean windowsAreFloating = task != null && task.isFloating();
if (fullscreenTask || (isChildWindow()
&& (mAttrs.privateFlags & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0)) {
@@ -651,10 +665,10 @@
mContainingFrame.top -= mContainingFrame.bottom - cf.bottom;
}
- if (freeformWorkspace) {
- // In free form mode we have only to set the rectangle if it wasn't set already. No
- // need to intersect it with the (visible) "content frame" since it is allowed to
- // be outside the visible desktop.
+ if (windowsAreFloating) {
+ // In floating modes (e.g. freeform, pinned) we have only to set the rectangle
+ // if it wasn't set already. No need to intersect it with the (visible)
+ // "content frame" since it is allowed to be outside the visible desktop.
if (mContainingFrame.isEmpty()) {
mContainingFrame.set(cf);
}
@@ -710,7 +724,7 @@
// Make sure the content and visible frames are inside of the
// final window frame.
- if (freeformWorkspace && !mFrame.isEmpty()) {
+ if (windowsAreFloating && !mFrame.isEmpty()) {
// Keep the frame out of the blocked system area, limit it in size to the content area
// and make sure that there is always a minimum visible so that the user can drag it
// into a usable area..
@@ -762,9 +776,9 @@
Math.min(mStableFrame.bottom, frame.bottom));
}
- if (!inFreeformWorkspace()) {
- // Freeform windows can be positioned outside of the display frame, but that is not a
- // reason to provide them with overscan insets.
+ if (!windowsAreFloating) {
+ // Windows from floating tasks (e.g. freeform, pinned) may be positioned outside
+ // of the display frame, but that is not a reason to provide them with overscan insets.
mOverscanInsets.set(Math.max(mOverscanFrame.left - frame.left, 0),
Math.max(mOverscanFrame.top - frame.top, 0),
Math.max(frame.right - mOverscanFrame.right, 0),
@@ -1075,7 +1089,7 @@
*/
private boolean isVisibleUnchecked() {
return mHasSurface && mPolicyVisibility && !mAttachedHidden
- && !mExiting && !mDestroying && (!mIsWallpaper || mWallpaperVisible);
+ && !mAnimatingExit && !mDestroying && (!mIsWallpaper || mWallpaperVisible);
}
/**
@@ -1100,7 +1114,7 @@
}
final AppWindowToken atoken = mAppToken;
final boolean animating = atoken != null && atoken.mAppAnimator.animation != null;
- return mHasSurface && !mDestroying && !mExiting
+ return mHasSurface && !mDestroying && !mAnimatingExit
&& (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
&& ((!mAttachedHidden && mViewVisibility == View.VISIBLE && !mRootToken.hidden)
|| mWinAnimator.mAnimation != null || animating);
@@ -1143,7 +1157,7 @@
return (mHasSurface || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
&& mPolicyVisibility && !mAttachedHidden
&& (atoken == null || !atoken.hiddenRequested)
- && !mExiting && !mDestroying;
+ && !mAnimatingExit && !mDestroying;
}
/**
@@ -1235,9 +1249,9 @@
return mViewVisibility == View.GONE
|| !mRelayoutCalled
|| (atoken == null && mRootToken.hidden)
- || (atoken != null && (atoken.hiddenRequested || atoken.hidden))
+ || (atoken != null && atoken.hiddenRequested)
|| mAttachedHidden
- || (mExiting && !isAnimatingLw())
+ || (mAnimatingExit && !isAnimatingLw())
|| mDestroying;
}
@@ -1283,7 +1297,7 @@
*/
boolean hasMoved() {
return mHasSurface && (mContentChanged || mMovedByResize)
- && !mExiting && !mWinAnimator.mLastHidden && mService.okToDisplay()
+ && !mAnimatingExit && !mWinAnimator.mLastHidden && mService.okToDisplay()
&& (mFrame.top != mLastFrame.top || mFrame.left != mLastFrame.left)
&& (mAttachedWindow == null || !mAttachedWindow.hasMoved());
}
@@ -1345,6 +1359,11 @@
mConfiguration = newConfig;
mOverrideConfig = newOverrideConfig;
mConfigHasChanged = false;
+
+ mMergedConfiguration.setTo(newConfig);
+ if (newOverrideConfig != null && newOverrideConfig != Configuration.EMPTY) {
+ mMergedConfiguration.updateFrom(newOverrideConfig);
+ }
}
void setHasSurface(boolean hasSurface) {
@@ -1374,6 +1393,39 @@
}
}
+ /**
+ * Notifies this window that the corresponding task has just moved in the stack.
+ * <p>
+ * This is used to fix the following: If we moved in the stack, and if the last clip rect was
+ * empty, meaning that our task was completely offscreen, we need to keep it invisible because
+ * the actual app transition that updates the visibility is delayed by a few transactions.
+ * Instead of messing around with the ordering and timing how transitions and transactions are
+ * executed, we introduce this little hack which prevents this window of getting visible again
+ * with the wrong bounds until the app transitions has started.
+ * <p>
+ * This method notifies the window about that we just moved in the stack so we can apply this
+ * logic in {@link WindowStateAnimator#updateSurfaceWindowCrop}
+ */
+ void notifyMovedInStack() {
+ mJustMovedInStack = true;
+ }
+
+ /**
+ * See {@link #notifyMovedInStack}.
+ *
+ * @return Whether we just got moved in the corresponding stack.
+ */
+ boolean hasJustMovedInStack() {
+ return mJustMovedInStack;
+ }
+
+ /**
+ * Resets that we just moved in the corresponding stack. See {@link #notifyMovedInStack}.
+ */
+ void resetJustMovedInStack() {
+ mJustMovedInStack = false;
+ }
+
private final class DeadWindowEventReceiver extends InputEventReceiver {
DeadWindowEventReceiver(InputChannel inputChannel) {
super(inputChannel, mService.mH.getLooper());
@@ -1438,11 +1490,11 @@
return;
}
- if (!mExiting && mAppDied) {
+ if (!mAnimatingExit && mAppDied) {
// If app died visible, apply a dim over the window to indicate that it's inactive
mDisplayContent.mDimLayerController.applyDimAbove(getDimLayerUser(), mWinAnimator);
} else if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0
- && mDisplayContent != null && !mExiting && isDisplayedLw()) {
+ && mDisplayContent != null && !mAnimatingExit && isDisplayedLw()) {
mDisplayContent.mDimLayerController.applyDimBehind(getDimLayerUser(), mWinAnimator);
}
}
@@ -1467,7 +1519,7 @@
win.mAnimateReplacingWindow = false;
win.mReplacingRemoveRequested = false;
win.mReplacingWindow = null;
- if (win.mExiting) {
+ if (win.mAnimatingExit) {
mService.removeWindowInnerLocked(win);
}
}
@@ -1573,9 +1625,10 @@
mTurnOnScreen = true;
}
if (isConfigChanged()) {
+ final Configuration newConfig = updateConfiguration();
if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + this + " visible with new config: "
- + mService.mCurConfiguration);
- outConfig.setTo(mService.mCurConfiguration);
+ + newConfig);
+ outConfig.setTo(newConfig);
}
}
@@ -1810,7 +1863,7 @@
}
boolean isClosing() {
- return mExiting || (mService.mClosingApps.contains(mAppToken));
+ return mAnimatingExit || (mService.mClosingApps.contains(mAppToken));
}
boolean isAnimatingWithSavedSurface() {
@@ -1836,6 +1889,12 @@
return false;
}
+ if (mResizedWhileGone) {
+ // Somebody resized our window while we were gone for layout, which means that the
+ // client got an old size, so we have an outdated surface here.
+ return false;
+ }
+
if (DEBUG_DISABLE_SAVING_SURFACES) {
return false;
}
@@ -1853,6 +1912,12 @@
mWinAnimator.hide("saved surface");
mWinAnimator.mDrawState = WindowStateAnimator.NO_SURFACE;
setHasSurface(false);
+ // The client should have disconnected at this point, but if it doesn't,
+ // we need to make sure it's disconnected. Otherwise when we reuse the surface
+ // the client can't reconnect to the buffer queue, and rendering will fail.
+ if (mWinAnimator.mSurfaceController != null) {
+ mWinAnimator.mSurfaceController.disconnectInTransaction();
+ }
} else {
mWinAnimator.destroySurfaceLocked();
}
@@ -1868,6 +1933,9 @@
}
public void restoreSavedSurface() {
+ if (!mSurfaceSaved) {
+ return;
+ }
mSurfaceSaved = false;
setHasSurface(true);
mWinAnimator.mDrawState = WindowStateAnimator.READY_TO_SHOW;
@@ -2003,21 +2071,30 @@
}
}
+ /**
+ * Update our current configurations, based on task configuration.
+ *
+ * @return A configuration suitable for sending to the client.
+ */
+ private Configuration updateConfiguration() {
+ final Task task = getTask();
+ final Configuration overrideConfig =
+ (task != null) ? task.mOverrideConfig : Configuration.EMPTY;
+ final boolean configChanged = isConfigChanged();
+ if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) && configChanged) {
+ Slog.i(TAG, "Sending new config to window " + this + ": " +
+ " / config=" + mService.mCurConfiguration + " overrideConfig=" + overrideConfig);
+ }
+ setConfiguration(mService.mCurConfiguration, overrideConfig);
+ return mMergedConfiguration;
+ }
+
void reportResized() {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wm.reportResized_" + getWindowTag());
try {
if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this
+ ": " + mCompatFrame);
- final boolean configChanged = isConfigChanged();
- final Task task = getTask();
- final Configuration overrideConfig =
- (task != null) ? task.mOverrideConfig : Configuration.EMPTY;
- if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) && configChanged) {
- Slog.i(TAG, "Sending new config to window " + this + ": "
- + " / config="
- + mService.mCurConfiguration + " overrideConfig=" + overrideConfig);
- }
- setConfiguration(mService.mCurConfiguration, overrideConfig);
+ final Configuration newConfig = isConfigChanged() ? updateConfiguration() : null;
if (DEBUG_ORIENTATION && mWinAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING)
Slog.i(TAG, "Resizing " + this + " WITH DRAW PENDING");
@@ -2028,7 +2105,6 @@
final Rect stableInsets = mLastStableInsets;
final Rect outsets = mLastOutsets;
final boolean reportDraw = mWinAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING;
- final Configuration newConfig = configChanged ? mConfiguration : null;
if (mAttrs.type != WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
&& mClient instanceof IWindow.Stub) {
// To prevent deadlock simulate one-way call if win.mClient is a local object.
@@ -2103,7 +2179,7 @@
Configuration newConfig) throws RemoteException {
mClient.resized(frame, overscanInsets, contentInsets, visibleInsets, stableInsets, outsets,
reportDraw, newConfig, getBackdropFrame(frame),
- isDragResizeChanged() /* forceRelayout */);
+ isDragResizeChanged() /* forceRelayout */, mPolicy.isNavBarForcedShownLw(this));
mDragResizingChangeReported = true;
}
@@ -2162,6 +2238,11 @@
if (task == null) {
return false;
}
+ if (mAttrs.width != MATCH_PARENT || mAttrs.height != MATCH_PARENT) {
+
+ // Floating windows never enter drag resize mode.
+ return false;
+ }
if (task.isDragResizing()) {
return true;
}
@@ -2290,7 +2371,8 @@
pw.print(prefix); pw.print("mHasSurface="); pw.print(mHasSurface);
pw.print(" mShownPosition="); mShownPosition.printShortString(pw);
pw.print(" isReadyForDisplay()="); pw.print(isReadyForDisplay());
- pw.print(" hasSavedSurface()="); pw.println(hasSavedSurface());
+ pw.print(" hasSavedSurface()="); pw.print(hasSavedSurface());
+ pw.print(" mWindowRemovalAllowed="); pw.println(mWindowRemovalAllowed);
if (dumpAll) {
pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
pw.print(" last="); mLastFrame.printShortString(pw);
@@ -2333,8 +2415,8 @@
}
pw.print(prefix); pw.print(mWinAnimator); pw.println(":");
mWinAnimator.dump(pw, prefix + " ", dumpAll);
- if (mExiting || mRemoveOnExit || mDestroying || mRemoved) {
- pw.print(prefix); pw.print("mExiting="); pw.print(mExiting);
+ if (mAnimatingExit || mRemoveOnExit || mDestroying || mRemoved) {
+ pw.print(prefix); pw.print("mAnimatingExit="); pw.print(mAnimatingExit);
pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
pw.print(" mDestroying="); pw.print(mDestroying);
pw.print(" mRemoved="); pw.println(mRemoved);
@@ -2395,12 +2477,12 @@
@Override
public String toString() {
final CharSequence title = getWindowTag();
- if (mStringNameCache == null || mLastTitle != title || mWasExiting != mExiting) {
+ if (mStringNameCache == null || mLastTitle != title || mWasExiting != mAnimatingExit) {
mLastTitle = title;
- mWasExiting = mExiting;
+ mWasExiting = mAnimatingExit;
mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this))
+ " u" + UserHandle.getUserId(mSession.mUid)
- + " " + mLastTitle + (mExiting ? " EXITING}" : "}");
+ + " " + mLastTitle + (mAnimatingExit ? " EXITING}" : "}");
}
return mStringNameCache;
}
@@ -2421,7 +2503,8 @@
final int ph = mContainingFrame.height();
final Task task = getTask();
final boolean nonFullscreenTask = task != null && !task.isFullscreen();
-
+ final boolean fitToDisplay = task != null &&
+ !task.isFloating();
float x, y;
int w,h;
@@ -2478,7 +2561,17 @@
(int) (y + mAttrs.verticalMargin * ph), mFrame);
// Now make sure the window fits in the overall display frame.
- Gravity.applyDisplay(mAttrs.gravity, mDisplayFrame, mFrame);
+ if (fitToDisplay) {
+ Gravity.applyDisplay(mAttrs.gravity, mDisplayFrame, mFrame);
+ }
+
+ // We need to make sure we update the CompatFrame as it is used for
+ // cropping decisions, etc, on systems where we lack a decor layer.
+ mCompatFrame.set(mFrame);
+ if (mEnforceSizeCompat) {
+ // See comparable block in computeFrameLw.
+ mCompatFrame.scale(mInvGlobalScale);
+ }
}
boolean isChildWindow() {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 0201296..c1ff96e 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -20,6 +20,7 @@
import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
@@ -29,7 +30,6 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_CROP;
-import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
@@ -375,7 +375,7 @@
// Done animating, clean up.
if (DEBUG_ANIM) Slog.v(
- TAG, "Animation done in " + this + ": exiting=" + mWin.mExiting
+ TAG, "Animation done in " + this + ": exiting=" + mWin.mAnimatingExit
+ ", reportedVisible="
+ (mWin.mAppToken != null ? mWin.mAppToken.reportedVisible : false));
@@ -430,7 +430,7 @@
void finishExit() {
if (DEBUG_ANIM) Slog.v(
TAG, "finishExit in " + this
- + ": exiting=" + mWin.mExiting
+ + ": exiting=" + mWin.mAnimatingExit
+ " remove=" + mWin.mRemoveOnExit
+ " windowAnimating=" + isWindowAnimating());
@@ -460,7 +460,7 @@
}
}
- if (!mWin.mExiting) {
+ if (!mWin.mAnimatingExit) {
return;
}
@@ -468,34 +468,33 @@
return;
}
- if (WindowManagerService.localLOGV) Slog.v(
- TAG, "Exit animation finished in " + this
- + ": remove=" + mWin.mRemoveOnExit);
+ if (WindowManagerService.localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG,
+ "Exit animation finished in " + this + ": remove=" + mWin.mRemoveOnExit);
mWin.mDestroying = true;
+ final boolean hasSurface = hasSurface();
+ if (hasSurface) {
+ hide("finishExit");
+ }
+
// If we have an app token, we ask it to destroy the surface for us,
// so that it can take care to ensure the activity has actually stopped
// and the surface is not still in use. Otherwise we add the service to
// mDestroySurface and allow it to be processed in our next transaction.
if (mWin.mAppToken != null) {
- if (hasSurface()) {
- hide("finishExit");
- }
mWin.mAppToken.destroySurfaces();
} else {
- if (hasSurface()) {
+ if (hasSurface) {
mService.mDestroySurface.add(mWin);
- hide("finishExit");
}
- mWin.mExiting = false;
if (mWin.mRemoveOnExit) {
mService.mPendingRemove.add(mWin);
mWin.mRemoveOnExit = false;
}
}
-
+ mWin.mAnimatingExit = false;
mWallpaperControllerLocked.hideWallpapers(mWin);
}
@@ -557,14 +556,21 @@
if (atoken == null || atoken.allDrawn || mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
result = performShowLocked();
}
- if (mDestroyPreservedSurfaceUponRedraw) {
- mService.mDestroyPreservedSurface.add(mWin);
- }
return result;
}
void preserveSurfaceLocked() {
if (mDestroyPreservedSurfaceUponRedraw) {
+ // This could happen when switching the surface mode very fast. For example,
+ // we preserved a surface when dragResizing changed to true. Then before the
+ // preserved surface is removed, dragResizing changed to false again.
+ // In this case, we need to leave the preserved surface alone, and destroy
+ // the actual surface, so that the createSurface call could create a surface
+ // of the proper size. The preserved surface will still be removed when client
+ // finishes drawing to the new surface.
+ mSurfaceDestroyDeferred = false;
+ destroySurfaceLocked();
+ mSurfaceDestroyDeferred = true;
return;
}
if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, "SET FREEZE LAYER", false);
@@ -593,119 +599,118 @@
return mSurfaceController;
}
- if (mSurfaceController == null) {
- if (DEBUG_ANIM || DEBUG_ORIENTATION) Slog.i(TAG,
- "createSurface " + this + ": mDrawState=DRAW_PENDING");
- mDrawState = DRAW_PENDING;
- if (w.mAppToken != null) {
- if (w.mAppToken.mAppAnimator.animation == null) {
- w.mAppToken.allDrawn = false;
- w.mAppToken.deferClearAllDrawn = false;
- } else {
- // Currently animating, persist current state of allDrawn until animation
- // is complete.
- w.mAppToken.deferClearAllDrawn = true;
- }
- }
-
- mService.makeWindowFreezingScreenIfNeededLocked(w);
-
- int flags = SurfaceControl.HIDDEN;
- final WindowManager.LayoutParams attrs = w.mAttrs;
-
- if (mService.isSecureLocked(w)) {
- flags |= SurfaceControl.SECURE;
- }
-
- mTmpSize.set(w.mFrame.left + w.mXOffset, w.mFrame.top + w.mYOffset, 0, 0);
- calculateSurfaceBounds(w, attrs);
- final int width = mTmpSize.width();
- final int height = mTmpSize.height();
-
- if (DEBUG_VISIBILITY) {
- Slog.v(TAG, "Creating surface in session "
- + mSession.mSurfaceSession + " window " + this
- + " w=" + width + " h=" + height
- + " x=" + mTmpSize.left + " y=" + mTmpSize.top
- + " format=" + attrs.format + " flags=" + flags);
- }
-
- // We may abort, so initialize to defaults.
- mLastSystemDecorRect.set(0, 0, 0, 0);
- mHasClipRect = false;
- mClipRect.set(0, 0, 0, 0);
- mLastClipRect.set(0, 0, 0, 0);
-
- // Set up surface control with initial size.
- try {
-
- final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0;
- final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
- if (!PixelFormat.formatHasAlpha(attrs.format)
- // Don't make surface with surfaceInsets opaque as they display a
- // translucent shadow.
- && attrs.surfaceInsets.left == 0
- && attrs.surfaceInsets.top == 0
- && attrs.surfaceInsets.right == 0
- && attrs.surfaceInsets.bottom == 0
- // Don't make surface opaque when resizing to reduce the amount of
- // artifacts shown in areas the app isn't drawing content to.
- && !w.isDragResizing()) {
- flags |= SurfaceControl.OPAQUE;
- }
-
- mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession,
- attrs.getTitle().toString(),
- width, height, format, flags, this);
-
- w.setHasSurface(true);
-
- if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
- Slog.i(TAG, " CREATE SURFACE "
- + mSurfaceController + " IN SESSION "
- + mSession.mSurfaceSession
- + ": pid=" + mSession.mPid + " format="
- + attrs.format + " flags=0x"
- + Integer.toHexString(flags)
- + " / " + this);
- }
- } catch (OutOfResourcesException e) {
- w.setHasSurface(false);
- Slog.w(TAG, "OutOfResourcesException creating surface");
- mService.reclaimSomeSurfaceMemoryLocked(this, "create", true);
- mDrawState = NO_SURFACE;
- return null;
- } catch (Exception e) {
- w.setHasSurface(false);
- Slog.e(TAG, "Exception creating surface", e);
- mDrawState = NO_SURFACE;
- return null;
- }
-
- if (WindowManagerService.localLOGV) {
- Slog.v(TAG, "Got surface: " + mSurfaceController
- + ", set left=" + w.mFrame.left + " top=" + w.mFrame.top
- + ", animLayer=" + mAnimLayer);
- }
-
- if (SHOW_LIGHT_TRANSACTIONS) {
- Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked");
- WindowManagerService.logSurface(w, "CREATE pos=("
- + w.mFrame.left + "," + w.mFrame.top + ") ("
- + width + "x" + height + "), layer=" + mAnimLayer + " HIDE", false);
- }
-
- // Start a new transaction and apply position & offset.
- final int layerStack = w.getDisplayContent().getDisplay().getLayerStack();
- if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
- "POS " + mTmpSize.left + ", " + mTmpSize.top, false);
- mSurfaceController.setPositionAndLayer(mTmpSize.left, mTmpSize.top, layerStack,
- mAnimLayer);
- mLastHidden = true;
-
- if (WindowManagerService.localLOGV) Slog.v(
- TAG, "Created surface " + this);
+ if (mSurfaceController != null) {
+ return mSurfaceController;
}
+
+ w.setHasSurface(false);
+
+ if (DEBUG_ANIM || DEBUG_ORIENTATION) Slog.i(TAG,
+ "createSurface " + this + ": mDrawState=DRAW_PENDING");
+
+ mDrawState = DRAW_PENDING;
+ if (w.mAppToken != null) {
+ if (w.mAppToken.mAppAnimator.animation == null) {
+ w.mAppToken.allDrawn = false;
+ w.mAppToken.deferClearAllDrawn = false;
+ } else {
+ // Currently animating, persist current state of allDrawn until animation
+ // is complete.
+ w.mAppToken.deferClearAllDrawn = true;
+ }
+ }
+
+ mService.makeWindowFreezingScreenIfNeededLocked(w);
+
+ int flags = SurfaceControl.HIDDEN;
+ final WindowManager.LayoutParams attrs = w.mAttrs;
+
+ if (mService.isSecureLocked(w)) {
+ flags |= SurfaceControl.SECURE;
+ }
+
+ mTmpSize.set(w.mFrame.left + w.mXOffset, w.mFrame.top + w.mYOffset, 0, 0);
+ calculateSurfaceBounds(w, attrs);
+ final int width = mTmpSize.width();
+ final int height = mTmpSize.height();
+
+ if (DEBUG_VISIBILITY) {
+ Slog.v(TAG, "Creating surface in session "
+ + mSession.mSurfaceSession + " window " + this
+ + " w=" + width + " h=" + height
+ + " x=" + mTmpSize.left + " y=" + mTmpSize.top
+ + " format=" + attrs.format + " flags=" + flags);
+ }
+
+ // We may abort, so initialize to defaults.
+ mLastSystemDecorRect.set(0, 0, 0, 0);
+ mHasClipRect = false;
+ mClipRect.set(0, 0, 0, 0);
+ mLastClipRect.set(0, 0, 0, 0);
+
+ // Set up surface control with initial size.
+ try {
+
+ final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0;
+ final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
+ if (!PixelFormat.formatHasAlpha(attrs.format)
+ // Don't make surface with surfaceInsets opaque as they display a
+ // translucent shadow.
+ && attrs.surfaceInsets.left == 0
+ && attrs.surfaceInsets.top == 0
+ && attrs.surfaceInsets.right == 0
+ && attrs.surfaceInsets.bottom == 0
+ // Don't make surface opaque when resizing to reduce the amount of
+ // artifacts shown in areas the app isn't drawing content to.
+ && !w.isDragResizing()) {
+ flags |= SurfaceControl.OPAQUE;
+ }
+
+ mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession,
+ attrs.getTitle().toString(),
+ width, height, format, flags, this);
+
+ w.setHasSurface(true);
+
+ if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
+ Slog.i(TAG, " CREATE SURFACE "
+ + mSurfaceController + " IN SESSION "
+ + mSession.mSurfaceSession
+ + ": pid=" + mSession.mPid + " format="
+ + attrs.format + " flags=0x"
+ + Integer.toHexString(flags)
+ + " / " + this);
+ }
+ } catch (OutOfResourcesException e) {
+ Slog.w(TAG, "OutOfResourcesException creating surface");
+ mService.reclaimSomeSurfaceMemoryLocked(this, "create", true);
+ mDrawState = NO_SURFACE;
+ return null;
+ } catch (Exception e) {
+ Slog.e(TAG, "Exception creating surface", e);
+ mDrawState = NO_SURFACE;
+ return null;
+ }
+
+ if (WindowManagerService.localLOGV) Slog.v(TAG, "Got surface: " + mSurfaceController
+ + ", set left=" + w.mFrame.left + " top=" + w.mFrame.top
+ + ", animLayer=" + mAnimLayer);
+
+ if (SHOW_LIGHT_TRANSACTIONS) {
+ Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked");
+ WindowManagerService.logSurface(w, "CREATE pos=("
+ + w.mFrame.left + "," + w.mFrame.top + ") ("
+ + width + "x" + height + "), layer=" + mAnimLayer + " HIDE", false);
+ }
+
+ // Start a new transaction and apply position & offset.
+ final int layerStack = w.getDisplayContent().getDisplay().getLayerStack();
+ if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
+ "POS " + mTmpSize.left + ", " + mTmpSize.top, false);
+ mSurfaceController.setPositionAndLayer(mTmpSize.left, mTmpSize.top, layerStack, mAnimLayer);
+ mLastHidden = true;
+
+ if (WindowManagerService.localLOGV) Slog.v(TAG, "Created surface " + this);
return mSurfaceController;
}
@@ -776,59 +781,59 @@
mWin.mSurfaceSaved = false;
- if (mSurfaceController != null) {
- int i = mWin.mChildWindows.size();
- // When destroying a surface we want to make sure child windows
- // are hidden. If we are preserving the surface until redraw though
- // we intend to swap it out with another surface for resizing. In this case
- // the window always remains visible to the user and the child windows
- // should likewise remain visable.
- while (!mDestroyPreservedSurfaceUponRedraw && i > 0) {
- i--;
- WindowState c = mWin.mChildWindows.get(i);
- c.mAttachedHidden = true;
- }
-
- try {
- if (DEBUG_VISIBILITY) logWithStack(TAG, "Window " + this + " destroying surface "
- + mSurfaceController + ", session " + mSession);
- if (mSurfaceDestroyDeferred) {
- if (mSurfaceController != null && mPendingDestroySurface != mSurfaceController) {
- if (mPendingDestroySurface != null) {
- if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
- WindowManagerService.logSurface(mWin, "DESTROY PENDING", true);
- }
- mPendingDestroySurface.destroyInTransaction();
- }
- mPendingDestroySurface = mSurfaceController;
- }
- } else {
- if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
- WindowManagerService.logSurface(mWin, "DESTROY", true);
- }
- destroySurface();
- }
- // Don't hide wallpaper if we're deferring the surface destroy
- // because of a surface change.
- if (!(mSurfaceDestroyDeferred && mDestroyPreservedSurfaceUponRedraw)) {
- mWallpaperControllerLocked.hideWallpapers(mWin);
- }
- } catch (RuntimeException e) {
- Slog.w(TAG, "Exception thrown when destroying Window " + this
- + " surface " + mSurfaceController + " session " + mSession
- + ": " + e.toString());
- }
-
- // Whether the surface was preserved (and copied to mPendingDestroySurface) or not, it
- // needs to be cleared to match the WindowState.mHasSurface state. It is also necessary
- // so it can be recreated successfully in mPendingDestroySurface case.
- mWin.setHasSurface(false);
- if (mSurfaceController != null) {
- mSurfaceController.setShown(false);
- }
- mSurfaceController = null;
- mDrawState = NO_SURFACE;
+ if (mSurfaceController == null) {
+ return;
}
+
+ int i = mWin.mChildWindows.size();
+ // When destroying a surface we want to make sure child windows are hidden. If we are
+ // preserving the surface until redraw though we intend to swap it out with another surface
+ // for resizing. In this case the window always remains visible to the user and the child
+ // windows should likewise remain visible.
+ while (!mDestroyPreservedSurfaceUponRedraw && i > 0) {
+ i--;
+ WindowState c = mWin.mChildWindows.get(i);
+ c.mAttachedHidden = true;
+ }
+
+ try {
+ if (DEBUG_VISIBILITY) logWithStack(TAG, "Window " + this + " destroying surface "
+ + mSurfaceController + ", session " + mSession);
+ if (mSurfaceDestroyDeferred) {
+ if (mSurfaceController != null && mPendingDestroySurface != mSurfaceController) {
+ if (mPendingDestroySurface != null) {
+ if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
+ WindowManagerService.logSurface(mWin, "DESTROY PENDING", true);
+ }
+ mPendingDestroySurface.destroyInTransaction();
+ }
+ mPendingDestroySurface = mSurfaceController;
+ }
+ } else {
+ if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
+ WindowManagerService.logSurface(mWin, "DESTROY", true);
+ }
+ destroySurface();
+ }
+ // Don't hide wallpaper if we're deferring the surface destroy
+ // because of a surface change.
+ if (!mDestroyPreservedSurfaceUponRedraw) {
+ mWallpaperControllerLocked.hideWallpapers(mWin);
+ }
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Exception thrown when destroying Window " + this
+ + " surface " + mSurfaceController + " session " + mSession + ": " + e.toString());
+ }
+
+ // Whether the surface was preserved (and copied to mPendingDestroySurface) or not, it
+ // needs to be cleared to match the WindowState.mHasSurface state. It is also necessary
+ // so it can be recreated successfully in mPendingDestroySurface case.
+ mWin.setHasSurface(false);
+ if (mSurfaceController != null) {
+ mSurfaceController.setShown(false);
+ }
+ mSurfaceController = null;
+ mDrawState = NO_SURFACE;
}
void destroyDeferredSurfaceLocked() {
@@ -1110,11 +1115,11 @@
}
}
- void updateSurfaceWindowCrop(final boolean recoveringMemory) {
+ Rect calculateSurfaceWindowCrop() {
final WindowState w = mWin;
final DisplayContent displayContent = w.getDisplayContent();
if (displayContent == null) {
- return;
+ return null;
}
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Updating crop for window: " + w + ", " + "mLastCrop=" +
@@ -1182,10 +1187,19 @@
clipRect.offset(attrs.surfaceInsets.left, attrs.surfaceInsets.top);
adjustCropToStackBounds(w, clipRect, isFreeformResizing);
- if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Clip rect after stack adjustment=" + mClipRect);
+ if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Clip rect after stack adjustment=" + clipRect);
w.transformFromScreenToSurfaceSpace(clipRect);
+ // See {@link WindowState#notifyMovedInStack} for why this is necessary.
+ if (w.hasJustMovedInStack() && mLastClipRect.isEmpty() && !clipRect.isEmpty()) {
+ clipRect.setEmpty();
+ }
+
+ return clipRect;
+ }
+
+ void updateSurfaceWindowCrop(Rect clipRect, boolean recoveringMemory) {
if (!clipRect.equals(mLastClipRect)) {
mLastClipRect.set(clipRect);
mSurfaceController.setCropInTransaction(clipRect, recoveringMemory);
@@ -1213,6 +1227,11 @@
return;
}
+ final WindowState winShowWhenLocked = (WindowState) mPolicy.getWinShowWhenLockedLw();
+ if (w == winShowWhenLocked) {
+ return;
+ }
+
final TaskStack stack = task.mStack;
stack.getDimBounds(mTmpStackBounds);
// When we resize we use the big surface approach, which means we can't trust the
@@ -1222,6 +1241,7 @@
w.mFrame.left + mWin.mXOffset - w.getAttrs().surfaceInsets.left;
final int frameY = isFreeformResizing ? (int) mSurfaceController.getY() :
w.mFrame.top + mWin.mYOffset - w.getAttrs().surfaceInsets.top;
+
// We need to do some acrobatics with surface position, because their clip region is
// relative to the inside of the surface, but the stack bounds aren't.
clipRect.left = Math.max(0,
@@ -1236,14 +1256,44 @@
void setSurfaceBoundariesLocked(final boolean recoveringMemory) {
final WindowState w = mWin;
+ final Task task = w.getTask();
mTmpSize.set(w.mShownPosition.x, w.mShownPosition.y, 0, 0);
calculateSurfaceBounds(w, w.getAttrs());
- mSurfaceController.setPositionInTransaction(mTmpSize.left, mTmpSize.top, recoveringMemory);
+ float extraHScale = (float) 1.0;
+ float extraVScale = (float) 1.0;
- mSurfaceController.setMatrixInTransaction(mDsDx * w.mHScale, mDtDx * w.mVScale,
- mDsDy * w.mHScale, mDtDy * w.mVScale, recoveringMemory);
+ final Rect crop = calculateSurfaceWindowCrop();
+ if (task != null && task.mStack.getForceScaleToCrop()) {
+ extraHScale = crop.width() / (float)mTmpSize.width();
+ extraVScale = crop.height() / (float)mTmpSize.height();
+
+ // In the case of ForceScaleToCrop we scale entire tasks together,
+ // and so we need to scale our offsets relative to the task bounds
+ // or parent and child windows would fall out of alignment.
+ int posX = (int) (mTmpSize.left - w.mAttrs.x * (1 - extraHScale));
+ int posY = (int) (mTmpSize.top - w.mAttrs.y * (1 - extraVScale));
+ posX += w.getAttrs().surfaceInsets.left * (1 - extraHScale);
+ posY += w.getAttrs().surfaceInsets.top * (1 - extraVScale);
+ mSurfaceController.setPositionInTransaction(posX, posY, recoveringMemory);
+
+ // Since we are scaled to fit in our previously desired crop, we can now
+ // expose the whole window in buffer space, and not risk extending
+ // past where the system would have cropped us
+ crop.set(0, 0, mTmpSize.width(), mTmpSize.height());
+ updateSurfaceWindowCrop(crop, recoveringMemory);
+ } else {
+ mSurfaceController.setPositionInTransaction(mTmpSize.left, mTmpSize.top,
+ recoveringMemory);
+ updateSurfaceWindowCrop(crop, recoveringMemory);
+ }
+
+
+ mSurfaceController.setMatrixInTransaction(mDsDx * w.mHScale * extraHScale,
+ mDtDx * w.mVScale * extraVScale,
+ mDsDy * w.mHScale * extraHScale,
+ mDtDy * w.mVScale * extraVScale, recoveringMemory);
mSurfaceResized = mSurfaceController.setSizeInTransaction(
mTmpSize.width(), mTmpSize.height(),
recoveringMemory);
@@ -1255,7 +1305,6 @@
w.applyDimLayerIfNeeded();
}
- updateSurfaceWindowCrop(recoveringMemory);
}
void prepareSurfaceLocked(final boolean recoveringMemory) {
@@ -1328,6 +1377,9 @@
if (prepared && mLastHidden && mDrawState == HAS_DRAWN) {
if (showSurfaceRobustlyLocked()) {
+ if (mDestroyPreservedSurfaceUponRedraw) {
+ mService.mDestroyPreservedSurface.add(mWin);
+ }
mAnimator.requestRemovalOfReplacedWindows(w);
mLastHidden = false;
if (mIsWallpaper) {
@@ -1391,7 +1443,7 @@
SurfaceControl.openTransaction();
mSurfaceController.setPositionInTransaction(mWin.mFrame.left + left,
mWin.mFrame.top + top, false);
- updateSurfaceWindowCrop(false);
+ updateSurfaceWindowCrop(calculateSurfaceWindowCrop(), false);
} catch (RuntimeException e) {
Slog.w(TAG, "Error positioning surface of " + mWin
+ " pos=(" + left + "," + top + ")", e);
@@ -1509,23 +1561,7 @@
}
if (mWin.mAttrs.type != TYPE_APPLICATION_STARTING && mWin.mAppToken != null) {
- mWin.mAppToken.firstWindowDrawn = true;
-
- // We now have a good window to show, remove dead placeholders
- mWin.mAppToken.removeAllDeadWindows();
-
- if (mWin.mAppToken.startingData != null) {
- if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG, "Finish starting "
- + mWin.mToken + ": first real window is shown, no animation");
- // If this initial window is animating, stop it -- we
- // will do an animation to reveal it from behind the
- // starting window, so there is no need for it to also
- // be doing its own stuff.
- clearAnimation();
- mService.mFinishedStarting.add(mWin.mAppToken);
- mService.mH.sendEmptyMessage(H.FINISHED_STARTING);
- }
- mWin.mAppToken.updateReportedVisibilityLocked();
+ mWin.mAppToken.onFirstWindowDrawn(mWin, this);
}
return true;
@@ -1736,8 +1772,18 @@
}
void destroySurface() {
- mSurfaceController.destroyInTransaction();
- mSurfaceController = null;
+ try {
+ if (mSurfaceController != null) {
+ mSurfaceController.destroyInTransaction();
+ }
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Exception thrown when destroying surface " + this
+ + " surface " + mSurfaceController + " session " + mSession + ": " + e);
+ } finally {
+ mWin.setHasSurface(false);
+ mSurfaceController = null;
+ mDrawState = NO_SURFACE;
+ }
}
void setMoveAnimation(int left, int top) {
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 3219bfe..fb07512 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
@@ -62,6 +63,8 @@
// the window. We achieve this by explicitly hiding the surface and not letting it be shown.
private boolean mHiddenForCrop = false;
+ // Initially a surface is hidden after just being created.
+ private boolean mHiddenForOtherReasons = true;
private final String title;
public WindowSurfaceController(SurfaceSession s,
@@ -94,6 +97,11 @@
void hideInTransaction(String reason) {
if (SHOW_TRANSACTIONS) logSurface("HIDE ( " + reason + " )", null);
+ mHiddenForOtherReasons = true;
+ updateVisibility();
+ }
+
+ private void hideSurface() {
if (mSurfaceControl != null) {
mSurfaceShown = false;
try {
@@ -130,14 +138,31 @@
void destroyInTransaction() {
// if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
- Slog.i(TAG, "Destroying surface " + this + " called by " + Debug.getCallers(4));
+ Slog.i(TAG, "Destroying surface " + this + " called by " + Debug.getCallers(8));
// }
try {
- mSurfaceControl.destroy();
- mSurfaceShown = false;
- mSurfaceControl = null;
+ if (mSurfaceControl != null) {
+ mSurfaceControl.destroy();
+ }
} catch (RuntimeException e) {
Slog.w(TAG, "Error destroying surface in: " + this, e);
+ } finally {
+ mSurfaceShown = false;
+ mSurfaceControl = null;
+ }
+ }
+
+ void disconnectInTransaction() {
+ if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
+ Slog.i(TAG, "Disconnecting client: " + this);
+ }
+
+ try {
+ if (mSurfaceControl != null) {
+ mSurfaceControl.disconnect();
+ }
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Error disconnecting surface in: " + this, e);
}
}
@@ -148,9 +173,10 @@
if (clipRect.width() > 0 && clipRect.height() > 0) {
mSurfaceControl.setWindowCrop(clipRect);
mHiddenForCrop = false;
+ updateVisibility();
} else {
- hideInTransaction("setCrop");
mHiddenForCrop = true;
+ updateVisibility();
}
} catch (RuntimeException e) {
Slog.w(TAG, "Error setting crop surface of " + this
@@ -313,11 +339,26 @@
"SHOW (performLayout)", null);
if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
+ " during relayout");
+ mHiddenForOtherReasons = false;
+ return updateVisibility();
+ }
- if (mHiddenForCrop) {
+ private boolean updateVisibility() {
+ if (mHiddenForCrop || mHiddenForOtherReasons) {
+ if (mSurfaceShown) {
+ hideSurface();
+ }
return false;
+ } else {
+ if (!mSurfaceShown) {
+ return showSurface();
+ } else {
+ return true;
+ }
}
+ }
+ private boolean showSurface() {
try {
mSurfaceShown = true;
mSurfaceControl.show();
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 4e1b644..e3955fe 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -1,5 +1,9 @@
package com.android.server.wm;
+import static android.app.ActivityManagerInternal.APP_TRANSITION_SAVED_SURFACE;
+import static android.app.ActivityManagerInternal.APP_TRANSITION_STARTING_WINDOW;
+import static android.app.ActivityManagerInternal.APP_TRANSITION_TIMEOUT;
+import static android.app.ActivityManagerInternal.APP_TRANSITION_WINDOWS_DRAWN;
import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
@@ -7,7 +11,6 @@
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
@@ -43,6 +46,7 @@
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.Debug;
+import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -647,6 +651,7 @@
for (int i = windows.size() - 1; i >= 0; i--) {
WindowState w = windows.get(i);
+ final Task task = w.getTask();
final boolean obscuredChanged = w.mObscured != mObscured;
// Update effect.
@@ -676,8 +681,11 @@
// currently animating... let's do something.
final int left = w.mFrame.left;
final int top = w.mFrame.top;
+ final boolean adjustedForMinimizedDockedStack = w.getTask() != null &&
+ w.getTask().mStack.isAdjustedForMinimizedDockedStack();
if ((w.mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0
- && !w.isDragResizing()) {
+ && !w.isDragResizing() && !adjustedForMinimizedDockedStack
+ && (task == null || !w.getTask().mStack.getFreezeMovementAnimations())) {
winAnimator.setMoveAnimation(left, top);
}
@@ -751,7 +759,7 @@
}
if ((w.isOnScreenIgnoringKeyguard()
|| winAnimator.mAttrType == TYPE_BASE_APPLICATION)
- && !w.mExiting && !w.mDestroying) {
+ && !w.mAnimatingExit && !w.mDestroying) {
if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
Slog.v(TAG, "Eval win " + w + ": isDrawn="
+ w.isDrawnLw()
@@ -781,6 +789,7 @@
}
}
} else if (w.isDrawnLw()) {
+ mService.mH.sendEmptyMessage(NOTIFY_STARTING_WINDOW_DRAWN);
atoken.startingDisplayed = true;
}
}
@@ -1099,6 +1108,7 @@
processApplicationsAnimatingInPlace(transit);
+ mTmpLayerAndToken.token = null;
handleClosingApps(transit, animLp, voiceInteraction, mTmpLayerAndToken);
final AppWindowToken topClosingApp = mTmpLayerAndToken.token;
final int topClosingLayer = mTmpLayerAndToken.layer;
@@ -1111,7 +1121,8 @@
final AppWindowAnimator closingAppAnimator = (topClosingApp == null) ? null :
topClosingApp.mAppAnimator;
- mService.mAppTransition.goodToGo(openingAppAnimator, closingAppAnimator);
+ mService.mAppTransition.goodToGo(openingAppAnimator, closingAppAnimator,
+ mService.mOpeningApps, mService.mClosingApps);
mService.mAppTransition.postAnimationCallback();
mService.mAppTransition.clear();
@@ -1181,17 +1192,17 @@
int layer = -1;
for (int j = 0; j < wtoken.windows.size(); j++) {
final WindowState win = wtoken.windows.get(j);
- // Clearing the mExiting flag before entering animation. It will be set to true
+ // Clearing the mAnimatingExit flag before entering animation. It will be set to true
// if app window is removed, or window relayout to invisible. We don't want to
// clear it out for windows that get replaced, because the animation depends on
// the flag to remove the replaced window.
//
- // We also don't clear the mExiting flag for windows which have the
+ // We also don't clear the mAnimatingExit flag for windows which have the
// mRemoveOnExit flag. This indicates an explicit remove request has been issued
// by the client. We should let animation proceed and not clear this flag or
// they won't eventually be removed by WindowStateAnimator#finishExit.
if (!win.mWillReplaceWindow && !win.mRemoveOnExit) {
- win.mExiting = false;
+ win.mAnimatingExit = false;
}
if (win.mWinAnimator.mAnimLayer > layer) {
layer = win.mWinAnimator.mAnimLayer;
@@ -1230,7 +1241,7 @@
wtoken.deferClearAllDrawn = false;
// Ensure that apps that are mid-starting are also scheduled to have their
// starting windows removed after the animation is complete
- if (wtoken.startingWindow != null && !wtoken.startingWindow.mExiting) {
+ if (wtoken.startingWindow != null && !wtoken.startingWindow.mAnimatingExit) {
mService.scheduleRemoveStartingWindowLocked(wtoken);
}
mService.mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
@@ -1259,6 +1270,7 @@
"Checking " + appsCount + " opening apps (frozen="
+ mService.mDisplayFrozen + " timeout="
+ mService.mAppTransition.isTimeout() + ")...");
+ int reason = APP_TRANSITION_TIMEOUT;
if (!mService.mAppTransition.isTimeout()) {
for (int i = 0; i < appsCount; i++) {
AppWindowToken wtoken = mService.mOpeningApps.valueAt(i);
@@ -1268,11 +1280,18 @@
+ wtoken.startingDisplayed + " startingMoved="
+ wtoken.startingMoved);
+ final boolean drawnBeforeRestoring = wtoken.allDrawn;
wtoken.restoreSavedSurfaces();
if (!wtoken.allDrawn && !wtoken.startingDisplayed && !wtoken.startingMoved) {
return false;
}
+ if (wtoken.allDrawn) {
+ reason = drawnBeforeRestoring ? APP_TRANSITION_WINDOWS_DRAWN
+ : APP_TRANSITION_SAVED_SURFACE;
+ } else {
+ reason = APP_TRANSITION_STARTING_WINDOW;
+ }
}
// We also need to wait for the specs to be fetched, if needed.
@@ -1282,9 +1301,15 @@
}
// If the wallpaper is visible, we need to check it's ready too.
- return !mWallpaperControllerLocked.isWallpaperVisible() ||
+ boolean wallpaperReady = !mWallpaperControllerLocked.isWallpaperVisible() ||
mWallpaperControllerLocked.wallpaperTransitionReady();
+ if (wallpaperReady) {
+ mService.mH.obtainMessage(NOTIFY_APP_TRANSITION_STARTING, reason, 0).sendToTarget();
+ return true;
+ }
+ return false;
}
+ mService.mH.obtainMessage(NOTIFY_APP_TRANSITION_STARTING, reason, 0).sendToTarget();
return true;
}
diff --git a/core/java/android/view/animation/ClipRectLRAnimation.java b/services/core/java/com/android/server/wm/animation/ClipRectLRAnimation.java
similarity index 87%
rename from core/java/android/view/animation/ClipRectLRAnimation.java
rename to services/core/java/com/android/server/wm/animation/ClipRectLRAnimation.java
index 8993cd3..0db4c70 100644
--- a/core/java/android/view/animation/ClipRectLRAnimation.java
+++ b/services/core/java/com/android/server/wm/animation/ClipRectLRAnimation.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -11,12 +11,14 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License.
+ * limitations under the License
*/
-package android.view.animation;
+package com.android.server.wm.animation;
import android.graphics.Rect;
+import android.view.animation.ClipRectAnimation;
+import android.view.animation.Transformation;
/**
* Special case of ClipRectAnimation that animates only the left/right
diff --git a/services/core/java/com/android/server/wm/animation/ClipRectTBAnimation.java b/services/core/java/com/android/server/wm/animation/ClipRectTBAnimation.java
new file mode 100644
index 0000000..1f5b1a3
--- /dev/null
+++ b/services/core/java/com/android/server/wm/animation/ClipRectTBAnimation.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm.animation;
+
+import android.graphics.Rect;
+import android.view.animation.ClipRectAnimation;
+import android.view.animation.Interpolator;
+import android.view.animation.Transformation;
+import android.view.animation.TranslateAnimation;
+
+/**
+ * Special case of ClipRectAnimation that animates only the top/bottom
+ * dimensions of the clip, picking up the other dimensions from whatever is
+ * set on the transform already. In addition to that, information about a vertical translation
+ * animation can be specified so this animation simulates as the clip would be applied after instead
+ * of before applying the translation.
+ */
+public class ClipRectTBAnimation extends ClipRectAnimation {
+
+ private final int mFromTranslateY;
+ private final int mToTranslateY;
+ private final Interpolator mTranslateInterpolator;
+ private float mNormalizedTime;
+
+ /**
+ * Constructor. Passes in 0 for Left/Right parameters of ClipRectAnimation
+ */
+ public ClipRectTBAnimation(int fromT, int fromB, int toT, int toB,
+ int fromTranslateY, int toTranslateY, Interpolator translateInterpolator) {
+ super(0, fromT, 0, fromB, 0, toT, 0, toB);
+ mFromTranslateY = fromTranslateY;
+ mToTranslateY = toTranslateY;
+ mTranslateInterpolator = translateInterpolator;
+ }
+
+ @Override
+ public boolean getTransformation(long currentTime, Transformation outTransformation) {
+
+ // Hack: Because translation animation has a different interpolator, we need to duplicate
+ // code from Animation here and use it to calculate/store the uninterpolated normalized
+ // time.
+ final long startOffset = getStartOffset();
+ final long duration = getDuration();
+ float normalizedTime;
+ if (duration != 0) {
+ normalizedTime = ((float) (currentTime - (getStartTime() + startOffset))) /
+ (float) duration;
+ } else {
+ // time is a step-change with a zero duration
+ normalizedTime = currentTime < getStartTime() ? 0.0f : 1.0f;
+ }
+ mNormalizedTime = normalizedTime;
+ return super.getTransformation(currentTime, outTransformation);
+ }
+
+ /**
+ * Calculates and sets clip rect on given transformation. It uses existing values
+ * on the Transformation for Left/Right clip parameters.
+ */
+ @Override
+ protected void applyTransformation(float it, Transformation tr) {
+ float translationT = mTranslateInterpolator.getInterpolation(mNormalizedTime);
+ int translation =
+ (int) (mFromTranslateY + (mToTranslateY - mFromTranslateY) * translationT);
+ Rect oldClipRect = tr.getClipRect();
+ tr.setClipRect(oldClipRect.left,
+ mFromRect.top - translation + (int) ((mToRect.top - mFromRect.top) * it),
+ oldClipRect.right,
+ mFromRect.bottom - translation + (int) ((mToRect.bottom - mFromRect.bottom) * it));
+ }
+
+}
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index bb571c3..5e5c6d9 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -17,6 +17,7 @@
$(LOCAL_REL_DIR)/com_android_server_AssetAtlasService.cpp \
$(LOCAL_REL_DIR)/com_android_server_connectivity_Vpn.cpp \
$(LOCAL_REL_DIR)/com_android_server_ConsumerIrService.cpp \
+ $(LOCAL_REL_DIR)/com_android_server_HardwarePropertiesManagerService.cpp \
$(LOCAL_REL_DIR)/com_android_server_hdmi_HdmiCecController.cpp \
$(LOCAL_REL_DIR)/com_android_server_input_InputApplicationHandle.cpp \
$(LOCAL_REL_DIR)/com_android_server_input_InputManagerService.cpp \
diff --git a/core/jni/android_os_HardwarePropertiesManager.cpp b/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
similarity index 93%
rename from core/jni/android_os_HardwarePropertiesManager.cpp
rename to services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
index dc1ba48..214d988 100644
--- a/core/jni/android_os_HardwarePropertiesManager.cpp
+++ b/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define LOG_TAG "HardwarePropertiesManager-JNI"
+#define LOG_TAG "HardwarePropertiesManagerService-JNI"
#include "JNIHelp.h"
#include "jni.h"
@@ -137,7 +137,7 @@
// ----------------------------------------------------------------------------
-static const JNINativeMethod gHardwarePropertiesManagerMethods[] = {
+static const JNINativeMethod gHardwarePropertiesManagerServiceMethods[] = {
/* name, signature, funcPtr */
{ "nativeInit", "()V",
(void*) nativeInit },
@@ -149,11 +149,11 @@
(void*) nativeGetCpuUsages }
};
-int register_android_os_HardwarePropertiesManager(JNIEnv* env) {
+int register_android_server_HardwarePropertiesManagerService(JNIEnv* env) {
gHardwarePropertiesModule = nullptr;
- int res = jniRegisterNativeMethods(env, "android/os/HardwarePropertiesManager",
- gHardwarePropertiesManagerMethods,
- NELEM(gHardwarePropertiesManagerMethods));
+ int res = jniRegisterNativeMethods(env, "com/android/server/HardwarePropertiesManagerService",
+ gHardwarePropertiesManagerServiceMethods,
+ NELEM(gHardwarePropertiesManagerServiceMethods));
jclass clazz = env->FindClass("android/os/CpuUsageInfo");
gCpuUsageInfoClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
gCpuUsageInfoClassInfo.initMethod = GetMethodIDOrDie(env, gCpuUsageInfoClassInfo.clazz,
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index cdd5519..60ed497 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -29,10 +29,11 @@
#include "android_runtime/Log.h"
#include <arpa/inet.h>
-#include <string.h>
-#include <pthread.h>
+#include <limits>
#include <linux/in.h>
#include <linux/in6.h>
+#include <pthread.h>
+#include <string.h>
static jobject mCallbacksObj = NULL;
@@ -42,7 +43,7 @@
static jmethodID method_reportAGpsStatus;
static jmethodID method_reportNmea;
static jmethodID method_setEngineCapabilities;
-static jmethodID method_setGpsYearOfHardware;
+static jmethodID method_setGnssYearOfHardware;
static jmethodID method_xtraDownloadRequest;
static jmethodID method_reportNiNotification;
static jmethodID method_requestRefLocation;
@@ -133,14 +134,13 @@
for (size_t i = 0; i < sGnssSvListSize; i++) {
GnssSvInfo& info = sGnssSvList[i];
info.svid = sv_status->sv_list[i].prn;
- // TODO: implement the correct logic to derive the constellation type
- // based on PRN ranges.
if (info.svid >=1 && info.svid <= 32) {
info.constellation = GNSS_CONSTELLATION_GPS;
} else {
+ ALOGD("Unknown constellation type with Svid = %d.", info.svid);
info.constellation = GNSS_CONSTELLATION_UNKNOWN;
}
- info.snr = sv_status->sv_list[i].snr;
+ info.c_n0_dbhz = sv_status->sv_list[i].snr;
info.elevation = sv_status->sv_list[i].elevation;
info.azimuth = sv_status->sv_list[i].azimuth;
info.flags = GNSS_SV_FLAGS_NONE;
@@ -198,10 +198,10 @@
checkAndClearExceptionFromCallback(env, __FUNCTION__);
}
-static void set_system_info_callback(const GpsSystemInfo* info) {
+static void set_system_info_callback(const GnssSystemInfo* info) {
ALOGD("set_system_info_callback: year_of_hw=%d\n", info->year_of_hw);
JNIEnv* env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(mCallbacksObj, method_setGpsYearOfHardware,
+ env->CallVoidMethod(mCallbacksObj, method_setGnssYearOfHardware,
info->year_of_hw);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
}
@@ -536,7 +536,7 @@
method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V");
method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V");
method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V");
- method_setGpsYearOfHardware = env->GetMethodID(clazz, "setGpsYearOfHardware", "(I)V");
+ method_setGnssYearOfHardware = env->GetMethodID(clazz, "setGnssYearOfHardware", "(I)V");
method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification",
"(IIIIILjava/lang/String;Ljava/lang/String;IILjava/lang/String;)V");
@@ -698,12 +698,12 @@
}
static jint android_location_GnssLocationProvider_read_sv_status(JNIEnv* env, jobject /* obj */,
- jintArray svidWithFlagArray, jfloatArray snrArray, jfloatArray elevArray,
+ jintArray svidWithFlagArray, jfloatArray cn0Array, jfloatArray elevArray,
jfloatArray azumArray)
{
// this should only be called from within a call to reportSvStatus
jint* svidWithFlags = env->GetIntArrayElements(svidWithFlagArray, 0);
- jfloat* snrs = env->GetFloatArrayElements(snrArray, 0);
+ jfloat* cn0s = env->GetFloatArrayElements(cn0Array, 0);
jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
jfloat* azim = env->GetFloatArrayElements(azumArray, 0);
@@ -713,13 +713,13 @@
svidWithFlags[i] = (info.svid << SVID_SHIFT_WIDTH) |
(info.constellation << CONSTELLATION_TYPE_SHIFT_WIDTH) |
info.flags;
- snrs[i] = info.snr;
+ cn0s[i] = info.c_n0_dbhz;
elev[i] = info.elevation;
azim[i] = info.azimuth;
}
env->ReleaseIntArrayElements(svidWithFlagArray, svidWithFlags, 0);
- env->ReleaseFloatArrayElements(snrArray, snrs, 0);
+ env->ReleaseFloatArrayElements(cn0Array, cn0s, 0);
env->ReleaseFloatArrayElements(elevArray, elev, 0);
env->ReleaseFloatArrayElements(azumArray, azim, 0);
return (jint) sGnssSvListSize;
@@ -1074,7 +1074,9 @@
template<>
const char *const JavaMethodHelper<uint16_t>::signature_ = "(S)V";
template<>
-const char *const JavaMethodHelper<int>::signature_ = "(I)V";
+const char *const JavaMethodHelper<int32_t>::signature_ = "(I)V";
+template<>
+const char *const JavaMethodHelper<uint32_t>::signature_ = "(I)V";
template<>
const char *const JavaMethodHelper<int64_t>::signature_ = "(J)V";
template<>
@@ -1089,38 +1091,52 @@
if (flags & (flag)) object.callSetter("set" # setter, (value))
static jobject translate_gps_clock(JNIEnv* env, GpsClock* clock) {
+ static uint32_t discontinuity_count_to_handle_old_lock_type = 0;
JavaObject object(env, "android/location/GnssClock");
GpsClockFlags flags = clock->flags;
- SET_IF(GPS_CLOCK_HAS_LEAP_SECOND, LeapSecond, clock->leap_second);
- SET(Type, clock->type);
- SET(TimeInNs, clock->time_ns);
- SET_IF(GPS_CLOCK_HAS_TIME_UNCERTAINTY,
- TimeUncertaintyInNs,
- clock->time_uncertainty_ns);
- SET_IF(GPS_CLOCK_HAS_FULL_BIAS, FullBiasInNs, clock->full_bias_ns);
- SET_IF(GPS_CLOCK_HAS_BIAS, BiasInNs, clock->bias_ns);
- SET_IF(GPS_CLOCK_HAS_BIAS_UNCERTAINTY,
- BiasUncertaintyInNs,
- clock->bias_uncertainty_ns);
- SET_IF(GPS_CLOCK_HAS_DRIFT, DriftInNsPerSec, clock->drift_nsps);
- SET_IF(GPS_CLOCK_HAS_DRIFT_UNCERTAINTY,
- DriftUncertaintyInNsPerSec,
- clock->drift_uncertainty_nsps);
+ SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND,
+ LeapSecond,
+ static_cast<int32_t>(clock->leap_second));
- /*
- if (flags & GPS_CLOCK_TYPE_LOCAL_HW_TIME) {
- if (size == sizeof(GnssClock)) {
- jmethodID setterMethod =
- env->GetMethodID(gpsClockClass,
- "setTimeOfLastHwClockDiscontinuityInNs",
- longSignature);
- env->CallVoidMethod(gpsClockObject,
- setterMethod,
- reinterpret_cast<GnssClock*>(clock)->time_of_last_hw_clock_discontinuity_ns);
- }
+ // GnssClock only supports the more effective HW_CLOCK type, so type
+ // handling and documentation complexity has been removed. To convert the
+ // old GPS_CLOCK types (active only in a limited number of older devices),
+ // the GPS time information is handled as an always discontinuous HW clock,
+ // with the GPS time information put into the full_bias_ns instead - so that
+ // time_ns + full_bias_ns = local estimate of GPS time (as remains true, in
+ // the new GnssClock struct.)
+ switch (clock->type) {
+ case GPS_CLOCK_TYPE_UNKNOWN:
+ // Clock type unsupported.
+ ALOGE("Unknown clock type provided.");
+ break;
+ case GPS_CLOCK_TYPE_LOCAL_HW_TIME:
+ // Already local hardware time. No need to do anything.
+ break;
+ case GPS_CLOCK_TYPE_GPS_TIME:
+ // GPS time, need to convert.
+ flags |= GNSS_CLOCK_HAS_FULL_BIAS;
+ clock->full_bias_ns = clock->time_ns;
+ clock->time_ns = 0;
+ SET(HardwareClockDiscontinuityCount,
+ discontinuity_count_to_handle_old_lock_type++);
+ break;
}
- */
+
+ SET(TimeNanos, clock->time_ns);
+ SET_IF(GNSS_CLOCK_HAS_TIME_UNCERTAINTY,
+ TimeUncertaintyNanos,
+ clock->time_uncertainty_ns);
+ SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasNanos, clock->full_bias_ns);
+ SET_IF(GNSS_CLOCK_HAS_BIAS, BiasNanos, clock->bias_ns);
+ SET_IF(GNSS_CLOCK_HAS_BIAS_UNCERTAINTY,
+ BiasUncertaintyNanos,
+ clock->bias_uncertainty_ns);
+ SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftNanosPerSecond, clock->drift_nsps);
+ SET_IF(GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY,
+ DriftUncertaintyNanosPerSecond,
+ clock->drift_uncertainty_nsps);
return object.get();
}
@@ -1129,25 +1145,24 @@
JavaObject object(env, "android/location/GnssClock");
GpsClockFlags flags = clock->flags;
- SET_IF(GPS_CLOCK_HAS_LEAP_SECOND, LeapSecond, clock->leap_second);
- SET(Type, clock->type);
- SET(TimeInNs, clock->time_ns);
- SET_IF(GPS_CLOCK_HAS_TIME_UNCERTAINTY,
- TimeUncertaintyInNs,
+ SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND,
+ LeapSecond,
+ static_cast<int32_t>(clock->leap_second));
+ SET(TimeNanos, clock->time_ns);
+ SET_IF(GNSS_CLOCK_HAS_TIME_UNCERTAINTY,
+ TimeUncertaintyNanos,
clock->time_uncertainty_ns);
- SET_IF(GPS_CLOCK_HAS_FULL_BIAS, FullBiasInNs, clock->full_bias_ns);
- SET_IF(GPS_CLOCK_HAS_BIAS, BiasInNs, clock->bias_ns);
- SET_IF(GPS_CLOCK_HAS_BIAS_UNCERTAINTY,
- BiasUncertaintyInNs,
+ SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasNanos, clock->full_bias_ns);
+ SET_IF(GNSS_CLOCK_HAS_BIAS, BiasNanos, clock->bias_ns);
+ SET_IF(GNSS_CLOCK_HAS_BIAS_UNCERTAINTY,
+ BiasUncertaintyNanos,
clock->bias_uncertainty_ns);
- SET_IF(GPS_CLOCK_HAS_DRIFT, DriftInNsPerSec, clock->drift_nsps);
- SET_IF(GPS_CLOCK_HAS_DRIFT_UNCERTAINTY,
- DriftUncertaintyInNsPerSec,
+ SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftNanosPerSecond, clock->drift_nsps);
+ SET_IF(GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY,
+ DriftUncertaintyNanosPerSecond,
clock->drift_uncertainty_nsps);
- SET_IF(GPS_CLOCK_TYPE_LOCAL_HW_TIME,
- TimeOfLastHwClockDiscontinuityInNs,
- clock->time_of_last_hw_clock_discontinuity_ns);
+ SET(HardwareClockDiscontinuityCount, clock->hw_clock_discontinuity_count);
return object.get();
}
@@ -1156,72 +1171,43 @@
GpsMeasurement* measurement) {
JavaObject object(env, "android/location/GnssMeasurement");
GpsMeasurementFlags flags = measurement->flags;
-
- SET(Svid, static_cast<int16_t>(measurement->prn));
- SET(TimeOffsetInNs, measurement->time_offset_ns);
- SET(State, measurement->state);
- SET(ReceivedGpsTowInNs, measurement->received_gps_tow_ns);
- SET(ReceivedGpsTowUncertaintyInNs,
+ SET(Svid, static_cast<int32_t>(measurement->prn));
+ if (measurement->prn >= 1 || measurement->prn <= 32) {
+ SET(ConstellationType, static_cast<int32_t>(GNSS_CONSTELLATION_GPS));
+ } else {
+ ALOGD("Unknown constellation type with Svid = %d.", measurement->prn);
+ SET(ConstellationType,
+ static_cast<int32_t>(GNSS_CONSTELLATION_UNKNOWN));
+ }
+ SET(TimeOffsetNanos, measurement->time_offset_ns);
+ SET(State, static_cast<int32_t>(measurement->state));
+ SET(ReceivedSvTimeNanos, measurement->received_gps_tow_ns);
+ SET(ReceivedSvTimeUncertaintyNanos,
measurement->received_gps_tow_uncertainty_ns);
- SET(Cn0InDbHz, measurement->c_n0_dbhz);
- SET(PseudorangeRateInMetersPerSec, measurement->pseudorange_rate_mps);
- SET(PseudorangeRateUncertaintyInMetersPerSec,
+ SET(Cn0DbHz, measurement->c_n0_dbhz);
+ SET(PseudorangeRateMetersPerSecond, measurement->pseudorange_rate_mps);
+ SET(PseudorangeRateUncertaintyMetersPerSecond,
measurement->pseudorange_rate_uncertainty_mps);
- SET(AccumulatedDeltaRangeState, measurement->accumulated_delta_range_state);
- SET(AccumulatedDeltaRangeInMeters, measurement->accumulated_delta_range_m);
- SET(AccumulatedDeltaRangeUncertaintyInMeters,
+ SET(AccumulatedDeltaRangeState,
+ static_cast<int32_t>(measurement->accumulated_delta_range_state));
+ SET(AccumulatedDeltaRangeMeters, measurement->accumulated_delta_range_m);
+ SET(AccumulatedDeltaRangeUncertaintyMeters,
measurement->accumulated_delta_range_uncertainty_m);
- SET_IF(GPS_MEASUREMENT_HAS_PSEUDORANGE,
- PseudorangeInMeters,
- measurement->pseudorange_m);
- SET_IF(GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY,
- PseudorangeUncertaintyInMeters,
- measurement->pseudorange_uncertainty_m);
- SET_IF(GPS_MEASUREMENT_HAS_CODE_PHASE,
- CodePhaseInChips,
- measurement->code_phase_chips);
- SET_IF(GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY,
- CodePhaseUncertaintyInChips,
- measurement->code_phase_uncertainty_chips);
- SET_IF(GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
- CarrierFrequencyInHz,
+ SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
+ CarrierFrequencyHz,
measurement->carrier_frequency_hz);
- SET_IF(GPS_MEASUREMENT_HAS_CARRIER_CYCLES,
+ SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
CarrierCycles,
measurement->carrier_cycles);
- SET_IF(GPS_MEASUREMENT_HAS_CARRIER_PHASE,
+ SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE,
CarrierPhase,
measurement->carrier_phase);
- SET_IF(GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
+ SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
CarrierPhaseUncertainty,
measurement->carrier_phase_uncertainty);
- SET(LossOfLock, measurement->loss_of_lock);
- SET_IF(GPS_MEASUREMENT_HAS_BIT_NUMBER, BitNumber, measurement->bit_number);
- SET_IF(GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT,
- TimeFromLastBitInMs,
- measurement->time_from_last_bit_ms);
- SET_IF(GPS_MEASUREMENT_HAS_DOPPLER_SHIFT,
- DopplerShiftInHz,
- measurement->doppler_shift_hz);
- SET_IF(GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY,
- DopplerShiftUncertaintyInHz,
- measurement->doppler_shift_uncertainty_hz);
- SET(MultipathIndicator, measurement->multipath_indicator);
- SET_IF(GPS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
- SET_IF(GPS_MEASUREMENT_HAS_ELEVATION,
- ElevationInDeg,
- measurement->elevation_deg);
- SET_IF(GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY,
- ElevationUncertaintyInDeg,
- measurement->elevation_uncertainty_deg);
- SET_IF(GPS_MEASUREMENT_HAS_AZIMUTH,
- AzimuthInDeg,
- measurement->azimuth_deg);
- SET_IF(GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY,
- AzimuthUncertaintyInDeg,
- measurement->azimuth_uncertainty_deg);
- SET(UsedInFix,
- (flags & GPS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix);
+ SET(MultipathIndicator,
+ static_cast<int32_t>(measurement->multipath_indicator));
+ SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
return object.get();
}
@@ -1232,75 +1218,36 @@
GpsMeasurementFlags flags = measurement->flags;
SET(Svid, measurement->svid);
- SET(TimeOffsetInNs, measurement->time_offset_ns);
- SET(State, measurement->state);
- SET(ReceivedGpsTowInNs, measurement->received_gps_tow_ns);
- SET(ReceivedGpsTowUncertaintyInNs,
- measurement->received_gps_tow_uncertainty_ns);
- SET(Cn0InDbHz, measurement->c_n0_dbhz);
- SET(PseudorangeRateInMetersPerSec, measurement->pseudorange_rate_mps);
- SET(PseudorangeRateUncertaintyInMetersPerSec,
+ SET(ConstellationType, static_cast<int32_t>(measurement->constellation));
+ SET(TimeOffsetNanos, measurement->time_offset_ns);
+ SET(State, static_cast<int32_t>(measurement->state));
+ SET(ReceivedSvTimeNanos, measurement->received_sv_time_in_ns);
+ SET(ReceivedSvTimeUncertaintyNanos,
+ measurement->received_sv_time_uncertainty_in_ns);
+ SET(Cn0DbHz, measurement->c_n0_dbhz);
+ SET(PseudorangeRateMetersPerSecond, measurement->pseudorange_rate_mps);
+ SET(PseudorangeRateUncertaintyMetersPerSecond,
measurement->pseudorange_rate_uncertainty_mps);
- SET(AccumulatedDeltaRangeState, measurement->accumulated_delta_range_state);
- SET(AccumulatedDeltaRangeInMeters, measurement->accumulated_delta_range_m);
- SET(AccumulatedDeltaRangeUncertaintyInMeters,
+ SET(AccumulatedDeltaRangeState,
+ static_cast<int32_t>(measurement->accumulated_delta_range_state));
+ SET(AccumulatedDeltaRangeMeters, measurement->accumulated_delta_range_m);
+ SET(AccumulatedDeltaRangeUncertaintyMeters,
measurement->accumulated_delta_range_uncertainty_m);
- SET_IF(GPS_MEASUREMENT_HAS_PSEUDORANGE,
- PseudorangeInMeters,
- measurement->pseudorange_m);
- SET_IF(GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY,
- PseudorangeUncertaintyInMeters,
- measurement->pseudorange_uncertainty_m);
- SET_IF(GPS_MEASUREMENT_HAS_CODE_PHASE,
- CodePhaseInChips,
- measurement->code_phase_chips);
- SET_IF(GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY,
- CodePhaseUncertaintyInChips,
- measurement->code_phase_uncertainty_chips);
- SET_IF(GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
- CarrierFrequencyInHz,
+ SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
+ CarrierFrequencyHz,
measurement->carrier_frequency_hz);
- SET_IF(GPS_MEASUREMENT_HAS_CARRIER_CYCLES,
+ SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
CarrierCycles,
measurement->carrier_cycles);
- SET_IF(GPS_MEASUREMENT_HAS_CARRIER_PHASE,
+ SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE,
CarrierPhase,
measurement->carrier_phase);
- SET_IF(GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
+ SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
CarrierPhaseUncertainty,
measurement->carrier_phase_uncertainty);
- SET(LossOfLock, measurement->loss_of_lock);
- SET_IF(GPS_MEASUREMENT_HAS_BIT_NUMBER, BitNumber, measurement->bit_number);
- SET_IF(GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT,
- TimeFromLastBitInMs,
- measurement->time_from_last_bit_ms);
- SET_IF(GPS_MEASUREMENT_HAS_DOPPLER_SHIFT,
- DopplerShiftInHz,
- measurement->doppler_shift_hz);
- SET_IF(GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY,
- DopplerShiftUncertaintyInHz,
- measurement->doppler_shift_uncertainty_hz);
- SET(MultipathIndicator, measurement->multipath_indicator);
- SET_IF(GPS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
- SET_IF(GPS_MEASUREMENT_HAS_ELEVATION,
- ElevationInDeg,
- measurement->elevation_deg);
- SET_IF(GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY,
- ElevationUncertaintyInDeg,
- measurement->elevation_uncertainty_deg);
- SET_IF(GPS_MEASUREMENT_HAS_AZIMUTH,
- AzimuthInDeg,
- measurement->azimuth_deg);
- SET_IF(GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY,
- AzimuthUncertaintyInDeg,
- measurement->azimuth_uncertainty_deg);
- SET(UsedInFix,
- (flags & GPS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix);
-
- SET(PseudorangeRateCarrierInMetersPerSec,
- measurement->pseudorange_rate_carrier_mps);
- SET(PseudorangeRateCarrierUncertaintyInMetersPerSec,
- measurement->pseudorange_rate_carrier_uncertainty_mps);
+ SET(MultipathIndicator,
+ static_cast<int32_t>(measurement->multipath_indicator));
+ SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
return object.get();
}
@@ -1480,11 +1427,22 @@
return NULL;
}
JavaObject object(env, "android/location/GnssNavigationMessage");
- SET(Type, message->type);
- SET(Svid, static_cast<int16_t>(message->prn));
- SET(MessageId, message->message_id);
- SET(SubmessageId, message->submessage_id);
+ SET(Svid, static_cast<int32_t>(message->prn));
+ if (message->prn >=1 && message->prn <= 32) {
+ SET(ConstellationType, static_cast<int32_t>(GNSS_CONSTELLATION_GPS));
+ // Legacy driver doesn't set the higher byte to constellation type
+ // correctly. Set the higher byte to 'GPS'.
+ SET(Type, static_cast<int32_t>(message->type | 0x0100));
+ } else {
+ ALOGD("Unknown constellation type with Svid = %d.", message->prn);
+ SET(ConstellationType,
+ static_cast<int32_t>(GNSS_CONSTELLATION_UNKNOWN));
+ SET(Type, static_cast<int32_t>(GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN));
+ }
+ SET(MessageId, static_cast<int32_t>(message->message_id));
+ SET(SubmessageId, static_cast<int32_t>(message->submessage_id));
object.callSetter("setData", data, dataLength);
+ SET(Status, static_cast<int32_t>(message->status));
return object.get();
}
@@ -1497,11 +1455,12 @@
return NULL;
}
JavaObject object(env, "android/location/GnssNavigationMessage");
- SET(Type, message->type);
- SET(Svid, message->svid);
- SET(MessageId, message->message_id);
- SET(SubmessageId, message->submessage_id);
+ SET(Type, static_cast<int32_t>(message->type));
+ SET(Svid, static_cast<int32_t>(message->svid));
+ SET(MessageId, static_cast<int32_t>(message->message_id));
+ SET(SubmessageId, static_cast<int32_t>(message->submessage_id));
object.callSetter("setData", data, dataLength);
+ SET(Status, static_cast<int32_t>(message->status));
return object.get();
}
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index ef5c56c..be99673 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -44,6 +44,7 @@
int register_android_server_tv_TvInputHal(JNIEnv* env);
int register_android_server_PersistentDataBlockService(JNIEnv* env);
int register_android_server_Watchdog(JNIEnv* env);
+int register_android_server_HardwarePropertiesManagerService(JNIEnv* env);
};
using namespace android;
@@ -83,6 +84,7 @@
register_android_server_tv_TvInputHal(env);
register_android_server_PersistentDataBlockService(env);
register_android_server_Watchdog(env);
+ register_android_server_HardwarePropertiesManagerService(env);
return JNI_VERSION_1_4;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 07539cc..ce86b2c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -31,8 +31,8 @@
import android.Manifest.permission;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accounts.AccountManager;
+import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
@@ -151,6 +151,8 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
@@ -280,6 +282,20 @@
private static final int PROFILE_KEYGUARD_FEATURES =
PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER | PROFILE_KEYGUARD_FEATURES_PROFILE_ONLY;
+ private static final int CODE_OK = 0;
+ private static final int CODE_HAS_DEVICE_OWNER = 1;
+ private static final int CODE_USER_HAS_PROFILE_OWNER = 2;
+ private static final int CODE_USER_NOT_RUNNING = 3;
+ private static final int CODE_USER_SETUP_COMPLETED = 4;
+ private static final int CODE_NONSYSTEM_USER_EXISTS = 5;
+ private static final int CODE_ACCOUNTS_NOT_EMPTY = 6;
+ private static final int CODE_NOT_SYSTEM_USER = 7;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({ CODE_OK, CODE_HAS_DEVICE_OWNER, CODE_USER_HAS_PROFILE_OWNER, CODE_USER_NOT_RUNNING,
+ CODE_USER_SETUP_COMPLETED, CODE_NOT_SYSTEM_USER })
+ private @interface DeviceOwnerPreConditionCode {}
+
private static final int DEVICE_ADMIN_DEACTIVATE_TIMEOUT = 10000;
final Context mContext;
@@ -308,7 +324,7 @@
* Whether or not device admin feature is supported. If it isn't return defaults for all
* public methods.
*/
- private boolean mHasFeature;
+ boolean mHasFeature;
private final SecurityLogMonitor mSecurityLogMonitor;
@@ -328,7 +344,7 @@
@Override
public void onReceive(Context context, Intent intent) {
- if (RemoteBugreportUtils.ACTION_REMOTE_BUGREPORT_DISPATCH.equals(intent.getAction())
+ if (DevicePolicyManager.ACTION_REMOTE_BUGREPORT_DISPATCH.equals(intent.getAction())
&& mRemoteBugreportServiceIsActive.get()) {
onBugreportFinished(intent);
}
@@ -342,10 +358,9 @@
String action = intent.getAction();
mInjector.getNotificationManager().cancel(LOG_TAG,
RemoteBugreportUtils.NOTIFICATION_ID);
- if (RemoteBugreportUtils.ACTION_REMOTE_BUGREPORT_SHARING_ACCEPTED.equals(action)) {
+ if (DevicePolicyManager.ACTION_BUGREPORT_SHARING_ACCEPTED.equals(action)) {
onBugreportSharingAccepted();
- } else if (RemoteBugreportUtils.ACTION_REMOTE_BUGREPORT_SHARING_DECLINED
- .equals(action)) {
+ } else if (DevicePolicyManager.ACTION_BUGREPORT_SHARING_DECLINED.equals(action)) {
onBugreportSharingDeclined();
}
mContext.unregisterReceiver(mRemoteBugreportConsentReceiver);
@@ -437,15 +452,14 @@
&& userHandle == mOwners.getDeviceOwnerUserId()
&& getDeviceOwnerRemoteBugreportUri() != null) {
IntentFilter filterConsent = new IntentFilter();
- filterConsent.addAction(
- RemoteBugreportUtils.ACTION_REMOTE_BUGREPORT_SHARING_DECLINED);
- filterConsent.addAction(
- RemoteBugreportUtils.ACTION_REMOTE_BUGREPORT_SHARING_ACCEPTED);
+ filterConsent.addAction(DevicePolicyManager.ACTION_BUGREPORT_SHARING_DECLINED);
+ filterConsent.addAction(DevicePolicyManager.ACTION_BUGREPORT_SHARING_ACCEPTED);
mContext.registerReceiver(mRemoteBugreportConsentReceiver, filterConsent);
- mInjector.getNotificationManager().notify(LOG_TAG,
+ mInjector.getNotificationManager().notifyAsUser(LOG_TAG,
RemoteBugreportUtils.NOTIFICATION_ID,
RemoteBugreportUtils.buildNotification(mContext,
- RemoteBugreportUtils.NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED));
+ DevicePolicyManager.NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED),
+ UserHandle.ALL);
}
if (Intent.ACTION_BOOT_COMPLETED.equals(action)
|| ACTION_EXPIRED_PASSWORD_NOTIFICATION.equals(action)) {
@@ -769,7 +783,7 @@
out.attribute(null, ATTR_VALUE, Boolean.toString(disableContactsSearch));
out.endTag(null, TAG_DISABLE_CONTACTS_SEARCH);
}
- if (disableBluetoothContactSharing) {
+ if (!disableBluetoothContactSharing) {
out.startTag(null, TAG_DISABLE_BLUETOOTH_CONTACT_SHARING);
out.attribute(null, ATTR_VALUE,
Boolean.toString(disableBluetoothContactSharing));
@@ -2053,31 +2067,31 @@
return null;
}
enforceFullCrossUsersPermission(userHandle);
- Intent resolveIntent = new Intent();
- resolveIntent.setComponent(adminName);
- List<ResolveInfo> infos = mContext.getPackageManager().queryBroadcastReceiversAsUser(
- resolveIntent,
- PackageManager.GET_META_DATA | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS |
- PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE,
- userHandle);
- if (infos == null || infos.size() <= 0) {
+ ActivityInfo ai = null;
+ try {
+ ai = mIPackageManager.getReceiverInfo(adminName,
+ PackageManager.GET_META_DATA |
+ PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS |
+ PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE, userHandle);
+ } catch (RemoteException e) {
+ // shouldn't happen.
+ }
+ if (ai == null) {
throw new IllegalArgumentException("Unknown admin: " + adminName);
}
- final ResolveInfo ri = infos.get(0);
-
- if (!permission.BIND_DEVICE_ADMIN.equals(ri.activityInfo.permission)) {
+ if (!permission.BIND_DEVICE_ADMIN.equals(ai.permission)) {
final String message = "DeviceAdminReceiver " + adminName + " must be protected with "
+ permission.BIND_DEVICE_ADMIN;
Slog.w(LOG_TAG, message);
if (throwForMissiongPermission &&
- ri.activityInfo.applicationInfo.targetSdkVersion > Build.VERSION_CODES.M) {
+ ai.applicationInfo.targetSdkVersion > Build.VERSION_CODES.M) {
throw new IllegalArgumentException(message);
}
}
try {
- return new DeviceAdminInfo(mContext, ri);
+ return new DeviceAdminInfo(mContext, ai);
} catch (XmlPullParserException | IOException e) {
Slog.w(LOG_TAG, "Bad device admin requested for user=" + userHandle + ": " + adminName,
e);
@@ -3875,7 +3889,7 @@
// challenge only and keep the screen on. However there is no easy way of doing that at the
// moment so we set the screen off timeout regardless of whether it affects the parent user
// or the profile challenge only.
- long timeMs = Integer.MAX_VALUE;
+ long timeMs = Long.MAX_VALUE;
List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
for (UserInfo userInfo : profiles) {
DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
@@ -3899,15 +3913,14 @@
final long ident = mInjector.binderClearCallingIdentity();
try {
- if (policy.mLastMaximumTimeToLock != Integer.MAX_VALUE) {
+ if (policy.mLastMaximumTimeToLock != Long.MAX_VALUE) {
// Make sure KEEP_SCREEN_ON is disabled, since that
// would allow bypassing of the maximum time to lock.
mInjector.settingsGlobalPutInt(Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0);
}
- // TODO It can overflow. Cap it.
- mInjector.getPowerManagerInternal()
- .setMaximumScreenOffTimeoutFromDeviceAdmin((int)policy.mLastMaximumTimeToLock);
+ mInjector.getPowerManagerInternal().setMaximumScreenOffTimeoutFromDeviceAdmin(
+ (int) Math.min(policy.mLastMaximumTimeToLock, Integer.MAX_VALUE));
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
@@ -4091,16 +4104,24 @@
}
@Override
- public boolean installKeyPair(ComponentName who, byte[] privKey, byte[] cert, String alias) {
+ public boolean installKeyPair(ComponentName who, byte[] privKey, byte[] cert, String alias,
+ boolean requestAccess) {
enforceCanManageInstalledKeys(who);
- final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
+ final int callingUid = mInjector.binderGetCallingUid();
final long id = mInjector.binderClearCallingIdentity();
try {
- final KeyChainConnection keyChainConnection = KeyChain.bindAsUser(mContext, userHandle);
+ final KeyChainConnection keyChainConnection =
+ KeyChain.bindAsUser(mContext, UserHandle.getUserHandleForUid(callingUid));
try {
IKeyChainService keyChain = keyChainConnection.getService();
- return keyChain.installKeyPair(privKey, cert, alias);
+ if (!keyChain.installKeyPair(privKey, cert, alias)) {
+ return false;
+ }
+ if (requestAccess) {
+ keyChain.setGrant(callingUid, alias, true);
+ }
+ return true;
} catch (RemoteException e) {
Log.e(LOG_TAG, "Installing certificate", e);
} finally {
@@ -4969,6 +4990,11 @@
return;
}
Preconditions.checkNotNull(who, "ComponentName is null");
+ // Allow setting this policy to true only if there is a split system user.
+ if (forceEphemeralUsers && !mInjector.userManagerIsSplitSystemUser()) {
+ throw new UnsupportedOperationException(
+ "Cannot force ephemeral users on systems without split system user.");
+ }
boolean removeAllUsers = false;
synchronized (this) {
final ActiveAdmin deviceOwner =
@@ -5056,9 +5082,9 @@
mRemoteBugreportServiceIsActive.set(true);
mRemoteBugreportSharingAccepted.set(false);
registerRemoteBugreportReceivers();
- mInjector.getNotificationManager().notify(LOG_TAG, RemoteBugreportUtils.NOTIFICATION_ID,
+ mInjector.getNotificationManager().notifyAsUser(LOG_TAG, RemoteBugreportUtils.NOTIFICATION_ID,
RemoteBugreportUtils.buildNotification(mContext,
- RemoteBugreportUtils.NOTIFICATION_BUGREPORT_STARTED));
+ DevicePolicyManager.NOTIFICATION_BUGREPORT_STARTED), UserHandle.ALL);
mHandler.postDelayed(mRemoteBugreportTimeoutRunnable,
RemoteBugreportUtils.REMOTE_BUGREPORT_TIMEOUT_MILLIS);
return true;
@@ -5092,7 +5118,7 @@
private void registerRemoteBugreportReceivers() {
try {
IntentFilter filterFinished = new IntentFilter(
- RemoteBugreportUtils.ACTION_REMOTE_BUGREPORT_DISPATCH,
+ DevicePolicyManager.ACTION_REMOTE_BUGREPORT_DISPATCH,
RemoteBugreportUtils.BUGREPORT_MIMETYPE);
mContext.registerReceiver(mRemoteBugreportFinishedReceiver, filterFinished);
} catch (IntentFilter.MalformedMimeTypeException e) {
@@ -5100,8 +5126,8 @@
Slog.w(LOG_TAG, "Failed to set type " + RemoteBugreportUtils.BUGREPORT_MIMETYPE, e);
}
IntentFilter filterConsent = new IntentFilter();
- filterConsent.addAction(RemoteBugreportUtils.ACTION_REMOTE_BUGREPORT_SHARING_DECLINED);
- filterConsent.addAction(RemoteBugreportUtils.ACTION_REMOTE_BUGREPORT_SHARING_ACCEPTED);
+ filterConsent.addAction(DevicePolicyManager.ACTION_BUGREPORT_SHARING_DECLINED);
+ filterConsent.addAction(DevicePolicyManager.ACTION_BUGREPORT_SHARING_ACCEPTED);
mContext.registerReceiver(mRemoteBugreportConsentReceiver, filterConsent);
}
@@ -5114,16 +5140,17 @@
bugreportUriString = bugreportUri.toString();
}
String bugreportHash = intent.getStringExtra(
- RemoteBugreportUtils.EXTRA_REMOTE_BUGREPORT_HASH);
+ DevicePolicyManager.EXTRA_REMOTE_BUGREPORT_HASH);
if (mRemoteBugreportSharingAccepted.get()) {
shareBugreportWithDeviceOwnerIfExists(bugreportUriString, bugreportHash);
mInjector.getNotificationManager().cancel(LOG_TAG,
RemoteBugreportUtils.NOTIFICATION_ID);
} else {
setDeviceOwnerRemoteBugreportUriAndHash(bugreportUriString, bugreportHash);
- mInjector.getNotificationManager().notify(LOG_TAG, RemoteBugreportUtils.NOTIFICATION_ID,
+ mInjector.getNotificationManager().notifyAsUser(LOG_TAG, RemoteBugreportUtils.NOTIFICATION_ID,
RemoteBugreportUtils.buildNotification(mContext,
- RemoteBugreportUtils.NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED));
+ DevicePolicyManager.NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED),
+ UserHandle.ALL);
}
mContext.unregisterReceiver(mRemoteBugreportFinishedReceiver);
}
@@ -5154,9 +5181,10 @@
if (bugreportUriString != null) {
shareBugreportWithDeviceOwnerIfExists(bugreportUriString, bugreportHash);
} else if (mRemoteBugreportServiceIsActive.get()) {
- mInjector.getNotificationManager().notify(LOG_TAG, RemoteBugreportUtils.NOTIFICATION_ID,
+ mInjector.getNotificationManager().notifyAsUser(LOG_TAG, RemoteBugreportUtils.NOTIFICATION_ID,
RemoteBugreportUtils.buildNotification(mContext,
- RemoteBugreportUtils.NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED));
+ DevicePolicyManager.NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED),
+ UserHandle.ALL);
}
}
@@ -5518,7 +5546,8 @@
Preconditions.checkNotNull(packageName, "packageName is null");
final int callingUid = mInjector.binderGetCallingUid();
try {
- int uid = mContext.getPackageManager().getPackageUidAsUser(packageName, 0);
+ int uid = mContext.getPackageManager().getPackageUidAsUser(packageName,
+ UserHandle.getUserId(callingUid));
if (uid != callingUid) {
throw new SecurityException("Invalid packageName");
}
@@ -5921,52 +5950,40 @@
/**
* The Device owner can only be set by adb or an app with the MANAGE_PROFILE_AND_DEVICE_OWNERS
* permission.
- * The device owner can only be set before the setup phase of the primary user has completed,
- * except for adb if no accounts or additional users are present on the device.
*/
private void enforceCanSetDeviceOwnerLocked(int userId) {
- if (mOwners.hasDeviceOwner()) {
- throw new IllegalStateException("Trying to set the device owner, but device owner "
- + "is already set.");
- }
- if (mOwners.hasProfileOwner(userId)) {
- throw new IllegalStateException("Trying to set the device owner, but the user already "
- + "has a profile owner.");
- }
- if (!mUserManager.isUserRunning(new UserHandle(userId))) {
- throw new IllegalStateException("User not running: " + userId);
- }
-
int callingUid = mInjector.binderGetCallingUid();
- if (callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID) {
- if (!hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
- return;
- }
- // STOPSHIP Do proper check in split user mode
- if (!mInjector.userManagerIsSplitSystemUser()) {
- if (mUserManager.getUserCount() > 1) {
- throw new IllegalStateException(
- "Not allowed to set the device owner because there "
- + "are already several users on the device");
- }
- if (AccountManager.get(mContext).getAccounts().length > 0) {
- throw new IllegalStateException(
- "Not allowed to set the device owner because there "
- + "are already some accounts on the device");
- }
- }
- return;
+ boolean isAdb = callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID;
+ if (!isAdb) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS, null);
}
- // STOPSHIP check the caller UID with userId
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS, null);
- // STOPSHIP Do proper check in split user mode
- if (!mInjector.userManagerIsSplitSystemUser()) {
- if (hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
- throw new IllegalStateException("Cannot set the device owner if the device is "
- + "already set-up");
- }
+ final int code = checkSetDeviceOwnerPreCondition(userId, isAdb);
+ switch (code) {
+ case CODE_OK:
+ return;
+ case CODE_HAS_DEVICE_OWNER:
+ throw new IllegalStateException(
+ "Trying to set the device owner, but device owner is already set.");
+ case CODE_USER_HAS_PROFILE_OWNER:
+ throw new IllegalStateException("Trying to set the device owner, but the user "
+ + "already has a profile owner.");
+ case CODE_USER_NOT_RUNNING:
+ throw new IllegalStateException("User not running: " + userId);
+ case CODE_NOT_SYSTEM_USER:
+ throw new IllegalStateException("User is not system user");
+ case CODE_USER_SETUP_COMPLETED:
+ throw new IllegalStateException(
+ "Cannot set the device owner if the device is already set-up");
+ case CODE_NONSYSTEM_USER_EXISTS:
+ throw new IllegalStateException("Not allowed to set the device owner because there "
+ + "are already several users on the device");
+ case CODE_ACCOUNTS_NOT_EMPTY:
+ throw new IllegalStateException("Not allowed to set the device owner because there "
+ + "are already some accounts on the device");
+ default:
+ throw new IllegalStateException("Unknown @DeviceOwnerPreConditionCode " + code);
}
}
@@ -6739,57 +6756,6 @@
}
}
- @Override
- public UserHandle createUser(ComponentName who, String name) {
- Preconditions.checkNotNull(who, "ComponentName is null");
- synchronized (this) {
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
-
- long id = mInjector.binderClearCallingIdentity();
- try {
- UserInfo userInfo = mUserManager.createUser(name, 0 /* flags */);
- if (userInfo != null) {
- return userInfo.getUserHandle();
- }
- return null;
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
- }
- }
- }
-
- @Override
- public UserHandle createAndInitializeUser(ComponentName who, String name,
- String ownerName, ComponentName profileOwnerComponent, Bundle adminExtras) {
- UserHandle user = createUser(who, name);
- if (user == null) {
- return null;
- }
- long id = mInjector.binderClearCallingIdentity();
- try {
- String profileOwnerPkg = profileOwnerComponent.getPackageName();
-
- final int userHandle = user.getIdentifier();
- try {
- // Install the profile owner if not present.
- if (!mIPackageManager.isPackageAvailable(profileOwnerPkg, userHandle)) {
- mIPackageManager.installExistingPackageAsUser(profileOwnerPkg, userHandle);
- }
-
- // Start user in background.
- mInjector.getIActivityManager().startUserInBackground(userHandle);
- } catch (RemoteException e) {
- Slog.e(LOG_TAG, "Failed to make remote calls for configureUser", e);
- }
-
- setActiveAdmin(profileOwnerComponent, true, userHandle, adminExtras);
- setProfileOwner(profileOwnerComponent, ownerName, userHandle);
- return user;
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
- }
- }
-
private void sendAdminEnabledBroadcastLocked(int userHandle) {
DevicePolicyData policyData = getUserData(userHandle);
if (policyData.mAdminBroadcastPending) {
@@ -6819,6 +6785,11 @@
if (!mInjector.binderGetCallingUserHandle().isSystem()) {
throw new SecurityException("createAndManageUser was called from non-system user");
}
+ if (!mInjector.userManagerIsSplitSystemUser()
+ && (flags & DevicePolicyManager.MAKE_USER_EPHEMERAL) != 0) {
+ throw new IllegalArgumentException(
+ "Ephemeral users are only supported on systems with a split system user.");
+ }
// Create user.
UserHandle user = null;
synchronized (this) {
@@ -7159,7 +7130,7 @@
intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE,
- parentUserId);
+ parentUserId).getList();
if (VERBOSE_LOG) {
Slog.d(LOG_TAG, "Enabling system activities: " + activitiesToEnable);
@@ -7776,9 +7747,11 @@
if (mUserSetupComplete.equals(uri)) {
updateUserSetupComplete();
} else if (mDeviceProvisioned.equals(uri)) {
- // Set PROPERTY_DEVICE_OWNER_PRESENT, for the SUW case where setting the property
- // is delayed until device is marked as provisioned.
- setDeviceOwnerSystemPropertyLocked();
+ synchronized (DevicePolicyManagerService.this) {
+ // Set PROPERTY_DEVICE_OWNER_PRESENT, for the SUW case where setting the property
+ // is delayed until device is marked as provisioned.
+ setDeviceOwnerSystemPropertyLocked();
+ }
}
}
}
@@ -7841,6 +7814,26 @@
listener.onCrossProfileWidgetProvidersChanged(userId, packages);
}
}
+
+ @Override
+ public boolean hasDeviceOwnerOrProfileOwner(String packageName, int userId) {
+ if (!mHasFeature || packageName == null) {
+ return false;
+ }
+ if (userId < 0) {
+ throw new UnsupportedOperationException("userId should be >= 0");
+ }
+ synchronized (DevicePolicyManagerService.this) {
+ if (packageName.equals(mOwners.getProfileOwnerPackage(userId))) {
+ return true;
+ }
+ if (userId == mOwners.getDeviceOwnerUserId()
+ && packageName.equals(mOwners.getDeviceOwnerPackageName())) {
+ return true;
+ }
+ }
+ return false;
+ }
}
/**
@@ -8067,6 +8060,10 @@
@Override
public boolean isProvisioningAllowed(String action) {
+ if (!mHasFeature) {
+ return false;
+ }
+
final int callingUserId = mInjector.userHandleGetCallingUserId();
if (DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE.equals(action)) {
if (!hasFeatureManagedUsers()) {
@@ -8131,23 +8128,55 @@
throw new IllegalArgumentException("Unknown provisioning action " + action);
}
- private boolean isDeviceOwnerProvisioningAllowed(int callingUserId) {
- synchronized (this) {
- if (mOwners.hasDeviceOwner()) {
- return false;
+ /*
+ * The device owner can only be set before the setup phase of the primary user has completed,
+ * except for adb command if no accounts or additional users are present on the device.
+ */
+ private synchronized @DeviceOwnerPreConditionCode int checkSetDeviceOwnerPreCondition(
+ int deviceOwnerUserId, boolean isAdb) {
+ if (mOwners.hasDeviceOwner()) {
+ return CODE_HAS_DEVICE_OWNER;
+ }
+ if (mOwners.hasProfileOwner(deviceOwnerUserId)) {
+ return CODE_USER_HAS_PROFILE_OWNER;
+ }
+ if (!mUserManager.isUserRunning(new UserHandle(deviceOwnerUserId))) {
+ return CODE_USER_NOT_RUNNING;
+ }
+ if (isAdb) {
+ // if shell command runs after user setup completed check device status. Otherwise, OK.
+ if (hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
+ if (!mInjector.userManagerIsSplitSystemUser()) {
+ if (mUserManager.getUserCount() > 1) {
+ return CODE_NONSYSTEM_USER_EXISTS;
+ }
+ if (AccountManager.get(mContext).getAccounts().length > 0) {
+ return CODE_ACCOUNTS_NOT_EMPTY;
+ }
+ } else {
+ // STOPSHIP Do proper check in split user mode
+ }
}
+ return CODE_OK;
+ } else {
+ if (!mInjector.userManagerIsSplitSystemUser()) {
+ // In non-split user mode, DO has to be user 0
+ if (deviceOwnerUserId != UserHandle.USER_SYSTEM) {
+ return CODE_NOT_SYSTEM_USER;
+ }
+ // In non-split user mode, only provision DO before setup wizard completes
+ if (hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
+ return CODE_USER_SETUP_COMPLETED;
+ }
+ } else {
+ // STOPSHIP Do proper check in split user mode
+ }
+ return CODE_OK;
}
- if (getProfileOwner(callingUserId) != null) {
- return false;
- }
- if (mInjector.settingsGlobalGetInt(Settings.Global.DEVICE_PROVISIONED, 0) != 0) {
- return false;
- }
- if (callingUserId != UserHandle.USER_SYSTEM) {
- // Device owner provisioning can only be initiated from system user.
- return false;
- }
- return true;
+ }
+
+ private boolean isDeviceOwnerProvisioningAllowed(int deviceOwnerUserId) {
+ return CODE_OK == checkSetDeviceOwnerPreCondition(deviceOwnerUserId, /* isAdb */ false);
}
private boolean hasFeatureManagedUsers() {
@@ -8475,7 +8504,7 @@
return false;
}
- private void disableDeviceLoggingIfNotCompliant() {
+ private synchronized void disableDeviceLoggingIfNotCompliant() {
if (!isDeviceOwnerManagedSingleUserDevice()) {
mInjector.securityLogSetLoggingEnabledProperty(false);
Slog.w(LOG_TAG, "Device logging turned off as it's no longer a single user device.");
@@ -8488,6 +8517,9 @@
ensureDeviceOwnerManagingSingleUser(admin);
synchronized (this) {
+ if (enabled == mInjector.securityLogGetLoggingEnabledProperty()) {
+ return;
+ }
mInjector.securityLogSetLoggingEnabledProperty(enabled);
if (enabled) {
mSecurityLogMonitor.start();
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java
index 117ba15..6d42dc9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java
@@ -19,8 +19,12 @@
import android.annotation.IntDef;
import android.app.Notification;
import android.app.PendingIntent;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.os.UserHandle;
+import android.provider.Settings;
import android.text.format.DateUtils;
import com.android.internal.R;
@@ -37,79 +41,62 @@
@Retention(RetentionPolicy.SOURCE)
@IntDef({
- NOTIFICATION_BUGREPORT_STARTED,
- NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED,
- NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED
+ DevicePolicyManager.NOTIFICATION_BUGREPORT_STARTED,
+ DevicePolicyManager.NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED,
+ DevicePolicyManager.NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED
})
@interface RemoteBugreportNotificationType {}
- static final int NOTIFICATION_BUGREPORT_STARTED = 1;
- static final int NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED = 2;
- static final int NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED = 3;
static final long REMOTE_BUGREPORT_TIMEOUT_MILLIS = 10 * DateUtils.MINUTE_IN_MILLIS;
static final String CTL_STOP = "ctl.stop";
static final String REMOTE_BUGREPORT_SERVICE = "bugreportremote";
- static final String ACTION_REMOTE_BUGREPORT_DISPATCH =
- "android.intent.action.REMOTE_BUGREPORT_DISPATCH";
- static final String ACTION_REMOTE_BUGREPORT_SHARING_ACCEPTED =
- "com.android.server.action.REMOTE_BUGREPORT_SHARING_ACCEPTED";
- static final String ACTION_REMOTE_BUGREPORT_SHARING_DECLINED =
- "com.android.server.action.REMOTE_BUGREPORT_SHARING_DECLINED";
- static final String EXTRA_REMOTE_BUGREPORT_HASH = "android.intent.extra.REMOTE_BUGREPORT_HASH";
-
static final String BUGREPORT_MIMETYPE = "application/vnd.android.bugreport";
static Notification buildNotification(Context context,
@RemoteBugreportNotificationType int type) {
+ Intent dialogIntent = new Intent(Settings.ACTION_SHOW_REMOTE_BUGREPORT_DIALOG);
+ dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ dialogIntent.putExtra(DevicePolicyManager.EXTRA_BUGREPORT_NOTIFICATION_TYPE, type);
+ PendingIntent pendingDialogIntent = PendingIntent.getActivityAsUser(context, type,
+ dialogIntent, 0, null, UserHandle.CURRENT);
+
Notification.Builder builder = new Notification.Builder(context)
.setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
.setOngoing(true)
.setLocalOnly(true)
+ .setPriority(Notification.PRIORITY_HIGH)
+ .setContentIntent(pendingDialogIntent)
.setColor(context.getColor(
com.android.internal.R.color.system_notification_accent_color));
- if (type == NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED) {
+ if (type == DevicePolicyManager.NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED) {
builder.setContentTitle(context.getString(
- R.string.sharing_remote_bugreport_notification_title))
- .setContentText(context.getString(
- R.string.sharing_remote_bugreport_notification_message))
- .setPriority(Notification.PRIORITY_HIGH)
- .setProgress(0, 0, true)
- .setStyle(new Notification.BigTextStyle().bigText(context.getString(
- R.string.sharing_remote_bugreport_notification_message)));
- } else {
+ R.string.sharing_remote_bugreport_notification_title))
+ .setProgress(0, 0, true);
+ } else if (type == DevicePolicyManager.NOTIFICATION_BUGREPORT_STARTED) {
+ builder.setContentTitle(context.getString(
+ R.string.taking_remote_bugreport_notification_title))
+ .setProgress(0, 0, true);
+ } else if (type == DevicePolicyManager.NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED) {
PendingIntent pendingIntentAccept = PendingIntent.getBroadcast(context, NOTIFICATION_ID,
- new Intent(ACTION_REMOTE_BUGREPORT_SHARING_ACCEPTED),
+ new Intent(DevicePolicyManager.ACTION_BUGREPORT_SHARING_ACCEPTED),
PendingIntent.FLAG_CANCEL_CURRENT);
PendingIntent pendingIntentDecline = PendingIntent.getBroadcast(context,
- NOTIFICATION_ID, new Intent(ACTION_REMOTE_BUGREPORT_SHARING_DECLINED),
+ NOTIFICATION_ID, new Intent(
+ DevicePolicyManager.ACTION_BUGREPORT_SHARING_DECLINED),
PendingIntent.FLAG_CANCEL_CURRENT);
builder.addAction(new Notification.Action.Builder(null /* icon */, context.getString(
- R.string.share_remote_bugreport_notification_decline),
- pendingIntentDecline).build())
+ R.string.decline_remote_bugreport_action), pendingIntentDecline).build())
.addAction(new Notification.Action.Builder(null /* icon */, context.getString(
- R.string.share_remote_bugreport_notification_accept),
- pendingIntentAccept).build())
+ R.string.share_remote_bugreport_action), pendingIntentAccept).build())
.setContentTitle(context.getString(
- R.string.share_remote_bugreport_notification_title));
-
- if (type == NOTIFICATION_BUGREPORT_STARTED) {
- builder.setContentText(context.getString(
- R.string.share_remote_bugreport_notification_message))
- .setStyle(new Notification.BigTextStyle().bigText(context.getString(
- R.string.share_remote_bugreport_notification_message)))
- .setProgress(0, 0, true)
- .setPriority(Notification.PRIORITY_MAX)
- .setVibrate(new long[0]);
- } else if (type == NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED) {
- builder.setContentText(context.getString(
- R.string.share_finished_remote_bugreport_notification_message))
- .setStyle(new Notification.BigTextStyle().bigText(context.getString(
- R.string.share_finished_remote_bugreport_notification_message)))
- .setPriority(Notification.PRIORITY_HIGH);
- }
+ R.string.share_remote_bugreport_notification_title))
+ .setContentText(context.getString(
+ R.string.share_remote_bugreport_notification_message_finished))
+ .setStyle(new Notification.BigTextStyle().bigText(context.getString(
+ R.string.share_remote_bugreport_notification_message_finished)));
}
return builder.build();
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java b/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
index f2d6180..cacc671 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
@@ -28,6 +28,8 @@
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
import android.os.Process;
@@ -42,6 +44,8 @@
class SecurityLogMonitor implements Runnable {
private final DevicePolicyManagerService mService;
+ private final Lock mLock = new ReentrantLock();
+
SecurityLogMonitor(DevicePolicyManagerService service) {
mService = service;
}
@@ -68,36 +72,50 @@
*/
private static final long POLLING_INTERVAL_MILLISECONDS = TimeUnit.MINUTES.toMillis(1);
- @GuardedBy("this")
+ @GuardedBy("mLock")
private Thread mMonitorThread = null;
- @GuardedBy("this")
+ @GuardedBy("mLock")
private ArrayList<SecurityEvent> mPendingLogs = new ArrayList<SecurityEvent>();
- @GuardedBy("this")
+ @GuardedBy("mLock")
private boolean mAllowedToRetrieve = false;
// When DO will be allowed to retrieves the log, in milliseconds.
- @GuardedBy("this")
+ @GuardedBy("mLock")
private long mNextAllowedRetrivalTimeMillis = -1;
- synchronized void start() {
- if (mMonitorThread == null) {
- mPendingLogs = new ArrayList<SecurityEvent>();
- mAllowedToRetrieve = false;
- mNextAllowedRetrivalTimeMillis = -1;
+ void start() {
+ mLock.lock();
+ try {
+ if (mMonitorThread == null) {
+ mPendingLogs = new ArrayList<SecurityEvent>();
+ mAllowedToRetrieve = false;
+ mNextAllowedRetrivalTimeMillis = -1;
- mMonitorThread = new Thread(this);
- mMonitorThread.start();
+ mMonitorThread = new Thread(this);
+ mMonitorThread.start();
+ }
+ } finally {
+ mLock.unlock();
}
}
- synchronized void stop() {
- if (mMonitorThread != null) {
- mMonitorThread.interrupt();
- try {
- mMonitorThread.join(TimeUnit.SECONDS.toMillis(5));
- } catch (InterruptedException e) {
- Log.e(TAG, "Interrupted while waiting for thread to stop", e);
+ void stop() {
+ mLock.lock();
+ try {
+ if (mMonitorThread != null) {
+ mMonitorThread.interrupt();
+ try {
+ mMonitorThread.join(TimeUnit.SECONDS.toMillis(5));
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Interrupted while waiting for thread to stop", e);
+ }
+ // Reset state and clear buffer
+ mPendingLogs = new ArrayList<SecurityEvent>();
+ mAllowedToRetrieve = false;
+ mNextAllowedRetrivalTimeMillis = -1;
+ mMonitorThread = null;
}
- mMonitorThread = null;
+ } finally {
+ mLock.unlock();
}
}
@@ -105,16 +123,21 @@
* Returns the new batch of logs since the last call to this method. Returns null if
* rate limit is exceeded.
*/
- synchronized List<SecurityEvent> retrieveLogs() {
- if (mAllowedToRetrieve) {
- mAllowedToRetrieve = false;
- mNextAllowedRetrivalTimeMillis = System.currentTimeMillis()
- + RATE_LIMIT_INTERVAL_MILLISECONDS;
- List<SecurityEvent> result = mPendingLogs;
- mPendingLogs = new ArrayList<SecurityEvent>();
- return result;
- } else {
- return null;
+ List<SecurityEvent> retrieveLogs() {
+ mLock.lock();
+ try {
+ if (mAllowedToRetrieve) {
+ mAllowedToRetrieve = false;
+ mNextAllowedRetrivalTimeMillis = System.currentTimeMillis()
+ + RATE_LIMIT_INTERVAL_MILLISECONDS;
+ List<SecurityEvent> result = mPendingLogs;
+ mPendingLogs = new ArrayList<SecurityEvent>();
+ return result;
+ } else {
+ return null;
+ }
+ } finally {
+ mLock.unlock();
}
}
@@ -141,7 +164,8 @@
}
if (!logs.isEmpty()) {
if (DEBUG) Slog.d(TAG, "processing new logs");
- synchronized (this) {
+ mLock.lockInterruptibly();
+ try {
mPendingLogs.addAll(logs);
if (mPendingLogs.size() > BUFFER_ENTRIES_MAXIMUM_LEVEL) {
// Truncate buffer down to half of BUFFER_ENTRIES_MAXIMUM_LEVEL
@@ -149,6 +173,8 @@
mPendingLogs.size() - (BUFFER_ENTRIES_MAXIMUM_LEVEL / 2),
mPendingLogs.size()));
}
+ } finally {
+ mLock.unlock();
}
lastLogTimestampNanos = logs.get(logs.size() - 1).getTimeNanos();
logs.clear();
@@ -163,18 +189,13 @@
}
}
if (DEBUG) Slog.d(TAG, "MonitorThread exit.");
- synchronized (this) {
- // Reset state and clear buffer
- mPendingLogs = new ArrayList<SecurityEvent>();
- mAllowedToRetrieve = false;
- mNextAllowedRetrivalTimeMillis = -1;
- }
}
- private void notifyDeviceOwnerIfNeeded() {
+ private void notifyDeviceOwnerIfNeeded() throws InterruptedException {
boolean shouldNotifyDO = false;
boolean allowToRetrieveNow = false;
- synchronized (this) {
+ mLock.lockInterruptibly();
+ try {
int logSize = mPendingLogs.size();
if (logSize >= BUFFER_ENTRIES_NOTIFICATION_LEVEL) {
// Allow DO to retrieve logs if too many pending logs
@@ -188,6 +209,8 @@
}
shouldNotifyDO = (!mAllowedToRetrieve) && allowToRetrieveNow;
mAllowedToRetrieve = allowToRetrieveNow;
+ } finally {
+ mLock.unlock();
}
if (shouldNotifyDO) {
if (DEBUG) Slog.d(TAG, "notify DO");
@@ -195,4 +218,4 @@
null);
}
}
-}
\ No newline at end of file
+}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index ac972a9..b8c31e3 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -59,6 +59,7 @@
import com.android.server.audio.AudioService;
import com.android.server.camera.CameraService;
import com.android.server.clipboard.ClipboardService;
+import com.android.server.connectivity.MetricsLoggerService;
import com.android.server.content.ContentService;
import com.android.server.devicepolicy.DevicePolicyManagerService;
import com.android.server.display.DisplayManagerService;
@@ -341,8 +342,8 @@
// always make sure uncrypt gets executed properly when needed.
// If '/cache/recovery/block.map' hasn't been created, stop the
// reboot which will fail for sure, and get a chance to capture a
- // bugreport when that's still feasible. (Bug; 26444951)
- if (PowerManager.REBOOT_RECOVERY.equals(reason)) {
+ // bugreport when that's still feasible. (Bug: 26444951)
+ if (PowerManager.REBOOT_RECOVERY_UPDATE.equals(reason)) {
File packageFile = new File(UNCRYPT_PACKAGE_FILE);
if (packageFile.exists()) {
String filename = null;
@@ -430,6 +431,24 @@
mPackageManager = mSystemContext.getPackageManager();
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+ // Manages A/B OTA dexopting. This is a bootstrap service as we need it to rename
+ // A/B artifacts after boot, before anything else might touch/need them.
+ // Note: this isn't needed during decryption (we don't have /data anyways).
+ if (!mOnlyCore) {
+ boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
+ false);
+ if (!disableOtaDexopt) {
+ traceBeginAndSlog("StartOtaDexOptService");
+ try {
+ OtaDexoptService.main(mSystemContext, mPackageManagerService);
+ } catch (Throwable e) {
+ reportWtf("starting OtaDexOptService", e);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+ }
+ }
+ }
+
traceBeginAndSlog("StartUserManagerService");
ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance());
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
@@ -488,6 +507,7 @@
MmsServiceBroker mmsService = null;
EntropyMixer entropyMixer = null;
VrManagerService vrManagerService = null;
+ HardwarePropertiesManagerService hardwarePropertiesService = null;
boolean disableStorage = SystemProperties.getBoolean("config.disable_storage", false);
boolean disableBluetooth = SystemProperties.getBoolean("config.disable_bluetooth", false);
@@ -601,6 +621,10 @@
} else {
mSystemServiceManager.startService(BluetoothService.class);
}
+
+ traceBeginAndSlog("ConnectivityMetricsLoggerService");
+ mSystemServiceManager.startService(MetricsLoggerService.class);
+ Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
} catch (RuntimeException e) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting core service", e);
@@ -832,6 +856,10 @@
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
+ if (!disableNonCoreServices) {
+ mSystemServiceManager.startService(RecoverySystemService.class);
+ }
+
/*
* MountService has a few dependencies: Notification Manager and
* AppWidget Provider. Make sure MountService is completely started
@@ -962,6 +990,17 @@
Slog.e(TAG, "Failure starting SerialService", e);
}
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+
+ Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER,
+ "StartHardwarePropertiesManagerService");
+ try {
+ hardwarePropertiesService = new HardwarePropertiesManagerService(context);
+ ServiceManager.addService(Context.HARDWARE_PROPERTIES_SERVICE,
+ hardwarePropertiesService);
+ } catch (Throwable e) {
+ Slog.e(TAG, "Failure starting HardwarePropertiesManagerService", e);
+ }
+ Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
mSystemServiceManager.startService(TwilightService.class);
@@ -1015,6 +1054,7 @@
traceBeginAndSlog("StartNetworkTimeUpdateService");
try {
networkTimeUpdater = new NetworkTimeUpdateService(context);
+ ServiceManager.addService("network_time_update_service", networkTimeUpdater);
} catch (Throwable e) {
reportWtf("starting NetworkTimeUpdate service", e);
}
@@ -1102,19 +1142,6 @@
reportWtf("starting BackgroundDexOptService", e);
}
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
-
- // Manages A/B OTA dexopting.
- boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
- false);
- if (!disableOtaDexopt) {
- traceBeginAndSlog("StartOtaDexOptService");
- try {
- OtaDexoptService.main(mSystemContext, mPackageManagerService);
- } catch (Throwable e) {
- reportWtf("starting BackgroundDexOptService", e);
- }
- Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
- }
}
mSystemServiceManager.startService(LauncherAppsService.class);
@@ -1258,10 +1285,12 @@
}
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
- Slog.i(TAG, "WebViewFactory preparation");
- Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "WebViewFactoryPreparation");
- mWebViewUpdateService.prepareWebViewInSystemServer();
- Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+ if (!mOnlyCore) {
+ Slog.i(TAG, "WebViewFactory preparation");
+ Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "WebViewFactoryPreparation");
+ mWebViewUpdateService.prepareWebViewInSystemServer();
+ Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+ }
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartSystemUI");
try {
diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java
index 5229b40..e2562cd 100644
--- a/services/net/java/android/net/dhcp/DhcpClient.java
+++ b/services/net/java/android/net/dhcp/DhcpClient.java
@@ -19,6 +19,7 @@
import com.android.internal.util.HexDump;
import com.android.internal.util.Protocol;
import com.android.internal.util.State;
+import com.android.internal.util.MessageUtils;
import com.android.internal.util.StateMachine;
import com.android.internal.util.WakeupMessage;
@@ -32,7 +33,6 @@
import android.os.IBinder;
import android.os.INetworkManagementService;
import android.os.Message;
-import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -40,16 +40,15 @@
import android.system.Os;
import android.system.PacketSocketAddress;
import android.util.Log;
+import android.util.SparseArray;
import android.util.TimeUtils;
import java.io.FileDescriptor;
import java.io.IOException;
import java.lang.Thread;
import java.net.Inet4Address;
-import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
-import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Random;
@@ -85,10 +84,10 @@
public class DhcpClient extends StateMachine {
private static final String TAG = "DhcpClient";
- private static final boolean DBG = true;
+ private static final boolean DBG = false;
private static final boolean STATE_DBG = false;
private static final boolean MSG_DBG = false;
- private static final boolean PACKET_DBG = true;
+ private static final boolean PACKET_DBG = false;
// Timers and timeouts.
private static final int SECONDS = 1000;
@@ -131,6 +130,11 @@
private static final int CMD_TIMEOUT = PRIVATE_BASE + 3;
private static final int CMD_ONESHOT_TIMEOUT = PRIVATE_BASE + 4;
+ // For message logging.
+ private static final Class[] sMessageClasses = { DhcpClient.class };
+ private static final SparseArray<String> sMessageNames =
+ MessageUtils.findMessageNames(sMessageClasses);
+
// DHCP parameters that we request.
private static final byte[] REQUESTED_PARAMS = new byte[] {
DHCP_SUBNET_MASK,
@@ -338,14 +342,14 @@
@Override
public void run() {
- maybeLog("Receive thread started");
+ if (DBG) Log.d(TAG, "Receive thread started");
while (!stopped) {
int length = 0; // Or compiler can't tell it's initialized if a parse error occurs.
try {
length = Os.read(mPacketSock, mPacket, 0, mPacket.length);
DhcpPacket packet = null;
packet = DhcpPacket.decodeFullPacket(mPacket, length, DhcpPacket.ENCAP_L2);
- maybeLog("Received packet: " + packet);
+ if (DBG) Log.d(TAG, "Received packet: " + packet);
sendMessage(CMD_RECEIVED_PACKET, packet);
} catch (IOException|ErrnoException e) {
if (!stopped) {
@@ -358,7 +362,7 @@
}
}
}
- maybeLog("Receive thread stopped");
+ if (DBG) Log.d(TAG, "Receive thread stopped");
}
}
@@ -369,12 +373,12 @@
private boolean transmitPacket(ByteBuffer buf, String description, Inet4Address to) {
try {
if (to.equals(INADDR_BROADCAST)) {
- maybeLog("Broadcasting " + description);
+ if (DBG) Log.d(TAG, "Broadcasting " + description);
Os.sendto(mPacketSock, buf.array(), 0, buf.limit(), 0, mInterfaceBroadcastAddr);
} else {
// It's safe to call getpeername here, because we only send unicast packets if we
// have an IP address, and we connect the UDP socket in DhcpHaveAddressState#enter.
- maybeLog("Unicasting " + description + " to " + Os.getpeername(mUdpSock));
+ if (DBG) Log.d(TAG, "Unicasting " + description + " to " + Os.getpeername(mUdpSock));
Os.write(mUdpSock, buf);
}
} catch(ErrnoException|IOException e) {
@@ -450,40 +454,13 @@
mController.sendMessage(CMD_ON_QUIT);
}
- private void maybeLog(String msg) {
- if (DBG) Log.d(TAG, msg);
- }
-
abstract class LoggingState extends State {
public void enter() {
if (STATE_DBG) Log.d(TAG, "Entering state " + getName());
}
private String messageName(int what) {
- switch (what) {
- case CMD_START_DHCP:
- return "CMD_START_DHCP";
- case CMD_STOP_DHCP:
- return "CMD_STOP_DHCP";
- case CMD_RENEW_DHCP:
- return "CMD_RENEW_DHCP";
- case CMD_PRE_DHCP_ACTION:
- return "CMD_PRE_DHCP_ACTION";
- case CMD_PRE_DHCP_ACTION_COMPLETE:
- return "CMD_PRE_DHCP_ACTION_COMPLETE";
- case CMD_POST_DHCP_ACTION:
- return "CMD_POST_DHCP_ACTION";
- case CMD_KICK:
- return "CMD_KICK";
- case CMD_RECEIVED_PACKET:
- return "CMD_RECEIVED_PACKET";
- case CMD_TIMEOUT:
- return "CMD_TIMEOUT";
- case CMD_ONESHOT_TIMEOUT:
- return "CMD_ONESHOT_TIMEOUT";
- default:
- return Integer.toString(what);
- }
+ return sMessageNames.get(what, Integer.toString(what));
}
private String messageToString(Message message) {
@@ -611,7 +588,7 @@
transitionTo(mStoppedState);
return HANDLED;
case CMD_ONESHOT_TIMEOUT:
- maybeLog("Timed out");
+ if (DBG) Log.d(TAG, "Timed out");
notifyFailure();
return HANDLED;
default:
@@ -809,7 +786,7 @@
@Override
public void exit() {
- maybeLog("Clearing IP address");
+ if (DBG) Log.d(TAG, "Clearing IP address");
setIpAddress(new LinkAddress("0.0.0.0/0"));
}
}
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index d0d87b1..c7c5015 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -16,12 +16,15 @@
package android.net.ip;
+import com.android.internal.util.MessageUtils;
+
import android.content.Context;
import android.net.DhcpResults;
import android.net.InterfaceConfiguration;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.LinkProperties.ProvisioningChange;
+import android.net.ProxyInfo;
import android.net.RouteInfo;
import android.net.StaticIpConfiguration;
import android.net.dhcp.DhcpClient;
@@ -29,7 +32,9 @@
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.text.TextUtils;
import android.util.Log;
+import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -58,9 +63,14 @@
* @hide
*/
public class IpManager extends StateMachine {
- private static final boolean DBG = true;
+ private static final boolean DBG = false;
private static final boolean VDBG = false;
+ // For message logging.
+ private static final Class[] sMessageClasses = { IpManager.class, DhcpClient.class };
+ private static final SparseArray<String> sWhatToString =
+ MessageUtils.findMessageNames(sMessageClasses);
+
/**
* Callbacks for handling IpManager events.
*/
@@ -85,6 +95,10 @@
public void onProvisioningSuccess(LinkProperties newLp) {}
public void onProvisioningFailure(LinkProperties newLp) {}
+ // This is called whenever 464xlat is being enabled or disabled (i.e.
+ // started or stopped).
+ public void on464XlatChange(boolean enabled) {}
+
// Invoked on LinkProperties changes.
public void onLinkPropertiesChange(LinkProperties newLp) {}
@@ -96,6 +110,35 @@
public void onQuit() {}
}
+ public static class WaitForProvisioningCallback extends Callback {
+ private LinkProperties mCallbackLinkProperties;
+
+ public LinkProperties waitForProvisioning() {
+ synchronized (this) {
+ try {
+ wait();
+ } catch (InterruptedException e) {}
+ return mCallbackLinkProperties;
+ }
+ }
+
+ @Override
+ public void onProvisioningSuccess(LinkProperties newLp) {
+ synchronized (this) {
+ mCallbackLinkProperties = newLp;
+ notify();
+ }
+ }
+
+ @Override
+ public void onProvisioningFailure(LinkProperties newLp) {
+ synchronized (this) {
+ mCallbackLinkProperties = null;
+ notify();
+ }
+ }
+ }
+
/**
* This class encapsulates parameters to be passed to
* IpManager#startProvisioning(). A defensive copy is made by IpManager
@@ -160,9 +203,18 @@
private static final int EVENT_PRE_DHCP_ACTION_COMPLETE = 4;
// Sent by NetlinkTracker to communicate netlink events.
private static final int EVENT_NETLINK_LINKPROPERTIES_CHANGED = 5;
+ private static final int CMD_UPDATE_TCP_BUFFER_SIZES = 6;
+ private static final int CMD_UPDATE_HTTP_PROXY = 7;
private static final int MAX_LOG_RECORDS = 1000;
+ private static final boolean NO_CALLBACKS = false;
+ private static final boolean SEND_CALLBACKS = true;
+
+ // This must match the interface prefix in clatd.c.
+ // TODO: Revert this hack once IpManager and Nat464Xlat work in concert.
+ private static final String CLAT_PREFIX = "v4-";
+
private final Object mLock = new Object();
private final State mStoppedState = new StoppedState();
private final State mStoppingState = new StoppingState();
@@ -171,6 +223,7 @@
private final String mTag;
private final Context mContext;
private final String mInterfaceName;
+ private final String mClatInterfaceName;
@VisibleForTesting
protected final Callback mCallback;
private final INetworkManagementService mNwService;
@@ -181,10 +234,12 @@
/**
* Non-final member variables accessed only from within our StateMachine.
*/
+ private ProvisioningConfiguration mConfiguration;
private IpReachabilityMonitor mIpReachabilityMonitor;
private DhcpClient mDhcpClient;
private DhcpResults mDhcpResults;
- private ProvisioningConfiguration mConfiguration;
+ private String mTcpBufferSizes;
+ private ProxyInfo mHttpProxy;
/**
* Member variables accessed both from within the StateMachine thread
@@ -195,15 +250,23 @@
public IpManager(Context context, String ifName, Callback callback)
throws IllegalArgumentException {
+ this(context, ifName, callback, INetworkManagementService.Stub.asInterface(
+ ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)));
+ }
+
+ /**
+ * An expanded constructor, useful for dependency injection.
+ */
+ public IpManager(Context context, String ifName, Callback callback,
+ INetworkManagementService nwService) throws IllegalArgumentException {
super(IpManager.class.getSimpleName() + "." + ifName);
mTag = getName();
mContext = context;
mInterfaceName = ifName;
+ mClatInterfaceName = CLAT_PREFIX + ifName;
mCallback = callback;
-
- mNwService = INetworkManagementService.Stub.asInterface(
- ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
+ mNwService = nwService;
mNetlinkTracker = new NetlinkTracker(
mInterfaceName,
@@ -212,7 +275,22 @@
public void update() {
sendMessage(EVENT_NETLINK_LINKPROPERTIES_CHANGED);
}
- });
+ }) {
+ @Override
+ public void interfaceAdded(String iface) {
+ if (mClatInterfaceName.equals(iface)) {
+ mCallback.on464XlatChange(true);
+ }
+ }
+
+ @Override
+ public void interfaceRemoved(String iface) {
+ if (mClatInterfaceName.equals(iface)) {
+ mCallback.on464XlatChange(false);
+ }
+ }
+ };
+
try {
mNwService.registerObserver(mNetlinkTracker);
} catch (RemoteException e) {
@@ -231,25 +309,6 @@
super.start();
}
- /**
- * A special constructor for use in testing that bypasses some of the more
- * complicated setup bits.
- *
- * TODO: Figure out how to delete this yet preserve testability.
- */
- @VisibleForTesting
- protected IpManager(String ifName, Callback callback) {
- super(IpManager.class.getSimpleName() + ".test-" + ifName);
- mTag = getName();
-
- mInterfaceName = ifName;
- mCallback = callback;
-
- mContext = null;
- mNwService = null;
- mNetlinkTracker = null;
- }
-
@Override
protected void onQuitting() {
mCallback.onQuit();
@@ -293,6 +352,26 @@
sendMessage(EVENT_PRE_DHCP_ACTION_COMPLETE);
}
+ /**
+ * Set the TCP buffer sizes to use.
+ *
+ * This may be called, repeatedly, at any time before or after a call to
+ * #startProvisioning(). The setting is cleared upon calling #stop().
+ */
+ public void setTcpBufferSizes(String tcpBufferSizes) {
+ sendMessage(CMD_UPDATE_TCP_BUFFER_SIZES, tcpBufferSizes);
+ }
+
+ /**
+ * Set the HTTP Proxy configuration to use.
+ *
+ * This may be called, repeatedly, at any time before or after a call to
+ * #startProvisioning(). The setting is cleared upon calling #stop().
+ */
+ public void setHttpProxy(ProxyInfo proxyInfo) {
+ sendMessage(CMD_UPDATE_HTTP_PROXY, proxyInfo);
+ }
+
public LinkProperties getLinkProperties() {
synchronized (mLock) {
return new LinkProperties(mLinkProperties);
@@ -306,26 +385,7 @@
@Override
protected String getWhatToString(int what) {
- // TODO: Investigate switching to reflection.
- switch (what) {
- case CMD_STOP:
- return "CMD_STOP";
- case CMD_START:
- return "CMD_START";
- case CMD_CONFIRM:
- return "CMD_CONFIRM";
- case EVENT_PRE_DHCP_ACTION_COMPLETE:
- return "EVENT_PRE_DHCP_ACTION_COMPLETE";
- case EVENT_NETLINK_LINKPROPERTIES_CHANGED:
- return "EVENT_NETLINK_LINKPROPERTIES_CHANGED";
- case DhcpClient.CMD_PRE_DHCP_ACTION:
- return "DhcpClient.CMD_PRE_DHCP_ACTION";
- case DhcpClient.CMD_POST_DHCP_ACTION:
- return "DhcpClient.CMD_POST_DHCP_ACTION";
- case DhcpClient.CMD_ON_QUIT:
- return "DhcpClient.CMD_ON_QUIT";
- }
- return "UNKNOWN:" + Integer.toString(what);
+ return sWhatToString.get(what, "UNKNOWN: " + Integer.toString(what));
}
@Override
@@ -355,8 +415,10 @@
// assigned to the interface, etc.
private void resetLinkProperties() {
mNetlinkTracker.clearLinkProperties();
- mDhcpResults = null;
mConfiguration = null;
+ mDhcpResults = null;
+ mTcpBufferSizes = "";
+ mHttpProxy = null;
synchronized (mLock) {
mLinkProperties = new LinkProperties();
@@ -513,13 +575,33 @@
newLp.setDomains(mDhcpResults.domains);
}
+ // [4] Add in TCP buffer sizes and HTTP Proxy config, if available.
+ if (!TextUtils.isEmpty(mTcpBufferSizes)) {
+ newLp.setTcpBufferSizes(mTcpBufferSizes);
+ }
+ if (mHttpProxy != null) {
+ newLp.setHttpProxy(mHttpProxy);
+ }
+
if (VDBG) {
Log.d(mTag, "newLp{" + newLp + "}");
}
-
return newLp;
}
+ // Returns false if we have lost provisioning, true otherwise.
+ private boolean handleLinkPropertiesUpdate(boolean sendCallbacks) {
+ final LinkProperties newLp = assembleLinkProperties();
+ if (linkPropertiesUnchanged(newLp)) {
+ return true;
+ }
+ final ProvisioningChange delta = setLinkProperties(newLp);
+ if (sendCallbacks) {
+ dispatchCallback(delta, newLp);
+ }
+ return (delta != ProvisioningChange.LOST_PROVISIONING);
+ }
+
private void clearIPv4Address() {
try {
final InterfaceConfiguration ifcg = new InterfaceConfiguration();
@@ -598,7 +680,17 @@
break;
case EVENT_NETLINK_LINKPROPERTIES_CHANGED:
- setLinkProperties(assembleLinkProperties());
+ handleLinkPropertiesUpdate(NO_CALLBACKS);
+ break;
+
+ case CMD_UPDATE_TCP_BUFFER_SIZES:
+ mTcpBufferSizes = (String) msg.obj;
+ handleLinkPropertiesUpdate(NO_CALLBACKS);
+ break;
+
+ case CMD_UPDATE_HTTP_PROXY:
+ mHttpProxy = (ProxyInfo) msg.obj;
+ handleLinkPropertiesUpdate(NO_CALLBACKS);
break;
case DhcpClient.CMD_ON_QUIT:
@@ -729,18 +821,23 @@
}
break;
- case EVENT_NETLINK_LINKPROPERTIES_CHANGED: {
- final LinkProperties newLp = assembleLinkProperties();
- if (linkPropertiesUnchanged(newLp)) {
- break;
- }
- final ProvisioningChange delta = setLinkProperties(newLp);
- dispatchCallback(delta, newLp);
- if (delta == ProvisioningChange.LOST_PROVISIONING) {
+ case EVENT_NETLINK_LINKPROPERTIES_CHANGED:
+ if (!handleLinkPropertiesUpdate(SEND_CALLBACKS)) {
transitionTo(mStoppedState);
}
break;
- }
+
+ case CMD_UPDATE_TCP_BUFFER_SIZES:
+ mTcpBufferSizes = (String) msg.obj;
+ // This cannot possibly change provisioning state.
+ handleLinkPropertiesUpdate(SEND_CALLBACKS);
+ break;
+
+ case CMD_UPDATE_HTTP_PROXY:
+ mHttpProxy = (ProxyInfo) msg.obj;
+ // This cannot possibly change provisioning state.
+ handleLinkPropertiesUpdate(SEND_CALLBACKS);
+ break;
case DhcpClient.CMD_PRE_DHCP_ACTION:
if (VDBG) { Log.d(mTag, "onPreDhcpAction()"); }
diff --git a/services/net/java/android/net/ip/IpReachabilityMonitor.java b/services/net/java/android/net/ip/IpReachabilityMonitor.java
index 88155f7..5b4fd50 100644
--- a/services/net/java/android/net/ip/IpReachabilityMonitor.java
+++ b/services/net/java/android/net/ip/IpReachabilityMonitor.java
@@ -132,7 +132,7 @@
*/
public class IpReachabilityMonitor {
private static final String TAG = "IpReachabilityMonitor";
- private static final boolean DBG = true;
+ private static final boolean DBG = false;
private static final boolean VDBG = false;
public interface Callback {
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 5874429..69f12eb 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -59,14 +59,17 @@
import android.os.MessageQueue;
import android.os.Messenger;
import android.os.MessageQueue.IdleHandler;
+import android.os.SystemClock;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
import android.util.LogPrinter;
+import com.android.internal.util.WakeupMessage;
import com.android.server.connectivity.NetworkAgentInfo;
import com.android.server.connectivity.NetworkMonitor;
+import com.android.server.net.NetworkPinner;
import java.net.InetAddress;
import java.util.concurrent.CountDownLatch;
@@ -87,10 +90,30 @@
private BroadcastInterceptingContext mServiceContext;
private WrappedConnectivityService mService;
- private ConnectivityManager mCm;
+ private WrappedConnectivityManager mCm;
private MockNetworkAgent mWiFiNetworkAgent;
private MockNetworkAgent mCellNetworkAgent;
+ // 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.
+ private class WrappedConnectivityManager extends ConnectivityManager {
+ private Network mFakeBoundNetwork;
+
+ public synchronized boolean bindProcessToNetwork(Network network) {
+ mFakeBoundNetwork = network;
+ return true;
+ }
+
+ public synchronized Network getBoundNetworkForProcess() {
+ return mFakeBoundNetwork;
+ }
+
+ public WrappedConnectivityManager(Context context, ConnectivityService service) {
+ super(context, service);
+ }
+ }
+
private class MockContext extends BroadcastInterceptingContext {
MockContext(Context base) {
super(base);
@@ -484,6 +507,35 @@
}
}
+ private class FakeWakeupMessage extends WakeupMessage {
+ private static final int UNREASONABLY_LONG_WAIT = 1000;
+
+ public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
+ super(context, handler, cmdName, cmd);
+ }
+
+ @Override
+ public void schedule(long when) {
+ long delayMs = when - SystemClock.elapsedRealtime();
+ if (delayMs < 0) delayMs = 0;
+ if (delayMs > UNREASONABLY_LONG_WAIT) {
+ fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
+ "ms into the future: " + delayMs);
+ }
+ mHandler.sendEmptyMessageDelayed(mCmd, delayMs);
+ }
+
+ @Override
+ public void cancel() {
+ mHandler.removeMessages(mCmd);
+ }
+
+ @Override
+ public void onAlarm() {
+ throw new AssertionError("Should never happen. Update this fake.");
+ }
+ }
+
// NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
private class WrappedNetworkMonitor extends NetworkMonitor {
// HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
@@ -498,6 +550,12 @@
protected int isCaptivePortal() {
return gen204ProbeResult;
}
+
+ @Override
+ protected WakeupMessage makeWakeupMessage(
+ Context context, Handler handler, String cmdName, int cmd) {
+ return new FakeWakeupMessage(context, handler, cmdName, cmd);
+ }
}
private class WrappedConnectivityService extends ConnectivityService {
@@ -575,10 +633,10 @@
int delays = 0;
while (!criteria.get()) {
try {
- Thread.sleep(100);
+ Thread.sleep(50);
} catch (InterruptedException e) {
}
- if (++delays == 5) fail();
+ if (++delays == 10) fail();
}
}
@@ -594,6 +652,8 @@
public void setUp() throws Exception {
super.setUp();
+ NetworkMonitor.SetDefaultLingerTime(120);
+
// InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
// http://b/25897652 .
if (Looper.myLooper() == null) {
@@ -607,7 +667,8 @@
mock(INetworkPolicyManager.class));
mService.systemReady();
- mCm = new ConnectivityManager(getContext(), mService);
+ mCm = new WrappedConnectivityManager(getContext(), mService);
+ mCm.bindProcessToNetwork(null);
}
private int transportToLegacyType(int transport) {
@@ -674,8 +735,6 @@
@LargeTest
public void testLingering() throws Exception {
- // Decrease linger timeout to the minimum allowed by AlarmManagerService.
- NetworkMonitor.SetDefaultLingerTime(5000);
verifyNoNetwork();
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
@@ -702,10 +761,8 @@
assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
// Test cellular linger timeout.
- try {
- Thread.sleep(6000);
- } catch (InterruptedException e) {
- }
+ waitFor(new Criteria() {
+ public boolean get() { return mCm.getAllNetworks().length == 1; } });
verifyActiveNetwork(TRANSPORT_WIFI);
assertEquals(1, mCm.getAllNetworks().length);
assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
@@ -1543,4 +1600,103 @@
String url = mCm.getCaptivePortalServerUrl();
assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
}
+
+ private static class TestNetworkPinner extends NetworkPinner {
+ public static boolean awaitPin(int timeoutMs) {
+ synchronized(sLock) {
+ if (sNetwork == null) {
+ try {
+ sLock.wait(timeoutMs);
+ } catch (InterruptedException e) {}
+ }
+ return sNetwork != null;
+ }
+ }
+
+ public static boolean awaitUnpin(int timeoutMs) {
+ synchronized(sLock) {
+ if (sNetwork != null) {
+ try {
+ sLock.wait(timeoutMs);
+ } catch (InterruptedException e) {}
+ }
+ return sNetwork == null;
+ }
+ }
+ }
+
+ private void assertPinnedToWifiWithCellDefault() {
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
+ assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ }
+
+ private void assertPinnedToWifiWithWifiDefault() {
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ }
+
+ private void assertNotPinnedToWifi() {
+ assertNull(mCm.getBoundNetworkForProcess());
+ assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ }
+
+ @SmallTest
+ public void testNetworkPinner() {
+ NetworkRequest wifiRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_WIFI)
+ .build();
+ assertNull(mCm.getBoundNetworkForProcess());
+
+ TestNetworkPinner.pin(mServiceContext, wifiRequest);
+ assertNull(mCm.getBoundNetworkForProcess());
+
+ mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent.connect(true);
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(false);
+
+ // When wi-fi connects, expect to be pinned.
+ assertTrue(TestNetworkPinner.awaitPin(100));
+ assertPinnedToWifiWithCellDefault();
+
+ // Disconnect and expect the pin to drop.
+ mWiFiNetworkAgent.disconnect();
+ assertTrue(TestNetworkPinner.awaitUnpin(100));
+ assertNotPinnedToWifi();
+
+ // Reconnecting does not cause the pin to come back.
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(false);
+ assertFalse(TestNetworkPinner.awaitPin(100));
+ assertNotPinnedToWifi();
+
+ // Pinning while connected causes the pin to take effect immediately.
+ TestNetworkPinner.pin(mServiceContext, wifiRequest);
+ assertTrue(TestNetworkPinner.awaitPin(100));
+ assertPinnedToWifiWithCellDefault();
+
+ // Explicitly unpin and expect to use the default network again.
+ TestNetworkPinner.unpin();
+ assertNotPinnedToWifi();
+
+ // Disconnect cell and wifi.
+ ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down.
+ mCellNetworkAgent.disconnect();
+ mWiFiNetworkAgent.disconnect();
+ waitFor(cv);
+
+ // Pinning takes effect even if the pinned network is the default when the pin is set...
+ TestNetworkPinner.pin(mServiceContext, wifiRequest);
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(false);
+ assertTrue(TestNetworkPinner.awaitPin(100));
+ assertPinnedToWifiWithWifiDefault();
+
+ // ... and is maintained even when that network is no longer the default.
+ cv = waitForConnectivityBroadcasts(1);
+ mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mCellNetworkAgent.connect(true);
+ waitFor(cv);
+ assertPinnedToWifiWithCellDefault();
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 6d168b0..8c47087 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -32,6 +32,7 @@
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.Settings;
import android.test.MoreAsserts;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArraySet;
@@ -60,6 +61,7 @@
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.validateMockitoUsage;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -208,7 +210,7 @@
/**
* Test for:
* {@link DevicePolicyManager#setActiveAdmin}
- * with replace=false and replace=true
+ * with replace=false and replace=true
* {@link DevicePolicyManager#isAdminActive}
* {@link DevicePolicyManager#isAdminActiveAsUser}
* {@link DevicePolicyManager#getActiveAdmins}
@@ -336,7 +338,7 @@
/**
* Test for:
* {@link DevicePolicyManager#setActiveAdmin}
- * with replace=false
+ * with replace=false
*/
public void testSetActiveAdmin_twiceWithoutReplace() throws Exception {
// 1. Make sure the caller has proper permissions.
@@ -967,6 +969,8 @@
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+ when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(true);
+
// Make sure the admin packge is installed to each user.
setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
setUpPackageManagerForAdmin(admin3, DpmMockContext.CALLER_SYSTEM_USER_UID);
@@ -999,12 +1003,14 @@
/**
* This essentially tests
- * {@code DevicePolicyManagerService.findOwnerComponentIfNecessaryLocked()}. (which is private.)
+ * {@code DevicePolicyManagerService.findOwnerComponentIfNecessaryLocked()}. (which is
+ * private.)
*
* We didn't use to persist the DO component class name, but now we do, and the above method
* finds the right component from a package name upon migration.
*/
public void testDeviceOwnerMigration() throws Exception {
+ when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(true);
checkDeviceOwnerWithMultipleDeviceAdmins();
// Overwrite the device owner setting and clears the clas name.
@@ -1196,7 +1202,7 @@
eq(UserHandle.USER_SYSTEM),
MockUtils.checkUserRestrictions(),
MockUtils.checkUserRestrictions(UserManager.DISALLOW_ADD_USER)
- );
+ );
reset(mContext.userManagerInternal);
dpm.addUserRestriction(admin1, UserManager.DISALLOW_OUTGOING_CALLS);
@@ -1833,4 +1839,76 @@
mContext.callerPermissions.removeAll(OWNER_SETUP_PERMISSIONS);
}
+
+ public void testSetMaximumTimeToLock() {
+ mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
+
+ dpm.setActiveAdmin(admin1, /* replace =*/ false);
+ dpm.setActiveAdmin(admin2, /* replace =*/ false);
+
+ reset(mMockContext.powerManagerInternal);
+ reset(mMockContext.settings);
+
+ dpm.setMaximumTimeToLock(admin1, 0);
+ verifyScreenTimeoutCall(null, false);
+ reset(mMockContext.powerManagerInternal);
+ reset(mMockContext.settings);
+
+ dpm.setMaximumTimeToLock(admin1, 1);
+ verifyScreenTimeoutCall(1, true);
+ reset(mMockContext.powerManagerInternal);
+ reset(mMockContext.settings);
+
+ dpm.setMaximumTimeToLock(admin2, 10);
+ verifyScreenTimeoutCall(null, false);
+ reset(mMockContext.powerManagerInternal);
+ reset(mMockContext.settings);
+
+ dpm.setMaximumTimeToLock(admin1, 5);
+ verifyScreenTimeoutCall(5, true);
+ reset(mMockContext.powerManagerInternal);
+ reset(mMockContext.settings);
+
+ dpm.setMaximumTimeToLock(admin2, 4);
+ verifyScreenTimeoutCall(4, true);
+ reset(mMockContext.powerManagerInternal);
+ reset(mMockContext.settings);
+
+ dpm.setMaximumTimeToLock(admin1, 0);
+ reset(mMockContext.powerManagerInternal);
+ reset(mMockContext.settings);
+
+ dpm.setMaximumTimeToLock(admin2, Integer.MAX_VALUE);
+ verifyScreenTimeoutCall(Integer.MAX_VALUE, true);
+ reset(mMockContext.powerManagerInternal);
+ reset(mMockContext.settings);
+
+ dpm.setMaximumTimeToLock(admin2, Integer.MAX_VALUE + 1);
+ verifyScreenTimeoutCall(Integer.MAX_VALUE, true);
+ reset(mMockContext.powerManagerInternal);
+ reset(mMockContext.settings);
+
+ dpm.setMaximumTimeToLock(admin2, 10);
+ verifyScreenTimeoutCall(10, true);
+ reset(mMockContext.powerManagerInternal);
+ reset(mMockContext.settings);
+
+ // There's no restriction; shold be set to MAX.
+ dpm.setMaximumTimeToLock(admin2, 0);
+ verifyScreenTimeoutCall(Integer.MAX_VALUE, false);
+ }
+
+ private void verifyScreenTimeoutCall(Integer expectedTimeout,
+ boolean shouldStayOnWhilePluggedInBeCleared) {
+ if (expectedTimeout == null) {
+ verify(mMockContext.powerManagerInternal, times(0))
+ .setMaximumScreenOffTimeoutFromDeviceAdmin(anyInt());
+ } else {
+ verify(mMockContext.powerManagerInternal, times(1))
+ .setMaximumScreenOffTimeoutFromDeviceAdmin(eq(expectedTimeout));
+ }
+ // TODO Verify calls to settingsGlobalPutInt. Tried but somehow mockito threw
+ // UnfinishedVerificationException.
+ }
}
+
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index 7a00098..ef8e420 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -44,11 +44,14 @@
import android.view.IWindowManager;
import org.junit.Assert;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
+import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
@@ -294,6 +297,50 @@
mUserInfos.add(uh);
when(userManager.getUsers()).thenReturn(mUserInfos);
+ when(userManager.getUserInfo(anyInt())).thenAnswer(
+ new Answer<UserInfo>() {
+ @Override
+ public UserInfo answer(InvocationOnMock invocation) throws Throwable {
+ final int userId = (int) invocation.getArguments()[0];
+ for (UserInfo ui : mUserInfos) {
+ if (ui.id == userId) {
+ return ui;
+ }
+ }
+ return null;
+ }
+ }
+ );
+ when(userManager.getProfiles(anyInt())).thenAnswer(
+ new Answer<List<UserInfo>>() {
+ @Override
+ public List<UserInfo> answer(InvocationOnMock invocation) throws Throwable {
+ final int userId = (int) invocation.getArguments()[0];
+ final ArrayList<UserInfo> ret = new ArrayList<UserInfo>();
+ UserInfo parent = null;
+ for (UserInfo ui : mUserInfos) {
+ if (ui.id == userId) {
+ parent = ui;
+ break;
+ }
+ }
+ if (parent == null) {
+ return ret;
+ }
+ ret.add(parent);
+ for (UserInfo ui : mUserInfos) {
+ if (ui.id == userId) {
+ continue;
+ }
+ if (ui.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
+ && ui.profileGroupId == parent.profileGroupId) {
+ ret.add(ui);
+ }
+ }
+ return ret;
+ }
+ }
+ );
// Create a data directory.
final File dir = new File(dataDir, "user" + userId);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
index ca43644..c80ca6c 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
@@ -154,8 +154,10 @@
aci.packageName = admin.getPackageName();
aci.name = admin.getClassName();
- doReturn(realResolveInfo).when(mMockContext.packageManager).queryBroadcastReceiversAsUser(
- MockUtils.checkIntentComponent(admin),
+ // Note we don't set up queryBroadcastReceivers. We don't use it in DPMS.
+
+ doReturn(aci).when(mMockContext.ipackageManager).getReceiverInfo(
+ eq(admin),
anyInt(),
eq(UserHandle.getUserId(packageUid)));
diff --git a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
index 577c3a1..edbff83 100644
--- a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
@@ -12,6 +12,7 @@
import android.util.Log;
import android.util.ArraySet;
+import com.android.server.job.JobStore.JobSet;
import com.android.server.job.controllers.JobStatus;
import java.util.Iterator;
@@ -58,15 +59,15 @@
.setMinimumLatency(runFromMillis)
.setPersisted(true)
.build();
- final JobStatus ts = new JobStatus(task, SOME_UID, null, -1);
+ final JobStatus ts = JobStatus.createFromJobInfo(task, SOME_UID, null, -1, null);
mTaskStoreUnderTest.add(ts);
Thread.sleep(IO_WAIT);
// Manually load tasks from xml file.
- final ArraySet<JobStatus> jobStatusSet = new ArraySet<JobStatus>();
+ final JobSet jobStatusSet = new JobSet();
mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet);
assertEquals("Didn't get expected number of persisted tasks.", 1, jobStatusSet.size());
- final JobStatus loadedTaskStatus = jobStatusSet.iterator().next();
+ final JobStatus loadedTaskStatus = jobStatusSet.getAllJobs().get(0);
assertTasksEqual(task, loadedTaskStatus.getJob());
assertTrue("JobStore#contains invalid.", mTaskStoreUnderTest.containsJob(ts));
assertEquals("Different uids.", SOME_UID, loadedTaskStatus.getUid());
@@ -91,16 +92,16 @@
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setPersisted(true)
.build();
- final JobStatus taskStatus1 = new JobStatus(task1, SOME_UID, null, -1);
- final JobStatus taskStatus2 = new JobStatus(task2, SOME_UID, null, -1);
+ final JobStatus taskStatus1 = JobStatus.createFromJobInfo(task1, SOME_UID, null, -1, null);
+ final JobStatus taskStatus2 = JobStatus.createFromJobInfo(task2, SOME_UID, null, -1, null);
mTaskStoreUnderTest.add(taskStatus1);
mTaskStoreUnderTest.add(taskStatus2);
Thread.sleep(IO_WAIT);
- final ArraySet<JobStatus> jobStatusSet = new ArraySet<JobStatus>();
+ final JobSet jobStatusSet = new JobSet();
mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet);
assertEquals("Incorrect # of persisted tasks.", 2, jobStatusSet.size());
- Iterator<JobStatus> it = jobStatusSet.iterator();
+ Iterator<JobStatus> it = jobStatusSet.getAllJobs().iterator();
JobStatus loaded1 = it.next();
JobStatus loaded2 = it.next();
@@ -140,15 +141,15 @@
extras.putInt("into", 3);
b.setExtras(extras);
final JobInfo task = b.build();
- JobStatus taskStatus = new JobStatus(task, SOME_UID, null, -1);
+ JobStatus taskStatus = JobStatus.createFromJobInfo(task, SOME_UID, null, -1, null);
mTaskStoreUnderTest.add(taskStatus);
Thread.sleep(IO_WAIT);
- final ArraySet<JobStatus> jobStatusSet = new ArraySet<JobStatus>();
+ final JobSet jobStatusSet = new JobSet();
mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet);
assertEquals("Incorrect # of persisted tasks.", 1, jobStatusSet.size());
- JobStatus loaded = jobStatusSet.iterator().next();
+ JobStatus loaded = jobStatusSet.getAllJobs().iterator().next();
assertTasksEqual(task, loaded.getJob());
}
public void testWritingTaskWithSourcePackage() throws Exception {
@@ -157,15 +158,16 @@
.setPeriodic(10000L)
.setRequiresCharging(true)
.setPersisted(true);
- JobStatus taskStatus = new JobStatus(b.build(), SOME_UID, "com.google.android.gms", 0);
+ JobStatus taskStatus = JobStatus.createFromJobInfo(b.build(), SOME_UID,
+ "com.google.android.gms", 0, null);
mTaskStoreUnderTest.add(taskStatus);
Thread.sleep(IO_WAIT);
- final ArraySet<JobStatus> jobStatusSet = new ArraySet<JobStatus>();
+ final JobSet jobStatusSet = new JobSet();
mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet);
assertEquals("Incorrect # of persisted tasks.", 1, jobStatusSet.size());
- JobStatus loaded = jobStatusSet.iterator().next();
+ JobStatus loaded = jobStatusSet.getAllJobs().iterator().next();
assertEquals("Source package not equal.", loaded.getSourcePackageName(),
taskStatus.getSourcePackageName());
assertEquals("Source user not equal.", loaded.getSourceUserId(),
@@ -178,15 +180,15 @@
.setPeriodic(5*60*60*1000, 1*60*60*1000)
.setRequiresCharging(true)
.setPersisted(true);
- JobStatus taskStatus = new JobStatus(b.build(), SOME_UID, null, -1);
+ JobStatus taskStatus = JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1, null);
mTaskStoreUnderTest.add(taskStatus);
Thread.sleep(IO_WAIT);
- final ArraySet<JobStatus> jobStatusSet = new ArraySet<JobStatus>();
+ final JobSet jobStatusSet = new JobSet();
mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet);
assertEquals("Incorrect # of persisted tasks.", 1, jobStatusSet.size());
- JobStatus loaded = jobStatusSet.iterator().next();
+ JobStatus loaded = jobStatusSet.getAllJobs().iterator().next();
assertEquals("Period not equal.", loaded.getJob().getIntervalMillis(),
taskStatus.getJob().getIntervalMillis());
assertEquals("Flex not equal.", loaded.getJob().getFlexMillis(),
@@ -203,16 +205,17 @@
SystemClock.elapsedRealtime() + (TWO_HOURS * ONE_HOUR) + TWO_HOURS; // > period+flex
final long invalidEarlyRuntimeElapsedMillis =
invalidLateRuntimeElapsedMillis - TWO_HOURS; // Early is (late - period).
- final JobStatus js = new JobStatus(b.build(), SOME_UID, "somePackage", 0 /* sourceUserId */,
+ final JobStatus js = new JobStatus(b.build(), SOME_UID, "somePackage",
+ 0 /* sourceUserId */, "someTag",
invalidEarlyRuntimeElapsedMillis, invalidLateRuntimeElapsedMillis);
mTaskStoreUnderTest.add(js);
Thread.sleep(IO_WAIT);
- final ArraySet<JobStatus> jobStatusSet = new ArraySet<JobStatus>();
+ final JobSet jobStatusSet = new JobSet();
mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet);
assertEquals("Incorrect # of persisted tasks.", 1, jobStatusSet.size());
- JobStatus loaded = jobStatusSet.iterator().next();
+ JobStatus loaded = jobStatusSet.getAllJobs().iterator().next();
// Assert early runtime was clamped to be under now + period. We can do <= here b/c we'll
// call SystemClock.elapsedRealtime after doing the disk i/o.
@@ -229,12 +232,12 @@
.setOverrideDeadline(5000)
.setPriority(42)
.setPersisted(true);
- final JobStatus js = new JobStatus(b.build(), SOME_UID, null, -1);
+ final JobStatus js = JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1, null);
mTaskStoreUnderTest.add(js);
Thread.sleep(IO_WAIT);
- final ArraySet<JobStatus> jobStatusSet = new ArraySet<JobStatus>();
+ final JobSet jobStatusSet = new JobSet();
mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet);
- JobStatus loaded = jobStatusSet.iterator().next();
+ JobStatus loaded = jobStatusSet.getAllJobs().iterator().next();
assertEquals("Priority not correctly persisted.", 42, loaded.getPriority());
}
@@ -245,18 +248,18 @@
JobInfo.Builder b = new Builder(42, mComponent)
.setOverrideDeadline(10000)
.setPersisted(false);
- JobStatus jsNonPersisted = new JobStatus(b.build(), SOME_UID, null, -1);
+ JobStatus jsNonPersisted = JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1, null);
mTaskStoreUnderTest.add(jsNonPersisted);
b = new Builder(43, mComponent)
.setOverrideDeadline(10000)
.setPersisted(true);
- JobStatus jsPersisted = new JobStatus(b.build(), SOME_UID, null, -1);
+ JobStatus jsPersisted = JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1, null);
mTaskStoreUnderTest.add(jsPersisted);
Thread.sleep(IO_WAIT);
- final ArraySet<JobStatus> jobStatusSet = new ArraySet<JobStatus>();
+ final JobSet jobStatusSet = new JobSet();
mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet);
assertEquals("Job count is incorrect.", 1, jobStatusSet.size());
- JobStatus jobStatus = jobStatusSet.iterator().next();
+ JobStatus jobStatus = jobStatusSet.getAllJobs().iterator().next();
assertEquals("Wrong job persisted.", 43, jobStatus.getJobId());
}
diff --git a/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java b/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java
index 31182fc..32501ad 100644
--- a/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java
@@ -15,17 +15,10 @@
*/
package com.android.server.notification;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_LOW;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_MAX;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_NONE;
-
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import android.app.Notification;
-import android.os.Handler;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.test.AndroidTestCase;
@@ -55,14 +48,13 @@
UserHandle user = UserHandle.ALL;
mHelper = new RankingHelper(getContext(), handler, mUsageStats,
- new String[] {TopicImportanceExtractor.class.getName()});
+ new String[] {ImportanceExtractor.class.getName()});
mNotiGroupGSortA = new Notification.Builder(getContext())
.setContentTitle("A")
.setGroup("G")
.setSortKey("A")
.setWhen(1205)
- .setTopic(new Notification.Topic("A", "a"))
.build();
mRecordGroupGSortA = new NotificationRecord(getContext(), new StatusBarNotification(
"package", "package", 1, null, 0, 0, 0, mNotiGroupGSortA, user));
@@ -72,7 +64,6 @@
.setGroup("G")
.setSortKey("B")
.setWhen(1200)
- .setTopic(new Notification.Topic("A", "a"))
.build();
mRecordGroupGSortB = new NotificationRecord(getContext(), new StatusBarNotification(
"package", "package", 1, null, 0, 0, 0, mNotiGroupGSortB, user));
@@ -80,7 +71,6 @@
mNotiNoGroup = new Notification.Builder(getContext())
.setContentTitle("C")
.setWhen(1201)
- .setTopic(new Notification.Topic("C", "c"))
.build();
mRecordNoGroup = new NotificationRecord(getContext(), new StatusBarNotification(
"package", "package", 1, null, 0, 0, 0, mNotiNoGroup, user));
@@ -88,7 +78,6 @@
mNotiNoGroup2 = new Notification.Builder(getContext())
.setContentTitle("D")
.setWhen(1202)
- .setTopic(new Notification.Topic("D", "d"))
.build();
mRecordNoGroup2 = new NotificationRecord(getContext(), new StatusBarNotification(
"package", "package", 1, null, 0, 0, 0, mNotiNoGroup2, user));
@@ -97,7 +86,6 @@
.setContentTitle("E")
.setWhen(1201)
.setSortKey("A")
- .setTopic(new Notification.Topic("E", "e"))
.build();
mRecordNoGroupSortA = new NotificationRecord(getContext(), new StatusBarNotification(
"package", "package", 1, null, 0, 0, 0, mNotiNoGroupSortA, user));
@@ -152,26 +140,4 @@
ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>();
mHelper.sort(notificationList);
}
-
- @SmallTest
- public void testTopicImportanceExtractor() throws Exception {
- mHelper.setImportance("package", 0, new Notification.Topic("A", "a"), IMPORTANCE_MAX);
- // There is no B. There never was a b. Moving on...
- mHelper.setImportance("package", 0, new Notification.Topic("C", "c"), IMPORTANCE_HIGH);
- mHelper.setImportance("package", 0, new Notification.Topic("D", "d"), IMPORTANCE_LOW);
- // watch out: different package.
- mHelper.setImportance("package2", 0, new Notification.Topic("E", "e"), IMPORTANCE_NONE);
-
- TopicImportanceExtractor validator = mHelper.findExtractor(TopicImportanceExtractor.class);
- validator.process(mRecordGroupGSortA);
- validator.process(mRecordGroupGSortB);
- validator.process(mRecordNoGroup);
- validator.process(mRecordNoGroup2);
- validator.process(mRecordNoGroupSortA);
- assertTrue(mRecordGroupGSortA.getTopicImportance() == IMPORTANCE_MAX);
- assertTrue(mRecordGroupGSortB.getTopicImportance() == IMPORTANCE_MAX);
- assertTrue(mRecordNoGroup.getTopicImportance() == IMPORTANCE_HIGH);
- assertTrue(mRecordNoGroup2.getTopicImportance() == IMPORTANCE_LOW);
- assertTrue(mRecordNoGroupSortA.getTopicImportance() == IMPORTANCE_UNSPECIFIED);
- }
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 8e891bf..8da1785 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -151,6 +151,8 @@
private ArrayList<UsageStatsManagerInternal.AppIdleStateChangeListener>
mPackageAccessListeners = new ArrayList<>();
+ private List<String> mCarrierPrivilegedApps;
+
public UsageStatsService(Context context) {
super(context);
}
@@ -170,10 +172,18 @@
+ mUsageStatsDir.getAbsolutePath());
}
- IntentFilter userActions = new IntentFilter(Intent.ACTION_USER_REMOVED);
- userActions.addAction(Intent.ACTION_USER_STARTED);
- getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, userActions,
- null, null);
+ IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
+ filter.addAction(Intent.ACTION_USER_STARTED);
+ getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, filter,
+ null, mHandler);
+
+ IntentFilter packageFilter = new IntentFilter();
+ packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+ packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+ packageFilter.addDataScheme("package");
+
+ getContext().registerReceiverAsUser(new PackageReceiver(), UserHandle.ALL, packageFilter,
+ null, mHandler);
mAppIdleEnabled = getContext().getResources().getBoolean(
com.android.internal.R.bool.config_enableAutoPowerModes);
@@ -232,15 +242,15 @@
}
private class UserActionsReceiver extends BroadcastReceiver {
-
@Override
public void onReceive(Context context, Intent intent) {
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
- if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
+ final String action = intent.getAction();
+ if (Intent.ACTION_USER_REMOVED.equals(action)) {
if (userId >= 0) {
mHandler.obtainMessage(MSG_REMOVE_USER, userId, 0).sendToTarget();
}
- } else if (Intent.ACTION_USER_STARTED.equals(intent.getAction())) {
+ } else if (Intent.ACTION_USER_STARTED.equals(action)) {
if (userId >=0) {
postCheckIdleStates(userId);
}
@@ -248,6 +258,17 @@
}
}
+ private class PackageReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (Intent.ACTION_PACKAGE_ADDED.equals(action)
+ || Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
+ clearCarrierPrivilegedApps();
+ }
+ }
+ }
+
private class DeviceStateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
@@ -416,7 +437,7 @@
return false;
}
} catch (RemoteException re) {
- return false;
+ throw re.rethrowFromSystemServer();
}
final long elapsedRealtime = SystemClock.elapsedRealtime();
@@ -784,6 +805,7 @@
return false;
}
} catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
}
if (isActiveDeviceAdmin(packageName, userId)) {
@@ -828,7 +850,7 @@
}
apps = slice.getList();
} catch (RemoteException e) {
- return new int[0];
+ throw e.rethrowFromSystemServer();
}
// State of each uid. Key is the uid. Value lower 16 bits is the number of apps
@@ -890,9 +912,30 @@
}
private boolean isCarrierApp(String packageName) {
- TelephonyManager telephonyManager = getContext().getSystemService(TelephonyManager.class);
- return telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName)
- == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
+ synchronized (mLock) {
+ if (mCarrierPrivilegedApps == null) {
+ fetchCarrierPrivilegedAppsLocked();
+ }
+ }
+ return mCarrierPrivilegedApps.contains(packageName);
+ }
+
+ void clearCarrierPrivilegedApps() {
+ if (DEBUG) {
+ Slog.i(TAG, "Clearing carrier privileged apps list");
+ }
+ synchronized (mLock) {
+ mCarrierPrivilegedApps = null; // Need to be refetched.
+ }
+ }
+
+ private void fetchCarrierPrivilegedAppsLocked() {
+ TelephonyManager telephonyManager =
+ getContext().getSystemService(TelephonyManager.class);
+ mCarrierPrivilegedApps = telephonyManager.getPackagesWithCarrierPrivileges();
+ if (DEBUG) {
+ Slog.d(TAG, "apps with carrier privilege " + mCarrierPrivilegedApps);
+ }
}
private boolean isActiveNetworkScorer(String packageName) {
@@ -963,6 +1006,9 @@
}
pw.println();
+ pw.println("Carrier privileged apps: " + mCarrierPrivilegedApps);
+
+ pw.println();
pw.println("Settings:");
pw.print(" mAppIdleDurationMillis=");
@@ -1213,7 +1259,7 @@
userId = ActivityManagerNative.getDefault().handleIncomingUser(Binder.getCallingPid(),
Binder.getCallingUid(), userId, false, true, "isAppInactive", null);
} catch (RemoteException re) {
- return false;
+ throw re.rethrowFromSystemServer();
}
final long token = Binder.clearCallingIdentity();
try {
@@ -1232,7 +1278,7 @@
Binder.getCallingPid(), callingUid, userId, false, true,
"setAppIdle", null);
} catch (RemoteException re) {
- return;
+ throw re.rethrowFromSystemServer();
}
getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE,
"No permission to change app idle state");
@@ -1257,6 +1303,17 @@
}
@Override
+ public void onCarrierPrivilegedAppsChanged() {
+ if (DEBUG) {
+ Slog.i(TAG, "Carrier privileged apps changed");
+ }
+ getContext().enforceCallingOrSelfPermission(
+ android.Manifest.permission.BIND_CARRIER_SERVICES,
+ "onCarrierPrivilegedAppsChanged can only be called by privileged apps.");
+ UsageStatsService.this.clearCarrierPrivilegedApps();
+ }
+
+ @Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index cde47bd..e05f00d 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -198,6 +198,8 @@
return STATUS_ERROR;
}
modelData.setHandle(handle[0]);
+ modelData.setLoaded();
+ Slog.d(TAG, "Generic sound model loaded with handle:" + handle[0]);
}
modelData.setCallback(callback);
modelData.setRecognitionConfig(recognitionConfig);
@@ -226,7 +228,7 @@
synchronized (mLock) {
if (DBG) {
- Slog.d(TAG, "startRecognition for keyphraseId=" + keyphraseId
+ Slog.d(TAG, "startKeyphraseRecognition for keyphraseId=" + keyphraseId
+ " soundModel=" + soundModel + ", listener=" + listener.asBinder()
+ ", recognitionConfig=" + recognitionConfig);
Slog.d(TAG, "moduleProperties=" + mModuleProperties);
@@ -242,13 +244,13 @@
}
if (mModuleProperties == null) {
- Slog.w(TAG, "Attempting startRecognition without the capability");
+ Slog.w(TAG, "Attempting startKeyphraseRecognition without the capability");
return STATUS_ERROR;
}
if (mModule == null) {
mModule = SoundTrigger.attachModule(mModuleProperties.id, this, null);
if (mModule == null) {
- Slog.w(TAG, "startRecognition cannot attach to sound trigger module");
+ Slog.w(TAG, "startKeyphraseRecognition cannot attach to sound trigger module");
return STATUS_ERROR;
}
}
@@ -346,27 +348,30 @@
return STATUS_ERROR;
}
- if (currentCallback == null || !modelData.modelStarted()) {
- // startRecognition hasn't been called or it failed.
- Slog.w(TAG, "Attempting stopRecognition without a successful startRecognition");
+ if (currentCallback == null || !modelData.isModelStarted()) {
+ // startGenericRecognition hasn't been called or it failed.
+ Slog.w(TAG, "Attempting stopGenericRecognition without a successful" +
+ " startGenericRecognition");
return STATUS_ERROR;
}
if (currentCallback.asBinder() != listener.asBinder()) {
// We don't allow a different listener to stop the recognition than the one
// that started it.
- Slog.w(TAG, "Attempting stopRecognition for another recognition");
+ Slog.w(TAG, "Attempting stopGenericRecognition for another recognition");
return STATUS_ERROR;
}
- int status = stopGenericRecognitionLocked(modelData, false /* don't notify for synchronous calls */);
+ int status = stopGenericRecognitionLocked(modelData,
+ false /* don't notify for synchronous calls */);
if (status != SoundTrigger.STATUS_OK) {
+ Slog.w(TAG, "stopGenericRecognition failed: " + status);
return status;
}
// We leave the sound model loaded but not started, this helps us when we start
// back.
// Also clear the internal state once the recognition has been stopped.
- modelData.clearState();
+ modelData.setLoaded();
modelData.clearCallback();
if (!computeRecognitionRunning()) {
internalClearGlobalStateLocked();
@@ -451,7 +456,7 @@
// Stop all generic recognition models.
for (ModelData model : mGenericModelDataMap.values()) {
- if (model.modelStarted()) {
+ if (model.isModelStarted()) {
int status = stopGenericRecognitionLocked(model,
false /* do not notify for synchronous calls */);
if (status != STATUS_OK) {
@@ -470,6 +475,66 @@
return mModuleProperties;
}
+ int unloadKeyphraseSoundModel(int keyphraseId) {
+ if (mModule == null || mCurrentKeyphraseModelHandle == INVALID_VALUE) {
+ return STATUS_ERROR;
+ }
+ if (mKeyphraseId != keyphraseId) {
+ Slog.w(TAG, "Given sound model is not the one loaded.");
+ return STATUS_ERROR;
+ }
+
+ synchronized (mLock) {
+ // Stop recognition if it's the current one.
+ mRequested = false;
+ int status = updateRecognitionLocked(false /* don't notify */);
+ if (status != SoundTrigger.STATUS_OK) {
+ Slog.w(TAG, "Stop recognition failed for keyphrase ID:" + status);
+ }
+
+ status = mModule.unloadSoundModel(mCurrentKeyphraseModelHandle);
+ if (status != SoundTrigger.STATUS_OK) {
+ Slog.w(TAG, "unloadKeyphraseSoundModel call failed with " + status);
+ }
+ internalClearKeyphraseSoundModelLocked();
+ return status;
+ }
+ }
+
+ int unloadGenericSoundModel(UUID modelId) {
+ if (modelId == null || mModule == null) {
+ return STATUS_ERROR;
+ }
+ ModelData modelData = mGenericModelDataMap.get(modelId);
+ if (modelData == null) {
+ Slog.w(TAG, "Unload error: Attempting unload invalid generic model with id:" + modelId);
+ return STATUS_ERROR;
+ }
+ synchronized (mLock) {
+ if (!modelData.isModelLoaded()) {
+ // Nothing to do here.
+ Slog.i(TAG, "Unload: Given generic model is not loaded:" + modelId);
+ return STATUS_OK;
+ }
+ if (modelData.isModelStarted()) {
+ int status = stopGenericRecognitionLocked(modelData,
+ false /* don't notify for synchronous calls */);
+ if (status != SoundTrigger.STATUS_OK) {
+ Slog.w(TAG, "stopGenericRecognition failed: " + status);
+ }
+ }
+
+ int status = mModule.unloadSoundModel(modelData.getHandle());
+ if (status != SoundTrigger.STATUS_OK) {
+ Slog.w(TAG, "unloadGenericSoundModel() call failed with " + status);
+ Slog.w(TAG, "unloadGenericSoundModel() force-marking model as unloaded.");
+ }
+ mGenericModelDataMap.remove(modelId);
+ if (DBG) dumpGenericModelState();
+ return status;
+ }
+ }
+
//---- SoundTrigger.StatusListener methods
@Override
public void onRecognition(RecognitionEvent event) {
@@ -508,7 +573,7 @@
}
private boolean isKeyphraseRecognitionEvent(RecognitionEvent event) {
- return mCurrentKeyphraseModelHandle == event.soundModelHandle;
+ return event instanceof KeyphraseRecognitionEvent;
}
private void onGenericRecognitionSuccessLocked(GenericRecognitionEvent event) {
@@ -530,9 +595,9 @@
}
try {
- callback.onDetected((GenericRecognitionEvent) event);
+ callback.onGenericSoundTriggerDetected((GenericRecognitionEvent) event);
} catch (RemoteException e) {
- Slog.w(TAG, "RemoteException in onDetected", e);
+ Slog.w(TAG, "RemoteException in onGenericSoundTriggerDetected", e);
}
model.setStopped();
@@ -650,10 +715,10 @@
try {
if (mKeyphraseListener != null) {
- mKeyphraseListener.onDetected((KeyphraseRecognitionEvent) event);
+ mKeyphraseListener.onKeyphraseDetected((KeyphraseRecognitionEvent) event);
}
} catch (RemoteException e) {
- Slog.w(TAG, "RemoteException in onDetected", e);
+ Slog.w(TAG, "RemoteException in onKeyphraseDetected", e);
}
mKeyphraseStarted = false;
@@ -702,7 +767,7 @@
int status = mModule.startRecognition(mCurrentKeyphraseModelHandle,
mRecognitionConfig);
if (status != SoundTrigger.STATUS_OK) {
- Slog.w(TAG, "startRecognition failed with " + status);
+ Slog.w(TAG, "startKeyphraseRecognition failed with " + status);
// Notify of error if needed.
if (notify) {
try {
@@ -902,7 +967,7 @@
int status = mModule.startRecognition(handle, config);
if (status != SoundTrigger.STATUS_OK) {
- Slog.w(TAG, "startRecognition failed with " + status);
+ Slog.w(TAG, "startGenericRecognition failed with " + status);
// Notify of error if needed.
if (notify) {
try {
@@ -912,6 +977,7 @@
}
}
} else {
+ Slog.i(TAG, "startRecognition successful.");
modelData.setStarted();
// Notify of resume if needed.
if (notify) {
@@ -922,6 +988,7 @@
}
}
}
+ if (DBG) dumpGenericModelState();
return status;
}
@@ -950,9 +1017,17 @@
}
}
}
+ if (DBG) dumpGenericModelState();
return status;
}
+ private void dumpGenericModelState() {
+ for (UUID modelId : mGenericModelDataMap.keySet()) {
+ ModelData modelData = mGenericModelDataMap.get(modelId);
+ Slog.i(TAG, "Model :" + modelData.toString());
+ }
+ }
+
// Computes whether we have any recognition running at all (voice or generic). Sets
// the mRecognitionRunning variable with the result.
private boolean computeRecognitionRunning() {
@@ -970,7 +1045,7 @@
}
for (UUID modelId : mGenericModelDataMap.keySet()) {
ModelData modelData = mGenericModelDataMap.get(modelId);
- if (modelData.modelStarted()) {
+ if (modelData.isModelStarted()) {
mRecognitionRunning = true;
return mRecognitionRunning;
}
@@ -1001,7 +1076,6 @@
// to SoundModel.TYPE_UNKNOWN;
private int mModelType = SoundModel.TYPE_UNKNOWN;
private IRecognitionStatusCallback mCallback = null;
- private SoundModel mSoundModel = null;
private RecognitionConfig mRecognitionConfig = null;
@@ -1026,8 +1100,7 @@
}
synchronized boolean isModelLoaded() {
- return (mModelState == MODEL_LOADED || mModelState == MODEL_STARTED) &&
- mSoundModel != null;
+ return (mModelState == MODEL_LOADED || mModelState == MODEL_STARTED);
}
synchronized void setStarted() {
@@ -1038,13 +1111,16 @@
mModelState = MODEL_LOADED;
}
- synchronized boolean modelStarted() {
+ synchronized void setLoaded() {
+ mModelState = MODEL_LOADED;
+ }
+
+ synchronized boolean isModelStarted() {
return mModelState == MODEL_STARTED;
}
synchronized void clearState() {
mModelState = MODEL_NOTLOADED;
- mSoundModel = null;
mModelHandle = INVALID_VALUE;
}
@@ -1067,5 +1143,18 @@
synchronized RecognitionConfig getRecognitionConfig() {
return mRecognitionConfig;
}
+
+ String stateToString() {
+ switch(mModelState) {
+ case MODEL_NOTLOADED: return "NOT_LOADED";
+ case MODEL_LOADED: return "LOADED";
+ case MODEL_STARTED: return "STARTED";
+ }
+ return "Unknown state";
+ }
+
+ public String toString() {
+ return "Handle: " + mModelHandle + "ModelState: " + stateToString();
+ }
}
}
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java
index 7722876..113431f 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java
@@ -75,5 +75,7 @@
public abstract ModuleProperties getModuleProperties();
+ public abstract int unloadKeyphraseModel(int keyphaseId);
+
public abstract void dump(FileDescriptor fd, PrintWriter pw, String[] args);
}
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index 251f314..a4c1210 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -122,10 +122,10 @@
public int startRecognition(ParcelUuid parcelUuid, IRecognitionStatusCallback callback,
RecognitionConfig config) {
enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
+ if (!isInitialized()) return STATUS_ERROR;
if (DEBUG) {
Slog.i(TAG, "startRecognition(): Uuid : " + parcelUuid);
}
- if (!isInitialized()) return STATUS_ERROR;
GenericSoundModel model = getSoundModel(parcelUuid);
if (model == null) {
@@ -173,6 +173,8 @@
if (DEBUG) {
Slog.i(TAG, "deleteSoundModel(): id = " + soundModelId);
}
+ // Unload the model if it is loaded.
+ mSoundTriggerHelper.unloadGenericSoundModel(soundModelId.getUuid());
mDbHelper.deleteGenericSoundModel(soundModelId.getUuid());
}
}
@@ -216,6 +218,12 @@
}
@Override
+ public int unloadKeyphraseModel(int keyphraseId) {
+ if (!isInitialized()) return STATUS_ERROR;
+ return mSoundTriggerHelper.unloadKeyphraseSoundModel(keyphraseId);
+ }
+
+ @Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!isInitialized()) return;
mSoundTriggerHelper.dump(fd, pw, args);
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 4a54643..837b4a4 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -75,7 +75,7 @@
*/
public class VoiceInteractionManagerService extends SystemService {
static final String TAG = "VoiceInteractionManagerService";
- static final boolean DEBUG = true;
+ static final boolean DEBUG = false;
final Context mContext;
final ContentResolver mResolver;
@@ -760,6 +760,10 @@
final long caller = Binder.clearCallingIdentity();
boolean deleted = false;
try {
+ int unloadStatus = mSoundTriggerInternal.unloadKeyphraseModel(keyphraseId);
+ if (unloadStatus != SoundTriggerInternal.STATUS_OK) {
+ Slog.w(TAG, "Unable to unload keyphrase sound model:" + unloadStatus);
+ }
deleted = mDbHelper.deleteKeyphraseSoundModel(keyphraseId, callingUid, bcp47Locale);
return deleted ? SoundTriggerInternal.STATUS_OK : SoundTriggerInternal.STATUS_ERROR;
} finally {
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index de90202..10808da 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -624,6 +624,21 @@
parcelableCall.getExtras(),
parcelableCall.getIntentExtras());
}
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("[pa: ");
+ sb.append(mAccountHandle);
+ sb.append(", hdl: ");
+ sb.append(Log.pii(mHandle));
+ sb.append(", caps: ");
+ sb.append(capabilitiesToString(mCallCapabilities));
+ sb.append(", props: ");
+ sb.append(mCallProperties);
+ sb.append("]");
+ return sb.toString();
+ }
}
public static abstract class Callback {
@@ -1000,6 +1015,48 @@
}
}
+ @Override
+ public String toString() {
+ return new StringBuilder().
+ append("Call [id: ").
+ append(mTelecomCallId).
+ append(", state: ").
+ append(stateToString(mState)).
+ append(", details: ").
+ append(mDetails).
+ append("]").toString();
+ }
+
+ /**
+ * @param state An integer value of a {@code STATE_*} constant.
+ * @return A string representation of the value.
+ */
+ private static String stateToString(int state) {
+ switch (state) {
+ case STATE_NEW:
+ return "NEW";
+ case STATE_RINGING:
+ return "RINGING";
+ case STATE_DIALING:
+ return "DIALING";
+ case STATE_ACTIVE:
+ return "ACTIVE";
+ case STATE_HOLDING:
+ return "HOLDING";
+ case STATE_DISCONNECTED:
+ return "DISCONNECTED";
+ case STATE_CONNECTING:
+ return "CONNECTING";
+ case STATE_DISCONNECTING:
+ return "DISCONNECTING";
+ case STATE_SELECT_PHONE_ACCOUNT:
+ return "SELECT_PHONE_ACCOUNT";
+ default:
+ Log.w(Call.class, "Unknown state %d", state);
+ return "UNKNOWN";
+ }
+ }
+
/**
* Adds a listener to this {@code Call}.
*
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index 094b3a9..1b70d65 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -181,7 +181,10 @@
* @hide
*/
public void removeCapability(int capability) {
- mConnectionCapabilities &= ~capability;
+ int newCapabilities = mConnectionCapabilities;
+ newCapabilities &= ~capability;
+
+ setConnectionCapabilities(newCapabilities);
}
/**
@@ -191,7 +194,10 @@
* @hide
*/
public void addCapability(int capability) {
- mConnectionCapabilities |= capability;
+ int newCapabilities = mConnectionCapabilities;
+ newCapabilities |= capability;
+
+ setConnectionCapabilities(newCapabilities);
}
/**
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index fa7a59d..4547c6a 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -297,6 +297,24 @@
*/
public static final String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
+ /**
+ * Connection event used to inform Telecom that it should play the on hold tone. This is used
+ * to play a tone when the peer puts the current call on hold. Sent to Telecom via
+ * {@link #sendConnectionEvent(String)}.
+ * @hide
+ */
+ public static final String EVENT_ON_HOLD_TONE_START =
+ "android.telecom.event.ON_HOLD_TONE_START";
+
+ /**
+ * Connection event used to inform Telecom that it should stop the on hold tone. This is used
+ * to stop a tone when the peer puts the current call on hold. Sent to Telecom via
+ * {@link #sendConnectionEvent(String)}.
+ * @hide
+ */
+ public static final String EVENT_ON_HOLD_TONE_END =
+ "android.telecom.event.ON_HOLD_TONE_END";
+
// Flag controlling whether PII is emitted into the logs
private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
@@ -447,6 +465,8 @@
public void onConferenceStarted() {}
public void onConferenceMergeFailed(Connection c) {}
public void onExtrasChanged(Connection c, Bundle extras) {}
+ /** @hide */
+ public void onConnectionEvent(Connection c, String event) {}
}
/**
@@ -1986,4 +2006,16 @@
l.onConferenceStarted();
}
}
+
+ /**
+ * Sends a connection event to Telecom.
+ *
+ * @param event The connection event.
+ * @hide
+ */
+ protected void sendConnectionEvent(String event) {
+ for (Listener l : mListeners) {
+ l.onConnectionEvent(this, event);
+ }
+ }
}
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index b4a7ce0..5b62e03 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -613,6 +613,14 @@
mAdapter.setExtras(id, extras);
}
}
+
+ @Override
+ public void onConnectionEvent(Connection connection, String event) {
+ String id = mIdByConnection.get(connection);
+ if (id != null) {
+ mAdapter.onConnectionEvent(id, event);
+ }
+ }
};
/** {@inheritDoc} */
@@ -1045,6 +1053,16 @@
}
/**
+ * Returns all the active {@code Conference}s for which this {@code ConnectionService}
+ * has taken responsibility.
+ *
+ * @return A collection of {@code Conference}s created by this {@code ConnectionService}.
+ */
+ public final Collection<Conference> getAllConferences() {
+ return mConferenceById.values();
+ }
+
+ /**
* Create a {@code Connection} given an incoming request. This is used to attach to existing
* incoming calls.
*
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
index 4562514..30fc5ad 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
@@ -412,4 +412,20 @@
}
}
}
+
+ /**
+ * Informs Telecom of a connection level event.
+ *
+ * @param callId The unique ID of the call.
+ * @param event The event.
+ */
+ void onConnectionEvent(String callId, String event) {
+ Log.v(this, "onConnectionEvent: %s", event);
+ for (IConnectionServiceAdapter adapter : mAdapters) {
+ try {
+ adapter.onConnectionEvent(callId, event);
+ } catch (RemoteException ignored) {
+ }
+ }
+ }
}
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
index 293dc11..6a8c1cb 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
@@ -62,6 +62,7 @@
private static final int MSG_ON_POST_DIAL_CHAR = 22;
private static final int MSG_SET_CONFERENCE_MERGE_FAILED = 23;
private static final int MSG_SET_EXTRAS = 24;
+ private static final int MSG_ON_CONNECTION_EVENT = 25;
private final IConnectionServiceAdapter mDelegate;
@@ -239,6 +240,16 @@
} finally {
args.recycle();
}
+ break;
+ }
+ case MSG_ON_CONNECTION_EVENT: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ mDelegate.onConnectionEvent((String) args.arg1, (String) args.arg2);
+ } finally {
+ args.recycle();
+ }
+ break;
}
}
}
@@ -419,6 +430,14 @@
args.arg2 = extras;
mHandler.obtainMessage(MSG_SET_EXTRAS, args).sendToTarget();
}
+
+ @Override
+ public final void onConnectionEvent(String connectionId, String event) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = connectionId;
+ args.arg2 = event;
+ mHandler.obtainMessage(MSG_ON_CONNECTION_EVENT, args).sendToTarget();
+ }
};
public ConnectionServiceAdapterServant(IConnectionServiceAdapter delegate) {
diff --git a/telecomm/java/android/telecom/DisconnectCause.java b/telecomm/java/android/telecom/DisconnectCause.java
index 3a7faf6..2eef7ee 100644
--- a/telecomm/java/android/telecom/DisconnectCause.java
+++ b/telecomm/java/android/telecom/DisconnectCause.java
@@ -92,8 +92,8 @@
/**
* Creates a new DisconnectCause.
*
- * @param label The localized label to show to the user to explain the disconnect.
* @param code The code for the disconnect cause.
+ * @param label The localized label to show to the user to explain the disconnect.
* @param description The localized description to show to the user to explain the disconnect.
* @param reason The reason for the disconnect.
*/
diff --git a/telecomm/java/android/telecom/Log.java b/telecomm/java/android/telecom/Log.java
index 3f32dbe..2ab0525 100644
--- a/telecomm/java/android/telecom/Log.java
+++ b/telecomm/java/android/telecom/Log.java
@@ -16,7 +16,10 @@
package android.telecom;
+import android.net.Uri;
import android.os.AsyncTask;
+import android.telephony.PhoneNumberUtils;
+import android.text.TextUtils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -152,10 +155,37 @@
public static String pii(Object pii) {
if (pii == null || VERBOSE) {
return String.valueOf(pii);
+ } if (pii instanceof Uri) {
+ return piiUri((Uri) pii);
}
return "[" + secureHash(String.valueOf(pii).getBytes()) + "]";
}
+ private static String piiUri(Uri handle) {
+ StringBuilder sb = new StringBuilder();
+ String scheme = handle.getScheme();
+ if (!TextUtils.isEmpty(scheme)) {
+ sb.append(scheme).append(":");
+ }
+ String value = handle.getSchemeSpecificPart();
+ if (!TextUtils.isEmpty(value)) {
+ for (int i = 0; i < value.length(); i++) {
+ char c = value.charAt(i);
+ if (PhoneNumberUtils.isStartsPostDial(c)) {
+ sb.append(c);
+ } else if (PhoneNumberUtils.isDialable(c)) {
+ sb.append("*");
+ } else if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) {
+ sb.append("*");
+ } else {
+ sb.append(c);
+ }
+ }
+ }
+ return sb.toString();
+
+ }
+
private static String secureHash(byte[] input) {
if (sMessageDigest != null) {
sMessageDigest.reset();
diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java
index f960959..0185808 100644
--- a/telecomm/java/android/telecom/RemoteConnection.java
+++ b/telecomm/java/android/telecom/RemoteConnection.java
@@ -209,6 +209,15 @@
* @param extras The extras containing other information associated with the connection.
*/
public void onExtrasChanged(RemoteConnection connection, @Nullable Bundle extras) {}
+
+ /**
+ * Handles a connection event propagated to this {@link RemoteConnection}.
+ *
+ * @param connection The {@code RemoteConnection} invoking this method.
+ * @param event The connection event.
+ * @hide
+ */
+ public void onConnectionEvent(RemoteConnection connection, String event) {}
}
/**
@@ -1291,6 +1300,20 @@
}
}
+ /** @hide */
+ void onConnectionEvent(final String event) {
+ for (CallbackRecord record : mCallbackRecords) {
+ final RemoteConnection connection = this;
+ final Callback callback = record.getCallback();
+ record.getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onConnectionEvent(connection, event);
+ }
+ });
+ }
+ }
+
/**
* Create a RemoteConnection represents a failure, and which will be in
* {@link Connection#STATE_DISCONNECTED}. Attempting to use it for anything will almost
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index dc0de0c..b85382f 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -330,6 +330,13 @@
.setExtras(extras);
}
}
+
+ @Override
+ public void onConnectionEvent(String callId, String event) {
+ if (mConnectionById.containsKey(callId)) {
+ findConnectionForAction(callId, "onConnectionEvent").onConnectionEvent(event);
+ }
+ }
};
private final ConnectionServiceAdapterServant mServant =
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 9f478df..605e0d3 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1425,7 +1425,9 @@
* <p> This method displays the UI to manage blocked numbers only if
* {@link android.provider.BlockedNumberContract#canCurrentUserBlockNumbers(Context)} returns
* {@code true} for the current user.
+ * @deprecated Use {@link #createManageBlockedNumbersIntent()} instead.
*/
+ // TODO: Delete this.
public void launchManageBlockedNumbersActivity() {
ITelecomService service = getTelecomService();
if (service != null) {
@@ -1437,6 +1439,26 @@
}
}
+ /**
+ * Creates the {@link Intent} which can be used with {@link Context#startActivity(Intent)} to
+ * launch the activity to manage blocked numbers.
+ * <p> This method displays the UI to manage blocked numbers only if
+ * {@link android.provider.BlockedNumberContract#canCurrentUserBlockNumbers(Context)} returns
+ * {@code true} for the current user.
+ */
+ public Intent createManageBlockedNumbersIntent() {
+ ITelecomService service = getTelecomService();
+ Intent result = null;
+ if (service != null) {
+ try {
+ result = service.createManageBlockedNumbersIntent();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelecomService#createManageBlockedNumbersIntent", e);
+ }
+ }
+ return result;
+ }
+
private ITelecomService getTelecomService() {
if (mTelecomServiceOverride != null) {
return mTelecomServiceOverride;
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
index 7647444..569c244 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
@@ -86,4 +86,6 @@
void addExistingConnection(String callId, in ParcelableConnection connection);
void setExtras(String callId, in Bundle extras);
+
+ void onConnectionEvent(String callId, String event);
}
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 95c8db5..3c250f1 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -17,6 +17,7 @@
package com.android.internal.telecom;
import android.content.ComponentName;
+import android.content.Intent;
import android.telecom.ParcelableCallAnalytics;
import android.telecom.PhoneAccountHandle;
import android.net.Uri;
@@ -247,5 +248,11 @@
/**
* @see TelecomServiceImpl#launchManageBlockedNumbersActivity
**/
+ // TODO: Delete this.
void launchManageBlockedNumbersActivity(in String callingPackageName);
+
+ /**
+ * @see TelecomServiceImpl#createManageBlockedNumbersIntent
+ **/
+ Intent createManageBlockedNumbersIntent();
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 3ad7d34..cd1c5e9 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -637,7 +637,7 @@
sDefaults.putBoolean(KEY_SHOW_CDMA_CHOICES_BOOL, false);
sDefaults.putBoolean(KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL, true);
sDefaults.putBoolean(KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL, true);
- sDefaults.putBoolean(KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL, true);
+ sDefaults.putBoolean(KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL, false);
sDefaults.putBoolean(KEY_SUPPORT_SWAP_AFTER_MERGE_BOOL, true);
sDefaults.putBoolean(KEY_USE_HFA_FOR_PROVISIONING_BOOL, false);
sDefaults.putBoolean(KEY_USE_OTASP_FOR_PROVISIONING_BOOL, false);
@@ -733,9 +733,28 @@
* @param subId the subscription ID, normally obtained from {@link SubscriptionManager}.
* @return A {@link PersistableBundle} containing the config for the given subId, or default
* values for an invalid subId.
+ *
+ * @deprecated use getConfig.
*/
@Nullable
public PersistableBundle getConfigForSubId(int subId) {
+ return getConfig(subId);
+ }
+
+ /**
+ * Gets the configuration values for a particular subscription, which is associated with a
+ * specific SIM card. If an invalid subId is used, the returned config will contain default
+ * values.
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ *
+ * @param subId the subscription ID, normally obtained from {@link SubscriptionManager}.
+ * @return A {@link PersistableBundle} containing the config for the given subId, or default
+ * values for an invalid subId.
+ */
+ @Nullable
+ public PersistableBundle getConfig(int subId) {
try {
ICarrierConfigLoader loader = getICarrierConfigLoader();
if (loader == null) {
@@ -757,11 +776,32 @@
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*
- * @see #getConfigForSubId
+ * @return A {@link PersistableBundle} containing the config for the default subscription.
*/
@Nullable
public PersistableBundle getConfig() {
- return getConfigForSubId(SubscriptionManager.getDefaultSubscriptionId());
+ return getConfig(SubscriptionManager.getDefaultSubscriptionId());
+ }
+
+ /**
+ * Calling this method triggers telephony services to fetch the current carrier configuration.
+ * <p>
+ * Normally this does not need to be called because the platform reloads config on its own.
+ * This should be called by a carrier service app if it wants to update config at an arbitrary
+ * moment.
+ * </p>
+ * <p>Requires that the calling app has carrier privileges.
+ * @see #hasCarrierPrivileges
+ * <p>
+ * This method returns before the reload has completed, and
+ * {@link android.service.carrier.CarrierService#onLoadConfig} will be called from an
+ * arbitrary thread.
+ * </p>
+ *
+ * @deprecated use notifyConfigChanged.
+ */
+ public void notifyConfigChangedForSubId(int subId) {
+ notifyConfigChanged(subId);
}
/**
@@ -779,7 +819,7 @@
* arbitrary thread.
* </p>
*/
- public void notifyConfigChangedForSubId(int subId) {
+ public void notifyConfigChanged(int subId) {
try {
ICarrierConfigLoader loader = getICarrierConfigLoader();
if (loader == null) {
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index ad007c6..39a9295 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -36,7 +36,7 @@
public class ServiceState implements Parcelable {
static final String LOG_TAG = "PHONE";
- static final boolean DBG = true;
+ static final boolean DBG = false;
static final boolean VDBG = false; // STOPSHIP if true
/**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index fcb42a4..b482811 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -47,6 +47,7 @@
import java.io.FileInputStream;
import java.io.IOException;
+import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -2931,10 +2932,27 @@
* @return an IccOpenLogicalChannelResponse object.
*/
public IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID) {
+ return iccOpenLogicalChannel(getDefaultSubscription(), AID);
+ }
+
+ /**
+ * Opens a logical channel to the ICC card.
+ *
+ * Input parameters equivalent to TS 27.007 AT+CCHO command.
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * @param subId The subscription to use.
+ * @param AID Application id. See ETSI 102.221 and 101.220.
+ * @return an IccOpenLogicalChannelResponse object.
+ */
+ public IccOpenLogicalChannelResponse iccOpenLogicalChannel(int subId, String AID) {
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.iccOpenLogicalChannel(AID);
+ return telephony.iccOpenLogicalChannel(subId, AID);
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -2955,10 +2973,28 @@
* @return true if the channel was closed successfully.
*/
public boolean iccCloseLogicalChannel(int channel) {
+ return iccCloseLogicalChannel(getDefaultSubscription(), channel);
+ }
+
+ /**
+ * Closes a previously opened logical channel to the ICC card.
+ *
+ * Input parameters equivalent to TS 27.007 AT+CCHC command.
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * @param subId The subscription to use.
+ * @param channel is the channel id to be closed as retruned by a successful
+ * iccOpenLogicalChannel.
+ * @return true if the channel was closed successfully.
+ */
+ public boolean iccCloseLogicalChannel(int subId, int channel) {
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.iccCloseLogicalChannel(channel);
+ return telephony.iccCloseLogicalChannel(subId, channel);
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -2988,10 +3024,38 @@
*/
public String iccTransmitApduLogicalChannel(int channel, int cla,
int instruction, int p1, int p2, int p3, String data) {
+ return iccTransmitApduLogicalChannel(getDefaultSubscription(), channel, cla,
+ instruction, p1, p2, p3, data);
+ }
+
+ /**
+ * Transmit an APDU to the ICC card over a logical channel.
+ *
+ * Input parameters equivalent to TS 27.007 AT+CGLA command.
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * @param subId The subscription to use.
+ * @param channel is the channel id to be closed as returned by a successful
+ * iccOpenLogicalChannel.
+ * @param cla Class of the APDU command.
+ * @param instruction Instruction of the APDU command.
+ * @param p1 P1 value of the APDU command.
+ * @param p2 P2 value of the APDU command.
+ * @param p3 P3 value of the APDU command. If p3 is negative a 4 byte APDU
+ * is sent to the SIM.
+ * @param data Data to be sent with the APDU.
+ * @return The APDU response from the ICC card with the status appended at
+ * the end.
+ */
+ public String iccTransmitApduLogicalChannel(int subId, int channel, int cla,
+ int instruction, int p1, int p2, int p3, String data) {
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.iccTransmitApduLogicalChannel(channel, cla,
+ return telephony.iccTransmitApduLogicalChannel(subId, channel, cla,
instruction, p1, p2, p3, data);
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
@@ -3020,10 +3084,36 @@
*/
public String iccTransmitApduBasicChannel(int cla,
int instruction, int p1, int p2, int p3, String data) {
+ return iccTransmitApduBasicChannel(getDefaultSubscription(), cla,
+ instruction, p1, p2, p3, data);
+ }
+
+ /**
+ * Transmit an APDU to the ICC card over the basic channel.
+ *
+ * Input parameters equivalent to TS 27.007 AT+CSIM command.
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * @param subId The subscription to use.
+ * @param cla Class of the APDU command.
+ * @param instruction Instruction of the APDU command.
+ * @param p1 P1 value of the APDU command.
+ * @param p2 P2 value of the APDU command.
+ * @param p3 P3 value of the APDU command. If p3 is negative a 4 byte APDU
+ * is sent to the SIM.
+ * @param data Data to be sent with the APDU.
+ * @return The APDU response from the ICC card with the status appended at
+ * the end.
+ */
+ public String iccTransmitApduBasicChannel(int subId, int cla,
+ int instruction, int p1, int p2, int p3, String data) {
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.iccTransmitApduBasicChannel(cla,
+ return telephony.iccTransmitApduBasicChannel(subId, cla,
instruction, p1, p2, p3, data);
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
@@ -3048,10 +3138,31 @@
*/
public byte[] iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
String filePath) {
+ return iccExchangeSimIO(getDefaultSubscription(), fileID, command, p1, p2, p3, filePath);
+ }
+
+ /**
+ * Returns the response APDU for a command APDU sent through SIM_IO.
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * @param subId The subscription to use.
+ * @param fileID
+ * @param command
+ * @param p1 P1 value of the APDU command.
+ * @param p2 P2 value of the APDU command.
+ * @param p3 P3 value of the APDU command.
+ * @param filePath
+ * @return The APDU response.
+ */
+ public byte[] iccExchangeSimIO(int subId, int fileID, int command, int p1, int p2,
+ int p3, String filePath) {
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.iccExchangeSimIO(fileID, command, p1, p2, p3, filePath);
+ return telephony.iccExchangeSimIO(subId, fileID, command, p1, p2, p3, filePath);
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -3073,10 +3184,29 @@
* returns an empty string.
*/
public String sendEnvelopeWithStatus(String content) {
+ return sendEnvelopeWithStatus(getDefaultSubscription(), content);
+ }
+
+ /**
+ * Send ENVELOPE to the SIM and return the response.
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * @param subId The subscription to use.
+ * @param content String containing SAT/USAT response in hexadecimal
+ * format starting with command tag. See TS 102 223 for
+ * details.
+ * @return The APDU response from the ICC card in hexadecimal format
+ * with the last 4 bytes being the status word. If the command fails,
+ * returns an empty string.
+ */
+ public String sendEnvelopeWithStatus(int subId, String content) {
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.sendEnvelopeWithStatus(content);
+ return telephony.sendEnvelopeWithStatus(subId, content);
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -3637,8 +3767,20 @@
* @return true on success; false on any failure.
*/
public boolean setPreferredNetworkTypeToGlobal() {
- return setPreferredNetworkType(getDefaultSubscription(),
- RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA);
+ return setPreferredNetworkTypeToGlobal(getDefaultSubscription());
+ }
+
+ /**
+ * Set the preferred network type to global mode which includes LTE, CDMA, EvDo and GSM/WCDMA.
+ *
+ * <p>
+ * Requires that the calling app has carrier privileges.
+ * @see #hasCarrierPrivileges
+ *
+ * @return true on success; false on any failure.
+ */
+ public boolean setPreferredNetworkTypeToGlobal(int subId) {
+ return setPreferredNetworkType(subId, RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA);
}
/**
@@ -3685,10 +3827,26 @@
* @return true if the app has carrier privileges.
*/
public boolean hasCarrierPrivileges() {
+ return hasCarrierPrivileges(getDefaultSubscription());
+ }
+
+ /**
+ * Has the calling application been granted carrier privileges by the carrier.
+ *
+ * If any of the packages in the calling UID has carrier privileges, the
+ * call will return true. This access is granted by the owner of the UICC
+ * card and does not depend on the registered carrier.
+ *
+ * @param subId The subscription to use.
+ * @return true if the app has carrier privileges.
+ */
+ public boolean hasCarrierPrivileges(int subId) {
try {
ITelephony telephony = getITelephony();
- if (telephony != null)
- return telephony.getCarrierPrivilegeStatus() == CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
+ if (telephony != null) {
+ return telephony.getCarrierPrivilegeStatus(subId) ==
+ CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
+ }
} catch (RemoteException ex) {
Rlog.e(TAG, "hasCarrierPrivileges RemoteException", ex);
} catch (NullPointerException ex) {
@@ -3712,10 +3870,29 @@
* @return true if the operation was executed correctly.
*/
public boolean setOperatorBrandOverride(String brand) {
+ return setOperatorBrandOverride(getDefaultSubscription(), brand);
+ }
+
+ /**
+ * Override the branding for the current ICCID.
+ *
+ * Once set, whenever the SIM is present in the device, the service
+ * provider name (SPN) and the operator name will both be replaced by the
+ * brand value input. To unset the value, the same function should be
+ * called with a null brand value.
+ *
+ * <p>Requires that the calling app has carrier privileges.
+ * @see #hasCarrierPrivileges
+ *
+ * @param subId The subscription to use.
+ * @param brand The brand name to display/set.
+ * @return true if the operation was executed correctly.
+ */
+ public boolean setOperatorBrandOverride(int subId, String brand) {
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.setOperatorBrandOverride(brand);
+ return telephony.setOperatorBrandOverride(subId, brand);
} catch (RemoteException ex) {
Rlog.e(TAG, "setOperatorBrandOverride RemoteException", ex);
} catch (NullPointerException ex) {
@@ -3746,10 +3923,37 @@
public boolean setRoamingOverride(List<String> gsmRoamingList,
List<String> gsmNonRoamingList, List<String> cdmaRoamingList,
List<String> cdmaNonRoamingList) {
+ return setRoamingOverride(getDefaultSubscription(), gsmRoamingList, gsmNonRoamingList,
+ cdmaRoamingList, cdmaNonRoamingList);
+ }
+
+ /**
+ * Override the roaming preference for the current ICCID.
+ *
+ * Using this call, the carrier app (see #hasCarrierPrivileges) can override
+ * the platform's notion of a network operator being considered roaming or not.
+ * The change only affects the ICCID that was active when this call was made.
+ *
+ * If null is passed as any of the input, the corresponding value is deleted.
+ *
+ * <p>Requires that the caller have carrier privilege. See #hasCarrierPrivileges.
+ *
+ * @param subId for which the roaming overrides apply.
+ * @param gsmRoamingList - List of MCCMNCs to be considered roaming for 3GPP RATs.
+ * @param gsmNonRoamingList - List of MCCMNCs to be considered not roaming for 3GPP RATs.
+ * @param cdmaRoamingList - List of SIDs to be considered roaming for 3GPP2 RATs.
+ * @param cdmaNonRoamingList - List of SIDs to be considered not roaming for 3GPP2 RATs.
+ * @return true if the operation was executed correctly.
+ *
+ * @hide
+ */
+ public boolean setRoamingOverride(int subId, List<String> gsmRoamingList,
+ List<String> gsmNonRoamingList, List<String> cdmaRoamingList,
+ List<String> cdmaNonRoamingList) {
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.setRoamingOverride(gsmRoamingList, gsmNonRoamingList,
+ return telephony.setRoamingOverride(subId, gsmRoamingList, gsmNonRoamingList,
cdmaRoamingList, cdmaNonRoamingList);
} catch (RemoteException ex) {
Rlog.e(TAG, "setRoamingOverride RemoteException", ex);
@@ -3857,6 +4061,21 @@
}
/** @hide */
+ public List<String> getPackagesWithCarrierPrivileges() {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.getPackagesWithCarrierPrivileges();
+ }
+ } catch (RemoteException ex) {
+ Rlog.e(TAG, "getPackagesWithCarrierPrivileges RemoteException", ex);
+ } catch (NullPointerException ex) {
+ Rlog.e(TAG, "getPackagesWithCarrierPrivileges NPE", ex);
+ }
+ return Collections.EMPTY_LIST;
+ }
+
+ /** @hide */
@SystemApi
public void dial(String number) {
try {
@@ -4184,7 +4403,6 @@
Log.e(TAG, "Error calling ITelephony#getDataEnabled", e);
} catch (NullPointerException e) {
}
- Log.d(TAG, "getDataEnabled: retVal=" + retVal);
return retVal;
}
diff --git a/telephony/java/com/android/ims/ImsCallProfile.java b/telephony/java/com/android/ims/ImsCallProfile.java
index 5f84e0c..96c6243 100644
--- a/telephony/java/com/android/ims/ImsCallProfile.java
+++ b/telephony/java/com/android/ims/ImsCallProfile.java
@@ -178,7 +178,7 @@
* Codec: Codec info.
* DisplayText: Display text for the call.
* AdditionalCallInfo: Additional call info.
- * CallRadioTech: The radio tech on which the call is placed.
+ * CallPull: Boolean value specifying if the call is a pulled call.
*/
public static final String EXTRA_OI = "oi";
public static final String EXTRA_CNA = "cna";
@@ -188,6 +188,7 @@
public static final String EXTRA_CODEC = "Codec";
public static final String EXTRA_DISPLAY_TEXT = "DisplayText";
public static final String EXTRA_ADDITIONAL_CALL_INFO = "AdditionalCallInfo";
+ public static final String EXTRA_IS_CALL_PULL = "CallPull";
/**
* Extra key which the RIL can use to indicate the radio technology used for a call.
diff --git a/telephony/java/com/android/ims/ImsReasonInfo.java b/telephony/java/com/android/ims/ImsReasonInfo.java
index c909c6d..558c1dc 100644
--- a/telephony/java/com/android/ims/ImsReasonInfo.java
+++ b/telephony/java/com/android/ims/ImsReasonInfo.java
@@ -241,6 +241,16 @@
public static final int CODE_ANSWERED_ELSEWHERE = 1014;
/**
+ * Call pull request failure from the network.
+ */
+ public static final int CODE_CALL_PULL_OUT_OF_SYNC = 1015;
+
+ /**
+ * Call ended due to being pulled onto another device.
+ */
+ public static final int CODE_CALL_END_CAUSE_CALL_PULL = 1016;
+
+ /**
* Supplementary services (HOLD/RESUME) failure error codes.
* Values for Supplemetary services failure - Failed, Cancelled and Re-Invite collision.
*/
@@ -249,12 +259,33 @@
public static final int CODE_SUPP_SVC_REINVITE_COLLISION = 1203;
/**
+ * DPD Procedure received no response or send failed
+ */
+ public static final int CODE_IWLAN_DPD_FAILURE = 1300;
+
+ /**
+ * Establishment of the ePDG Tunnel Failed
+ */
+ public static final int CODE_EPDG_TUNNEL_ESTABLISH_FAILURE = 1400;
+
+ /**
+ * Re-keying of the ePDG Tunnel Failed; may not always result in teardown
+ */
+ public static final int CODE_EPDG_TUNNEL_REKEY_FAILURE = 1401;
+
+ /**
+ * Connection to the packet gateway is lost
+ */
+ public static final int CODE_EPDG_TUNNEL_LOST_CONNECTION = 1402;
+
+ /**
* Network string error messages.
* mExtraMessage may have these values.
*/
public static final String EXTRA_MSG_SERVICE_NOT_AUTHORIZED
= "Forbidden. Not Authorized for Service";
+
// For main reason code
public int mCode;
// For the extra code value; it depends on the code value.
diff --git a/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl b/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
index 69259d0..04cb1f2 100644
--- a/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
@@ -18,6 +18,8 @@
import com.android.ims.ImsReasonInfo;
+import android.net.Uri;
+
/**
* A listener type for receiving notifications about the changes to
* the IMS connection(registration).
@@ -100,4 +102,9 @@
* @param count The number of waiting voice messages.
*/
void voiceMessageCountUpdate(int count);
+
+ /**
+ * Notifies the application when the list of URIs associated with IMS client is updated.
+ */
+ void registrationAssociatedUriChanged(in Uri[] uris);
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 62f294c..2727319 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -538,27 +538,30 @@
*
* Input parameters equivalent to TS 27.007 AT+CCHO command.
*
+ * @param subId The subscription to use.
* @param AID Application id. See ETSI 102.221 and 101.220.
* @return an IccOpenLogicalChannelResponse object.
*/
- IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID);
+ IccOpenLogicalChannelResponse iccOpenLogicalChannel(int subId, String AID);
/**
* Closes a previously opened logical channel to the ICC card.
*
* Input parameters equivalent to TS 27.007 AT+CCHC command.
*
+ * @param subId The subscription to use.
* @param channel is the channel id to be closed as retruned by a
* successful iccOpenLogicalChannel.
* @return true if the channel was closed successfully.
*/
- boolean iccCloseLogicalChannel(int channel);
+ boolean iccCloseLogicalChannel(int subId, int channel);
/**
* Transmit an APDU to the ICC card over a logical channel.
*
* Input parameters equivalent to TS 27.007 AT+CGLA command.
*
+ * @param subId The subscription to use.
* @param channel is the channel id to be closed as retruned by a
* successful iccOpenLogicalChannel.
* @param cla Class of the APDU command.
@@ -571,7 +574,7 @@
* @return The APDU response from the ICC card with the status appended at
* the end.
*/
- String iccTransmitApduLogicalChannel(int channel, int cla, int instruction,
+ String iccTransmitApduLogicalChannel(int subId, int channel, int cla, int instruction,
int p1, int p2, int p3, String data);
/**
@@ -579,6 +582,7 @@
*
* Input parameters equivalent to TS 27.007 AT+CSIM command.
*
+ * @param subId The subscription to use.
* @param cla Class of the APDU command.
* @param instruction Instruction of the APDU command.
* @param p1 P1 value of the APDU command.
@@ -589,12 +593,13 @@
* @return The APDU response from the ICC card with the status appended at
* the end.
*/
- String iccTransmitApduBasicChannel(int cla, int instruction,
+ String iccTransmitApduBasicChannel(int subId, int cla, int instruction,
int p1, int p2, int p3, String data);
/**
* Returns the response APDU for a command APDU sent through SIM_IO.
*
+ * @param subId The subscription to use.
* @param fileID
* @param command
* @param p1 P1 value of the APDU command.
@@ -603,12 +608,13 @@
* @param filePath
* @return The APDU response.
*/
- byte[] iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
+ byte[] iccExchangeSimIO(int subId, int fileID, int command, int p1, int p2, int p3,
String filePath);
/**
* Send ENVELOPE to the SIM and returns the response.
*
+ * @param subId The subscription to use.
* @param contents String containing SAT/USAT response in hexadecimal
* format starting with command tag. See TS 102 223 for
* details.
@@ -616,7 +622,7 @@
* being the status word. If the command fails, returns an empty
* string.
*/
- String sendEnvelopeWithStatus(String content);
+ String sendEnvelopeWithStatus(int subId, String content);
/**
* Read one of the NV items defined in {@link RadioNVItems} / {@code ril_nv_items.h}.
@@ -768,9 +774,10 @@
*
* TODO: Add a link to documentation.
*
+ * @param subId The subscription to use.
* @return carrier privilege status defined in TelephonyManager.
*/
- int getCarrierPrivilegeStatus();
+ int getCarrierPrivilegeStatus(int subId);
/**
* Similar to above, but check for the package whose name is pkgName.
@@ -842,10 +849,11 @@
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
* or has to be carrier app - see #hasCarrierPrivileges.
*
+ * @param subId The subscription to use.
* @param brand The brand name to display/set.
* @return true if the operation was executed correctly.
*/
- boolean setOperatorBrandOverride(String brand);
+ boolean setOperatorBrandOverride(int subId, String brand);
/**
* Override the roaming indicator for the current ICCID.
@@ -858,13 +866,14 @@
*
* <p>Requires that the caller have carrier privilege. See #hasCarrierPrivileges.
*
+ * @param subId for which the roaming overrides apply.
* @param gsmRoamingList - List of MCCMNCs to be considered roaming for 3GPP RATs.
* @param gsmNonRoamingList - List of MCCMNCs to be considered not roaming for 3GPP RATs.
* @param cdmaRoamingList - List of SIDs to be considered roaming for 3GPP2 RATs.
* @param cdmaNonRoamingList - List of SIDs to be considered not roaming for 3GPP2 RATs.
* @return true if the operation was executed correctly.
*/
- boolean setRoamingOverride(in List<String> gsmRoamingList,
+ boolean setRoamingOverride(int subId, in List<String> gsmRoamingList,
in List<String> gsmNonRoamingList, in List<String> cdmaRoamingList,
in List<String> cdmaNonRoamingList);
@@ -1028,4 +1037,9 @@
* @return {@code true} if the vibration is set for this PhoneAccount, {@code false} otherwise.
*/
boolean isVoicemailVibrationEnabled(in PhoneAccountHandle accountHandle);
+
+ /**
+ * Returns a list of packages that have carrier privileges.
+ */
+ List<String> getPackagesWithCarrierPrivileges();
}
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index da43460..e851c8d 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -25,7 +25,6 @@
import android.content.IntentSender;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
-import android.content.pm.ContainerEncryptionParams;
import android.content.pm.EphemeralApplicationInfo;
import android.content.pm.FeatureInfo;
import android.content.pm.IPackageDataObserver;
@@ -44,7 +43,6 @@
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
-import android.content.pm.VerificationParams;
import android.content.pm.VerifierDeviceIdentity;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
@@ -520,6 +518,14 @@
throw new UnsupportedOperationException();
}
+ /** @hide */
+ @Override
+ public Drawable getManagedUserBadgedDrawable(Drawable drawable, Rect badgeLocation,
+ int badgeDensity) {
+ throw new UnsupportedOperationException();
+ }
+
+
@Override
public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
throw new UnsupportedOperationException();
@@ -602,14 +608,6 @@
throw new UnsupportedOperationException();
}
- /** @hide */
- @Override
- public void installPackageAsUser(Uri packageURI, PackageInstallObserver observer,
- int flags, String installerPackageName, int userId) {
- throw new UnsupportedOperationException();
- }
-
-
@Override
public void setInstallerPackageName(String targetPackage,
String installerPackageName) {
@@ -873,26 +871,6 @@
* @hide
*/
@Override
- public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
- int flags, String installerPackageName, Uri verificationURI,
- ContainerEncryptionParams encryptionParams) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * @hide
- */
- @Override
- public void installPackageWithVerificationAndEncryption(Uri packageURI,
- IPackageInstallObserver observer, int flags, String installerPackageName,
- VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * @hide
- */
- @Override
public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden,
UserHandle user) {
return false;
@@ -1024,27 +1002,6 @@
* @hide
*/
@Override
- public void installPackageWithVerification(Uri packageURI,
- PackageInstallObserver observer, int flags, String installerPackageName,
- Uri verificationURI,
- ContainerEncryptionParams encryptionParams) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * @hide
- */
- @Override
- public void installPackageWithVerificationAndEncryption(Uri packageURI,
- PackageInstallObserver observer, int flags, String installerPackageName,
- VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * @hide
- */
- @Override
public void addCrossProfileIntentFilter(IntentFilter filter, int sourceUserId, int targetUserId,
int flags) {
throw new UnsupportedOperationException();
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
index 8b8d604..4bed941 100644
--- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -60,6 +60,8 @@
// optional parameter: comma separated list of required account types before proceeding
// with the app launch
private static final String KEY_REQUIRED_ACCOUNTS = "required_accounts";
+ private static final String WEARABLE_ACTION_GOOGLE =
+ "com.google.android.wearable.action.GOOGLE";
private static final int INITIAL_LAUNCH_IDLE_TIMEOUT = 7500; //7.5s to allow app to idle
private static final int POST_LAUNCH_IDLE_TIMEOUT = 750; //750ms idle for non initial launches
private static final int BETWEEN_LAUNCH_SLEEP_TIMEOUT = 2000; //2s between launching apps
@@ -183,6 +185,13 @@
Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> ris = pm.queryIntentActivities(intentToResolve, 0);
+ resolveLoop(ris, intentToResolve, pm);
+ intentToResolve = new Intent(WEARABLE_ACTION_GOOGLE);
+ ris = pm.queryIntentActivities(intentToResolve, 0);
+ resolveLoop(ris, intentToResolve, pm);
+ }
+
+ private void resolveLoop(List<ResolveInfo> ris, Intent intentToResolve, PackageManager pm) {
if (ris == null || ris.isEmpty()) {
Log.i(TAG, "Could not find any apps");
} else {
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.mk b/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.mk
index 616a11b..39ad0ac 100644
--- a/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.mk
+++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.mk
@@ -38,6 +38,8 @@
sobeloperator.cpp \
stats_scorer.cpp
+LOCAL_CFLAGS += -Wall -Wextra -Werror -Wno-unused-parameter
+
LOCAL_STATIC_LIBRARIES += \
libcutils
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/colorspace.cpp b/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/colorspace.cpp
index 63e2ebf..ffb8003 100644
--- a/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/colorspace.cpp
+++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/colorspace.cpp
@@ -65,9 +65,6 @@
uint8* pInV = pInput + size + size / 4;
Rgba* pOutColor = pOutput;
- const int u_offset = size;
- const int v_offset = u_offset + size / 4;
-
for (int y = 0; y < height; y += 2) {
for (int x = 0; x < width; x += 2) {
int u, v, y1, y2, y3, y4;
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/sobeloperator.cpp b/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/sobeloperator.cpp
index dc5c305..808b90d 100644
--- a/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/sobeloperator.cpp
+++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/sobeloperator.cpp
@@ -81,8 +81,6 @@
short* gyPtr = new short[3 * numPixels];
computeGradient(srcPtr, width, height, gxPtr, gyPtr);
- unsigned char* mag = magPtr;
- unsigned char* dir = dirPtr;
for (int i = 0; i < numPixels; ++i) {
for (int c = 0; c < 3; c++) {
int gx = static_cast<int>(*(gxPtr + 3 * i + c) / 8 + 127.5);
diff --git a/tests/HwAccelerationTest/res/drawable/default_wallpaper.jpg b/tests/HwAccelerationTest/res/drawable/default_wallpaper.jpg
deleted file mode 100644
index 5acad94..0000000
--- a/tests/HwAccelerationTest/res/drawable/default_wallpaper.jpg
+++ /dev/null
Binary files differ
diff --git a/tests/HwAccelerationTest/res/drawable/default_wallpaper.png b/tests/HwAccelerationTest/res/drawable/default_wallpaper.png
new file mode 100644
index 0000000..187a6c0
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable/default_wallpaper.png
Binary files differ
diff --git a/tests/HwAccelerationTest/res/layout/projection_clipping.xml b/tests/HwAccelerationTest/res/layout/projection_clipping.xml
index 1f2b939..1ea9f9c 100644
--- a/tests/HwAccelerationTest/res/layout/projection_clipping.xml
+++ b/tests/HwAccelerationTest/res/layout/projection_clipping.xml
@@ -3,24 +3,32 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
- <FrameLayout
+ <ScrollView
+ android:orientation="vertical"
android:translationX="50dp"
android:translationY="50dp"
android:elevation="30dp"
android:layout_width="200dp"
android:layout_height="200dp"
android:background="@drawable/round_rect_background">
- <View
- android:id="@+id/clickable1"
- android:layout_width="100dp"
- android:layout_height="100dp"
- android:background="?android:attr/selectableItemBackgroundBorderless"/>
- <View
- android:id="@+id/clickable2"
- android:translationX="50dp"
- android:translationY="10dp"
- android:layout_width="150dp"
- android:layout_height="100dp"
- android:background="?android:attr/selectableItemBackgroundBorderless"/>
- </FrameLayout>
+ <FrameLayout
+ android:layout_width="200dp"
+ android:layout_height="wrap_content">
+ <View
+ android:layout_width="200dp"
+ android:layout_height="2000dp"/>
+ <View
+ android:id="@+id/clickable1"
+ android:layout_width="100dp"
+ android:layout_height="100dp"
+ android:background="?android:attr/selectableItemBackgroundBorderless"/>
+ <View
+ android:id="@+id/clickable2"
+ android:translationX="50dp"
+ android:translationY="10dp"
+ android:layout_width="150dp"
+ android:layout_height="100dp"
+ android:background="?android:attr/selectableItemBackgroundBorderless"/>
+ </FrameLayout>
+ </ScrollView>
</LinearLayout>
diff --git a/tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java b/tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java
index 9f48d56..eda3f5e 100644
--- a/tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java
+++ b/tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java
@@ -17,19 +17,28 @@
package android.security.net.config;
import android.app.Activity;
+import android.os.Build;
import android.test.ActivityUnitTestCase;
import android.util.ArraySet;
import android.util.Pair;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.URL;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.TrustManager;
+import com.android.org.conscrypt.TrustedCertificateStore;
+
public class NetworkSecurityConfigTests extends ActivityUnitTestCase<Activity> {
public NetworkSecurityConfigTests() {
@@ -40,6 +49,51 @@
private static final byte[] G2_SPKI_SHA256
= hexToBytes("ec722969cb64200ab6638f68ac538e40abab5b19a6485661042a1061c4612776");
+ private static final byte[] TEST_CA_BYTES
+ = hexToBytes(
+ "3082036130820249a003020102020900bd54597d6750ea62300d06092a86"
+ + "4886f70d01010b05003047310b3009060355040613025553310b30090603"
+ + "5504080c0243413110300e060355040a0c07416e64726f69643119301706"
+ + "035504030c104e53436f6e6669672054657374204341301e170d31363032"
+ + "32343030313130325a170d3136303332353030313130325a3047310b3009"
+ + "060355040613025553310b300906035504080c0243413110300e06035504"
+ + "0a0c07416e64726f69643119301706035504030c104e53436f6e66696720"
+ + "5465737420434130820122300d06092a864886f70d01010105000382010f"
+ + "003082010a0282010100e15ce8fd5794029841e760d68d6e0159c9c67630"
+ + "089775bc728d83dae7e29e23fe5f6e113b789f4c5b22f052300ec6d5faa5"
+ + "724432e7bac96682792ef6e9617c939c4329dce8788cbdf3a11b621fac9e"
+ + "2edbec2d7e5e07296bbb544b89263137a6a31573a2362e05ca8ff9c886bf"
+ + "52df4ff93c45475145a40a83f2670e23669220a5a4bf2c6860edb78d3022"
+ + "192fb5dc5e8c118f70870f89da292dfe522751462f020ed556653c8b07f8"
+ + "89712a6e8196c457a637439e3073d7d917ab55aa51a146826367f7b5922a"
+ + "64fb2f95099de21eb98341fa76faa79ffbda123fe5b8adc614b16174e8b0"
+ + "dfdac2bbc4d526d2487ad2b009d53996ec23ffbd732112efa66b02030100"
+ + "01a350304e301d0603551d0e04160414f66e1a95486c879edd60a5756bc2"
+ + "f1f4677e128e301f0603551d23041830168014f66e1a95486c879edd60a5"
+ + "756bc2f1f4677e128e300c0603551d13040530030101ff300d06092a8648"
+ + "86f70d01010b05000382010100d2856130dccae24e5f8901900d94bc642f"
+ + "85466ab7cfa1066399077a168cd4b56603a9e2af9d2e58aec13101e338a4"
+ + "8e95e9c7a84d7991f0d381d4965eaada1b80fbbd8277445f449babe64f53"
+ + "ba625387460b592a1a97b14b8251115e6610350021a6e716ae22b905f8d4"
+ + "eae24e668e71b12ab51fd2f2bb600e074487dec720c3db14dbca504844b6"
+ + "933bb0248283ea95464747689c37d706d4839c7d0e9bd86abf98ddce5d36"
+ + "8b38bfe5062353e28d5be378827fade1caa6bba3df9cd9ebf83d839eae52"
+ + "780181f31973f15f982686ba6d899f7b644fd1f26c8ebb99f4c986faaf4c"
+ + "1b9e3d9d391943ce3fb9fa2e631bd66b8ef3d47fd85acf09ea3a30f15f");
+
+ private static final X509Certificate TEST_CA_CERT;
+
+ static {
+ try {
+ CertificateFactory factory = CertificateFactory.getInstance("X.509");
+ Certificate cert = factory.generateCertificate(new ByteArrayInputStream(TEST_CA_BYTES));
+ TEST_CA_CERT = (X509Certificate) cert;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+
private static byte[] hexToBytes(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
@@ -51,7 +105,6 @@
}
-
/**
* Return a NetworkSecurityConfig that has an empty TrustAnchor set. This should always cause a
* SSLHandshakeException when used for a connection.
@@ -174,7 +227,7 @@
public void testConfigBuilderUsesParents() throws Exception {
// Check that a builder with a parent uses the parent's values when non is set.
NetworkSecurityConfig config = new NetworkSecurityConfig.Builder()
- .setParent(NetworkSecurityConfig.getDefaultBuilder())
+ .setParent(NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.N))
.build();
assert(!config.getTrustAnchors().isEmpty());
}
@@ -208,4 +261,38 @@
TestUtils.assertUrlConnectionSucceeds(context, "developer.android.com", 443);
TestUtils.assertUrlConnectionFails(context, "google.com", 443);
}
+
+ public void testUserAddedCaOptIn() throws Exception {
+ TrustedCertificateStore store = new TrustedCertificateStore();
+ try {
+ // Install the test CA.
+ store.installCertificate(TEST_CA_CERT);
+ NetworkSecurityConfig preNConfig =
+ NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.M).build();
+ NetworkSecurityConfig nConfig =
+ NetworkSecurityConfig.getDefaultBuilder(Build.VERSION_CODES.N).build();
+ Set<TrustAnchor> preNAnchors = preNConfig.getTrustAnchors();
+ Set<TrustAnchor> nAnchors = nConfig.getTrustAnchors();
+ Set<X509Certificate> preNCerts = new HashSet<X509Certificate>();
+ for (TrustAnchor anchor : preNAnchors) {
+ preNCerts.add(anchor.certificate);
+ }
+ Set<X509Certificate> nCerts = new HashSet<X509Certificate>();
+ for (TrustAnchor anchor : nAnchors) {
+ nCerts.add(anchor.certificate);
+ }
+ assertTrue(preNCerts.contains(TEST_CA_CERT));
+ assertFalse(nCerts.contains(TEST_CA_CERT));
+ } finally {
+ // Delete the user added CA. We don't know the alias so just delete them all.
+ for (String alias : store.aliases()) {
+ if (store.isUser(alias)) {
+ try {
+ store.deleteCertificateEntry(alias);
+ } catch (Exception ignored) {
+ }
+ }
+ }
+ }
+ }
}
diff --git a/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java b/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java
index c8a8d6c..6463e1f 100644
--- a/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java
+++ b/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java
@@ -47,7 +47,7 @@
OnBufferingUpdateListener, OnCompletionListener, OnErrorListener,
OnAudioFocusChangeListener {
private static final String TAG = "MediaPlayerManager";
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
private static long sDebugInstanceId = 0;
private static final String[] SUPPORTED_FEATURES = {
diff --git a/tests/SoundTriggerTestApp/AndroidManifest.xml b/tests/SoundTriggerTestApp/AndroidManifest.xml
index a72b3dd..dc4cdb5 100644
--- a/tests/SoundTriggerTestApp/AndroidManifest.xml
+++ b/tests/SoundTriggerTestApp/AndroidManifest.xml
@@ -2,10 +2,12 @@
package="com.android.test.soundtrigger">
<uses-permission android:name="android.permission.MANAGE_SOUND_TRIGGER" />
+ <uses-permission android:name="android.permission.WAKE_LOCk" />
<application>
<activity
android:name="TestSoundTriggerActivity"
android:label="SoundTrigger Test Application"
+ android:screenOrientation="portrait"
android:theme="@android:style/Theme.Material">
<!--
<intent-filter>
diff --git a/tests/SoundTriggerTestApp/res/layout/main.xml b/tests/SoundTriggerTestApp/res/layout/main.xml
index 5ecc770..702be49 100644
--- a/tests/SoundTriggerTestApp/res/layout/main.xml
+++ b/tests/SoundTriggerTestApp/res/layout/main.xml
@@ -66,6 +66,7 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="20dp"
+ android:checkedButton="@+id/model_one"
android:orientation="vertical">
<RadioButton android:id="@+id/model_one"
android:layout_width="wrap_content"
@@ -84,15 +85,21 @@
android:onClick="onRadioButtonClicked"/>
</RadioGroup>
- <TextView
- android:id="@+id/console"
- android:gravity="left"
+<ScrollView
+ android:id="@+id/scroller_id"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:scrollbars="vertical"
+ android:fillViewport="true">
+
+ <TextView
+ android:id="@+id/console"
android:paddingTop="20pt"
android:layout_height="fill_parent"
- android:layout_width="match_parent"
- android:maxLines="40"
+ android:layout_width="fill_parent"
android:textSize="14dp"
- android:scrollbars = "vertical"
+ android:layout_weight="1.0"
android:text="@string/none">
</TextView>
+</ScrollView>
</LinearLayout>
diff --git a/tests/SoundTriggerTestApp/res/values/strings.xml b/tests/SoundTriggerTestApp/res/values/strings.xml
index 5f0fb1d..b4ca71b 100644
--- a/tests/SoundTriggerTestApp/res/values/strings.xml
+++ b/tests/SoundTriggerTestApp/res/values/strings.xml
@@ -24,5 +24,5 @@
<string name="model_one">Model One</string>
<string name="model_two">Model Two</string>
<string name="model_three">Model Three</string>
- <string name="none">Debug messages appear here:</string>
+ <string name="none">Debug messages appear here:\n</string>
</resources>
diff --git a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java
index 96a6966..3ca96d2 100644
--- a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java
+++ b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java
@@ -28,16 +28,19 @@
import android.text.Editable;
import android.text.method.ScrollingMovementMethod;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.PowerManager;
import android.os.UserManager;
import android.util.Log;
import android.view.View;
import android.widget.RadioButton;
+import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
public class TestSoundTriggerActivity extends Activity {
private static final String TAG = "TestSoundTriggerActivity";
- private static final boolean DBG = true;
+ private static final boolean DBG = false;
private SoundTriggerUtil mSoundTriggerUtil;
private Random mRandom;
@@ -52,6 +55,9 @@
private TextView mDebugView = null;
private int mSelectedModelId = 1;
+ private ScrollView mScrollView = null;
+ private PowerManager.WakeLock mScreenWakelock;
+ private Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -59,35 +65,68 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mDebugView = (TextView) findViewById(R.id.console);
+ mScrollView = (ScrollView) findViewById(R.id.scroller_id);
mDebugView.setText(mDebugView.getText(), TextView.BufferType.EDITABLE);
mDebugView.setMovementMethod(new ScrollingMovementMethod());
mSoundTriggerUtil = new SoundTriggerUtil(this);
mRandom = new Random();
+ mHandler = new Handler();
}
private void postMessage(String msg) {
Log.i(TAG, "Posted: " + msg);
((Editable) mDebugView.getText()).append(msg + "\n");
+ if ((mDebugView.getMeasuredHeight() - mScrollView.getScrollY()) <=
+ (mScrollView.getHeight() + mDebugView.getLineHeight())) {
+ scrollToBottom();
+ }
}
- private UUID getSelectedUuid() {
+ private void scrollToBottom() {
+ mScrollView.post(new Runnable() {
+ public void run() {
+ mScrollView.smoothScrollTo(0, mDebugView.getBottom());
+ }
+ });
+ }
+
+ private synchronized UUID getSelectedUuid() {
if (mSelectedModelId == 2) return mModelUuid2;
if (mSelectedModelId == 3) return mModelUuid3;
return mModelUuid1; // Default.
}
- private void setDetector(SoundTriggerDetector detector) {
- if (mSelectedModelId == 2) mDetector2 = detector;
- if (mSelectedModelId == 3) mDetector3 = detector;
+ private synchronized void setDetector(SoundTriggerDetector detector) {
+ if (mSelectedModelId == 2) {
+ mDetector2 = detector;
+ return;
+ }
+ if (mSelectedModelId == 3) {
+ mDetector3 = detector;
+ return;
+ }
mDetector1 = detector;
}
- private SoundTriggerDetector getDetector() {
+ private synchronized SoundTriggerDetector getDetector() {
if (mSelectedModelId == 2) return mDetector2;
if (mSelectedModelId == 3) return mDetector3;
return mDetector1;
}
+ private void screenWakeup() {
+ PowerManager pm = ((PowerManager)getSystemService(POWER_SERVICE));
+ if (mScreenWakelock == null) {
+ mScreenWakelock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "TAG");
+ }
+ mScreenWakelock.acquire();
+ }
+
+ private void screenRelease() {
+ PowerManager pm = ((PowerManager)getSystemService(POWER_SERVICE));
+ mScreenWakelock.release();
+ }
+
/**
* Called when the user clicks the enroll button.
* Performs a fresh enrollment.
@@ -124,7 +163,7 @@
Toast.makeText(this, "Sound model not found!!!", Toast.LENGTH_SHORT).show();
return;
}
- boolean status = mSoundTriggerUtil.deleteSoundModel(mModelUuid1);
+ boolean status = mSoundTriggerUtil.deleteSoundModel(modelUuid);
if (status) {
Toast.makeText(this, "Successfully deleted model UUID=" + soundModel.uuid,
Toast.LENGTH_SHORT)
@@ -165,7 +204,10 @@
UUID modelUuid = getSelectedUuid();
SoundTriggerDetector detector = getDetector();
if (detector == null) {
- Log.i(TAG, "Created an instance of the SoundTriggerDetector.");
+ Log.i(TAG, "Created an instance of the SoundTriggerDetector for model #" +
+ mSelectedModelId);
+ postMessage("Created an instance of the SoundTriggerDetector for model #" +
+ mSelectedModelId);
detector = mSoundTriggerUtil.createSoundTriggerDetector(modelUuid,
new DetectorCallback());
setDetector(detector);
@@ -174,6 +216,7 @@
if (!detector.startRecognition(
SoundTriggerDetector.RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS)) {
Log.e(TAG, "Fast failure attempting to start recognition.");
+ postMessage("Fast failure attempting to start recognition:" + mSelectedModelId);
}
}
@@ -181,30 +224,38 @@
SoundTriggerDetector detector = getDetector();
if (detector == null) {
Log.e(TAG, "Stop called on null detector.");
+ postMessage("Error: Stop called on null detector.");
return;
}
postMessage("Triggering stop recognition for model: " + mSelectedModelId);
if (!detector.stopRecognition()) {
Log.e(TAG, "Fast failure attempting to stop recognition.");
+ postMessage("Fast failure attempting to stop recognition: " + mSelectedModelId);
}
}
- public void onRadioButtonClicked(View view) {
+ public synchronized void onRadioButtonClicked(View view) {
// Is the button now checked?
boolean checked = ((RadioButton) view).isChecked();
// Check which radio button was clicked
switch(view.getId()) {
case R.id.model_one:
- if (checked) mSelectedModelId = 1;
- postMessage("Selected model one.");
+ if (checked) {
+ mSelectedModelId = 1;
+ postMessage("Selected model one.");
+ }
break;
case R.id.model_two:
- if (checked) mSelectedModelId = 2;
- postMessage("Selected model two.");
+ if (checked) {
+ mSelectedModelId = 2;
+ postMessage("Selected model two.");
+ }
break;
case R.id.model_three:
- if (checked) mSelectedModelId = 3;
- postMessage("Selected model three.");
+ if (checked) {
+ mSelectedModelId = 3;
+ postMessage("Selected model three.");
+ }
break;
}
}
@@ -217,6 +268,13 @@
public void onDetected(SoundTriggerDetector.EventPayload event) {
postMessage("onDetected(): " + eventPayloadToString(event));
+ screenWakeup();
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ screenRelease();
+ }
+ }, 1000L);
}
public void onError() {
diff --git a/tests/SoundTriggerTests/Android.mk b/tests/SoundTriggerTests/Android.mk
index 407a9d7..ac562b9 100644
--- a/tests/SoundTriggerTests/Android.mk
+++ b/tests/SoundTriggerTests/Android.mk
@@ -18,7 +18,14 @@
LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
+ifeq ($(SOUND_TRIGGER_USE_STUB_MODULE), 1)
+ LOCAL_SRC_FILES := $(call all-subdir-java-files)
+ LOCAL_PRIVILEGED_MODULE := true
+ LOCAL_CERTIFICATE := platform
+ TARGET_OUT_DATA_APPS_PRIVILEGED := $(TARGET_OUT_DATA)/priv-app
+else
+ LOCAL_SRC_FILES := src/android/hardware/soundtrigger/SoundTriggerTest.java
+endif
LOCAL_JAVA_LIBRARIES := android.test.runner
diff --git a/tests/SoundTriggerTests/AndroidManifest.xml b/tests/SoundTriggerTests/AndroidManifest.xml
index 5e5a108..e8b9dd3 100644
--- a/tests/SoundTriggerTests/AndroidManifest.xml
+++ b/tests/SoundTriggerTests/AndroidManifest.xml
@@ -14,7 +14,10 @@
limitations under the License.
-->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android.hardware.soundtrigger">
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.hardware.soundtrigger">
+ <uses-permission android:name="android.permission.MANAGE_SOUND_TRIGGER" />
+
<application>
<uses-library android:name="android.test.runner" />
</application>
diff --git a/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java b/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java
new file mode 100644
index 0000000..7acb472
--- /dev/null
+++ b/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.hardware.soundtrigger;
+
+import java.util.Random;
+import java.util.UUID;
+
+import android.content.Context;
+import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
+import android.media.soundtrigger.SoundTriggerManager;
+import android.os.ParcelUuid;
+import android.os.ServiceManager;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.internal.app.ISoundTriggerService;
+
+import java.util.Arrays;
+import java.util.Random;
+import java.util.UUID;
+
+public class GenericSoundModelTest extends AndroidTestCase {
+ private Random mRandom = new Random();
+
+ @SmallTest
+ public void testUpdateGenericSoundModel() throws Exception {
+ Context context = getContext();
+ ISoundTriggerService mSoundTriggerService = ISoundTriggerService.Stub.asInterface(
+ ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE));
+ SoundTriggerManager mSoundTriggerManager = (SoundTriggerManager) context.getSystemService(
+ Context.SOUND_TRIGGER_SERVICE);
+
+ byte[] data = new byte[1024];
+ mRandom.nextBytes(data);
+ UUID modelUuid = UUID.randomUUID();
+ UUID mVendorUuid = UUID.randomUUID();
+ GenericSoundModel model = new GenericSoundModel(modelUuid, mVendorUuid, data);
+
+ mSoundTriggerService.updateSoundModel(model);
+ GenericSoundModel returnedModel =
+ mSoundTriggerService.getSoundModel(new ParcelUuid(modelUuid));
+
+ assertEquals(model, returnedModel);
+
+ // Cleanup sound model
+ mSoundTriggerService.deleteSoundModel(new ParcelUuid(modelUuid));
+ }
+
+
+ @SmallTest
+ public void testDeleteGenericSoundModel() throws Exception {
+ Context context = getContext();
+ ISoundTriggerService mSoundTriggerService = ISoundTriggerService.Stub.asInterface(
+ ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE));
+ SoundTriggerManager mSoundTriggerManager = (SoundTriggerManager) context.getSystemService(
+ Context.SOUND_TRIGGER_SERVICE);
+
+ byte[] data = new byte[1024];
+ mRandom.nextBytes(data);
+ UUID modelUuid = UUID.randomUUID();
+ UUID mVendorUuid = UUID.randomUUID();
+ GenericSoundModel model = new GenericSoundModel(modelUuid, mVendorUuid, data);
+
+ mSoundTriggerService.updateSoundModel(model);
+ mSoundTriggerService.deleteSoundModel(new ParcelUuid(modelUuid));
+
+ GenericSoundModel returnedModel =
+ mSoundTriggerService.getSoundModel(new ParcelUuid(modelUuid));
+ assertEquals(null, returnedModel);
+ }
+}
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
index 46de201..0da1bb1 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
@@ -86,6 +86,167 @@
}
private Test[] mTests = new Test[] {
+ new Test("Min priority") {
+ public void run()
+ {
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("Min priority")
+ .setLights(0xff0000ff, 1, 0)
+ .setPriority(Notification.PRIORITY_MIN)
+ .build();
+ mNM.notify(7000, n);
+ }
+ },
+ new Test("Min priority, high pri flag") {
+ public void run()
+ {
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("Min priority, high pri flag")
+ .setLights(0xff0000ff, 1, 0)
+ .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
+ .setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
+ getPackageName() + "/raw/ringer"))
+ .setPriority(Notification.PRIORITY_MIN)
+ .setFullScreenIntent(makeIntent2(), true)
+ .build();
+ mNM.notify(7001, n);
+ }
+ },
+ new Test("Low priority") {
+ public void run()
+ {
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("Low priority")
+ .setLights(0xff0000ff, 1, 0)
+ .setPriority(Notification.PRIORITY_LOW)
+ .build();
+ mNM.notify(7002, n);
+ }
+ },
+ new Test("Default priority") {
+ public void run()
+ {
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("Default priority")
+ .setLights(0xff0000ff, 1, 0)
+ .setPriority(Notification.PRIORITY_DEFAULT)
+ .build();
+ mNM.notify(7004, n);
+ }
+ },
+ new Test("High priority") {
+ public void run()
+ {
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("High priority")
+ .setLights(0xff0000ff, 1, 0)
+ .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
+ .setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
+ getPackageName() + "/raw/ringer"))
+ .setPriority(Notification.PRIORITY_HIGH)
+ .build();
+ mNM.notify(7006, n);
+ }
+ },
+ new Test("Max priority") {
+ public void run()
+ {
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("Max priority")
+ .setLights(0xff0000ff, 1, 0)
+ .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
+ .setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
+ getPackageName() + "/raw/ringer"))
+ .setPriority(Notification.PRIORITY_MAX)
+ .setFullScreenIntent(makeIntent2(), false)
+ .build();
+ mNM.notify(7007, n);
+ }
+ },
+ new Test("Max priority with delay") {
+ public void run()
+ {
+ try {
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {
+ }
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("Max priority")
+ .setLights(0xff0000ff, 1, 0)
+ .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
+ .setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
+ getPackageName() + "/raw/ringer"))
+ .setPriority(Notification.PRIORITY_MAX)
+ .setFullScreenIntent(makeIntent2(), false)
+ .build();
+ mNM.notify(7008, n);
+ }
+ },
+ new Test("public notification") {
+ public void run()
+ {
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("public notification")
+ .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
+ .setPriority(Notification.PRIORITY_DEFAULT)
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .build();
+ mNM.notify(7009, n);
+ }
+ },
+ new Test("private notification, no public") {
+ public void run()
+ {
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("private only notification")
+ .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
+ .setPriority(Notification.PRIORITY_DEFAULT)
+ .setVisibility(Notification.VISIBILITY_PRIVATE)
+ .build();
+ mNM.notify(7010, n);
+ }
+ },
+ new Test("private notification, has public") {
+ public void run()
+ {
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("private version of notification")
+ .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
+ .setPriority(Notification.PRIORITY_DEFAULT)
+ .setVisibility(Notification.VISIBILITY_PRIVATE)
+ .setPublicVersion(new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("public notification of private notification")
+ .setPriority(Notification.PRIORITY_DEFAULT)
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .build())
+ .build();
+ mNM.notify(7011, n);
+ }
+ },
+ new Test("secret notification") {
+ public void run()
+ {
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("secret notification")
+ .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
+ .setPriority(Notification.PRIORITY_DEFAULT)
+ .setVisibility(Notification.VISIBILITY_SECRET)
+ .build();
+ mNM.notify(7012, n);
+ }
+ },
new Test("Off") {
public void run() {
PowerManager pm = (PowerManager)NotificationTestList.this.getSystemService(Context.POWER_SERVICE);
@@ -162,78 +323,6 @@
}
},
- new Test("with topic Hello") {
- public void run() {
- Notification.BigTextStyle bigText = new Notification.BigTextStyle();
- bigText.bigText("FgBHreherhethethethe\ntwetwrterter\netetweterteryetry");
- Notification n = new Notification.Builder(NotificationTestList.this)
- .setSmallIcon(R.drawable.icon1)
- .setStyle(bigText)
- .setWhen(mActivityCreateTime)
- .setContentTitle("hihi")
- .setContentText("This is a notification!!!")
- .setContentIntent(makeIntent2())
- .setTopic(new Notification.Topic("hello", "Hello"))
- .build();
-
- mNM.notify(70, n);
- }
- },
-
- new Test("with topic GoodBye") {
- public void run() {
- Notification.BigPictureStyle picture = new Notification.BigPictureStyle();
- picture.bigPicture(BitmapFactory.decodeResource(getResources(),
- R.id.large_icon_pineapple2));
- Notification n = new Notification.Builder(NotificationTestList.this)
- .setSmallIcon(R.drawable.icon1)
- .setWhen(mActivityCreateTime)
- .setContentTitle("byebye")
- .setContentText("This is a notification!!!")
- .setContentIntent(makeIntent2())
- .setTopic(new Notification.Topic("bye", "Goodbye"))
- .setStyle(picture)
- .build();
-
- mNM.notify(71, n);
- }
- },
- new Test("with topic Bananas") {
- public void run() {
- Notification.BigTextStyle bigText = new Notification.BigTextStyle();
- bigText.bigText("bananas are great\nso tasty\nyum\nyum\nyum\n");
- Notification n = new Notification.Builder(NotificationTestList.this)
- .setSmallIcon(R.drawable.icon1)
- .setStyle(bigText)
- .setWhen(mActivityCreateTime)
- .setContentTitle("bananananana")
- .setContentText("This is a banana!!!")
- .setContentIntent(makeIntent2())
- .setTopic(new Notification.Topic("bananas", "Bananas"))
- .build();
-
- mNM.notify(72, n);
- }
- },
-
- new Test("with delete intent") {
- public void run() {
- Notification.BigTextStyle bigText = new Notification.BigTextStyle();
- bigText.bigText("bananas are great\nso tasty\nyum\nyum\nyum\n");
- Notification n = new Notification.Builder(NotificationTestList.this)
- .setSmallIcon(R.drawable.icon1)
- .setStyle(bigText)
- .setWhen(mActivityCreateTime)
- .setContentTitle("bananananana")
- .setContentText("This is a banana!!!")
- .setTopic(new Notification.Topic("bananas", "Bananas"))
- .setDeleteIntent(makeIntent2())
- .build();
-
- mNM.notify(73, n);
- }
- },
-
new Test("Is blocked?") {
public void run() {
Toast.makeText(NotificationTestList.this,
@@ -242,18 +331,10 @@
}
},
- new Test("Topic banana importance?") {
+ new Test("importance?") {
public void run() {
Toast.makeText(NotificationTestList.this,
- "bananas importance? " + mNM.getImportance("bananas"),
- Toast.LENGTH_LONG).show();
- }
- },
-
- new Test("Topic garbage importance?") {
- public void run() {
- Toast.makeText(NotificationTestList.this,
- "garbage importance? " + mNM.getImportance("garbage"),
+ "importance? " + mNM.getImportance(),
Toast.LENGTH_LONG).show();
}
},
diff --git a/tests/UiBench/res/layout/activity_transition.xml b/tests/UiBench/res/layout/activity_transition.xml
index d4c6610..4556b02 100644
--- a/tests/UiBench/res/layout/activity_transition.xml
+++ b/tests/UiBench/res/layout/activity_transition.xml
@@ -15,6 +15,7 @@
~ limitations under the License
-->
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/transition_grid_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="true"
@@ -25,8 +26,6 @@
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:scaleType="centerCrop"
- android:layout_column="0"
- android:layout_row="0"
android:src="@drawable/ducky"
android:onClick="clicked"
android:transitionName="ducky"/>
@@ -36,8 +35,6 @@
android:layout_width="wrap_content"
android:scaleType="centerCrop"
android:src="@drawable/woot"
- android:layout_column="1"
- android:layout_row="0"
android:onClick="clicked"
android:transitionName="woot"/>
<ImageView
@@ -46,8 +43,6 @@
android:layout_width="wrap_content"
android:scaleType="centerCrop"
android:src="@drawable/ball"
- android:layout_column="0"
- android:layout_row="1"
android:onClick="clicked"
android:transitionName="ball"/>
<ImageView
@@ -56,8 +51,6 @@
android:layout_width="wrap_content"
android:scaleType="centerCrop"
android:src="@drawable/block"
- android:layout_column="1"
- android:layout_row="1"
android:onClick="clicked"
android:transitionName="block"/>
<ImageView
@@ -66,8 +59,6 @@
android:layout_width="wrap_content"
android:scaleType="centerCrop"
android:src="@drawable/jellies"
- android:layout_column="0"
- android:layout_row="2"
android:onClick="clicked"
android:transitionName="jellies"/>
<ImageView
@@ -76,8 +67,6 @@
android:layout_width="wrap_content"
android:scaleType="centerCrop"
android:src="@drawable/mug"
- android:layout_column="1"
- android:layout_row="2"
android:onClick="clicked"
android:transitionName="mug"/>
<ImageView
@@ -86,8 +75,6 @@
android:layout_width="wrap_content"
android:scaleType="centerCrop"
android:src="@drawable/pencil"
- android:layout_column="0"
- android:layout_row="3"
android:onClick="clicked"
android:transitionName="pencil"/>
<ImageView
@@ -96,8 +83,6 @@
android:layout_width="wrap_content"
android:scaleType="centerCrop"
android:src="@drawable/scissors"
- android:layout_column="1"
- android:layout_row="3"
android:onClick="clicked"
android:transitionName="scissors"/>
</GridLayout>
\ No newline at end of file
diff --git a/tests/UiBench/src/com/android/test/uibench/ActivityTransition.java b/tests/UiBench/src/com/android/test/uibench/ActivityTransition.java
index 1106a13..0a069c2 100644
--- a/tests/UiBench/src/com/android/test/uibench/ActivityTransition.java
+++ b/tests/UiBench/src/com/android/test/uibench/ActivityTransition.java
@@ -18,11 +18,13 @@
import android.app.ActivityOptions;
import android.app.SharedElementCallback;
import android.content.Intent;
+import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
+import android.widget.GridLayout;
import android.widget.ImageView;
import java.util.List;
@@ -90,6 +92,13 @@
getWindow().setBackgroundDrawable(new ColorDrawable(Color.BLACK));
setContentView(R.layout.activity_transition);
setupHero();
+
+ // Ensure that all images are visible regardless of orientation.
+ GridLayout gridLayout = (GridLayout) findViewById(R.id.transition_grid_layout);
+ boolean isPortrait =
+ getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
+ gridLayout.setRowCount(isPortrait ? 4 : 2);
+ gridLayout.setColumnCount(isPortrait ? 2 : 4);
}
private void setupHero() {
diff --git a/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java b/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java
index 2494db7..54c944f9 100644
--- a/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java
+++ b/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java
@@ -31,7 +31,7 @@
public class TestEnrollmentActivity extends Activity {
private static final String TAG = "TestEnrollmentActivity";
- private static final boolean DBG = true;
+ private static final boolean DBG = false;
/** Keyphrase related constants, must match those defined in enrollment_application.xml */
private static final int KEYPHRASE_ID = 101;
diff --git a/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java
index 3791d02..d7f4a38 100644
--- a/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java
@@ -140,7 +140,7 @@
@SmallTest
public void testSET_ACTIVITY_WATCHER() {
try {
- mAm.setActivityController(null);
+ mAm.setActivityController(null, false);
fail("IActivityManager.setActivityController did not throw SecurityException as"
+ " expected");
} catch (SecurityException e) {
diff --git a/tests/touchlag/Android.mk b/tests/touchlag/Android.mk
index 4f8aa1e..70b1989 100644
--- a/tests/touchlag/Android.mk
+++ b/tests/touchlag/Android.mk
@@ -9,6 +9,8 @@
LOCAL_MODULE:= test-touchlag
+LOCAL_CFLAGS += -Wall -Wextra -Werror
+
LOCAL_MODULE_TAGS := tests
include $(BUILD_EXECUTABLE)
diff --git a/tests/touchlag/touchlag.cpp b/tests/touchlag/touchlag.cpp
index df4befb..9264a25 100644
--- a/tests/touchlag/touchlag.cpp
+++ b/tests/touchlag/touchlag.cpp
@@ -54,11 +54,11 @@
void drawTwoPixels(Buffer* buf, uint32_t pixel, ssize_t x, ssize_t y, size_t w) {
if (y>0 && y<ssize_t(buf->h)) {
uint32_t* bits = buf->pixels + y * buf->s;
- if (x>=0 && x<buf->w) {
+ if (x>=0 && x<ssize_t(buf->w)) {
bits[x] = pixel;
}
ssize_t W(w);
- if ((x+W)>=0 && (x+W)<buf->w) {
+ if ((x+W)>=0 && (x+W)<ssize_t(buf->w)) {
bits[x+W] = pixel;
}
}
@@ -251,13 +251,13 @@
Queue queue;
- int x=0, y=0, down=0;
+ int x=0, y=0;
int lag_x=0, lag_y=0;
clearBuffer(&framebuffer, 0);
while (true) {
uint32_t crt = 0;
- int err = ioctl(fd, FBIO_WAITFORVSYNC, &crt);
+ ioctl(fd, FBIO_WAITFORVSYNC, &crt);
// draw beam marker
drawRect(&framebuffer, 0x400000, framebuffer.w-2, 0, 2, framebuffer.h);
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index 3b01827..cbd8480 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -373,7 +373,7 @@
void AaptLocaleValue::initFromResTable(const ResTable_config& config) {
config.unpackLanguage(language);
config.unpackRegion(region);
- if (config.localeScriptWasProvided) {
+ if (config.localeScript[0] && !config.localeScriptWasComputed) {
memcpy(script, config.localeScript, sizeof(config.localeScript));
}
@@ -388,10 +388,10 @@
if (script[0]) {
memcpy(out->localeScript, script, sizeof(out->localeScript));
- out->localeScriptWasProvided = true;
+ out->localeScriptWasComputed = false;
} else {
out->computeScript();
- out->localeScriptWasProvided = false;
+ out->localeScriptWasComputed = true;
}
if (variant[0]) {
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index e87c7d40..6a4b637 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -308,29 +308,11 @@
}
added = true;
- String16 attr16("attr");
-
- if (outTable->hasBagOrEntry(myPackage, attr16, ident)) {
- sourcePos.error("Attribute \"%s\" has already been defined\n",
- String8(ident).string());
+ if (!outTable->makeAttribute(myPackage, ident, sourcePos, type, comment, appendComment)) {
hasErrors = true;
return UNKNOWN_ERROR;
}
-
- char numberStr[16];
- sprintf(numberStr, "%d", type);
- status_t err = outTable->addBag(sourcePos, myPackage,
- attr16, ident, String16(""),
- String16("^type"),
- String16(numberStr), NULL, NULL);
- if (err != NO_ERROR) {
- hasErrors = true;
- return err;
- }
- outTable->appendComment(myPackage, attr16, ident, comment, appendComment);
- //printf("Attribute %s comment: %s\n", String8(ident).string(),
- // String8(comment).string());
- return err;
+ return NO_ERROR;
}
};
@@ -2115,6 +2097,61 @@
return false;
}
+bool ResourceTable::makeAttribute(const String16& package,
+ const String16& name,
+ const SourcePos& source,
+ int32_t format,
+ const String16& comment,
+ bool shouldAppendComment) {
+ const String16 attr16("attr");
+
+ // First look for this in the included resources...
+ uint32_t rid = mAssets->getIncludedResources()
+ .identifierForName(name.string(), name.size(),
+ attr16.string(), attr16.size(),
+ package.string(), package.size());
+ if (rid != 0) {
+ source.error("Attribute \"%s\" has already been defined", String8(name).string());
+ return false;
+ }
+
+ sp<ResourceTable::Entry> entry = getEntry(package, attr16, name, source, false);
+ if (entry == NULL) {
+ source.error("Failed to create entry attr/%s", String8(name).string());
+ return false;
+ }
+
+ if (entry->makeItABag(source) != NO_ERROR) {
+ return false;
+ }
+
+ const String16 formatKey16("^type");
+ const String16 formatValue16(String8::format("%d", format));
+
+ ssize_t idx = entry->getBag().indexOfKey(formatKey16);
+ if (idx >= 0) {
+ // We have already set a format for this attribute, check if they are different.
+ // We allow duplicate attribute definitions so long as they are identical.
+ // This is to ensure inter-operation with libraries that define the same generic attribute.
+ const Item& formatItem = entry->getBag().valueAt(idx);
+ if ((format & (ResTable_map::TYPE_ENUM | ResTable_map::TYPE_FLAGS)) ||
+ formatItem.value != formatValue16) {
+ source.error("Attribute \"%s\" already defined with incompatible format.\n"
+ "%s:%d: Original attribute defined here.",
+ String8(name).string(), formatItem.sourcePos.file.string(),
+ formatItem.sourcePos.line);
+ return false;
+ }
+ } else {
+ entry->addToBag(source, formatKey16, formatValue16);
+ // Increment the number of resources we have. This is used to determine if we should
+ // even generate a resource table.
+ mNumLocal++;
+ }
+ appendComment(package, attr16, name, comment, shouldAppendComment);
+ return true;
+}
+
void ResourceTable::canAddEntry(const SourcePos& pos,
const String16& package, const String16& type, const String16& name)
{
diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h
index 4b7b3cd..cf1e992 100644
--- a/tools/aapt/ResourceTable.h
+++ b/tools/aapt/ResourceTable.h
@@ -571,6 +571,18 @@
void getDensityVaryingResources(KeyedVector<Symbol, Vector<SymbolDefinition> >& resources);
+ /**
+ * Make an attribute with the specified format. If another attribute with the same name but
+ * different format exists, this method returns false. If the name is not taken, or if the
+ * format is identical, this returns true.
+ */
+ bool makeAttribute(const String16& package,
+ const String16& name,
+ const SourcePos& source,
+ int32_t format,
+ const String16& comment,
+ bool appendComment);
+
private:
void writePublicDefinitions(const String16& package, FILE* fp, bool pub);
sp<Package> getPackage(const String16& package);
diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk
index f9d35ab..57a7692 100644
--- a/tools/aapt2/Android.mk
+++ b/tools/aapt2/Android.mk
@@ -13,15 +13,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-
-# This tool is prebuilt if we're doing an app-only build.
-ifeq ($(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)),)
+LOCAL_PATH:= $(call my-dir)
# ==========================================================
# Setup some common variables for the different build
# targets here.
# ==========================================================
-LOCAL_PATH:= $(call my-dir)
main := Main.cpp
sources := \
@@ -192,4 +189,6 @@
include $(BUILD_HOST_EXECUTABLE)
-endif # No TARGET_BUILD_APPS or TARGET_BUILD_PDK
+ifeq ($(ONE_SHOT_MAKEFILE),)
+include $(call all-makefiles-under,$(LOCAL_PATH))
+endif
diff --git a/tools/aapt2/Locale.cpp b/tools/aapt2/Locale.cpp
index 6acf3b0..12f56fc 100644
--- a/tools/aapt2/Locale.cpp
+++ b/tools/aapt2/Locale.cpp
@@ -253,7 +253,7 @@
void LocaleValue::initFromResTable(const ResTable_config& config) {
config.unpackLanguage(language);
config.unpackRegion(region);
- if (config.localeScriptWasProvided) {
+ if (config.localeScript[0] && !config.localeScriptWasComputed) {
memcpy(script, config.localeScript, sizeof(config.localeScript));
}
@@ -268,10 +268,10 @@
if (script[0]) {
memcpy(out->localeScript, script, sizeof(out->localeScript));
- out->localeScriptWasProvided = true;
+ out->localeScriptWasComputed = false;
} else {
out->computeScript();
- out->localeScriptWasProvided = false;
+ out->localeScriptWasComputed = true;
}
if (variant[0]) {
diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h
index c71e249..4d1db5b 100644
--- a/tools/aapt2/Resource.h
+++ b/tools/aapt2/Resource.h
@@ -81,9 +81,6 @@
ResourceName(const StringPiece16& p, ResourceType t, const StringPiece16& e);
bool isValid() const;
- bool operator<(const ResourceName& rhs) const;
- bool operator==(const ResourceName& rhs) const;
- bool operator!=(const ResourceName& rhs) const;
std::u16string toString() const;
};
@@ -109,10 +106,6 @@
ResourceName toResourceName() const;
bool isValid() const;
-
- bool operator<(const ResourceNameRef& rhs) const;
- bool operator==(const ResourceNameRef& rhs) const;
- bool operator!=(const ResourceNameRef& rhs) const;
};
/**
@@ -138,17 +131,11 @@
uint8_t packageId() const;
uint8_t typeId() const;
uint16_t entryId() const;
- bool operator<(const ResourceId& rhs) const;
- bool operator==(const ResourceId& rhs) const;
};
struct SourcedResourceName {
ResourceName name;
size_t line;
-
- inline bool operator==(const SourcedResourceName& rhs) const {
- return name == rhs.name && line == rhs.line;
- }
};
struct ResourceFile {
@@ -227,16 +214,23 @@
return static_cast<uint16_t>(id);
}
-inline bool ResourceId::operator<(const ResourceId& rhs) const {
- return id < rhs.id;
+inline bool operator<(const ResourceId& lhs, const ResourceId& rhs) {
+ return lhs.id < rhs.id;
}
-inline bool ResourceId::operator==(const ResourceId& rhs) const {
- return id == rhs.id;
+inline bool operator>(const ResourceId& lhs, const ResourceId& rhs) {
+ return lhs.id > rhs.id;
}
-inline ::std::ostream& operator<<(::std::ostream& out,
- const ResourceId& resId) {
+inline bool operator==(const ResourceId& lhs, const ResourceId& rhs) {
+ return lhs.id == rhs.id;
+}
+
+inline bool operator!=(const ResourceId& lhs, const ResourceId& rhs) {
+ return lhs.id != rhs.id;
+}
+
+inline ::std::ostream& operator<<(::std::ostream& out, const ResourceId& resId) {
std::ios_base::fmtflags oldFlags = out.flags();
char oldFill = out.fill();
out << "0x" << std::internal << std::setfill('0') << std::setw(8)
@@ -266,29 +260,21 @@
return !package.empty() && !entry.empty();
}
-inline bool ResourceName::operator<(const ResourceName& rhs) const {
- return std::tie(package, type, entry)
+inline bool operator<(const ResourceName& lhs, const ResourceName& rhs) {
+ return std::tie(lhs.package, lhs.type, lhs.entry)
< std::tie(rhs.package, rhs.type, rhs.entry);
}
-inline bool operator<(const ResourceName& lhs, const ResourceNameRef& b) {
- return ResourceNameRef(lhs) < b;
-}
-
-inline bool ResourceName::operator==(const ResourceName& rhs) const {
- return std::tie(package, type, entry)
+inline bool operator==(const ResourceName& lhs, const ResourceName& rhs) {
+ return std::tie(lhs.package, lhs.type, lhs.entry)
== std::tie(rhs.package, rhs.type, rhs.entry);
}
-inline bool ResourceName::operator!=(const ResourceName& rhs) const {
- return std::tie(package, type, entry)
+inline bool operator!=(const ResourceName& lhs, const ResourceName& rhs) {
+ return std::tie(lhs.package, lhs.type, lhs.entry)
!= std::tie(rhs.package, rhs.type, rhs.entry);
}
-inline bool operator!=(const ResourceName& lhs, const ResourceNameRef& rhs) {
- return ResourceNameRef(lhs) != rhs;
-}
-
inline std::u16string ResourceName::toString() const {
std::u16string result;
if (!package.empty()) {
@@ -333,18 +319,18 @@
return !package.empty() && !entry.empty();
}
-inline bool ResourceNameRef::operator<(const ResourceNameRef& rhs) const {
- return std::tie(package, type, entry)
+inline bool operator<(const ResourceNameRef& lhs, const ResourceNameRef& rhs) {
+ return std::tie(lhs.package, lhs.type, lhs.entry)
< std::tie(rhs.package, rhs.type, rhs.entry);
}
-inline bool ResourceNameRef::operator==(const ResourceNameRef& rhs) const {
- return std::tie(package, type, entry)
+inline bool operator==(const ResourceNameRef& lhs, const ResourceNameRef& rhs) {
+ return std::tie(lhs.package, lhs.type, lhs.entry)
== std::tie(rhs.package, rhs.type, rhs.entry);
}
-inline bool ResourceNameRef::operator!=(const ResourceNameRef& rhs) const {
- return std::tie(package, type, entry)
+inline bool operator!=(const ResourceNameRef& lhs, const ResourceNameRef& rhs) {
+ return std::tie(lhs.package, lhs.type, lhs.entry)
!= std::tie(rhs.package, rhs.type, rhs.entry);
}
@@ -355,6 +341,18 @@
return out << name.type << "/" << name.entry;
}
+inline bool operator<(const ResourceName& lhs, const ResourceNameRef& b) {
+ return ResourceNameRef(lhs) < b;
+}
+
+inline bool operator!=(const ResourceName& lhs, const ResourceNameRef& rhs) {
+ return ResourceNameRef(lhs) != rhs;
+}
+
+inline bool operator==(const SourcedResourceName& lhs, const SourcedResourceName& rhs) {
+ return lhs.name == rhs.name && lhs.line == rhs.line;
+}
+
} // namespace aapt
#endif // AAPT_RESOURCE_H
diff --git a/tools/aapt2/compile/Compile.cpp b/tools/aapt2/compile/Compile.cpp
index 5f9719e..2452a1d 100644
--- a/tools/aapt2/compile/Compile.cpp
+++ b/tools/aapt2/compile/Compile.cpp
@@ -422,10 +422,6 @@
}
class CompileContext : public IAaptContext {
-private:
- StdErrDiagnostics mDiagnostics;
- bool mVerbose = false;
-
public:
void setVerbose(bool val) {
mVerbose = val;
@@ -444,18 +440,24 @@
return nullptr;
}
- StringPiece16 getCompilationPackage() override {
- return {};
+ const std::u16string& getCompilationPackage() override {
+ static std::u16string empty;
+ return empty;
}
uint8_t getPackageId() override {
return 0x0;
}
- ISymbolTable* getExternalSymbols() override {
+ SymbolTable* getExternalSymbols() override {
abort();
return nullptr;
}
+
+private:
+ StdErrDiagnostics mDiagnostics;
+ bool mVerbose = false;
+
};
/**
diff --git a/tools/aapt2/compile/Png.cpp b/tools/aapt2/compile/Png.cpp
index 9837c4e..bbf7f41 100644
--- a/tools/aapt2/compile/Png.cpp
+++ b/tools/aapt2/compile/Png.cpp
@@ -1175,7 +1175,7 @@
if (errorMsg) {
std::stringstream err;
err << "9-patch malformed: " << errorMsg;
- if (!errorEdge) {
+ if (errorEdge) {
err << "." << std::endl;
if (errorPixel >= 0) {
err << "Found at pixel #" << errorPixel << " along " << errorEdge << " edge";
diff --git a/tools/aapt2/data/AndroidManifest.xml b/tools/aapt2/data/AndroidManifest.xml
deleted file mode 100644
index d3b2fbe..0000000
--- a/tools/aapt2/data/AndroidManifest.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.app">
- <application
- android:name=".ActivityMain">
- </application>
-</manifest>
diff --git a/tools/aapt2/data/Makefile b/tools/aapt2/data/Makefile
deleted file mode 100644
index 37012de..0000000
--- a/tools/aapt2/data/Makefile
+++ /dev/null
@@ -1,61 +0,0 @@
-##
-# Environment dependent variables
-##
-
-AAPT := aapt2
-ZIPALIGN := zipalign -f 4
-FRAMEWORK := ../../../../../out/target/common/obj/APPS/framework-res_intermediates/package-export.apk
-
-##
-# Project depenedent variables
-##
-
-LOCAL_PACKAGE := com.android.app
-LOCAL_RESOURCE_DIR := res
-LOCAL_LIBS := lib/out/package.apk
-LOCAL_OUT := out
-LOCAL_GEN := out/gen
-LOCAL_PROGUARD := out/proguard.rule
-
-##
-# AAPT2 custom rules.
-##
-
-PRIVATE_R_FILE := $(LOCAL_GEN)/$(subst .,/,$(LOCAL_PACKAGE))/R.java
-$(info PRIVATE_R_FILE = $(PRIVATE_R_FILE))
-
-# Eg: framework.apk, etc.
-PRIVATE_INCLUDES := $(FRAMEWORK)
-$(info PRIVATE_INCLUDES = $(PRIVATE_INCLUDES))
-
-# Eg: res/drawable/icon.png, res/values/styles.xml
-PRIVATE_RESOURCES := $(shell find $(LOCAL_RESOURCE_DIR) -mindepth 1 -maxdepth 2 -type f)
-$(info PRIVATE_RESOURCES = $(PRIVATE_RESOURCES))
-
-PRIVATE_RESOURCE_OBJECTS := $(subst /,_,$(patsubst $(LOCAL_RESOURCE_DIR)/%,%,$(filter $(LOCAL_RESOURCE_DIR)/values%,$(PRIVATE_RESOURCES))))
-PRIVATE_RESOURCE_OBJECTS := $(addprefix $(LOCAL_OUT)/,$(PRIVATE_RESOURCE_OBJECTS:.xml=.arsc.flat))
-$(info PRIVATE_RESOURCE_OBJECTS = $(PRIVATE_RESOURCE_OBJECTS))
-
-PRIVATE_FILE_OBJECTS := $(subst /,_,$(patsubst $(LOCAL_RESOURCE_DIR)/%,%,$(filter-out $(LOCAL_RESOURCE_DIR)/values%,$(PRIVATE_RESOURCES))))
-PRIVATE_FILE_OBJECTS := $(addprefix $(LOCAL_OUT)/,$(addsuffix .flat,$(PRIVATE_FILE_OBJECTS)))
-$(info PRIVATE_FILE_OBJECTS = $(PRIVATE_FILE_OBJECTS))
-
-.SECONDEXPANSION:
-
-$(LOCAL_OUT)/%.arsc.flat: $(LOCAL_RESOURCE_DIR)/$$(subst _,/,%).xml
- $(AAPT) compile -o $(LOCAL_OUT) $<
-
-$(LOCAL_OUT)/%.flat: $(LOCAL_RESOURCE_DIR)/$$(subst _,/,%)
- $(AAPT) compile -o $(LOCAL_OUT) $<
-
-$(LOCAL_PROGUARD) $(LOCAL_OUT)/package.apk: AndroidManifest.xml
-$(PRIVATE_R_FILE) $(LOCAL_PROGUARD) $(LOCAL_OUT)/package.apk: $(PRIVATE_FILE_OBJECTS) $(PRIVATE_RESOURCE_OBJECTS)
- $(AAPT) link -o $(LOCAL_OUT)/package.apk --manifest AndroidManifest.xml --java $(LOCAL_GEN) --proguard $(LOCAL_PROGUARD) -I $(PRIVATE_INCLUDES) $(filter-out AndroidManifest.xml,$^) -v
-
-# Create the out directory if needed.
-dummy := $(shell test -d $(LOCAL_OUT) || mkdir -p $(LOCAL_OUT))
-
-.PHONY: all
-all: $(LOCAL_OUT)/package.apk $(LOCAL_PROGUARD) $(PRIVATE_R_FILE)
-
-.DEFAULT_GOAL := all
diff --git a/tools/aapt2/data/lib/AndroidManifest.xml b/tools/aapt2/data/lib/AndroidManifest.xml
deleted file mode 100644
index 08b468e..0000000
--- a/tools/aapt2/data/lib/AndroidManifest.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.appcompat">
-
- <uses-feature android:name="bloooop" />
-</manifest>
diff --git a/tools/aapt2/data/lib/Makefile b/tools/aapt2/data/lib/Makefile
deleted file mode 100644
index 741be9a..0000000
--- a/tools/aapt2/data/lib/Makefile
+++ /dev/null
@@ -1,81 +0,0 @@
-##
-# Environment dependent variables
-##
-
-AAPT := aapt2
-ZIPALIGN := zipalign -f 4
-FRAMEWORK := ../../../../../../out/target/common/obj/APPS/framework-res_intermediates/package-export.apk
-
-##
-# Project depenedent variables
-##
-
-LOCAL_PACKAGE := android.appcompat
-LOCAL_RESOURCE_DIR := res
-LOCAL_OUT := out
-LOCAL_GEN := out/gen
-
-##
-# AAPT2 custom rules.
-##
-
-PRIVATE_APK_UNALIGNED := $(LOCAL_OUT)/package-unaligned.apk
-PRIVATE_APK_ALIGNED := $(LOCAL_OUT)/package.apk
-
-# Eg: framework.apk, etc.
-PRIVATE_LIBS := $(FRAMEWORK)
-$(info PRIVATE_LIBS = $(PRIVATE_LIBS))
-
-# Eg: gen/com/android/app/R.java
-PRIVATE_R_JAVA := $(LOCAL_GEN)/$(subst .,/,$(LOCAL_PACKAGE))/R.java
-$(info PRIVATE_R_JAVA = $(PRIVATE_R_JAVA))
-
-# Eg: res/drawable/icon.png, res/values/styles.xml
-PRIVATE_RESOURCES := $(shell find $(LOCAL_RESOURCE_DIR) -mindepth 1 -maxdepth 2 -type f)
-$(info PRIVATE_RESOURCES = $(PRIVATE_RESOURCES))
-
-# Eg: drawable, values, layouts
-PRIVATE_RESOURCE_TYPES := \
- $(patsubst $(LOCAL_RESOURCE_DIR)/%/,%,$(sort $(dir $(PRIVATE_RESOURCES))))
-$(info PRIVATE_RESOURCE_TYPES = $(PRIVATE_RESOURCE_TYPES))
-
-# Eg: out/values-v4.apk, out/drawable-xhdpi.apk
-PRIVATE_INTERMEDIATE_TABLES := $(patsubst %,$(LOCAL_OUT)/%.apk,$(PRIVATE_RESOURCE_TYPES))
-$(info PRIVATE_INTERMEDIATE_TABLES = $(PRIVATE_INTERMEDIATE_TABLES))
-
-# Generates rules for collect phase.
-# $1: Resource type (values-v4)
-# returns: out/values-v4.apk: res/values-v4/styles.xml res/values-v4/colors.xml
-define make-collect-rule
-$(LOCAL_OUT)/$1.apk: $(filter $(LOCAL_RESOURCE_DIR)/$1/%,$(PRIVATE_RESOURCES))
- $(AAPT) compile -o $$@ $$^
-endef
-
-# Collect: out/values-v4.apk <- res/values-v4/styles.xml res/values-v4/colors.xml
-$(foreach d,$(PRIVATE_RESOURCE_TYPES),$(eval $(call make-collect-rule,$d)))
-
-# Link: out/package-unaligned.apk <- out/values-v4.apk out/drawable-v4.apk
-$(PRIVATE_APK_UNALIGNED): $(PRIVATE_INTERMEDIATE_TABLES) $(PRIVATE_LIBS) AndroidManifest.xml
- $(AAPT) link --manifest AndroidManifest.xml $(addprefix -I ,$(PRIVATE_LIBS)) --java $(LOCAL_GEN) -o $@ $(PRIVATE_INTERMEDIATE_TABLES) --static-lib
-
-# R.java: gen/com/android/app/R.java <- out/resources.arsc
-# No action since R.java is generated when out/resources.arsc is.
-$(PRIVATE_R_JAVA): $(PRIVATE_APK_UNALIGNED)
-
-# Assemble: zip out/resources.arsc AndroidManifest.xml and res/**/*
-$(PRIVATE_APK_ALIGNED): $(PRIVATE_APK_UNALIGNED)
- $(ZIPALIGN) $< $@
-
-# Create the out directory if needed.
-dummy := $(shell test -d $(LOCAL_OUT) || mkdir -p $(LOCAL_OUT))
-
-.PHONY: java
-java: $(PRIVATE_R_JAVA)
-
-.PHONY: assemble
-assemble: $(PRIVATE_APK_ALIGNED)
-
-.PHONY: all
-all: assemble java
-
-.DEFAULT_GOAL := all
diff --git a/tools/aapt2/data/lib/res/layout/main.xml b/tools/aapt2/data/lib/res/layout/main.xml
deleted file mode 100644
index 187ed2d..0000000
--- a/tools/aapt2/data/lib/res/layout/main.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
diff --git a/tools/aapt2/data/lib/res/raw/hello.txt b/tools/aapt2/data/lib/res/raw/hello.txt
deleted file mode 100644
index 44fc22b..0000000
--- a/tools/aapt2/data/lib/res/raw/hello.txt
+++ /dev/null
@@ -1 +0,0 @@
-Oh howdy there
diff --git a/tools/aapt2/data/lib/res/values/styles.xml b/tools/aapt2/data/lib/res/values/styles.xml
deleted file mode 100644
index 4ce6333..0000000
--- a/tools/aapt2/data/lib/res/values/styles.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <style name="Platform.AppCompat" parent="@android:style/Theme">
- <item name="android:windowNoTitle">true</item>
- </style>
-
- <bool name="allow">true</bool>
-</resources>
diff --git a/tools/aapt2/data/res/drawable/image.xml b/tools/aapt2/data/res/drawable/image.xml
deleted file mode 100644
index 9b38739..0000000
--- a/tools/aapt2/data/res/drawable/image.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<vector />
diff --git a/tools/aapt2/data/res/layout-v21/main.xml b/tools/aapt2/data/res/layout-v21/main.xml
deleted file mode 100644
index 959b349..0000000
--- a/tools/aapt2/data/res/layout-v21/main.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:support="http://schemas.android.com/apk/res/android.appcompat"
- android:id="@+id/view"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-</LinearLayout>
diff --git a/tools/aapt2/data/res/layout/main.xml b/tools/aapt2/data/res/layout/main.xml
deleted file mode 100644
index 8a5e9e8..0000000
--- a/tools/aapt2/data/res/layout/main.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:support="http://schemas.android.com/apk/res/android.appcompat"
- android:id="@+id/view"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <fragment class="android.test.sample.App$Inner" />
-
- <variable name="user" type="com.android.User" />
-
- <View xmlns:app="http://schemas.android.com/apk/res-auto"
- android:id="@+id/me"
- android:layout_width="1dp"
- android:onClick="doClick"
- android:text="@{user.name}"
- android:background="#ffffff"
- android:layout_height="match_parent"
- app:flags="complex|weak"
- android:colorAccent="#ffffff"/>
-</LinearLayout>
diff --git a/tools/aapt2/data/res/values-v4/styles.xml b/tools/aapt2/data/res/values-v4/styles.xml
deleted file mode 100644
index 979a82a..0000000
--- a/tools/aapt2/data/res/values-v4/styles.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <style name="App" parent="android:Theme.Material">
- <item name="android:colorAccent">@color/accent</item>
- <item name="android:text">Hey</item>
- </style>
-</resources>
diff --git a/tools/aapt2/data/res/values/colors.xml b/tools/aapt2/data/res/values/colors.xml
deleted file mode 100644
index 89db5fb..0000000
--- a/tools/aapt2/data/res/values/colors.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <color name="primary">#f44336</color>
- <color name="primary_dark">#b71c1c</color>
- <color name="accent">#fdd835</color>
-</resources>
diff --git a/tools/aapt2/data/res/values/styles.xml b/tools/aapt2/data/res/values/styles.xml
deleted file mode 100644
index 2bbdad1..0000000
--- a/tools/aapt2/data/res/values/styles.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources xmlns:lib="http://schemas.android.com/apk/res/android.appcompat">
- <style name="App">
- <item name="android:background">@color/primary</item>
- <item name="android:colorPrimary">@color/primary</item>
- <item name="android:colorPrimaryDark">@color/primary_dark</item>
- <item name="android:colorAccent">@color/accent</item>
- </style>
- <attr name="custom" format="reference" />
- <style name="Pop">
- <item name="custom">@android:drawable/btn_default</item>
- <item name="android:focusable">true</item>
- </style>
- <string name="yo">@string/wow</string>
-
- <declare-styleable name="View">
- <attr name="custom" />
- <attr name="decor">
- <enum name="no-border" value="0"/>
- <enum name="border" value="1"/>
- <enum name="shadow" value="2"/>
- </attr>
- </declare-styleable>
-
-</resources>
diff --git a/tools/aapt2/data/res/values/test.xml b/tools/aapt2/data/res/values/test.xml
deleted file mode 100644
index d7ab1c8..0000000
--- a/tools/aapt2/data/res/values/test.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="hooha"><font bgcolor="#ffffff">Hey guys!</font> <xliff:g>My</xliff:g> name is <b>Adam</b>. How <b><i>are</i></b> you?</string>
- <public name="hooha" type="string" id="0x7f020001"/>
- <string name="wow">@android:string/ok</string>
- <public name="layout_width" type="attr" />
- <attr name="layout_width" format="boolean" />
- <attr name="flags">
- <flag name="complex" value="1" />
- <flag name="pub" value="2" />
- <flag name="weak" value="4" />
- </attr>
-</resources>
diff --git a/tools/aapt2/data/resources.arsc b/tools/aapt2/data/resources.arsc
deleted file mode 100644
index 6a416df..0000000
--- a/tools/aapt2/data/resources.arsc
+++ /dev/null
Binary files differ
diff --git a/tools/aapt2/data/resources_base.arsc b/tools/aapt2/data/resources_base.arsc
deleted file mode 100644
index f9d0610..0000000
--- a/tools/aapt2/data/resources_base.arsc
+++ /dev/null
Binary files differ
diff --git a/tools/aapt2/data/resources_hdpi.arsc b/tools/aapt2/data/resources_hdpi.arsc
deleted file mode 100644
index 97232a3..0000000
--- a/tools/aapt2/data/resources_hdpi.arsc
+++ /dev/null
Binary files differ
diff --git a/tools/aapt2/dump/Dump.cpp b/tools/aapt2/dump/Dump.cpp
index ad7de0a..56b9f9a 100644
--- a/tools/aapt2/dump/Dump.cpp
+++ b/tools/aapt2/dump/Dump.cpp
@@ -17,6 +17,7 @@
#include "Debug.h"
#include "Diagnostics.h"
#include "Flags.h"
+#include "io/ZipArchive.h"
#include "process/IResourceTableConsumer.h"
#include "proto/ProtoSerialize.h"
#include "util/Files.h"
@@ -56,6 +57,35 @@
void tryDumpFile(IAaptContext* context, const std::string& filePath) {
std::string err;
+ std::unique_ptr<io::ZipFileCollection> zip = io::ZipFileCollection::create(filePath, &err);
+ if (zip) {
+ io::IFile* file = zip->findFile("resources.arsc.flat");
+ if (file) {
+ std::unique_ptr<io::IData> data = file->openAsData();
+ if (!data) {
+ context->getDiagnostics()->error(DiagMessage(filePath)
+ << "failed to open resources.arsc.flat");
+ return;
+ }
+
+ pb::ResourceTable pbTable;
+ if (!pbTable.ParseFromArray(data->data(), data->size())) {
+ context->getDiagnostics()->error(DiagMessage(filePath)
+ << "invalid resources.arsc.flat");
+ return;
+ }
+
+ std::unique_ptr<ResourceTable> table = deserializeTableFromPb(
+ pbTable, Source(filePath), context->getDiagnostics());
+ if (table) {
+ DebugPrintTableOptions debugPrintTableOptions;
+ debugPrintTableOptions.showSources = true;
+ Debug::printTable(table.get(), debugPrintTableOptions);
+ }
+ }
+ return;
+ }
+
Maybe<android::FileMap> file = file::mmapPath(filePath, &err);
if (!file) {
context->getDiagnostics()->error(DiagMessage(filePath) << err);
@@ -90,15 +120,16 @@
return nullptr;
}
- StringPiece16 getCompilationPackage() override {
- return {};
+ const std::u16string& getCompilationPackage() override {
+ static std::u16string empty;
+ return empty;
}
uint8_t getPackageId() override {
return 0;
}
- ISymbolTable* getExternalSymbols() override {
+ SymbolTable* getExternalSymbols() override {
abort();
return nullptr;
}
diff --git a/tools/aapt2/flatten/XmlFlattener.cpp b/tools/aapt2/flatten/XmlFlattener.cpp
index 8219462..3eac633 100644
--- a/tools/aapt2/flatten/XmlFlattener.cpp
+++ b/tools/aapt2/flatten/XmlFlattener.cpp
@@ -144,9 +144,9 @@
}
static bool cmpXmlAttributeById(const xml::Attribute* a, const xml::Attribute* b) {
- if (a->compiledAttribute) {
- if (b->compiledAttribute) {
- return a->compiledAttribute.value().id < b->compiledAttribute.value().id;
+ if (a->compiledAttribute && a->compiledAttribute.value().id) {
+ if (b->compiledAttribute && b->compiledAttribute.value().id) {
+ return a->compiledAttribute.value().id.value() < b->compiledAttribute.value().id.value();
}
return true;
} else if (!b->compiledAttribute) {
@@ -167,8 +167,8 @@
// Filter the attributes.
for (xml::Attribute& attr : node->attributes) {
- if (mOptions.maxSdkLevel && attr.compiledAttribute) {
- size_t sdkLevel = findAttributeSdkLevel(attr.compiledAttribute.value().id);
+ if (mOptions.maxSdkLevel && attr.compiledAttribute && attr.compiledAttribute.value().id) {
+ size_t sdkLevel = findAttributeSdkLevel(attr.compiledAttribute.value().id.value());
if (sdkLevel > mOptions.maxSdkLevel.value()) {
continue;
}
@@ -191,8 +191,8 @@
uint16_t attributeIndex = 1;
for (const xml::Attribute* xmlAttr : mFilteredAttrs) {
// Assign the indices for specific attributes.
- if (xmlAttr->compiledAttribute &&
- xmlAttr->compiledAttribute.value().id == kIdAttr) {
+ if (xmlAttr->compiledAttribute && xmlAttr->compiledAttribute.value().id &&
+ xmlAttr->compiledAttribute.value().id.value() == kIdAttr) {
flatElem->idIndex = util::hostToDevice16(attributeIndex);
} else if (xmlAttr->namespaceUri.empty()) {
if (xmlAttr->name == u"class") {
@@ -208,7 +208,7 @@
flatAttr->rawValue.index = util::hostToDevice32(-1);
- if (!xmlAttr->compiledAttribute) {
+ if (!xmlAttr->compiledAttribute || !xmlAttr->compiledAttribute.value().id) {
// The attribute has no associated ResourceID, so the string order doesn't matter.
addString(xmlAttr->name, kLowPriority, &flatAttr->name);
} else {
@@ -221,17 +221,17 @@
// Lookup the StringPool for this package and make the reference there.
const xml::AaptAttribute& aaptAttr = xmlAttr->compiledAttribute.value();
- StringPool::Ref nameRef = mPackagePools[aaptAttr.id.packageId()].makeRef(
- xmlAttr->name, StringPool::Context{ aaptAttr.id.id });
+ StringPool::Ref nameRef = mPackagePools[aaptAttr.id.value().packageId()].makeRef(
+ xmlAttr->name, StringPool::Context{ aaptAttr.id.value().id });
// Add it to the list of strings to flatten.
addString(nameRef, &flatAttr->name);
+ }
- if (mOptions.keepRawValues) {
- // Keep raw values (this is for static libraries).
- // TODO(with a smarter inflater for binary XML, we can do without this).
- addString(xmlAttr->value, kLowPriority, &flatAttr->rawValue);
- }
+ if (mOptions.keepRawValues || !xmlAttr->compiledValue) {
+ // Keep raw values if the value is not compiled or
+ // if we're building a static library (need symbols).
+ addString(xmlAttr->value, kLowPriority, &flatAttr->rawValue);
}
if (xmlAttr->compiledValue) {
@@ -240,7 +240,6 @@
} else {
// Flatten as a regular string type.
flatAttr->typedValue.dataType = android::Res_value::TYPE_STRING;
- addString(xmlAttr->value, kLowPriority, &flatAttr->rawValue);
addString(xmlAttr->value, kLowPriority,
(ResStringPool_ref*) &flatAttr->typedValue.data);
}
diff --git a/tools/aapt2/flatten/XmlFlattener_test.cpp b/tools/aapt2/flatten/XmlFlattener_test.cpp
index 8648879..fef5ca3 100644
--- a/tools/aapt2/flatten/XmlFlattener_test.cpp
+++ b/tools/aapt2/flatten/XmlFlattener_test.cpp
@@ -32,7 +32,7 @@
mContext = test::ContextBuilder()
.setCompilationPackage(u"com.app.test")
.setNameManglerPolicy(NameManglerPolicy{ u"com.app.test" })
- .setSymbolTable(test::StaticSymbolTableBuilder()
+ .addSymbolSource(test::StaticSymbolSourceBuilder()
.addSymbol(u"@android:attr/id", ResourceId(0x010100d0),
test::AttributeBuilder().build())
.addSymbol(u"@com.app.test:id/id", ResourceId(0x7f020000))
diff --git a/tools/aapt2/integration-tests/Android.mk b/tools/aapt2/integration-tests/Android.mk
new file mode 100644
index 0000000..6361f9b
--- /dev/null
+++ b/tools/aapt2/integration-tests/Android.mk
@@ -0,0 +1,2 @@
+LOCAL_PATH := $(call my-dir)
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tools/aapt2/integration-tests/AppOne/Android.mk b/tools/aapt2/integration-tests/AppOne/Android.mk
new file mode 100644
index 0000000..bc40a62
--- /dev/null
+++ b/tools/aapt2/integration-tests/AppOne/Android.mk
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_USE_AAPT2 := true
+LOCAL_PACKAGE_NAME := AaptTestAppOne
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under,src)
+LOCAL_STATIC_ANDROID_LIBRARIES := \
+ AaptTestStaticLibOne \
+ AaptTestStaticLibTwo
+LOCAL_AAPT_FLAGS := --no-version-vectors
+include $(BUILD_PACKAGE)
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml
similarity index 67%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to tools/aapt2/integration-tests/AppOne/AndroidManifest.xml
index 31c0162..b6d8f2d 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,9 +13,5 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/system_secondary_color" />
- <corners
- android:topLeftRadius="0dp"
- android:topRightRadius="0dp" />
-</shape>
+
+<manifest package="com.android.aapt.app.one" />
diff --git a/tools/aapt2/data/res/drawable/icon.png b/tools/aapt2/integration-tests/AppOne/res/drawable/icon.png
similarity index 100%
rename from tools/aapt2/data/res/drawable/icon.png
rename to tools/aapt2/integration-tests/AppOne/res/drawable/icon.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/tools/aapt2/integration-tests/AppOne/res/drawable/image.xml
similarity index 68%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to tools/aapt2/integration-tests/AppOne/res/drawable/image.xml
index 31c0162..6132a75 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/tools/aapt2/integration-tests/AppOne/res/drawable/image.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,9 +13,5 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/system_secondary_color" />
- <corners
- android:topLeftRadius="0dp"
- android:topRightRadius="0dp" />
-</shape>
+
+<vector />
diff --git a/tools/aapt2/data/res/drawable/test.9.png b/tools/aapt2/integration-tests/AppOne/res/drawable/test.9.png
similarity index 100%
rename from tools/aapt2/data/res/drawable/test.9.png
rename to tools/aapt2/integration-tests/AppOne/res/drawable/test.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/tools/aapt2/integration-tests/AppOne/res/layout-v21/main.xml
similarity index 63%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to tools/aapt2/integration-tests/AppOne/res/layout-v21/main.xml
index 31c0162..9f5a4a8 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/tools/aapt2/integration-tests/AppOne/res/layout-v21/main.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,9 +13,10 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/system_secondary_color" />
- <corners
- android:topLeftRadius="0dp"
- android:topRightRadius="0dp" />
-</shape>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:support="http://schemas.android.com/apk/res/android.appcompat"
+ android:id="@+id/view"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+</LinearLayout>
diff --git a/tools/aapt2/integration-tests/AppOne/res/layout/main.xml b/tools/aapt2/integration-tests/AppOne/res/layout/main.xml
new file mode 100644
index 0000000..ab1a251
--- /dev/null
+++ b/tools/aapt2/integration-tests/AppOne/res/layout/main.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:support="http://schemas.android.com/apk/res/android.appcompat"
+ android:id="@+id/view"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <fragment class="android.test.sample.App$Inner" />
+
+ <variable name="user" type="com.android.User" />
+
+ <View xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/me"
+ android:layout_width="1dp"
+ android:onClick="doClick"
+ android:text="@{user.name}"
+ android:background="#ffffff"
+ android:layout_height="match_parent"
+ app:flags="complex|weak"
+ android:colorAccent="#ffffff"/>
+</LinearLayout>
diff --git a/tools/aapt2/data/res/raw/test.txt b/tools/aapt2/integration-tests/AppOne/res/raw/test.txt
similarity index 100%
rename from tools/aapt2/data/res/raw/test.txt
rename to tools/aapt2/integration-tests/AppOne/res/raw/test.txt
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/tools/aapt2/integration-tests/AppOne/res/values-v4/styles.xml
similarity index 67%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to tools/aapt2/integration-tests/AppOne/res/values-v4/styles.xml
index 31c0162..d8c11e2 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/tools/aapt2/integration-tests/AppOne/res/values-v4/styles.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,9 +13,10 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/system_secondary_color" />
- <corners
- android:topLeftRadius="0dp"
- android:topRightRadius="0dp" />
-</shape>
+
+<resources>
+ <style name="App" parent="android:Theme.Material">
+ <item name="android:colorAccent">@color/accent</item>
+ <item name="android:text">Hey</item>
+ </style>
+</resources>
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/tools/aapt2/integration-tests/AppOne/res/values/colors.xml
similarity index 67%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to tools/aapt2/integration-tests/AppOne/res/values/colors.xml
index 31c0162..4df5077 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/tools/aapt2/integration-tests/AppOne/res/values/colors.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,9 +13,9 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/system_secondary_color" />
- <corners
- android:topLeftRadius="0dp"
- android:topRightRadius="0dp" />
-</shape>
+
+<resources>
+ <color name="primary">#f44336</color>
+ <color name="primary_dark">#b71c1c</color>
+ <color name="accent">#fdd835</color>
+</resources>
diff --git a/tools/aapt2/integration-tests/AppOne/res/values/styles.xml b/tools/aapt2/integration-tests/AppOne/res/values/styles.xml
new file mode 100644
index 0000000..f05845c
--- /dev/null
+++ b/tools/aapt2/integration-tests/AppOne/res/values/styles.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources xmlns:lib="http://schemas.android.com/apk/res/android.appcompat">
+ <style name="App">
+ <item name="android:background">@color/primary</item>
+ <item name="android:colorPrimary">@color/primary</item>
+ <item name="android:colorPrimaryDark">@color/primary_dark</item>
+ <item name="android:colorAccent">@color/accent</item>
+ </style>
+ <attr name="custom" format="reference" />
+ <style name="Pop">
+ <item name="custom">@android:drawable/btn_default</item>
+ <item name="android:focusable">true</item>
+ </style>
+ <string name="yo">@string/wow</string>
+
+ <declare-styleable name="View">
+ <attr name="custom" />
+ <attr name="decor">
+ <enum name="no-border" value="0"/>
+ <enum name="border" value="1"/>
+ <enum name="shadow" value="2"/>
+ </attr>
+ </declare-styleable>
+
+</resources>
diff --git a/tools/aapt2/integration-tests/AppOne/res/values/test.xml b/tools/aapt2/integration-tests/AppOne/res/values/test.xml
new file mode 100644
index 0000000..f4b7471
--- /dev/null
+++ b/tools/aapt2/integration-tests/AppOne/res/values/test.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Reference the two static libraries -->
+ <string name="AppFooBar">@string/FooBar</string>
+ <string name="AppFoo">@string/Foo</string>
+
+ <string name="hooha"><font bgcolor="#ffffff">Hey guys!</font> <xliff:g>My</xliff:g> name is <b>Adam</b>. How <b><i>are</i></b> you?</string>
+ <public name="hooha" type="string" id="0x7f020001"/>
+ <string name="wow">@android:string/ok</string>
+ <public name="layout_width" type="attr" />
+ <attr name="layout_width" format="boolean" />
+ <attr name="flags">
+ <flag name="complex" value="1" />
+ <flag name="pub" value="2" />
+ <flag name="weak" value="4" />
+ </attr>
+</resources>
diff --git a/tools/aapt2/integration-tests/AppOne/src/com/android/aapt/app/one/AppOne.java b/tools/aapt2/integration-tests/AppOne/src/com/android/aapt/app/one/AppOne.java
new file mode 100644
index 0000000..472b35a
--- /dev/null
+++ b/tools/aapt2/integration-tests/AppOne/src/com/android/aapt/app/one/AppOne.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.aapt.app.one;
+
+public class AppOne {
+ // IDs from StaticLibOne
+ public static int FooId = com.android.aapt.staticlib.one.R.string.Foo;
+ public static int LayoutId = com.android.aapt.staticlib.one.R.layout.layout;
+
+ // IDs from StaticLibTwo
+ public static int FooBarId = com.android.aapt.staticlib.two.R.string.FooBar;
+}
+
diff --git a/tools/aapt2/integration-tests/StaticLibOne/Android.mk b/tools/aapt2/integration-tests/StaticLibOne/Android.mk
new file mode 100644
index 0000000..d59dc60
--- /dev/null
+++ b/tools/aapt2/integration-tests/StaticLibOne/Android.mk
@@ -0,0 +1,25 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_USE_AAPT2 := true
+LOCAL_MODULE := AaptTestStaticLibOne
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under,src)
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/tools/aapt2/integration-tests/StaticLibOne/AndroidManifest.xml
similarity index 67%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to tools/aapt2/integration-tests/StaticLibOne/AndroidManifest.xml
index 31c0162..705047e 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/tools/aapt2/integration-tests/StaticLibOne/AndroidManifest.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,9 +13,5 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/system_secondary_color" />
- <corners
- android:topLeftRadius="0dp"
- android:topRightRadius="0dp" />
-</shape>
+
+<manifest package="com.android.aapt.staticlib.one" />
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/tools/aapt2/integration-tests/StaticLibOne/res/layout/layout.xml
similarity index 67%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to tools/aapt2/integration-tests/StaticLibOne/res/layout/layout.xml
index 31c0162..683c91c 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/tools/aapt2/integration-tests/StaticLibOne/res/layout/layout.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,9 +13,6 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/system_secondary_color" />
- <corners
- android:topLeftRadius="0dp"
- android:topRightRadius="0dp" />
-</shape>
+
+<View xmlns:android="http://schemas.android.com/apk/res/android"
+ android:text="@string/Foo" />
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/tools/aapt2/integration-tests/StaticLibOne/res/values/values.xml
similarity index 67%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to tools/aapt2/integration-tests/StaticLibOne/res/values/values.xml
index 31c0162..2b24544 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/tools/aapt2/integration-tests/StaticLibOne/res/values/values.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,9 +13,10 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/system_secondary_color" />
- <corners
- android:topLeftRadius="0dp"
- android:topRightRadius="0dp" />
-</shape>
+
+<resources>
+ <attr name="StaticLibOne_attr" format="string" />
+
+ <string name="Foo">Foo</string>
+ <string name="Foo" product="tablet">Bar</string>
+</resources>
diff --git a/core/java/android/hardware/camera2/utils/LongParcelable.aidl b/tools/aapt2/integration-tests/StaticLibOne/src/com/android/aapt/staticlib/one/StaticLibOne.java
similarity index 64%
rename from core/java/android/hardware/camera2/utils/LongParcelable.aidl
rename to tools/aapt2/integration-tests/StaticLibOne/src/com/android/aapt/staticlib/one/StaticLibOne.java
index 98ad1b2..cf48f67 100644
--- a/core/java/android/hardware/camera2/utils/LongParcelable.aidl
+++ b/tools/aapt2/integration-tests/StaticLibOne/src/com/android/aapt/staticlib/one/StaticLibOne.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,8 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.aapt.staticlib.one;
-package android.hardware.camera2.utils;
-
-/** @hide */
-parcelable LongParcelable;
+public class StaticLibOne {
+ // IDs from StaticLibOne
+ public static int FooId = com.android.aapt.staticlib.one.R.string.Foo;
+ public static int LayoutId = com.android.aapt.staticlib.one.R.layout.layout;
+}
diff --git a/tools/aapt2/integration-tests/StaticLibTwo/Android.mk b/tools/aapt2/integration-tests/StaticLibTwo/Android.mk
new file mode 100644
index 0000000..8b6eb41
--- /dev/null
+++ b/tools/aapt2/integration-tests/StaticLibTwo/Android.mk
@@ -0,0 +1,27 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_USE_AAPT2 := true
+LOCAL_MODULE := AaptTestStaticLibTwo
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under,src)
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_SHARED_ANDROID_LIBRARIES := AaptTestStaticLibOne
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/tools/aapt2/integration-tests/StaticLibTwo/AndroidManifest.xml
similarity index 67%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to tools/aapt2/integration-tests/StaticLibTwo/AndroidManifest.xml
index 31c0162..28f0699 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/tools/aapt2/integration-tests/StaticLibTwo/AndroidManifest.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,9 +13,5 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/system_secondary_color" />
- <corners
- android:topLeftRadius="0dp"
- android:topRightRadius="0dp" />
-</shape>
+
+<manifest package="com.android.aapt.staticlib.two" />
diff --git a/tools/aapt2/integration-tests/StaticLibTwo/res/drawable/vector.xml b/tools/aapt2/integration-tests/StaticLibTwo/res/drawable/vector.xml
new file mode 100644
index 0000000..dd5979f
--- /dev/null
+++ b/tools/aapt2/integration-tests/StaticLibTwo/res/drawable/vector.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pathData="1123"/>
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/tools/aapt2/integration-tests/StaticLibTwo/res/layout/layout_two.xml
similarity index 67%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to tools/aapt2/integration-tests/StaticLibTwo/res/layout/layout_two.xml
index 31c0162..ba98307 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/tools/aapt2/integration-tests/StaticLibTwo/res/layout/layout_two.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,9 +13,6 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/system_secondary_color" />
- <corners
- android:topLeftRadius="0dp"
- android:topRightRadius="0dp" />
-</shape>
+
+<View xmlns:custom="http://schemas.android.com/apk/res-auto"
+ custom:StaticLibOne_attr="@string/FooBar" />
diff --git a/packages/SystemUI/res/drawable/qs_background_secondary.xml b/tools/aapt2/integration-tests/StaticLibTwo/res/values/values.xml
similarity index 67%
copy from packages/SystemUI/res/drawable/qs_background_secondary.xml
copy to tools/aapt2/integration-tests/StaticLibTwo/res/values/values.xml
index 31c0162..97bb2a5 100644
--- a/packages/SystemUI/res/drawable/qs_background_secondary.xml
+++ b/tools/aapt2/integration-tests/StaticLibTwo/res/values/values.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,9 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/system_secondary_color" />
- <corners
- android:topLeftRadius="0dp"
- android:topRightRadius="0dp" />
-</shape>
+
+<resources>
+ <string name="FooBar">@string/Foo</string>
+</resources>
diff --git a/tools/aapt2/integration-tests/StaticLibTwo/src/com/android/aapt/staticlib/two/StaticLibTwo.java b/tools/aapt2/integration-tests/StaticLibTwo/src/com/android/aapt/staticlib/two/StaticLibTwo.java
new file mode 100644
index 0000000..7110dcd
--- /dev/null
+++ b/tools/aapt2/integration-tests/StaticLibTwo/src/com/android/aapt/staticlib/two/StaticLibTwo.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.aapt.staticlib.two;
+
+public class StaticLibTwo {
+ // IDs from StaticLibOne
+ public static int FooId = com.android.aapt.staticlib.one.R.string.Foo;
+ public static int LayoutId = com.android.aapt.staticlib.one.R.layout.layout;
+
+ // IDs from StaticLibTwo
+ public static int FooBarId = com.android.aapt.staticlib.two.R.string.FooBar;
+}
diff --git a/tools/aapt2/io/ZipArchive.cpp b/tools/aapt2/io/ZipArchive.cpp
index 329dac9..b3e7a02 100644
--- a/tools/aapt2/io/ZipArchive.cpp
+++ b/tools/aapt2/io/ZipArchive.cpp
@@ -92,9 +92,8 @@
return {};
}
- ZipString suffix(".flat");
void* cookie = nullptr;
- result = StartIteration(collection->mHandle, &cookie, nullptr, &suffix);
+ result = StartIteration(collection->mHandle, &cookie, nullptr, nullptr);
if (result != 0) {
if (outError) *outError = ErrorCodeString(result);
return {};
diff --git a/tools/aapt2/java/ClassDefinitionWriter.h b/tools/aapt2/java/ClassDefinitionWriter.h
index 04e1274..cf92c9a 100644
--- a/tools/aapt2/java/ClassDefinitionWriter.h
+++ b/tools/aapt2/java/ClassDefinitionWriter.h
@@ -65,7 +65,7 @@
<< "String " << name << "=\"" << val << "\";\n";
}
- void addResourceMember(const StringPiece16& name, AnnotationProcessor* processor,
+ void addResourceMember(const StringPiece& name, AnnotationProcessor* processor,
const ResourceId id) {
ensureClassDeclaration();
if (processor) {
@@ -76,7 +76,7 @@
}
template <typename Iterator, typename FieldAccessorFunc>
- void addArrayMember(const StringPiece16& name, AnnotationProcessor* processor,
+ void addArrayMember(const StringPiece& name, AnnotationProcessor* processor,
const Iterator begin, const Iterator end, FieldAccessorFunc f) {
ensureClassDeclaration();
if (processor) {
diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp
index 6e340a2..1076ffe 100644
--- a/tools/aapt2/java/JavaClassGenerator.cpp
+++ b/tools/aapt2/java/JavaClassGenerator.cpp
@@ -68,16 +68,41 @@
* Java symbols can not contain . or -, but those are valid in a resource name.
* Replace those with '_'.
*/
-static std::u16string transform(const StringPiece16& symbol) {
- std::u16string output = symbol.toString();
- for (char16_t& c : output) {
- if (c == u'.' || c == u'-') {
- c = u'_';
+static std::string transform(const StringPiece16& symbol) {
+ std::string output = util::utf16ToUtf8(symbol);
+ for (char& c : output) {
+ if (c == '.' || c == '-') {
+ c = '_';
}
}
return output;
}
+/**
+ * Transforms an attribute in a styleable to the Java field name:
+ *
+ * <declare-styleable name="Foo">
+ * <attr name="android:bar" />
+ * <attr name="bar" />
+ * </declare-styleable>
+ *
+ * Foo_android_bar
+ * Foo_bar
+ */
+static std::string transformNestedAttr(const ResourceNameRef& attrName,
+ const std::string& styleableClassName,
+ const StringPiece16& packageNameToGenerate) {
+ std::string output = styleableClassName;
+
+ // We may reference IDs from other packages, so prefix the entry name with
+ // the package.
+ if (!attrName.package.empty() && packageNameToGenerate != attrName.package) {
+ output += "_" + transform(attrName.package);
+ }
+ output += "_" + transform(attrName.entry);
+ return output;
+}
+
bool JavaClassGenerator::skipSymbol(SymbolState state) {
switch (mOptions.types) {
case JavaClassGeneratorOptions::SymbolTypes::kAll:
@@ -90,48 +115,91 @@
return true;
}
+struct StyleableAttr {
+ const Reference* attrRef;
+ std::string fieldName;
+};
+
+static bool lessStyleableAttr(const StyleableAttr& lhs, const StyleableAttr& rhs) {
+ const ResourceId lhsId = lhs.attrRef->id ? lhs.attrRef->id.value() : ResourceId(0);
+ const ResourceId rhsId = rhs.attrRef->id ? rhs.attrRef->id.value() : ResourceId(0);
+ if (lhsId < rhsId) {
+ return true;
+ } else if (lhsId > rhsId) {
+ return false;
+ } else {
+ return lhs.attrRef->name.value() < rhs.attrRef->name.value();
+ }
+}
+
void JavaClassGenerator::writeStyleableEntryForClass(ClassDefinitionWriter* outClassDef,
AnnotationProcessor* processor,
const StringPiece16& packageNameToGenerate,
const std::u16string& entryName,
const Styleable* styleable) {
+ const std::string className = transform(entryName);
+
// This must be sorted by resource ID.
- std::vector<std::pair<ResourceId, ResourceNameRef>> sortedAttributes;
+ std::vector<StyleableAttr> sortedAttributes;
sortedAttributes.reserve(styleable->entries.size());
for (const auto& attr : styleable->entries) {
// If we are not encoding final attributes, the styleable entry may have no ID
// if we are building a static library.
assert((!mOptions.useFinal || attr.id) && "no ID set for Styleable entry");
assert(attr.name && "no name set for Styleable entry");
- sortedAttributes.emplace_back(attr.id ? attr.id.value() : ResourceId(0), attr.name.value());
- }
- std::sort(sortedAttributes.begin(), sortedAttributes.end());
- auto accessorFunc = [](const std::pair<ResourceId, ResourceNameRef>& a) -> ResourceId {
- return a.first;
+ sortedAttributes.emplace_back(StyleableAttr{
+ &attr, transformNestedAttr(attr.name.value(), className, packageNameToGenerate) });
+ }
+ std::sort(sortedAttributes.begin(), sortedAttributes.end(), lessStyleableAttr);
+
+ const size_t attrCount = sortedAttributes.size();
+
+ if (attrCount > 0) {
+ // Build the comment string for the Styleable. It includes details about the
+ // child attributes.
+ std::stringstream styleableComment;
+ styleableComment << "Attributes that can be used with a " << className << ".\n";
+ styleableComment << "<table>\n"
+ "<colgroup align=\"left\" />\n"
+ "<colgroup align=\"left\">\n"
+ "<tr><th>Attribute</th><th>Description</th></tr>\n";
+ for (const auto& entry : sortedAttributes) {
+ const ResourceName& attrName = entry.attrRef->name.value();
+ styleableComment << "<tr><td><code>{@link #" << entry.fieldName << " "
+ << attrName.package << ":" << attrName.entry
+ << "}</code></td><td></td></tr>\n";
+ }
+ styleableComment << "</table>\n";
+ for (const auto& entry : sortedAttributes) {
+ styleableComment << "@see #" << entry.fieldName << "\n";
+ }
+ processor->appendComment(styleableComment.str());
+ }
+
+ auto accessorFunc = [](const StyleableAttr& a) -> ResourceId {
+ return a.attrRef->id ? a.attrRef->id.value() : ResourceId(0);
};
// First we emit the array containing the IDs of each attribute.
- outClassDef->addArrayMember(transform(entryName), processor,
+ outClassDef->addArrayMember(className, processor,
sortedAttributes.begin(),
sortedAttributes.end(),
accessorFunc);
// Now we emit the indices into the array.
- size_t attrCount = sortedAttributes.size();
for (size_t i = 0; i < attrCount; i++) {
- std::stringstream name;
- name << transform(entryName);
+ const ResourceName& attrName = sortedAttributes[i].attrRef->name.value();
- // We may reference IDs from other packages, so prefix the entry name with
- // the package.
- const ResourceNameRef& itemName = sortedAttributes[i].second;
- if (!itemName.package.empty() && packageNameToGenerate != itemName.package) {
- name << "_" << transform(itemName.package);
+ AnnotationProcessor attrProcessor;
+ std::stringstream doclavaComments;
+ doclavaComments << "@attr name ";
+ if (!attrName.package.empty()) {
+ doclavaComments << attrName.package << ":";
}
- name << "_" << transform(itemName.entry);
-
- outClassDef->addIntMember(name.str(), nullptr, i);
+ doclavaComments << attrName.entry;
+ attrProcessor.appendComment(doclavaComments.str());
+ outClassDef->addIntMember(sortedAttributes[i].fieldName, &attrProcessor, i);
}
}
@@ -223,8 +291,10 @@
continue;
}
- ResourceId id(package->id.value(), type->id.value(), entry->id.value());
- assert(id.isValid());
+ ResourceId id;
+ if (package->id && type->id && entry->id) {
+ id = ResourceId(package->id.value(), type->id.value(), entry->id.value());
+ }
std::u16string unmangledPackage;
std::u16string unmangledName = entry->name;
diff --git a/tools/aapt2/java/JavaClassGenerator_test.cpp b/tools/aapt2/java/JavaClassGenerator_test.cpp
index e9e7881..63d38a8 100644
--- a/tools/aapt2/java/JavaClassGenerator_test.cpp
+++ b/tools/aapt2/java/JavaClassGenerator_test.cpp
@@ -227,7 +227,32 @@
}
TEST(JavaClassGeneratorTest, CommentsForStyleablesAndNestedAttributesArePresent) {
+ Attribute attr(false);
+ attr.setComment(StringPiece16(u"This is an attribute"));
+ Styleable styleable;
+ styleable.entries.push_back(Reference(test::parseNameOrDie(u"@android:attr/one")));
+ styleable.setComment(StringPiece16(u"This is a styleable"));
+
+ std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
+ .setPackageId(u"android", 0x01)
+ .addValue(u"@android:attr/one", util::make_unique<Attribute>(attr))
+ .addValue(u"@android:styleable/Container",
+ std::unique_ptr<Styleable>(styleable.clone(nullptr)))
+ .build();
+
+ JavaClassGeneratorOptions options;
+ options.useFinal = false;
+ JavaClassGenerator generator(table.get(), options);
+
+ std::stringstream out;
+ ASSERT_TRUE(generator.generate(u"android", &out));
+ std::string actual = out.str();
+
+ EXPECT_NE(std::string::npos, actual.find("@attr name android:one"));
+ EXPECT_NE(std::string::npos, actual.find("@attr description"));
+ EXPECT_NE(std::string::npos, actual.find(util::utf16ToUtf8(attr.getComment())));
+ EXPECT_NE(std::string::npos, actual.find(util::utf16ToUtf8(styleable.getComment())));
}
} // namespace aapt
diff --git a/tools/aapt2/link/Link.cpp b/tools/aapt2/link/Link.cpp
index d83f6def..5003d96 100644
--- a/tools/aapt2/link/Link.cpp
+++ b/tools/aapt2/link/Link.cpp
@@ -62,7 +62,9 @@
std::set<std::u16string> extraJavaPackages;
Maybe<std::string> generateProguardRulesPath;
bool noAutoVersion = false;
+ bool noVersionVectors = false;
bool staticLib = false;
+ bool noStaticLibPackages = false;
bool generateNonFinalIds = false;
bool outputToDirectory = false;
bool autoAddOverlay = false;
@@ -74,37 +76,58 @@
TableSplitterOptions tableSplitterOptions;
};
-struct LinkContext : public IAaptContext {
- StdErrDiagnostics mDiagnostics;
- std::unique_ptr<NameMangler> mNameMangler;
- std::u16string mCompilationPackage;
- uint8_t mPackageId;
- std::unique_ptr<ISymbolTable> mSymbols;
- bool mVerbose = false;
+class LinkContext : public IAaptContext {
+public:
+ LinkContext() : mNameMangler({}) {
+ }
IDiagnostics* getDiagnostics() override {
return &mDiagnostics;
}
NameMangler* getNameMangler() override {
- return mNameMangler.get();
+ return &mNameMangler;
}
- StringPiece16 getCompilationPackage() override {
+ void setNameManglerPolicy(const NameManglerPolicy& policy) {
+ mNameMangler = NameMangler(policy);
+ }
+
+ const std::u16string& getCompilationPackage() override {
return mCompilationPackage;
}
+ void setCompilationPackage(const StringPiece16& packageName) {
+ mCompilationPackage = packageName.toString();
+ }
+
uint8_t getPackageId() override {
return mPackageId;
}
- ISymbolTable* getExternalSymbols() override {
- return mSymbols.get();
+ void setPackageId(uint8_t id) {
+ mPackageId = id;
+ }
+
+ SymbolTable* getExternalSymbols() override {
+ return &mSymbols;
}
bool verbose() override {
return mVerbose;
}
+
+ void setVerbose(bool val) {
+ mVerbose = val;
+ }
+
+private:
+ StdErrDiagnostics mDiagnostics;
+ NameMangler mNameMangler;
+ std::u16string mCompilationPackage;
+ uint8_t mPackageId = 0x0;
+ SymbolTable mSymbols;
+ bool mVerbose = false;
};
static bool copyFileToArchive(io::IFile* file, const std::string& outPath,
@@ -117,11 +140,19 @@
return false;
}
- CompiledFileInputStream inputStream(data->data(), data->size());
- if (!inputStream.CompiledFile()) {
- context->getDiagnostics()->error(DiagMessage(file->getSource())
- << "invalid compiled file header");
- return false;
+ const uint8_t* buffer = reinterpret_cast<const uint8_t*>(data->data());
+ size_t bufferSize = data->size();
+
+ // If the file ends with .flat, we must strip off the CompiledFileHeader from it.
+ if (util::stringEndsWith<char>(file->getSource().path, ".flat")) {
+ CompiledFileInputStream inputStream(data->data(), data->size());
+ if (!inputStream.CompiledFile()) {
+ context->getDiagnostics()->error(DiagMessage(file->getSource())
+ << "invalid compiled file header");
+ return false;
+ }
+ buffer = reinterpret_cast<const uint8_t*>(inputStream.data());
+ bufferSize = inputStream.size();
}
if (context->verbose()) {
@@ -129,8 +160,7 @@
}
if (writer->startEntry(outPath, compressionFlags)) {
- if (writer->writeEntry(reinterpret_cast<const uint8_t*>(inputStream.data()),
- inputStream.size())) {
+ if (writer->writeEntry(buffer, bufferSize)) {
if (writer->finishEntry()) {
return true;
}
@@ -156,7 +186,7 @@
DiagMessage msg;
msg << "writing " << path << " to archive";
if (maxSdkLevel) {
- msg << " maxSdkLevel=" << maxSdkLevel.value();
+ msg << " maxSdkLevel=" << maxSdkLevel.value() << " keepRawValues=" << keepRawValues;
}
context->getDiagnostics()->note(msg);
}
@@ -248,6 +278,7 @@
struct ResourceFileFlattenerOptions {
bool noAutoVersion = false;
+ bool noVersionVectors = false;
bool keepRawValues = false;
bool doNotCompressAnything = false;
std::vector<std::string> extensionsToNotCompress;
@@ -267,14 +298,13 @@
io::IFile* fileToCopy;
std::unique_ptr<xml::XmlResource> xmlToFlatten;
std::string dstPath;
+ bool skipVersion = false;
};
uint32_t getCompressionFlags(const StringPiece& str);
- std::unique_ptr<xml::XmlResource> linkAndVersionXmlFile(const ResourceEntry* entry,
- const ResourceFile& fileDesc,
- io::IFile* file,
- ResourceTable* table);
+ bool linkAndVersionXmlFile(const ResourceEntry* entry, const ResourceFile& fileDesc,
+ io::IFile* file, ResourceTable* table, FileOperation* outFileOp);
ResourceFileFlattenerOptions mOptions;
IAaptContext* mContext;
@@ -294,11 +324,11 @@
return ArchiveEntry::kCompress;
}
-std::unique_ptr<xml::XmlResource> ResourceFileFlattener::linkAndVersionXmlFile(
- const ResourceEntry* entry,
- const ResourceFile& fileDesc,
- io::IFile* file,
- ResourceTable* table) {
+bool ResourceFileFlattener::linkAndVersionXmlFile(const ResourceEntry* entry,
+ const ResourceFile& fileDesc,
+ io::IFile* file,
+ ResourceTable* table,
+ FileOperation* outFileOp) {
const StringPiece srcPath = file->getSource().path;
if (mContext->verbose()) {
mContext->getDiagnostics()->note(DiagMessage() << "linking " << srcPath);
@@ -307,51 +337,67 @@
std::unique_ptr<io::IData> data = file->openAsData();
if (!data) {
mContext->getDiagnostics()->error(DiagMessage(file->getSource()) << "failed to open file");
- return {};
+ return false;
}
- std::unique_ptr<xml::XmlResource> xmlRes;
if (util::stringEndsWith<char>(srcPath, ".flat")) {
- xmlRes = loadBinaryXmlSkipFileExport(file->getSource(), data->data(), data->size(),
- mContext->getDiagnostics());
+ outFileOp->xmlToFlatten = loadBinaryXmlSkipFileExport(file->getSource(),
+ data->data(), data->size(),
+ mContext->getDiagnostics());
} else {
- xmlRes = xml::inflate(data->data(), data->size(), mContext->getDiagnostics(),
- file->getSource());
+ outFileOp->xmlToFlatten = xml::inflate(data->data(), data->size(),
+ mContext->getDiagnostics(),
+ file->getSource());
}
- if (!xmlRes) {
- return {};
+ if (!outFileOp->xmlToFlatten) {
+ return false;
}
// Copy the the file description header.
- xmlRes->file = fileDesc;
+ outFileOp->xmlToFlatten->file = fileDesc;
XmlReferenceLinker xmlLinker;
- if (!xmlLinker.consume(mContext, xmlRes.get())) {
- return {};
+ if (!xmlLinker.consume(mContext, outFileOp->xmlToFlatten.get())) {
+ return false;
}
- if (!proguard::collectProguardRules(xmlRes->file.source, xmlRes.get(), mKeepSet)) {
- return {};
+ if (!proguard::collectProguardRules(outFileOp->xmlToFlatten->file.source,
+ outFileOp->xmlToFlatten.get(), mKeepSet)) {
+ return false;
}
if (!mOptions.noAutoVersion) {
+ if (mOptions.noVersionVectors) {
+ // Skip this if it is a vector or animated-vector.
+ xml::Element* el = xml::findRootElement(outFileOp->xmlToFlatten.get());
+ if (el && el->namespaceUri.empty()) {
+ if (el->name == u"vector" || el->name == u"animated-vector") {
+ // We are NOT going to version this file.
+ outFileOp->skipVersion = true;
+ return true;
+ }
+ }
+ }
+
// Find the first SDK level used that is higher than this defined config and
// not superseded by a lower or equal SDK level resource.
for (int sdkLevel : xmlLinker.getSdkLevels()) {
- if (sdkLevel > xmlRes->file.config.sdkVersion) {
- if (!shouldGenerateVersionedResource(entry, xmlRes->file.config, sdkLevel)) {
+ if (sdkLevel > outFileOp->xmlToFlatten->file.config.sdkVersion) {
+ if (!shouldGenerateVersionedResource(entry, outFileOp->xmlToFlatten->file.config,
+ sdkLevel)) {
// If we shouldn't generate a versioned resource, stop checking.
break;
}
- ResourceFile versionedFileDesc = xmlRes->file;
- versionedFileDesc.config.sdkVersion = sdkLevel;
+ ResourceFile versionedFileDesc = outFileOp->xmlToFlatten->file;
+ versionedFileDesc.config.sdkVersion = (uint16_t) sdkLevel;
if (mContext->verbose()) {
mContext->getDiagnostics()->note(DiagMessage(versionedFileDesc.source)
<< "auto-versioning resource from config '"
- << xmlRes->file.config << "' -> '"
+ << outFileOp->xmlToFlatten->file.config
+ << "' -> '"
<< versionedFileDesc.config << "'");
}
@@ -365,13 +411,13 @@
file,
mContext->getDiagnostics());
if (!added) {
- return {};
+ return false;
}
break;
}
}
}
- return xmlRes;
+ return true;
}
/**
@@ -415,9 +461,7 @@
fileDesc.config = configValue->config;
fileDesc.name = ResourceName(pkg->name, type->type, entry->name);
fileDesc.source = fileRef->getSource();
- fileOp.xmlToFlatten = linkAndVersionXmlFile(entry.get(), fileDesc,
- file, table);
- if (!fileOp.xmlToFlatten) {
+ if (!linkAndVersionXmlFile(entry.get(), fileDesc, file, table, &fileOp)) {
error = true;
continue;
}
@@ -447,7 +491,7 @@
if (fileOp.xmlToFlatten) {
Maybe<size_t> maxSdkLevel;
- if (!mOptions.noAutoVersion) {
+ if (!mOptions.noAutoVersion && !fileOp.skipVersion) {
maxSdkLevel = std::max<size_t>(config.sdkVersion, 1u);
}
@@ -474,39 +518,61 @@
class LinkCommand {
public:
LinkCommand(LinkContext* context, const LinkOptions& options) :
- mOptions(options), mContext(context), mFinalTable(), mFileCollection(nullptr) {
- std::unique_ptr<io::FileCollection> fileCollection =
- util::make_unique<io::FileCollection>();
-
- // Get a pointer to the FileCollection for convenience, but it will be owned by the vector.
- mFileCollection = fileCollection.get();
-
- // Move it to the collection.
- mCollections.push_back(std::move(fileCollection));
+ mOptions(options), mContext(context), mFinalTable(),
+ mFileCollection(util::make_unique<io::FileCollection>()) {
}
/**
* Creates a SymbolTable that loads symbols from the various APKs and caches the
* results for faster lookup.
*/
- std::unique_ptr<ISymbolTable> createSymbolTableFromIncludePaths() {
- AssetManagerSymbolTableBuilder builder;
+ bool loadSymbolsFromIncludePaths() {
+ std::unique_ptr<AssetManagerSymbolSource> assetSource =
+ util::make_unique<AssetManagerSymbolSource>();
for (const std::string& path : mOptions.includePaths) {
if (mContext->verbose()) {
mContext->getDiagnostics()->note(DiagMessage(path) << "loading include path");
}
- std::unique_ptr<android::AssetManager> assetManager =
- util::make_unique<android::AssetManager>();
- int32_t cookie = 0;
- if (!assetManager->addAssetPath(android::String8(path.data(), path.size()), &cookie)) {
+ // First try to load the file as a static lib.
+ std::string errorStr;
+ std::unique_ptr<ResourceTable> staticInclude = loadStaticLibrary(path, &errorStr);
+ if (staticInclude) {
+ if (!mOptions.staticLib) {
+ // Can't include static libraries when not building a static library.
+ mContext->getDiagnostics()->error(
+ DiagMessage(path) << "can't include static library when building app");
+ return false;
+ }
+
+ // If we are using --no-static-lib-packages, we need to rename the package of this
+ // table to our compilation package.
+ if (mOptions.noStaticLibPackages) {
+ if (ResourceTablePackage* pkg = staticInclude->findPackageById(0x7f)) {
+ pkg->name = mContext->getCompilationPackage();
+ }
+ }
+
+ mContext->getExternalSymbols()->appendSource(
+ util::make_unique<ResourceTableSymbolSource>(staticInclude.get()));
+
+ mStaticTableIncludes.push_back(std::move(staticInclude));
+
+ } else if (!errorStr.empty()) {
+ // We had an error with reading, so fail.
+ mContext->getDiagnostics()->error(DiagMessage(path) << errorStr);
+ return false;
+ }
+
+ if (!assetSource->addAssetPath(path)) {
mContext->getDiagnostics()->error(
DiagMessage(path) << "failed to load include path");
- return {};
+ return false;
}
- builder.add(std::move(assetManager));
}
- return builder.build();
+
+ mContext->getExternalSymbols()->appendSource(std::move(assetSource));
+ return true;
}
Maybe<AppInfo> extractAppInfoFromManifest(xml::XmlResource* xmlRes) {
@@ -571,6 +637,35 @@
return !error;
}
+ /**
+ * Returns true if no IDs have been set, false otherwise.
+ */
+ bool verifyNoIdsSet() {
+ for (const auto& package : mFinalTable.packages) {
+ for (const auto& type : package->types) {
+ if (type->id) {
+ mContext->getDiagnostics()->error(DiagMessage() << "type " << type->type
+ << " has ID " << std::hex
+ << (int) type->id.value()
+ << std::dec << " assigned");
+ return false;
+ }
+
+ for (const auto& entry : type->entries) {
+ if (entry->id) {
+ ResourceNameRef resName(package->name, type->type, entry->name);
+ mContext->getDiagnostics()->error(DiagMessage() << "entry " << resName
+ << " has ID " << std::hex
+ << (int) entry->id.value()
+ << std::dec << " assigned");
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
std::unique_ptr<IArchiveWriter> makeArchiveWriter() {
if (mOptions.outputToDirectory) {
return createDirectoryArchiveWriter(mContext->getDiagnostics(), mOptions.outputPath);
@@ -599,6 +694,32 @@
return false;
}
+ bool flattenTableToPb(ResourceTable* table, IArchiveWriter* writer) {
+ // Create the file/zip entry.
+ if (!writer->startEntry("resources.arsc.flat", 0)) {
+ mContext->getDiagnostics()->error(DiagMessage() << "failed to open");
+ return false;
+ }
+
+ std::unique_ptr<pb::ResourceTable> pbTable = serializeTableToPb(table);
+
+ // Wrap our IArchiveWriter with an adaptor that implements the ZeroCopyOutputStream
+ // interface.
+ {
+ google::protobuf::io::CopyingOutputStreamAdaptor adaptor(writer);
+
+ if (!pbTable->SerializeToZeroCopyStream(&adaptor)) {
+ mContext->getDiagnostics()->error(DiagMessage() << "failed to write");
+ return false;
+ }
+ }
+
+ if (!writer->finishEntry()) {
+ mContext->getDiagnostics()->error(DiagMessage() << "failed to finish entry");
+ return false;
+ }
+ return true;
+ }
bool writeJavaFile(ResourceTable* table, const StringPiece16& packageNameToGenerate,
const StringPiece16& outPackage, JavaClassGeneratorOptions javaOptions) {
@@ -674,18 +795,91 @@
return true;
}
- bool mergeStaticLibrary(const std::string& input) {
- // TODO(adamlesinski): Load resources from a static library APK and merge the table into
- // TableMerger.
- mContext->getDiagnostics()->warn(DiagMessage()
- << "linking static libraries not supported yet: "
- << input);
+ std::unique_ptr<ResourceTable> loadStaticLibrary(const std::string& input,
+ std::string* outError) {
+ std::unique_ptr<io::ZipFileCollection> collection = io::ZipFileCollection::create(
+ input, outError);
+ if (!collection) {
+ return {};
+ }
+ return loadTablePbFromCollection(collection.get());
+ }
+
+ std::unique_ptr<ResourceTable> loadTablePbFromCollection(io::IFileCollection* collection) {
+ io::IFile* file = collection->findFile("resources.arsc.flat");
+ if (!file) {
+ return {};
+ }
+
+ std::unique_ptr<io::IData> data = file->openAsData();
+ return loadTableFromPb(file->getSource(), data->data(), data->size(),
+ mContext->getDiagnostics());
+ }
+
+ bool mergeStaticLibrary(const std::string& input, bool override) {
+ if (mContext->verbose()) {
+ mContext->getDiagnostics()->note(DiagMessage() << "merging static library " << input);
+ }
+
+ std::string errorStr;
+ std::unique_ptr<io::ZipFileCollection> collection =
+ io::ZipFileCollection::create(input, &errorStr);
+ if (!collection) {
+ mContext->getDiagnostics()->error(DiagMessage(input) << errorStr);
+ return false;
+ }
+
+ std::unique_ptr<ResourceTable> table = loadTablePbFromCollection(collection.get());
+ if (!table) {
+ mContext->getDiagnostics()->error(DiagMessage(input) << "invalid static library");
+ return false;
+ }
+
+ ResourceTablePackage* pkg = table->findPackageById(0x7f);
+ if (!pkg) {
+ mContext->getDiagnostics()->error(DiagMessage(input)
+ << "static library has no package");
+ return false;
+ }
+
+ bool result;
+ if (mOptions.noStaticLibPackages) {
+ // Merge all resources as if they were in the compilation package. This is the old
+ // behaviour of aapt.
+
+ // Add the package to the set of --extra-packages so we emit an R.java for each
+ // library package.
+ if (!pkg->name.empty()) {
+ mOptions.extraJavaPackages.insert(pkg->name);
+ }
+
+ pkg->name = u"";
+ if (override) {
+ result = mTableMerger->mergeOverlay(Source(input), table.get(), collection.get());
+ } else {
+ result = mTableMerger->merge(Source(input), table.get(), collection.get());
+ }
+
+ } else {
+ // This is the proper way to merge libraries, where the package name is preserved
+ // and resource names are mangled.
+ result = mTableMerger->mergeAndMangle(Source(input), pkg->name, table.get(),
+ collection.get());
+ }
+
+ if (!result) {
+ return false;
+ }
+
+ // Make sure to move the collection into the set of IFileCollections.
+ mCollections.push_back(std::move(collection));
return true;
}
bool mergeResourceTable(io::IFile* file, bool override) {
if (mContext->verbose()) {
- mContext->getDiagnostics()->note(DiagMessage() << "linking " << file->getSource());
+ mContext->getDiagnostics()->note(DiagMessage() << "merging resource table "
+ << file->getSource());
}
std::unique_ptr<io::IData> data = file->openAsData();
@@ -711,13 +905,14 @@
return result;
}
- bool mergeCompiledFile(io::IFile* file, std::unique_ptr<ResourceFile> fileDesc, bool overlay) {
+ bool mergeCompiledFile(io::IFile* file, ResourceFile* fileDesc, bool override) {
if (mContext->verbose()) {
- mContext->getDiagnostics()->note(DiagMessage() << "adding " << file->getSource());
+ mContext->getDiagnostics()->note(DiagMessage() << "merging compiled file "
+ << file->getSource());
}
bool result = false;
- if (overlay) {
+ if (override) {
result = mTableMerger->mergeFileOverlay(*fileDesc, file);
} else {
result = mTableMerger->mergeFile(*fileDesc, file);
@@ -730,7 +925,7 @@
// Add the exports of this file to the table.
for (SourcedResourceName& exportedSymbol : fileDesc->exportedSymbols) {
if (exportedSymbol.name.package.empty()) {
- exportedSymbol.name.package = mContext->getCompilationPackage().toString();
+ exportedSymbol.name.package = mContext->getCompilationPackage();
}
ResourceNameRef resName = exportedSymbol.name;
@@ -743,11 +938,9 @@
std::unique_ptr<Id> id = util::make_unique<Id>();
id->setSource(fileDesc->source.withLine(exportedSymbol.line));
- bool result = mFinalTable.addResourceAllowMangled(resName,
- ConfigDescription::defaultConfig(),
- std::string(),
- std::move(id),
- mContext->getDiagnostics());
+ bool result = mFinalTable.addResourceAllowMangled(
+ resName, ConfigDescription::defaultConfig(), std::string(), std::move(id),
+ mContext->getDiagnostics());
if (!result) {
return false;
}
@@ -756,12 +949,21 @@
}
/**
- * Creates an io::IFileCollection from the ZIP archive and processes the files within.
+ * Takes a path to load as a ZIP file and merges the files within into the master ResourceTable.
+ * If override is true, conflicting resources are allowed to override each other, in order of
+ * last seen.
+ *
+ * An io::IFileCollection is created from the ZIP file and added to the set of
+ * io::IFileCollections that are open.
*/
bool mergeArchive(const std::string& input, bool override) {
+ if (mContext->verbose()) {
+ mContext->getDiagnostics()->note(DiagMessage() << "merging archive " << input);
+ }
+
std::string errorStr;
- std::unique_ptr<io::ZipFileCollection> collection = io::ZipFileCollection::create(
- input, &errorStr);
+ std::unique_ptr<io::ZipFileCollection> collection =
+ io::ZipFileCollection::create(input, &errorStr);
if (!collection) {
mContext->getDiagnostics()->error(DiagMessage(input) << errorStr);
return false;
@@ -769,7 +971,7 @@
bool error = false;
for (auto iter = collection->iterator(); iter->hasNext(); ) {
- if (!processFile(iter->next(), override)) {
+ if (!mergeFile(iter->next(), override)) {
error = true;
}
}
@@ -779,22 +981,45 @@
return !error;
}
- bool processFile(const std::string& path, bool override) {
+ /**
+ * Takes a path to load and merge into the master ResourceTable. If override is true,
+ * conflicting resources are allowed to override each other, in order of last seen.
+ *
+ * If the file path ends with .flata, .jar, .jack, or .zip the file is treated as ZIP archive
+ * and the files within are merged individually.
+ *
+ * Otherwise the files is processed on its own.
+ */
+ bool mergePath(const std::string& path, bool override) {
if (util::stringEndsWith<char>(path, ".flata") ||
util::stringEndsWith<char>(path, ".jar") ||
util::stringEndsWith<char>(path, ".jack") ||
util::stringEndsWith<char>(path, ".zip")) {
return mergeArchive(path, override);
+ } else if (util::stringEndsWith<char>(path, ".apk")) {
+ return mergeStaticLibrary(path, override);
}
io::IFile* file = mFileCollection->insertFile(path);
- return processFile(file, override);
+ return mergeFile(file, override);
}
- bool processFile(io::IFile* file, bool override) {
+ /**
+ * Takes a file to load and merge into the master ResourceTable. If override is true,
+ * conflicting resources are allowed to override each other, in order of last seen.
+ *
+ * If the file ends with .arsc.flat, then it is loaded as a ResourceTable and merged into the
+ * master ResourceTable. If the file ends with .flat, then it is treated like a compiled file
+ * and the header data is read and merged into the final ResourceTable.
+ *
+ * All other file types are ignored. This is because these files could be coming from a zip,
+ * where we could have other files like classes.dex.
+ */
+ bool mergeFile(io::IFile* file, bool override) {
const Source& src = file->getSource();
if (util::stringEndsWith<char>(src.path, ".arsc.flat")) {
return mergeResourceTable(file, override);
+
} else if (util::stringEndsWith<char>(src.path, ".flat")){
// Try opening the file and looking for an Export header.
std::unique_ptr<io::IData> data = file->openAsData();
@@ -806,9 +1031,8 @@
std::unique_ptr<ResourceFile> resourceFile = loadFileExportHeader(
src, data->data(), data->size(), mContext->getDiagnostics());
if (resourceFile) {
- return mergeCompiledFile(file, std::move(resourceFile), override);
+ return mergeCompiledFile(file, resourceFile.get(), override);
}
-
return false;
}
@@ -826,32 +1050,30 @@
}
if (Maybe<AppInfo> maybeAppInfo = extractAppInfoFromManifest(manifestXml.get())) {
- mContext->mCompilationPackage = maybeAppInfo.value().package;
+ mContext->setCompilationPackage(maybeAppInfo.value().package);
} else {
mContext->getDiagnostics()->error(DiagMessage(mOptions.manifestPath)
<< "no package specified in <manifest> tag");
return 1;
}
- if (!util::isJavaPackageName(mContext->mCompilationPackage)) {
+ if (!util::isJavaPackageName(mContext->getCompilationPackage())) {
mContext->getDiagnostics()->error(DiagMessage(mOptions.manifestPath)
<< "invalid package name '"
- << mContext->mCompilationPackage
+ << mContext->getCompilationPackage()
<< "'");
return 1;
}
- mContext->mNameMangler = util::make_unique<NameMangler>(
- NameManglerPolicy{ mContext->mCompilationPackage });
+ mContext->setNameManglerPolicy(NameManglerPolicy{ mContext->getCompilationPackage() });
- if (mContext->mCompilationPackage == u"android") {
- mContext->mPackageId = 0x01;
+ if (mContext->getCompilationPackage() == u"android") {
+ mContext->setPackageId(0x01);
} else {
- mContext->mPackageId = 0x7f;
+ mContext->setPackageId(0x7f);
}
- mContext->mSymbols = createSymbolTableFromIncludePaths();
- if (!mContext->mSymbols) {
+ if (!loadSymbolsFromIncludePaths()) {
return 1;
}
@@ -861,20 +1083,21 @@
if (mContext->verbose()) {
mContext->getDiagnostics()->note(
- DiagMessage() << "linking package '" << mContext->mCompilationPackage << "' "
- << "with package ID " << std::hex << (int) mContext->mPackageId);
+ DiagMessage() << "linking package '" << mContext->getCompilationPackage()
+ << "' with package ID " << std::hex
+ << (int) mContext->getPackageId());
}
for (const std::string& input : inputFiles) {
- if (!processFile(input, false)) {
+ if (!mergePath(input, false)) {
mContext->getDiagnostics()->error(DiagMessage() << "failed parsing input");
return 1;
}
}
for (const std::string& input : mOptions.overlayFiles) {
- if (!processFile(input, true)) {
+ if (!mergePath(input, true)) {
mContext->getDiagnostics()->error(DiagMessage() << "failed parsing overlays");
return 1;
}
@@ -893,20 +1116,28 @@
}
}
- {
+ if (!mOptions.staticLib) {
+ // Assign IDs if we are building a regular app.
IdAssigner idAssigner;
if (!idAssigner.consume(mContext, &mFinalTable)) {
mContext->getDiagnostics()->error(DiagMessage() << "failed assigning IDs");
return 1;
}
+ } else {
+ // Static libs are merged with other apps, and ID collisions are bad, so verify that
+ // no IDs have been set.
+ if (!verifyNoIdsSet()) {
+ return 1;
+ }
}
- mContext->mNameMangler = util::make_unique<NameMangler>(NameManglerPolicy{
- mContext->mCompilationPackage, mTableMerger->getMergedPackages() });
- mContext->mSymbols = JoinedSymbolTableBuilder()
- .addSymbolTable(util::make_unique<SymbolTableWrapper>(&mFinalTable))
- .addSymbolTable(std::move(mContext->mSymbols))
- .build();
+ // Add the names to mangle based on our source merge earlier.
+ mContext->setNameManglerPolicy(NameManglerPolicy{
+ mContext->getCompilationPackage(), mTableMerger->getMergedPackages() });
+
+ // Add our table to the symbol table.
+ mContext->getExternalSymbols()->prependSource(
+ util::make_unique<ResourceTableSymbolSource>(&mFinalTable));
{
ReferenceLinker linker;
@@ -915,20 +1146,32 @@
return 1;
}
- ProductFilter productFilter(mOptions.products);
- if (!productFilter.consume(mContext, &mFinalTable)) {
- mContext->getDiagnostics()->error(DiagMessage() << "failed stripping products");
- return 1;
- }
+ if (mOptions.staticLib) {
+ if (!mOptions.products.empty()) {
+ mContext->getDiagnostics()->warn(
+ DiagMessage() << "can't select products when building static library");
+ }
- // TODO(adamlesinski): Actually pass in split constraints and handle splits at the file
- // level.
- TableSplitter tableSplitter({}, mOptions.tableSplitterOptions);
- if (!tableSplitter.verifySplitConstraints(mContext)) {
- return 1;
- }
+ if (mOptions.tableSplitterOptions.configFilter != nullptr ||
+ mOptions.tableSplitterOptions.preferredDensity) {
+ mContext->getDiagnostics()->warn(
+ DiagMessage() << "can't strip resources when building static library");
+ }
+ } else {
+ ProductFilter productFilter(mOptions.products);
+ if (!productFilter.consume(mContext, &mFinalTable)) {
+ mContext->getDiagnostics()->error(DiagMessage() << "failed stripping products");
+ return 1;
+ }
- tableSplitter.splitTable(&mFinalTable);
+ // TODO(adamlesinski): Actually pass in split constraints and handle splits at the file
+ // level.
+ TableSplitter tableSplitter({}, mOptions.tableSplitterOptions);
+ if (!tableSplitter.verifySplitConstraints(mContext)) {
+ return 1;
+ }
+ tableSplitter.splitTable(&mFinalTable);
+ }
}
proguard::KeepSet proguardKeepSet;
@@ -949,7 +1192,7 @@
// AndroidManifest.xml has no resource name, but the CallSite is built from the name
// (aka, which package the AndroidManifest.xml is coming from).
// So we give it a package name so it can see local resources.
- manifestXml->file.name.package = mContext->getCompilationPackage().toString();
+ manifestXml->file.name.package = mContext->getCompilationPackage();
XmlReferenceLinker manifestLinker;
if (manifestLinker.consume(mContext, manifestXml.get())) {
@@ -986,6 +1229,7 @@
fileFlattenerOptions.doNotCompressAnything = mOptions.doNotCompressAnything;
fileFlattenerOptions.extensionsToNotCompress = mOptions.extensionsToNotCompress;
fileFlattenerOptions.noAutoVersion = mOptions.noAutoVersion;
+ fileFlattenerOptions.noVersionVectors = mOptions.noVersionVectors;
ResourceFileFlattener fileFlattener(fileFlattenerOptions, mContext, &proguardKeepSet);
if (!fileFlattener.flatten(&mFinalTable, archiveWriter.get())) {
@@ -1001,9 +1245,18 @@
}
}
- if (!flattenTable(&mFinalTable, archiveWriter.get())) {
- mContext->getDiagnostics()->error(DiagMessage() << "failed to write resources.arsc");
- return 1;
+ if (mOptions.staticLib) {
+ if (!flattenTableToPb(&mFinalTable, archiveWriter.get())) {
+ mContext->getDiagnostics()->error(DiagMessage()
+ << "failed to write resources.arsc.flat");
+ return 1;
+ }
+ } else {
+ if (!flattenTable(&mFinalTable, archiveWriter.get())) {
+ mContext->getDiagnostics()->error(DiagMessage()
+ << "failed to write resources.arsc");
+ return 1;
+ }
}
if (mOptions.generateJavaClassPath) {
@@ -1065,14 +1318,17 @@
LinkContext* mContext;
ResourceTable mFinalTable;
- ResourceTable mLocalFileTable;
std::unique_ptr<TableMerger> mTableMerger;
// A pointer to the FileCollection representing the filesystem (not archives).
- io::FileCollection* mFileCollection;
+ std::unique_ptr<io::FileCollection> mFileCollection;
// A vector of IFileCollections. This is mainly here to keep ownership of the collections.
std::vector<std::unique_ptr<io::IFileCollection>> mCollections;
+
+ // A vector of ResourceTables. This is here to retain ownership, so that the SymbolTable
+ // can use these.
+ std::vector<std::unique_ptr<ResourceTable>> mStaticTableIncludes;
};
int link(const std::vector<StringPiece>& args) {
@@ -1089,6 +1345,7 @@
Maybe<std::string> productList;
bool legacyXFlag = false;
bool requireLocalization = false;
+ bool verbose = false;
Flags flags = Flags()
.requiredFlag("-o", "Output path", &options.outputPath)
.requiredFlag("--manifest", "Path to the Android manifest to build",
@@ -1104,6 +1361,10 @@
.optionalSwitch("--no-auto-version",
"Disables automatic style and layout SDK versioning",
&options.noAutoVersion)
+ .optionalSwitch("--no-version-vectors",
+ "Disables automatic versioning of vector drawables. Use this only\n"
+ "when building with vector drawable support library",
+ &options.noVersionVectors)
.optionalSwitch("-x", "Legacy flag that specifies to use the package identifier 0x01",
&legacyXFlag)
.optionalSwitch("-z", "Require localization of strings marked 'suggested'",
@@ -1127,6 +1388,9 @@
.optionalFlag("--version-name", "Version name to inject into the AndroidManifest.xml "
"if none is present", &versionName)
.optionalSwitch("--static-lib", "Generate a static Android library", &options.staticLib)
+ .optionalSwitch("--no-static-lib-packages",
+ "Merge all library resources under the app's package",
+ &options.noStaticLibPackages)
.optionalSwitch("--non-final-ids", "Generates R.java without the final modifier.\n"
"This is implied when --static-lib is specified.",
&options.generateNonFinalIds)
@@ -1148,12 +1412,16 @@
&renameInstrumentationTargetPackage)
.optionalFlagList("-0", "File extensions not to compress",
&options.extensionsToNotCompress)
- .optionalSwitch("-v", "Enables verbose logging", &context.mVerbose);
+ .optionalSwitch("-v", "Enables verbose logging", &verbose);
if (!flags.parse("aapt2 link", args, &std::cerr)) {
return 1;
}
+ if (verbose) {
+ context.setVerbose(verbose);
+ }
+
if (privateSymbolsPackage) {
options.privateSymbols = util::utf8ToUtf16(privateSymbolsPackage.value());
}
@@ -1252,6 +1520,12 @@
options.tableSplitterOptions.preferredDensity = preferredDensityConfig.density;
}
+ // Turn off auto versioning for static-libs.
+ if (options.staticLib) {
+ options.noAutoVersion = true;
+ options.noVersionVectors = true;
+ }
+
LinkCommand cmd(&context, options);
return cmd.run(flags.getArgs());
}
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index f40fbfb..18c47df 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -30,7 +30,7 @@
.setCompilationPackage(u"android")
.setPackageId(0x01)
.setNameManglerPolicy(NameManglerPolicy{ u"android" })
- .setSymbolTable(test::StaticSymbolTableBuilder()
+ .addSymbolSource(test::StaticSymbolSourceBuilder()
.addSymbol(u"@android:attr/package", ResourceId(0x01010000),
test::AttributeBuilder()
.setTypeMask(android::ResTable_map::TYPE_STRING)
diff --git a/tools/aapt2/link/ReferenceLinker.cpp b/tools/aapt2/link/ReferenceLinker.cpp
index ef3fe4f..66eb0df 100644
--- a/tools/aapt2/link/ReferenceLinker.cpp
+++ b/tools/aapt2/link/ReferenceLinker.cpp
@@ -14,9 +14,8 @@
* limitations under the License.
*/
-#include "ReferenceLinker.h"
-
#include "Diagnostics.h"
+#include "ReferenceLinker.h"
#include "ResourceTable.h"
#include "ResourceUtils.h"
#include "ResourceValues.h"
@@ -43,45 +42,10 @@
* NOTE: All of the entries in the ResourceTable must be assigned IDs.
*/
class ReferenceLinkerVisitor : public ValueVisitor {
-private:
- IAaptContext* mContext;
- ISymbolTable* mSymbols;
- xml::IPackageDeclStack* mPackageDecls;
- StringPool* mStringPool;
- CallSite* mCallSite;
- bool mError = false;
-
- /**
- * Transform a RawString value into a more specific, appropriate value, based on the
- * Attribute. If a non RawString value is passed in, this is an identity transform.
- */
- std::unique_ptr<Item> parseValueWithAttribute(std::unique_ptr<Item> value,
- const Attribute* attr) {
- if (RawString* rawString = valueCast<RawString>(value.get())) {
- std::unique_ptr<Item> transformed =
- ResourceUtils::parseItemForAttribute(*rawString->value, attr);
-
- // If we could not parse as any specific type, try a basic STRING.
- if (!transformed && (attr->typeMask & android::ResTable_map::TYPE_STRING)) {
- util::StringBuilder stringBuilder;
- stringBuilder.append(*rawString->value);
- if (stringBuilder) {
- transformed = util::make_unique<String>(
- mStringPool->makeRef(stringBuilder.str()));
- }
- }
-
- if (transformed) {
- return transformed;
- }
- };
- return value;
- }
-
public:
using ValueVisitor::visit;
- ReferenceLinkerVisitor(IAaptContext* context, ISymbolTable* symbols, StringPool* stringPool,
+ ReferenceLinkerVisitor(IAaptContext* context, SymbolTable* symbols, StringPool* stringPool,
xml::IPackageDeclStack* decl,CallSite* callSite) :
mContext(context), mSymbols(symbols), mPackageDecls(decl), mStringPool(stringPool),
mCallSite(callSite) {
@@ -114,10 +78,11 @@
&transformedReference);
// Find the attribute in the symbol table and check if it is visible from this callsite.
- const ISymbolTable::Symbol* symbol = ReferenceLinker::resolveAttributeCheckVisibility(
+ const SymbolTable::Symbol* symbol = ReferenceLinker::resolveAttributeCheckVisibility(
transformedReference, mContext->getNameMangler(), mSymbols, mCallSite, &errStr);
if (symbol) {
// Assign our style key the correct ID.
+ // The ID may not exist.
entry.key.id = symbol->id;
// Try to convert the value to a more specific, typed value based on the
@@ -156,6 +121,41 @@
bool hasError() {
return mError;
}
+
+private:
+ IAaptContext* mContext;
+ SymbolTable* mSymbols;
+ xml::IPackageDeclStack* mPackageDecls;
+ StringPool* mStringPool;
+ CallSite* mCallSite;
+ bool mError = false;
+
+ /**
+ * Transform a RawString value into a more specific, appropriate value, based on the
+ * Attribute. If a non RawString value is passed in, this is an identity transform.
+ */
+ std::unique_ptr<Item> parseValueWithAttribute(std::unique_ptr<Item> value,
+ const Attribute* attr) {
+ if (RawString* rawString = valueCast<RawString>(value.get())) {
+ std::unique_ptr<Item> transformed =
+ ResourceUtils::parseItemForAttribute(*rawString->value, attr);
+
+ // If we could not parse as any specific type, try a basic STRING.
+ if (!transformed && (attr->typeMask & android::ResTable_map::TYPE_STRING)) {
+ util::StringBuilder stringBuilder;
+ stringBuilder.append(*rawString->value);
+ if (stringBuilder) {
+ transformed = util::make_unique<String>(
+ mStringPool->makeRef(stringBuilder.str()));
+ }
+ }
+
+ if (transformed) {
+ return transformed;
+ }
+ };
+ return value;
+ }
};
} // namespace
@@ -164,13 +164,13 @@
* The symbol is visible if it is public, or if the reference to it is requesting private access
* or if the callsite comes from the same package.
*/
-bool ReferenceLinker::isSymbolVisible(const ISymbolTable::Symbol& symbol, const Reference& ref,
+bool ReferenceLinker::isSymbolVisible(const SymbolTable::Symbol& symbol, const Reference& ref,
const CallSite& callSite) {
if (!symbol.isPublic && !ref.privateReference) {
if (ref.name) {
return callSite.resource.package == ref.name.value().package;
- } else if (ref.id) {
- return ref.id.value().packageId() == symbol.id.packageId();
+ } else if (ref.id && symbol.id) {
+ return ref.id.value().packageId() == symbol.id.value().packageId();
} else {
return false;
}
@@ -178,9 +178,9 @@
return true;
}
-const ISymbolTable::Symbol* ReferenceLinker::resolveSymbol(const Reference& reference,
- NameMangler* mangler,
- ISymbolTable* symbols) {
+const SymbolTable::Symbol* ReferenceLinker::resolveSymbol(const Reference& reference,
+ NameMangler* mangler,
+ SymbolTable* symbols) {
if (reference.name) {
Maybe<ResourceName> mangled = mangler->mangleName(reference.name.value());
return symbols->findByName(mangled ? mangled.value() : reference.name.value());
@@ -191,10 +191,10 @@
}
}
-const ISymbolTable::Symbol* ReferenceLinker::resolveSymbolCheckVisibility(
- const Reference& reference, NameMangler* nameMangler, ISymbolTable* symbols,
+const SymbolTable::Symbol* ReferenceLinker::resolveSymbolCheckVisibility(
+ const Reference& reference, NameMangler* nameMangler, SymbolTable* symbols,
CallSite* callSite, std::string* outError) {
- const ISymbolTable::Symbol* symbol = resolveSymbol(reference, nameMangler, symbols);
+ const SymbolTable::Symbol* symbol = resolveSymbol(reference, nameMangler, symbols);
if (!symbol) {
if (outError) *outError = "not found";
return nullptr;
@@ -207,12 +207,12 @@
return symbol;
}
-const ISymbolTable::Symbol* ReferenceLinker::resolveAttributeCheckVisibility(
- const Reference& reference, NameMangler* nameMangler, ISymbolTable* symbols,
+const SymbolTable::Symbol* ReferenceLinker::resolveAttributeCheckVisibility(
+ const Reference& reference, NameMangler* nameMangler, SymbolTable* symbols,
CallSite* callSite, std::string* outError) {
- const ISymbolTable::Symbol* symbol = resolveSymbolCheckVisibility(reference, nameMangler,
- symbols, callSite,
- outError);
+ const SymbolTable::Symbol* symbol = resolveSymbolCheckVisibility(reference, nameMangler,
+ symbols, callSite,
+ outError);
if (!symbol) {
return nullptr;
}
@@ -226,10 +226,10 @@
Maybe<xml::AaptAttribute> ReferenceLinker::compileXmlAttribute(const Reference& reference,
NameMangler* nameMangler,
- ISymbolTable* symbols,
+ SymbolTable* symbols,
CallSite* callSite,
std::string* outError) {
- const ISymbolTable::Symbol* symbol = resolveSymbol(reference, nameMangler, symbols);
+ const SymbolTable::Symbol* symbol = resolveSymbol(reference, nameMangler, symbols);
if (!symbol) {
return {};
}
@@ -256,7 +256,7 @@
}
bool ReferenceLinker::linkReference(Reference* reference, IAaptContext* context,
- ISymbolTable* symbols, xml::IPackageDeclStack* decls,
+ SymbolTable* symbols, xml::IPackageDeclStack* decls,
CallSite* callSite) {
assert(reference);
assert(reference->name || reference->id);
@@ -266,9 +266,12 @@
&transformedReference);
std::string errStr;
- const ISymbolTable::Symbol* s = resolveSymbolCheckVisibility(
+ const SymbolTable::Symbol* s = resolveSymbolCheckVisibility(
transformedReference, context->getNameMangler(), symbols, callSite, &errStr);
if (s) {
+ // The ID may not exist. This is fine because of the possibility of building against
+ // libraries without assigned IDs.
+ // Ex: Linking against own resources when building a static library.
reference->id = s->id;
return true;
}
diff --git a/tools/aapt2/link/ReferenceLinker.h b/tools/aapt2/link/ReferenceLinker.h
index a0eb00c..7993aaf 100644
--- a/tools/aapt2/link/ReferenceLinker.h
+++ b/tools/aapt2/link/ReferenceLinker.h
@@ -38,36 +38,36 @@
/**
* Returns true if the symbol is visible by the reference and from the callsite.
*/
- static bool isSymbolVisible(const ISymbolTable::Symbol& symbol, const Reference& ref,
+ static bool isSymbolVisible(const SymbolTable::Symbol& symbol, const Reference& ref,
const CallSite& callSite);
/**
* Performs name mangling and looks up the resource in the symbol table. Returns nullptr
* if the symbol was not found.
*/
- static const ISymbolTable::Symbol* resolveSymbol(const Reference& reference,
- NameMangler* mangler, ISymbolTable* symbols);
+ static const SymbolTable::Symbol* resolveSymbol(const Reference& reference,
+ NameMangler* mangler, SymbolTable* symbols);
/**
* Performs name mangling and looks up the resource in the symbol table. If the symbol is
* not visible by the reference at the callsite, nullptr is returned. outError holds
* the error message.
*/
- static const ISymbolTable::Symbol* resolveSymbolCheckVisibility(const Reference& reference,
- NameMangler* nameMangler,
- ISymbolTable* symbols,
- CallSite* callSite,
- std::string* outError);
+ static const SymbolTable::Symbol* resolveSymbolCheckVisibility(const Reference& reference,
+ NameMangler* nameMangler,
+ SymbolTable* symbols,
+ CallSite* callSite,
+ std::string* outError);
/**
* Same as resolveSymbolCheckVisibility(), but also makes sure the symbol is an attribute.
* That is, the return value will have a non-null value for ISymbolTable::Symbol::attribute.
*/
- static const ISymbolTable::Symbol* resolveAttributeCheckVisibility(const Reference& reference,
- NameMangler* nameMangler,
- ISymbolTable* symbols,
- CallSite* callSite,
- std::string* outError);
+ static const SymbolTable::Symbol* resolveAttributeCheckVisibility(const Reference& reference,
+ NameMangler* nameMangler,
+ SymbolTable* symbols,
+ CallSite* callSite,
+ std::string* outError);
/**
* Resolves the attribute reference and returns an xml::AaptAttribute if successful.
@@ -75,7 +75,7 @@
*/
static Maybe<xml::AaptAttribute> compileXmlAttribute(const Reference& reference,
NameMangler* nameMangler,
- ISymbolTable* symbols,
+ SymbolTable* symbols,
CallSite* callSite,
std::string* outError);
@@ -92,7 +92,7 @@
* to the reference at the callsite, the reference is updated with an ID.
* Returns false on failure, and an error message is logged to the IDiagnostics in the context.
*/
- static bool linkReference(Reference* reference, IAaptContext* context, ISymbolTable* symbols,
+ static bool linkReference(Reference* reference, IAaptContext* context, SymbolTable* symbols,
xml::IPackageDeclStack* decls, CallSite* callSite);
/**
diff --git a/tools/aapt2/link/ReferenceLinker_test.cpp b/tools/aapt2/link/ReferenceLinker_test.cpp
index 8d324fe..76b2309 100644
--- a/tools/aapt2/link/ReferenceLinker_test.cpp
+++ b/tools/aapt2/link/ReferenceLinker_test.cpp
@@ -15,12 +15,9 @@
*/
#include "link/ReferenceLinker.h"
-#include "process/SymbolTable.h"
+#include "test/Test.h"
-#include "test/Builders.h"
-#include "test/Context.h"
-
-#include <gtest/gtest.h>
+using android::ResTable_map;
namespace aapt {
@@ -41,12 +38,10 @@
.setCompilationPackage(u"com.app.test")
.setPackageId(0x7f)
.setNameManglerPolicy(NameManglerPolicy{ u"com.app.test" })
- .setSymbolTable(JoinedSymbolTableBuilder()
- .addSymbolTable(util::make_unique<SymbolTableWrapper>(table.get()))
- .addSymbolTable(test::StaticSymbolTableBuilder()
- .addPublicSymbol(u"@android:string/ok", ResourceId(0x01040034))
- .build())
- .build())
+ .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+ .addSymbolSource(test::StaticSymbolSourceBuilder()
+ .addPublicSymbol(u"@android:string/ok", ResourceId(0x01040034))
+ .build())
.build();
ReferenceLinker linker;
@@ -91,19 +86,20 @@
.setCompilationPackage(u"com.app.test")
.setPackageId(0x7f)
.setNameManglerPolicy(NameManglerPolicy{ u"com.app.test" })
- .setSymbolTable(test::StaticSymbolTableBuilder()
- .addPublicSymbol(u"@android:style/Theme.Material", ResourceId(0x01060000))
- .addPublicSymbol(u"@android:attr/foo", ResourceId(0x01010001),
- test::AttributeBuilder()
- .setTypeMask(android::ResTable_map::TYPE_COLOR)
- .build())
- .addPublicSymbol(u"@android:attr/bar", ResourceId(0x01010002),
- test::AttributeBuilder()
- .setTypeMask(android::ResTable_map::TYPE_FLAGS)
- .addItem(u"one", 0x01)
- .addItem(u"two", 0x02)
- .build())
- .build())
+ .addSymbolSource(test::StaticSymbolSourceBuilder()
+ .addPublicSymbol(u"@android:style/Theme.Material",
+ ResourceId(0x01060000))
+ .addPublicSymbol(u"@android:attr/foo", ResourceId(0x01010001),
+ test::AttributeBuilder()
+ .setTypeMask(ResTable_map::TYPE_COLOR)
+ .build())
+ .addPublicSymbol(u"@android:attr/bar", ResourceId(0x01010002),
+ test::AttributeBuilder()
+ .setTypeMask(ResTable_map::TYPE_FLAGS)
+ .addItem(u"one", 0x01)
+ .addItem(u"two", 0x02)
+ .build())
+ .build())
.build();
ReferenceLinker linker;
@@ -131,11 +127,13 @@
.setCompilationPackage(u"com.app.test")
.setPackageId(0x7f)
.setNameManglerPolicy(NameManglerPolicy{ u"com.app.test", { u"com.android.support" } })
- .setSymbolTable(test::StaticSymbolTableBuilder()
- .addPublicSymbol(u"@com.app.test:attr/com.android.support$foo",
- ResourceId(0x7f010000), test::AttributeBuilder()
- .setTypeMask(android::ResTable_map::TYPE_COLOR).build())
- .build())
+ .addSymbolSource(test::StaticSymbolSourceBuilder()
+ .addPublicSymbol(u"@com.app.test:attr/com.android.support$foo",
+ ResourceId(0x7f010000),
+ test::AttributeBuilder()
+ .setTypeMask(ResTable_map::TYPE_COLOR)
+ .build())
+ .build())
.build();
std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
@@ -167,12 +165,10 @@
.setCompilationPackage(u"com.app.test")
.setPackageId(0x7f)
.setNameManglerPolicy(NameManglerPolicy{ u"com.app.test" })
- .setSymbolTable(JoinedSymbolTableBuilder()
- .addSymbolTable(util::make_unique<SymbolTableWrapper>(table.get()))
- .addSymbolTable(test::StaticSymbolTableBuilder()
- .addSymbol(u"@android:string/hidden", ResourceId(0x01040034))
- .build())
- .build())
+ .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+ .addSymbolSource(test::StaticSymbolSourceBuilder()
+ .addSymbol(u"@android:string/hidden", ResourceId(0x01040034))
+ .build())
.build();
ReferenceLinker linker;
@@ -190,13 +186,12 @@
.setCompilationPackage(u"com.app.test")
.setPackageId(0x7f)
.setNameManglerPolicy(NameManglerPolicy{ u"com.app.test", { u"com.app.lib" } })
- .setSymbolTable(JoinedSymbolTableBuilder()
- .addSymbolTable(util::make_unique<SymbolTableWrapper>(table.get()))
- .addSymbolTable(test::StaticSymbolTableBuilder()
- .addSymbol(u"@com.app.test:string/com.app.lib$hidden",
- ResourceId(0x7f040034))
- .build())
- .build())
+ .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+ .addSymbolSource(test::StaticSymbolSourceBuilder()
+ .addSymbol(u"@com.app.test:string/com.app.lib$hidden",
+ ResourceId(0x7f040034))
+ .build())
+
.build();
ReferenceLinker linker;
@@ -215,15 +210,14 @@
.setCompilationPackage(u"com.app.test")
.setPackageId(0x7f)
.setNameManglerPolicy(NameManglerPolicy{ u"com.app.test" })
- .setSymbolTable(JoinedSymbolTableBuilder()
- .addSymbolTable(util::make_unique<SymbolTableWrapper>(table.get()))
- .addSymbolTable(test::StaticSymbolTableBuilder()
- .addSymbol(u"@android:attr/hidden", ResourceId(0x01010001),
- test::AttributeBuilder()
- .setTypeMask(android::ResTable_map::TYPE_COLOR)
- .build())
- .build())
- .build())
+ .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+ .addSymbolSource(test::StaticSymbolSourceBuilder()
+ .addSymbol(u"@android:attr/hidden", ResourceId(0x01010001),
+ test::AttributeBuilder()
+ .setTypeMask(
+ android::ResTable_map::TYPE_COLOR)
+ .build())
+ .build())
.build();
ReferenceLinker linker;
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index 5f11745..7471e15 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -34,10 +34,21 @@
assert(mMasterPackage && "package name or ID already taken");
}
+bool TableMerger::merge(const Source& src, ResourceTable* table,
+ io::IFileCollection* collection) {
+ return mergeImpl(src, table, collection, false /* overlay */, true /* allow new */);
+}
+
+bool TableMerger::mergeOverlay(const Source& src, ResourceTable* table,
+ io::IFileCollection* collection) {
+ return mergeImpl(src, table, collection, true /* overlay */, mOptions.autoAddOverlay);
+}
+
/**
* This will merge packages with the same package name (or no package name).
*/
bool TableMerger::mergeImpl(const Source& src, ResourceTable* table,
+ io::IFileCollection* collection,
bool overlay, bool allowNew) {
const uint8_t desiredPackageId = mContext->getPackageId();
@@ -51,26 +62,36 @@
}
if (package->name.empty() || mContext->getCompilationPackage() == package->name) {
+ FileMergeCallback callback;
+ if (collection) {
+ callback = [&](const ResourceNameRef& name, const ConfigDescription& config,
+ FileReference* newFile, FileReference* oldFile) -> bool {
+ // The old file's path points inside the APK, so we can use it as is.
+ io::IFile* f = collection->findFile(util::utf16ToUtf8(*oldFile->path));
+ if (!f) {
+ mContext->getDiagnostics()->error(DiagMessage(src) << "file '"
+ << *oldFile->path
+ << "' not found");
+ return false;
+ }
+
+ newFile->file = f;
+ return true;
+ };
+ }
+
// Merge here. Once the entries are merged and mangled, any references to
// them are still valid. This is because un-mangled references are
// mangled, then looked up at resolution time.
// Also, when linking, we convert references with no package name to use
// the compilation package name.
error |= !doMerge(src, table, package.get(),
- false /* mangle */, overlay, allowNew, {});
+ false /* mangle */, overlay, allowNew, callback);
}
}
return !error;
}
-bool TableMerger::merge(const Source& src, ResourceTable* table) {
- return mergeImpl(src, table, false /* overlay */, true /* allow new */);
-}
-
-bool TableMerger::mergeOverlay(const Source& src, ResourceTable* table) {
- return mergeImpl(src, table, true /* overlay */, mOptions.autoAddOverlay);
-}
-
/**
* This will merge and mangle resources from a static library.
*/
diff --git a/tools/aapt2/link/TableMerger.h b/tools/aapt2/link/TableMerger.h
index b3c22dd..80c2a5e 100644
--- a/tools/aapt2/link/TableMerger.h
+++ b/tools/aapt2/link/TableMerger.h
@@ -65,13 +65,17 @@
/**
* Merges resources from the same or empty package. This is for local sources.
+ * An io::IFileCollection is optional and used to find the referenced Files and process them.
*/
- bool merge(const Source& src, ResourceTable* table);
+ bool merge(const Source& src, ResourceTable* table,
+ io::IFileCollection* collection = nullptr);
/**
* Merges resources from an overlay ResourceTable.
+ * An io::IFileCollection is optional and used to find the referenced Files and process them.
*/
- bool mergeOverlay(const Source& src, ResourceTable* table);
+ bool mergeOverlay(const Source& src, ResourceTable* table,
+ io::IFileCollection* collection = nullptr);
/**
* Merges resources from the given package, mangling the name. This is for static libraries.
@@ -104,7 +108,7 @@
bool mergeFileImpl(const ResourceFile& fileDesc, io::IFile* file, bool overlay);
- bool mergeImpl(const Source& src, ResourceTable* srcTable,
+ bool mergeImpl(const Source& src, ResourceTable* srcTable, io::IFileCollection* collection,
bool overlay, bool allowNew);
bool doMerge(const Source& src, ResourceTable* srcTable, ResourceTablePackage* srcPackage,
diff --git a/tools/aapt2/link/XmlReferenceLinker.cpp b/tools/aapt2/link/XmlReferenceLinker.cpp
index a26d763..568bc74 100644
--- a/tools/aapt2/link/XmlReferenceLinker.cpp
+++ b/tools/aapt2/link/XmlReferenceLinker.cpp
@@ -34,17 +34,10 @@
* as needed.
*/
class ReferenceVisitor : public ValueVisitor {
-private:
- IAaptContext* mContext;
- ISymbolTable* mSymbols;
- xml::IPackageDeclStack* mDecls;
- CallSite* mCallSite;
- bool mError;
-
public:
using ValueVisitor::visit;
- ReferenceVisitor(IAaptContext* context, ISymbolTable* symbols, xml::IPackageDeclStack* decls,
+ ReferenceVisitor(IAaptContext* context, SymbolTable* symbols, xml::IPackageDeclStack* decls,
CallSite* callSite) :
mContext(context), mSymbols(symbols), mDecls(decls), mCallSite(callSite),
mError(false) {
@@ -59,25 +52,23 @@
bool hasError() const {
return mError;
}
+
+private:
+ IAaptContext* mContext;
+ SymbolTable* mSymbols;
+ xml::IPackageDeclStack* mDecls;
+ CallSite* mCallSite;
+ bool mError;
};
/**
* Visits each xml Element and compiles the attributes within.
*/
class XmlVisitor : public xml::PackageAwareVisitor {
-private:
- IAaptContext* mContext;
- ISymbolTable* mSymbols;
- Source mSource;
- std::set<int>* mSdkLevelsFound;
- CallSite* mCallSite;
- ReferenceVisitor mReferenceVisitor;
- bool mError = false;
-
public:
using xml::PackageAwareVisitor::visit;
- XmlVisitor(IAaptContext* context, ISymbolTable* symbols, const Source& source,
+ XmlVisitor(IAaptContext* context, SymbolTable* symbols, const Source& source,
std::set<int>* sdkLevelsFound, CallSite* callSite) :
mContext(context), mSymbols(symbols), mSource(source), mSdkLevelsFound(sdkLevelsFound),
mCallSite(callSite), mReferenceVisitor(context, symbols, this, callSite) {
@@ -105,10 +96,13 @@
// Convert the string value into a compiled Value if this is a valid attribute.
if (attr.compiledAttribute) {
- // Record all SDK levels from which the attributes were defined.
- const int sdkLevel = findAttributeSdkLevel(attr.compiledAttribute.value().id);
- if (sdkLevel > 1) {
- mSdkLevelsFound->insert(sdkLevel);
+ if (attr.compiledAttribute.value().id) {
+ // Record all SDK levels from which the attributes were defined.
+ const size_t sdkLevel = findAttributeSdkLevel(
+ attr.compiledAttribute.value().id.value());
+ if (sdkLevel > 1) {
+ mSdkLevelsFound->insert(sdkLevel);
+ }
}
const Attribute* attribute = &attr.compiledAttribute.value().attribute;
@@ -124,6 +118,7 @@
<< *attribute);
mError = true;
}
+
} else {
mContext->getDiagnostics()->error(DiagMessage(source)
<< "attribute '" << package << ":"
@@ -150,6 +145,15 @@
bool hasError() {
return mError || mReferenceVisitor.hasError();
}
+
+private:
+ IAaptContext* mContext;
+ SymbolTable* mSymbols;
+ Source mSource;
+ std::set<int>* mSdkLevelsFound;
+ CallSite* mCallSite;
+ ReferenceVisitor mReferenceVisitor;
+ bool mError = false;
};
} // namespace
diff --git a/tools/aapt2/link/XmlReferenceLinker_test.cpp b/tools/aapt2/link/XmlReferenceLinker_test.cpp
index 3bfaf91..af9098b 100644
--- a/tools/aapt2/link/XmlReferenceLinker_test.cpp
+++ b/tools/aapt2/link/XmlReferenceLinker_test.cpp
@@ -14,12 +14,9 @@
* limitations under the License.
*/
+#include <test/Context.h>
#include "link/Linkers.h"
-
-#include "test/Builders.h"
-#include "test/Context.h"
-
-#include <gtest/gtest.h>
+#include "test/Test.h"
namespace aapt {
@@ -30,7 +27,7 @@
.setCompilationPackage(u"com.app.test")
.setNameManglerPolicy(
NameManglerPolicy{ u"com.app.test", { u"com.android.support" } })
- .setSymbolTable(test::StaticSymbolTableBuilder()
+ .addSymbolSource(test::StaticSymbolSourceBuilder()
.addPublicSymbol(u"@android:attr/layout_width", ResourceId(0x01010000),
test::AttributeBuilder()
.setTypeMask(android::ResTable_map::TYPE_ENUM |
@@ -92,14 +89,16 @@
u"layout_width");
ASSERT_NE(xmlAttr, nullptr);
AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
- EXPECT_EQ(xmlAttr->compiledAttribute.value().id, ResourceId(0x01010000));
+ AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
+ EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(), ResourceId(0x01010000));
ASSERT_NE(xmlAttr->compiledValue, nullptr);
ASSERT_NE(valueCast<BinaryPrimitive>(xmlAttr->compiledValue.get()), nullptr);
xmlAttr = viewEl->findAttribute(u"http://schemas.android.com/apk/res/android", u"background");
ASSERT_NE(xmlAttr, nullptr);
AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
- EXPECT_EQ(xmlAttr->compiledAttribute.value().id, ResourceId(0x01010001));
+ AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
+ EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(), ResourceId(0x01010001));
ASSERT_NE(xmlAttr->compiledValue, nullptr);
Reference* ref = valueCast<Reference>(xmlAttr->compiledValue.get());
ASSERT_NE(ref, nullptr);
@@ -163,7 +162,8 @@
u"http://schemas.android.com/apk/res/com.android.support", u"colorAccent");
ASSERT_NE(xmlAttr, nullptr);
AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
- EXPECT_EQ(xmlAttr->compiledAttribute.value().id, ResourceId(0x7f010001));
+ AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
+ EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(), ResourceId(0x7f010001));
ASSERT_NE(valueCast<BinaryPrimitive>(xmlAttr->compiledValue.get()), nullptr);
}
@@ -182,7 +182,8 @@
u"colorAccent");
ASSERT_NE(xmlAttr, nullptr);
AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
- EXPECT_EQ(xmlAttr->compiledAttribute.value().id, ResourceId(0x7f010000));
+ AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
+ EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(), ResourceId(0x7f010000));
Reference* ref = valueCast<Reference>(xmlAttr->compiledValue.get());
ASSERT_NE(ref, nullptr);
AAPT_ASSERT_TRUE(ref->name);
@@ -209,7 +210,8 @@
u"attr");
ASSERT_NE(xmlAttr, nullptr);
AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
- EXPECT_EQ(xmlAttr->compiledAttribute.value().id, ResourceId(0x01010002));
+ AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
+ EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(), ResourceId(0x01010002));
Reference* ref = valueCast<Reference>(xmlAttr->compiledValue.get());
ASSERT_NE(ref, nullptr);
AAPT_ASSERT_TRUE(ref->id);
@@ -223,7 +225,8 @@
xmlAttr = viewEl->findAttribute(u"http://schemas.android.com/apk/res/com.app.test", u"attr");
ASSERT_NE(xmlAttr, nullptr);
AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
- EXPECT_EQ(xmlAttr->compiledAttribute.value().id, ResourceId(0x7f010002));
+ AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
+ EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(), ResourceId(0x7f010002));
ref = valueCast<Reference>(xmlAttr->compiledValue.get());
ASSERT_NE(ref, nullptr);
AAPT_ASSERT_TRUE(ref->id);
@@ -246,7 +249,8 @@
u"http://schemas.android.com/apk/res/com.app.test", u"attr");
ASSERT_NE(xmlAttr, nullptr);
AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
- EXPECT_EQ(xmlAttr->compiledAttribute.value().id, ResourceId(0x7f010002));
+ AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
+ EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(), ResourceId(0x7f010002));
Reference* ref = valueCast<Reference>(xmlAttr->compiledValue.get());
ASSERT_NE(ref, nullptr);
AAPT_ASSERT_TRUE(ref->id);
diff --git a/tools/aapt2/process/IResourceTableConsumer.h b/tools/aapt2/process/IResourceTableConsumer.h
index 3a88044..9affb83 100644
--- a/tools/aapt2/process/IResourceTableConsumer.h
+++ b/tools/aapt2/process/IResourceTableConsumer.h
@@ -30,14 +30,14 @@
namespace aapt {
class ResourceTable;
-struct ISymbolTable;
+class SymbolTable;
struct IAaptContext {
virtual ~IAaptContext() = default;
- virtual ISymbolTable* getExternalSymbols() = 0;
+ virtual SymbolTable* getExternalSymbols() = 0;
virtual IDiagnostics* getDiagnostics() = 0;
- virtual StringPiece16 getCompilationPackage() = 0;
+ virtual const std::u16string& getCompilationPackage() = 0;
virtual uint8_t getPackageId() = 0;
virtual NameMangler* getNameMangler() = 0;
virtual bool verbose() = 0;
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index b6030a2..a8f9bfe 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -25,11 +25,59 @@
namespace aapt {
-const ISymbolTable::Symbol* SymbolTableWrapper::findByName(const ResourceName& name) {
+void SymbolTable::appendSource(std::unique_ptr<ISymbolSource> source) {
+ mSources.push_back(std::move(source));
+
+ // We do not clear the cache, because sources earlier in the list take precedent.
+}
+
+void SymbolTable::prependSource(std::unique_ptr<ISymbolSource> source) {
+ mSources.insert(mSources.begin(), std::move(source));
+
+ // We must clear the cache in case we did a lookup before adding this resource.
+ mCache.clear();
+}
+
+const SymbolTable::Symbol* SymbolTable::findByName(const ResourceName& name) {
if (const std::shared_ptr<Symbol>& s = mCache.get(name)) {
return s.get();
}
+ // We did not find it in the cache, so look through the sources.
+ for (auto& symbolSource : mSources) {
+ std::unique_ptr<Symbol> symbol = symbolSource->findByName(name);
+ if (symbol) {
+ // Take ownership of the symbol into a shared_ptr. We do this because LruCache
+ // doesn't support unique_ptr.
+ std::shared_ptr<Symbol> sharedSymbol = std::shared_ptr<Symbol>(symbol.release());
+ mCache.put(name, sharedSymbol);
+ return sharedSymbol.get();
+ }
+ }
+ return nullptr;
+}
+
+const SymbolTable::Symbol* SymbolTable::findById(ResourceId id) {
+ if (const std::shared_ptr<Symbol>& s = mIdCache.get(id)) {
+ return s.get();
+ }
+
+ // We did not find it in the cache, so look through the sources.
+ for (auto& symbolSource : mSources) {
+ std::unique_ptr<Symbol> symbol = symbolSource->findById(id);
+ if (symbol) {
+ // Take ownership of the symbol into a shared_ptr. We do this because LruCache
+ // doesn't support unique_ptr.
+ std::shared_ptr<Symbol> sharedSymbol = std::shared_ptr<Symbol>(symbol.release());
+ mIdCache.put(id, sharedSymbol);
+ return sharedSymbol.get();
+ }
+ }
+ return nullptr;
+}
+
+std::unique_ptr<SymbolTable::Symbol> ResourceTableSymbolSource::findByName(
+ const ResourceName& name) {
Maybe<ResourceTable::SearchResult> result = mTable->findResource(name);
if (!result) {
if (name.type == ResourceType::kAttr) {
@@ -41,16 +89,13 @@
ResourceTable::SearchResult sr = result.value();
- // If no ID exists, we treat the symbol as missing. SymbolTables are used to
- // find symbols to link.
- if (!sr.package->id || !sr.type->id || !sr.entry->id) {
- return {};
- }
-
- std::shared_ptr<Symbol> symbol = std::make_shared<Symbol>();
- symbol->id = ResourceId(sr.package->id.value(), sr.type->id.value(), sr.entry->id.value());
+ std::unique_ptr<SymbolTable::Symbol> symbol = util::make_unique<SymbolTable::Symbol>();
symbol->isPublic = (sr.entry->symbolStatus.state == SymbolState::kPublic);
+ if (sr.package->id && sr.type->id && sr.entry->id) {
+ symbol->id = ResourceId(sr.package->id.value(), sr.type->id.value(), sr.entry->id.value());
+ }
+
if (name.type == ResourceType::kAttr || name.type == ResourceType::kAttrPrivate) {
const ConfigDescription kDefaultConfig;
ResourceConfigValue* configValue = sr.entry->findValue(kDefaultConfig);
@@ -63,18 +108,16 @@
}
}
}
-
- if (name.type == ResourceType::kAttrPrivate) {
- // Masquerade this entry as kAttr.
- mCache.put(ResourceName(name.package, ResourceType::kAttr, name.entry), symbol);
- } else {
- mCache.put(name, symbol);
- }
- return symbol.get();
+ return symbol;
}
-static std::shared_ptr<ISymbolTable::Symbol> lookupAttributeInTable(const android::ResTable& table,
- ResourceId id) {
+bool AssetManagerSymbolSource::addAssetPath(const StringPiece& path) {
+ int32_t cookie = 0;
+ return mAssets.addAssetPath(android::String8(path.data(), path.size()), &cookie);
+}
+
+static std::unique_ptr<SymbolTable::Symbol> lookupAttributeInTable(const android::ResTable& table,
+ ResourceId id) {
// Try as a bag.
const android::ResTable::bag_entry* entry;
ssize_t count = table.lockBag(id.id, &entry);
@@ -84,7 +127,7 @@
}
// We found a resource.
- std::shared_ptr<ISymbolTable::Symbol> s = std::make_shared<ISymbolTable::Symbol>();
+ std::unique_ptr<SymbolTable::Symbol> s = util::make_unique<SymbolTable::Symbol>();
s->id = id;
// Check to see if it is an attribute.
@@ -138,43 +181,36 @@
return s;
}
-const ISymbolTable::Symbol* AssetManagerSymbolTableBuilder::AssetManagerSymbolTable::findByName(
+std::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::findByName(
const ResourceName& name) {
- if (const std::shared_ptr<Symbol>& s = mCache.get(name)) {
- return s.get();
+ const android::ResTable& table = mAssets.getResources(false);
+ StringPiece16 typeStr = toString(name.type);
+ uint32_t typeSpecFlags = 0;
+ ResourceId resId = table.identifierForName(name.entry.data(), name.entry.size(),
+ typeStr.data(), typeStr.size(),
+ name.package.data(), name.package.size(),
+ &typeSpecFlags);
+ if (!resId.isValid()) {
+ return {};
}
- for (const auto& asset : mAssets) {
- const android::ResTable& table = asset->getResources(false);
- StringPiece16 typeStr = toString(name.type);
- uint32_t typeSpecFlags = 0;
- ResourceId resId = table.identifierForName(name.entry.data(), name.entry.size(),
- typeStr.data(), typeStr.size(),
- name.package.data(), name.package.size(),
- &typeSpecFlags);
- if (!resId.isValid()) {
- continue;
- }
-
- std::shared_ptr<Symbol> s;
- if (name.type == ResourceType::kAttr) {
- s = lookupAttributeInTable(table, resId);
- } else {
- s = std::make_shared<Symbol>();
- s->id = resId;
- }
-
- if (s) {
- s->isPublic = (typeSpecFlags & android::ResTable_typeSpec::SPEC_PUBLIC) != 0;
- mCache.put(name, s);
- return s.get();
- }
+ std::unique_ptr<SymbolTable::Symbol> s;
+ if (name.type == ResourceType::kAttr) {
+ s = lookupAttributeInTable(table, resId);
+ } else {
+ s = util::make_unique<SymbolTable::Symbol>();
+ s->id = resId;
}
- return nullptr;
+
+ if (s) {
+ s->isPublic = (typeSpecFlags & android::ResTable_typeSpec::SPEC_PUBLIC) != 0;
+ return s;
+ }
+ return {};
}
static Maybe<ResourceName> getResourceName(const android::ResTable& table, ResourceId id) {
- android::ResTable::resource_name resName;
+ android::ResTable::resource_name resName = {};
if (!table.getResourceName(id.id, true, &resName)) {
return {};
}
@@ -211,55 +247,27 @@
return name;
}
-const ISymbolTable::Symbol* AssetManagerSymbolTableBuilder::AssetManagerSymbolTable::findById(
- ResourceId id) {
- if (const std::shared_ptr<Symbol>& s = mIdCache.get(id)) {
- return s.get();
+std::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::findById(ResourceId id) {
+ const android::ResTable& table = mAssets.getResources(false);
+ Maybe<ResourceName> maybeName = getResourceName(table, id);
+ if (!maybeName) {
+ return {};
}
- for (const auto& asset : mAssets) {
- const android::ResTable& table = asset->getResources(false);
+ uint32_t typeSpecFlags = 0;
+ table.getResourceFlags(id.id, &typeSpecFlags);
- Maybe<ResourceName> maybeName = getResourceName(table, id);
- if (!maybeName) {
- continue;
- }
-
- uint32_t typeSpecFlags = 0;
- table.getResourceFlags(id.id, &typeSpecFlags);
-
- std::shared_ptr<Symbol> s;
- if (maybeName.value().type == ResourceType::kAttr) {
- s = lookupAttributeInTable(table, id);
- } else {
- s = std::make_shared<Symbol>();
- s->id = id;
- }
-
- if (s) {
- s->isPublic = (typeSpecFlags & android::ResTable_typeSpec::SPEC_PUBLIC) != 0;
- mIdCache.put(id, s);
- return s.get();
- }
+ std::unique_ptr<SymbolTable::Symbol> s;
+ if (maybeName.value().type == ResourceType::kAttr) {
+ s = lookupAttributeInTable(table, id);
+ } else {
+ s = util::make_unique<SymbolTable::Symbol>();
+ s->id = id;
}
- return nullptr;
-}
-const ISymbolTable::Symbol* JoinedSymbolTableBuilder::JoinedSymbolTable::findByName(
- const ResourceName& name) {
- for (auto& symbolTable : mSymbolTables) {
- if (const Symbol* s = symbolTable->findByName(name)) {
- return s;
- }
- }
- return {};
-}
-
-const ISymbolTable::Symbol* JoinedSymbolTableBuilder::JoinedSymbolTable::findById(ResourceId id) {
- for (auto& symbolTable : mSymbolTables) {
- if (const Symbol* s = symbolTable->findById(id)) {
- return s;
- }
+ if (s) {
+ s->isPublic = (typeSpecFlags & android::ResTable_typeSpec::SPEC_PUBLIC) != 0;
+ return s;
}
return {};
}
diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h
index 22096ed..8ea1c75 100644
--- a/tools/aapt2/process/SymbolTable.h
+++ b/tools/aapt2/process/SymbolTable.h
@@ -25,37 +25,20 @@
#include <utils/JenkinsHash.h>
#include <utils/LruCache.h>
+#include <android-base/macros.h>
#include <androidfw/AssetManager.h>
#include <algorithm>
-#include <map>
#include <memory>
#include <vector>
namespace aapt {
-struct ISymbolTable {
- virtual ~ISymbolTable() = default;
-
- struct Symbol {
- ResourceId id;
- std::unique_ptr<Attribute> attribute;
- bool isPublic;
- };
-
- /**
- * Never hold on to the result between calls to findByName or findById. The results
- * are typically stored in a cache which may evict entries.
- */
- virtual const Symbol* findByName(const ResourceName& name) = 0;
- virtual const Symbol* findById(ResourceId id) = 0;
-};
-
inline android::hash_t hash_type(const ResourceName& name) {
std::hash<std::u16string> strHash;
android::hash_t hash = 0;
- hash = android::JenkinsHashMix(hash, strHash(name.package));
+ hash = android::JenkinsHashMix(hash, (uint32_t) strHash(name.package));
hash = android::JenkinsHashMix(hash, (uint32_t) name.type);
- hash = android::JenkinsHashMix(hash, strHash(name.entry));
+ hash = android::JenkinsHashMix(hash, (uint32_t) strHash(name.entry));
return hash;
}
@@ -63,88 +46,87 @@
return android::hash_type(id.id);
}
-/**
- * Presents a ResourceTable as an ISymbolTable, caching results.
- * Instances of this class must outlive the encompassed ResourceTable.
- * Since symbols are cached, the ResourceTable should not change during the
- * lifetime of this SymbolTableWrapper.
- *
- * If a resource in the ResourceTable does not have a ResourceID assigned to it,
- * it is ignored.
- *
- * Lookups by ID are ignored.
- */
-class SymbolTableWrapper : public ISymbolTable {
+class ISymbolSource;
+
+class SymbolTable {
+public:
+ struct Symbol {
+ Maybe<ResourceId> id;
+ std::unique_ptr<Attribute> attribute;
+ bool isPublic;
+ };
+
+ SymbolTable() : mCache(200), mIdCache(200) {
+ }
+
+ void appendSource(std::unique_ptr<ISymbolSource> source);
+ void prependSource(std::unique_ptr<ISymbolSource> source);
+
+ /**
+ * Never hold on to the result between calls to findByName or findById. The results
+ * are typically stored in a cache which may evict entries.
+ */
+ const Symbol* findByName(const ResourceName& name);
+ const Symbol* findById(ResourceId id);
+
private:
- ResourceTable* mTable;
+ std::vector<std::unique_ptr<ISymbolSource>> mSources;
// We use shared_ptr because unique_ptr is not supported and
// we need automatic deletion.
android::LruCache<ResourceName, std::shared_ptr<Symbol>> mCache;
+ android::LruCache<ResourceId, std::shared_ptr<Symbol>> mIdCache;
+ DISALLOW_COPY_AND_ASSIGN(SymbolTable);
+};
+
+/**
+ * An interface that a symbol source implements in order to surface symbol information
+ * to the symbol table.
+ */
+class ISymbolSource {
public:
- SymbolTableWrapper(ResourceTable* table) : mTable(table), mCache(200) {
+ virtual ~ISymbolSource() = default;
+
+ virtual std::unique_ptr<SymbolTable::Symbol> findByName(const ResourceName& name) = 0;
+ virtual std::unique_ptr<SymbolTable::Symbol> findById(ResourceId id) = 0;
+};
+
+/**
+ * Exposes the resources in a ResourceTable as symbols for SymbolTable.
+ * Instances of this class must outlive the encompassed ResourceTable.
+ * Lookups by ID are ignored.
+ */
+class ResourceTableSymbolSource : public ISymbolSource {
+public:
+ explicit ResourceTableSymbolSource(ResourceTable* table) : mTable(table) {
}
- const Symbol* findByName(const ResourceName& name) override;
+ std::unique_ptr<SymbolTable::Symbol> findByName(const ResourceName& name) override;
- // Unsupported, all queries to ResourceTable should be done by name.
- const Symbol* findById(ResourceId id) override {
+ std::unique_ptr<SymbolTable::Symbol> findById(ResourceId id) override {
return {};
}
+
+private:
+ ResourceTable* mTable;
+
+ DISALLOW_COPY_AND_ASSIGN(ResourceTableSymbolSource);
};
-class AssetManagerSymbolTableBuilder {
-private:
- struct AssetManagerSymbolTable : public ISymbolTable {
- std::vector<std::unique_ptr<android::AssetManager>> mAssets;
-
- // We use shared_ptr because unique_ptr is not supported and
- // we need automatic deletion.
- android::LruCache<ResourceName, std::shared_ptr<Symbol>> mCache;
- android::LruCache<ResourceId, std::shared_ptr<Symbol>> mIdCache;
-
- AssetManagerSymbolTable() : mCache(200), mIdCache(200) {
- }
-
- const Symbol* findByName(const ResourceName& name) override;
- const Symbol* findById(ResourceId id) override;
- };
-
- std::unique_ptr<AssetManagerSymbolTable> mSymbolTable =
- util::make_unique<AssetManagerSymbolTable>();
-
+class AssetManagerSymbolSource : public ISymbolSource {
public:
- AssetManagerSymbolTableBuilder& add(std::unique_ptr<android::AssetManager> assetManager) {
- mSymbolTable->mAssets.push_back(std::move(assetManager));
- return *this;
- }
+ AssetManagerSymbolSource() = default;
- std::unique_ptr<ISymbolTable> build() {
- return std::move(mSymbolTable);
- }
-};
+ bool addAssetPath(const StringPiece& path);
-class JoinedSymbolTableBuilder {
+ std::unique_ptr<SymbolTable::Symbol> findByName(const ResourceName& name) override;
+ std::unique_ptr<SymbolTable::Symbol> findById(ResourceId id) override;
+
private:
- struct JoinedSymbolTable : public ISymbolTable {
- std::vector<std::unique_ptr<ISymbolTable>> mSymbolTables;
+ android::AssetManager mAssets;
- const Symbol* findByName(const ResourceName& name) override;
- const Symbol* findById(ResourceId id) override;
- };
-
- std::unique_ptr<JoinedSymbolTable> mSymbolTable = util::make_unique<JoinedSymbolTable>();
-
-public:
- JoinedSymbolTableBuilder& addSymbolTable(std::unique_ptr<ISymbolTable> table) {
- mSymbolTable->mSymbolTables.push_back(std::move(table));
- return *this;
- }
-
- std::unique_ptr<ISymbolTable> build() {
- return std::move(mSymbolTable);
- }
+ DISALLOW_COPY_AND_ASSIGN(AssetManagerSymbolSource);
};
} // namespace aapt
diff --git a/tools/aapt2/process/SymbolTable_test.cpp b/tools/aapt2/process/SymbolTable_test.cpp
index 1dc3b4f..34f31be 100644
--- a/tools/aapt2/process/SymbolTable_test.cpp
+++ b/tools/aapt2/process/SymbolTable_test.cpp
@@ -15,14 +15,11 @@
*/
#include "process/SymbolTable.h"
-#include "test/Builders.h"
-#include "test/Context.h"
-
-#include <gtest/gtest.h>
+#include "test/Test.h"
namespace aapt {
-TEST(SymbolTableWrapperTest, FindSymbolsWithIds) {
+TEST(ResourceTableSymbolSourceTest, FindSymbols) {
std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
.addSimple(u"@android:id/foo", ResourceId(0x01020000))
.addSimple(u"@android:id/bar")
@@ -30,27 +27,27 @@
test::AttributeBuilder().build())
.build();
- SymbolTableWrapper symbolTable(table.get());
- EXPECT_NE(symbolTable.findByName(test::parseNameOrDie(u"@android:id/foo")), nullptr);
- EXPECT_EQ(symbolTable.findByName(test::parseNameOrDie(u"@android:id/bar")), nullptr);
+ ResourceTableSymbolSource symbolSource(table.get());
+ EXPECT_NE(nullptr, symbolSource.findByName(test::parseNameOrDie(u"@android:id/foo")));
+ EXPECT_NE(nullptr, symbolSource.findByName(test::parseNameOrDie(u"@android:id/bar")));
- const ISymbolTable::Symbol* s = symbolTable.findByName(
+ std::unique_ptr<SymbolTable::Symbol> s = symbolSource.findByName(
test::parseNameOrDie(u"@android:attr/foo"));
- ASSERT_NE(s, nullptr);
- EXPECT_NE(s->attribute, nullptr);
+ ASSERT_NE(nullptr, s);
+ EXPECT_NE(nullptr, s->attribute);
}
-TEST(SymbolTableWrapperTest, FindPrivateAttrSymbol) {
+TEST(ResourceTableSymbolSourceTest, FindPrivateAttrSymbol) {
std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
.addValue(u"@android:^attr-private/foo", ResourceId(0x01010000),
test::AttributeBuilder().build())
.build();
- SymbolTableWrapper symbolTable(table.get());
- const ISymbolTable::Symbol* s = symbolTable.findByName(
+ ResourceTableSymbolSource symbolSource(table.get());
+ std::unique_ptr<SymbolTable::Symbol> s = symbolSource.findByName(
test::parseNameOrDie(u"@android:attr/foo"));
- ASSERT_NE(s, nullptr);
- EXPECT_NE(s->attribute, nullptr);
+ ASSERT_NE(nullptr, s);
+ EXPECT_NE(nullptr, s->attribute);
}
} // namespace aapt
diff --git a/tools/aapt2/proto/TableProtoDeserializer.cpp b/tools/aapt2/proto/TableProtoDeserializer.cpp
index 9856a00..86883f8 100644
--- a/tools/aapt2/proto/TableProtoDeserializer.cpp
+++ b/tools/aapt2/proto/TableProtoDeserializer.cpp
@@ -483,8 +483,13 @@
}
const size_t padding = 4 - (pbSize & 0x03);
- mData += sizeof(uint64_t) + pbSize + padding;
- mSize -= sizeof(uint64_t) + pbSize + padding;
+ const size_t offset = sizeof(uint64_t) + pbSize + padding;
+ if (offset > mSize) {
+ return nullptr;
+ }
+
+ mData += offset;
+ mSize -= offset;
mPbFile = std::move(pbFile);
}
return mPbFile.get();
diff --git a/tools/aapt2/proto/TableProtoSerializer.cpp b/tools/aapt2/proto/TableProtoSerializer.cpp
index b3d87d8..5d1b72b 100644
--- a/tools/aapt2/proto/TableProtoSerializer.cpp
+++ b/tools/aapt2/proto/TableProtoSerializer.cpp
@@ -178,10 +178,13 @@
void serializeReferenceToPb(const Reference& ref, pb::Reference* pbRef) {
if (ref.id) {
pbRef->set_id(ref.id.value().id);
- } else if (ref.name) {
+ }
+
+ if (ref.name) {
StringPool::Ref symbolRef = mSymbolPool->makeRef(ref.name.value().toString());
pbRef->set_symbol_idx(static_cast<uint32_t>(symbolRef.getIndex()));
}
+
pbRef->set_private_(ref.privateReference);
pbRef->set_type(serializeReferenceTypeToPb(ref.referenceType));
}
diff --git a/tools/aapt2/proto/TableProtoSerializer_test.cpp b/tools/aapt2/proto/TableProtoSerializer_test.cpp
index 70a33f7..dd995d8 100644
--- a/tools/aapt2/proto/TableProtoSerializer_test.cpp
+++ b/tools/aapt2/proto/TableProtoSerializer_test.cpp
@@ -62,6 +62,17 @@
test::buildPrimitive(android::Res_value::TYPE_INT_DEC, 321u),
context->getDiagnostics()));
+ // Make a reference with both resource name and resource ID.
+ // The reference should point to a resource outside of this table to test that both
+ // name and id get serialized.
+ Reference expectedRef;
+ expectedRef.name = test::parseNameOrDie(u"@android:layout/main");
+ expectedRef.id = ResourceId(0x01020000);
+ ASSERT_TRUE(table->addResource(test::parseNameOrDie(u"@com.app.a:layout/abc"),
+ ConfigDescription::defaultConfig(), std::string(),
+ util::make_unique<Reference>(expectedRef),
+ context->getDiagnostics()));
+
std::unique_ptr<pb::ResourceTable> pbTable = serializeTableToPb(table.get());
ASSERT_NE(nullptr, pbTable);
@@ -90,6 +101,13 @@
newTable.get(), u"@com.app.a:integer/one", test::parseConfigOrDie("land"), "tablet");
ASSERT_NE(nullptr, prim);
EXPECT_EQ(321u, prim->value.data);
+
+ Reference* actualRef = test::getValue<Reference>(newTable.get(), u"@com.app.a:layout/abc");
+ ASSERT_NE(nullptr, actualRef);
+ AAPT_ASSERT_TRUE(actualRef->name);
+ AAPT_ASSERT_TRUE(actualRef->id);
+ EXPECT_EQ(expectedRef.name.value(), actualRef->name.value());
+ EXPECT_EQ(expectedRef.id.value(), actualRef->id.value());
}
TEST(TableProtoSerializer, SerializeFileHeader) {
@@ -130,4 +148,27 @@
EXPECT_EQ(test::parseNameOrDie(u"@+id/unchecked"), file->exportedSymbols[0].name);
}
+TEST(TableProtoSerializer, DeserializeCorruptHeaderSafely) {
+ ResourceFile f;
+ std::unique_ptr<pb::CompiledFile> pbFile = serializeCompiledFileToPb(f);
+
+ const std::string expectedData = "1234";
+
+ std::string outputStr;
+ {
+ google::protobuf::io::StringOutputStream outStream(&outputStr);
+ CompiledFileOutputStream outFileStream(&outStream, pbFile.get());
+
+ ASSERT_TRUE(outFileStream.Write(expectedData.data(), expectedData.size()));
+ ASSERT_TRUE(outFileStream.Finish());
+ }
+
+ outputStr[0] = 0xff;
+
+ CompiledFileInputStream inFileStream(outputStr.data(), outputStr.size());
+ EXPECT_EQ(nullptr, inFileStream.CompiledFile());
+ EXPECT_EQ(nullptr, inFileStream.data());
+ EXPECT_EQ(0u, inFileStream.size());
+}
+
} // namespace aapt
diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h
index 834caf8..8c56ebc 100644
--- a/tools/aapt2/test/Builders.h
+++ b/tools/aapt2/test/Builders.h
@@ -246,7 +246,7 @@
inline std::unique_ptr<xml::XmlResource> buildXmlDomForPackageName(IAaptContext* context,
const StringPiece& str) {
std::unique_ptr<xml::XmlResource> doc = buildXmlDom(str);
- doc->file.name.package = context->getCompilationPackage().toString();
+ doc->file.name.package = context->getCompilationPackage();
return doc;
}
diff --git a/tools/aapt2/test/Context.h b/tools/aapt2/test/Context.h
index e540cd7..96752d3 100644
--- a/tools/aapt2/test/Context.h
+++ b/tools/aapt2/test/Context.h
@@ -31,33 +31,16 @@
namespace test {
class Context : public IAaptContext {
-private:
- friend class ContextBuilder;
-
- Context() = default;
-
- Maybe<std::u16string> mCompilationPackage;
- Maybe<uint8_t> mPackageId;
- std::unique_ptr<IDiagnostics> mDiagnostics = util::make_unique<StdErrDiagnostics>();
- std::unique_ptr<ISymbolTable> mSymbols;
- std::unique_ptr<NameMangler> mNameMangler;
-
public:
- ISymbolTable* getExternalSymbols() override {
- assert(mSymbols && "test symbols not set");
- return mSymbols.get();
- }
-
- void setSymbolTable(std::unique_ptr<ISymbolTable> symbols) {
- mSymbols = std::move(symbols);
+ SymbolTable* getExternalSymbols() override {
+ return &mSymbols;
}
IDiagnostics* getDiagnostics() override {
- assert(mDiagnostics && "test diagnostics not set");
- return mDiagnostics.get();
+ return &mDiagnostics;
}
- StringPiece16 getCompilationPackage() override {
+ const std::u16string& getCompilationPackage() override {
assert(mCompilationPackage && "package name not set");
return mCompilationPackage.value();
}
@@ -68,13 +51,24 @@
}
NameMangler* getNameMangler() override {
- assert(mNameMangler && "test name mangler not set");
- return mNameMangler.get();
+ return &mNameMangler;
}
bool verbose() override {
return false;
}
+
+private:
+ friend class ContextBuilder;
+
+ Context() : mNameMangler({}) {
+ }
+
+ Maybe<std::u16string> mCompilationPackage;
+ Maybe<uint8_t> mPackageId;
+ StdErrDiagnostics mDiagnostics;
+ SymbolTable mSymbols;
+ NameMangler mNameMangler;
};
class ContextBuilder {
@@ -92,18 +86,13 @@
return *this;
}
- ContextBuilder& setSymbolTable(std::unique_ptr<ISymbolTable> symbols) {
- mContext->mSymbols = std::move(symbols);
- return *this;
- }
-
- ContextBuilder& setDiagnostics(std::unique_ptr<IDiagnostics> diag) {
- mContext->mDiagnostics = std::move(diag);
- return *this;
- }
-
ContextBuilder& setNameManglerPolicy(NameManglerPolicy policy) {
- mContext->mNameMangler = util::make_unique<NameMangler>(policy);
+ mContext->mNameMangler = NameMangler(policy);
+ return *this;
+ }
+
+ ContextBuilder& addSymbolSource(std::unique_ptr<ISymbolSource> src) {
+ mContext->getExternalSymbols()->appendSource(std::move(src));
return *this;
}
@@ -112,57 +101,72 @@
}
};
-class StaticSymbolTableBuilder {
-private:
- struct SymbolTable : public ISymbolTable {
- std::list<std::unique_ptr<Symbol>> mSymbols;
- std::map<ResourceName, Symbol*> mNameMap;
- std::map<ResourceId, Symbol*> mIdMap;
+class StaticSymbolSourceBuilder {
+public:
+ StaticSymbolSourceBuilder& addPublicSymbol(const StringPiece16& name, ResourceId id,
+ std::unique_ptr<Attribute> attr = {}) {
+ std::unique_ptr<SymbolTable::Symbol> symbol = util::make_unique<SymbolTable::Symbol>(
+ id, std::move(attr), true);
+ mSymbolSource->mNameMap[parseNameOrDie(name)] = symbol.get();
+ mSymbolSource->mIdMap[id] = symbol.get();
+ mSymbolSource->mSymbols.push_back(std::move(symbol));
+ return *this;
+ }
- const Symbol* findByName(const ResourceName& name) override {
+ StaticSymbolSourceBuilder& addSymbol(const StringPiece16& name, ResourceId id,
+ std::unique_ptr<Attribute> attr = {}) {
+ std::unique_ptr<SymbolTable::Symbol> symbol = util::make_unique<SymbolTable::Symbol>(
+ id, std::move(attr), false);
+ mSymbolSource->mNameMap[parseNameOrDie(name)] = symbol.get();
+ mSymbolSource->mIdMap[id] = symbol.get();
+ mSymbolSource->mSymbols.push_back(std::move(symbol));
+ return *this;
+ }
+
+ std::unique_ptr<ISymbolSource> build() {
+ return std::move(mSymbolSource);
+ }
+
+private:
+ class StaticSymbolSource : public ISymbolSource {
+ public:
+ StaticSymbolSource() = default;
+
+ std::unique_ptr<SymbolTable::Symbol> findByName(const ResourceName& name) override {
auto iter = mNameMap.find(name);
if (iter != mNameMap.end()) {
- return iter->second;
+ return cloneSymbol(iter->second);
}
return nullptr;
}
- const Symbol* findById(ResourceId id) override {
+ std::unique_ptr<SymbolTable::Symbol> findById(ResourceId id) override {
auto iter = mIdMap.find(id);
if (iter != mIdMap.end()) {
- return iter->second;
+ return cloneSymbol(iter->second);
}
return nullptr;
}
+
+ std::list<std::unique_ptr<SymbolTable::Symbol>> mSymbols;
+ std::map<ResourceName, SymbolTable::Symbol*> mNameMap;
+ std::map<ResourceId, SymbolTable::Symbol*> mIdMap;
+
+ private:
+ std::unique_ptr<SymbolTable::Symbol> cloneSymbol(SymbolTable::Symbol* sym) {
+ std::unique_ptr<SymbolTable::Symbol> clone = util::make_unique<SymbolTable::Symbol>();
+ clone->id = sym->id;
+ if (sym->attribute) {
+ clone->attribute = std::unique_ptr<Attribute>(sym->attribute->clone(nullptr));
+ }
+ clone->isPublic = sym->isPublic;
+ return clone;
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(StaticSymbolSource);
};
- std::unique_ptr<SymbolTable> mSymbolTable = util::make_unique<SymbolTable>();
-
-public:
- StaticSymbolTableBuilder& addPublicSymbol(const StringPiece16& name, ResourceId id,
- std::unique_ptr<Attribute> attr = {}) {
- std::unique_ptr<ISymbolTable::Symbol> symbol = util::make_unique<ISymbolTable::Symbol>(
- id, std::move(attr));
- symbol->isPublic = true;
- mSymbolTable->mNameMap[parseNameOrDie(name)] = symbol.get();
- mSymbolTable->mIdMap[id] = symbol.get();
- mSymbolTable->mSymbols.push_back(std::move(symbol));
- return *this;
- }
-
- StaticSymbolTableBuilder& addSymbol(const StringPiece16& name, ResourceId id,
- std::unique_ptr<Attribute> attr = {}) {
- std::unique_ptr<ISymbolTable::Symbol> symbol = util::make_unique<ISymbolTable::Symbol>(
- id, std::move(attr));
- mSymbolTable->mNameMap[parseNameOrDie(name)] = symbol.get();
- mSymbolTable->mIdMap[id] = symbol.get();
- mSymbolTable->mSymbols.push_back(std::move(symbol));
- return *this;
- }
-
- std::unique_ptr<ISymbolTable> build() {
- return std::move(mSymbolTable);
- }
+ std::unique_ptr<StaticSymbolSource> mSymbolSource = util::make_unique<StaticSymbolSource>();
};
} // namespace test
diff --git a/media/mca/effect/java/android/media/effect/package-info.java b/tools/aapt2/test/Test.h
similarity index 64%
rename from media/mca/effect/java/android/media/effect/package-info.java
rename to tools/aapt2/test/Test.h
index b2c14ff..d4845cf 100644
--- a/media/mca/effect/java/android/media/effect/package-info.java
+++ b/tools/aapt2/test/Test.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,15 +14,19 @@
* limitations under the License.
*/
+#ifndef AAPT_TEST_TEST_H
+#define AAPT_TEST_TEST_H
-package android.media.effect;
+#include "test/Builders.h"
+#include "test/Common.h"
+#include "test/Context.h"
-/**
- * <h1>Effect Framework</h1>
- *
- * This package includes a collection of high-performance visual effects that make use of the
- * mobile filter framework subsystem.
- *
- * TODO: More Documentation
- *
- */
+#include <gtest/gtest.h>
+
+namespace aapt {
+namespace test {
+
+} // namespace test
+} // namespace aapt
+
+#endif // AAPT_TEST_TEST_H
diff --git a/tools/aapt2/xml/XmlDom.h b/tools/aapt2/xml/XmlDom.h
index 033b0a4..b374d20 100644
--- a/tools/aapt2/xml/XmlDom.h
+++ b/tools/aapt2/xml/XmlDom.h
@@ -68,7 +68,7 @@
};
struct AaptAttribute {
- ResourceId id;
+ Maybe<ResourceId> id;
aapt::Attribute attribute;
};
diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py
index df76bc9..a8a8c5c 100644
--- a/tools/apilint/apilint.py
+++ b/tools/apilint/apilint.py
@@ -264,6 +264,9 @@
if "static" in f.split and "final" in f.split:
if re.match("[A-Z0-9_]+", f.name) is None:
error(clazz, f, "C2", "Constant field names must be FOO_NAME")
+ elif f.typ != "java.lang.String":
+ if f.name.startswith("MIN_") or f.name.startswith("MAX_"):
+ warn(clazz, f, "C8", "If min/max could change in future, make them dynamic methods")
def verify_enums(clazz):
@@ -417,6 +420,9 @@
if len(creator) == 0 or len(write) == 0 or len(describe) == 0:
error(clazz, None, "FW3", "Parcelable requires CREATOR, writeToParcel, and describeContents; missing one")
+ if " final class " not in clazz.raw:
+ error(clazz, None, "FW8", "Parcelable classes must be final")
+
def verify_protected(clazz):
"""Verify that no protected methods or fields are allowed."""
@@ -730,6 +736,13 @@
if "throws java.lang.Exception" in m.raw or "throws java.lang.Throwable" in m.raw or "throws java.lang.Error" in m.raw:
error(clazz, m, "S1", "Methods must not throw generic exceptions")
+ if "throws android.os.RemoteException" in m.raw:
+ if clazz.name == "android.content.ContentProviderClient": continue
+ if clazz.name == "android.os.Binder": continue
+ if clazz.name == "android.os.IBinder": continue
+
+ error(clazz, m, "FW9", "Methods calling into system server should rethrow RemoteException as RuntimeException")
+
def verify_google(clazz):
"""Verifies that APIs never reference Google."""
@@ -946,6 +959,27 @@
error(clazz, f, "C7", "Expected resource name in this class to be FooBar_Baz style")
+def verify_files(clazz):
+ """Verifies that methods accepting File also accept streams."""
+
+ has_file = set()
+ has_stream = set()
+
+ test = []
+ test.extend(clazz.ctors)
+ test.extend(clazz.methods)
+
+ for m in test:
+ if "java.io.File" in m.args:
+ has_file.add(m)
+ if "java.io.FileDescriptor" in m.args or "android.os.ParcelFileDescriptor" in m.args or "java.io.InputStream" in m.args or "java.io.OutputStream" in m.args:
+ has_stream.add(m.name)
+
+ for m in has_file:
+ if m.name not in has_stream:
+ warn(clazz, m, "M10", "Methods accepting File should also accept FileDescriptor or streams")
+
+
def examine_clazz(clazz):
"""Find all style issues in the given class."""
if clazz.pkg.name.startswith("java"): return
@@ -954,6 +988,7 @@
if clazz.pkg.name.startswith("org.xml"): return
if clazz.pkg.name.startswith("org.json"): return
if clazz.pkg.name.startswith("org.w3c"): return
+ if clazz.pkg.name.startswith("android.icu."): return
verify_constants(clazz)
verify_enums(clazz)
@@ -989,6 +1024,7 @@
verify_context_first(clazz)
verify_listener_last(clazz)
verify_resource_names(clazz)
+ verify_files(clazz)
def examine_stream(stream):
diff --git a/tools/layoutlib/.idea/libraries/junit.xml b/tools/layoutlib/.idea/libraries/junit.xml
new file mode 100644
index 0000000..c889f5f
--- /dev/null
+++ b/tools/layoutlib/.idea/libraries/junit.xml
@@ -0,0 +1,11 @@
+<component name="libraryTable">
+ <library name="junit">
+ <CLASSES>
+ <root url="jar://$PROJECT_DIR$/../../../../out/host/common/obj/JAVA_LIBRARIES/junit_intermediates/javalib.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="file://$PROJECT_DIR$/../../../../external/junit/src" />
+ </SOURCES>
+ </library>
+</component>
\ No newline at end of file
diff --git a/tools/layoutlib/.idea/runConfigurations/Create.xml b/tools/layoutlib/.idea/runConfigurations/Create.xml
index 58f057a..fb798b6 100644
--- a/tools/layoutlib/.idea/runConfigurations/Create.xml
+++ b/tools/layoutlib/.idea/runConfigurations/Create.xml
@@ -2,7 +2,7 @@
<configuration default="false" name="Create" type="Application" factoryName="Application" singleton="true">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<option name="MAIN_CLASS_NAME" value="com.android.tools.layoutlib.create.Main" />
- <option name="VM_PARAMETERS" value="" />
+ <option name="VM_PARAMETERS" value="-ea" />
<option name="PROGRAM_PARAMETERS" value="out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar out/target/common/obj/JAVA_LIBRARIES/core-libart_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/icu4j-icudata-jarjar_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/icu4j-icutzdata-jarjar_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/ext_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/ext_intermediates/javalib.jar" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/../../../../" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
diff --git a/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk
index c2ad9ef..663e1e2 100644
--- a/tools/layoutlib/Android.mk
+++ b/tools/layoutlib/Android.mk
@@ -40,10 +40,8 @@
built_ext_classes := $(call java-lib-files,ext)
built_ext_data := $(call intermediates-dir-for, \
JAVA_LIBRARIES,ext,,COMMON)/javalib.jar
-built_icudata_dep := $(call java-lib-deps,icu4j-icudata-jarjar)
-built_icudata_data := $(call java-lib-files,icu4j-icudata-jarjar)
-built_icutzdata_dep := $(call java-lib-deps,icu4j-icutzdata-jarjar)
-built_icutzdata_data := $(call java-lib-files,icu4j-icutzdata-jarjar)
+built_icudata_dep := $(call java-lib-deps,icu4j-icudata-host-jarjar,HOST)
+built_icutzdata_dep := $(call java-lib-deps,icu4j-icutzdata-host-jarjar,HOST)
built_layoutlib_create_jar := $(call intermediates-dir-for, \
JAVA_LIBRARIES,layoutlib_create,HOST)/javalib.jar
@@ -77,8 +75,8 @@
$(built_core_classes) \
$(built_framework_classes) \
$(built_ext_classes) \
- $(built_icudata_data) \
- $(built_icutzdata_data) \
+ $(built_icudata_dep) \
+ $(built_icutzdata_dep) \
$(built_ext_data)
$(hide) ls -l $(built_framework_classes)
diff --git a/tools/layoutlib/bridge/bridge.iml b/tools/layoutlib/bridge/bridge.iml
index ccc10b3..57d08cb 100644
--- a/tools/layoutlib/bridge/bridge.iml
+++ b/tools/layoutlib/bridge/bridge.iml
@@ -84,6 +84,6 @@
</SOURCES>
</library>
</orderEntry>
- <orderEntry type="library" scope="TEST" name="JUnit4" level="application" />
+ <orderEntry type="library" scope="TEST" name="junit" level="project" />
</component>
</module>
\ No newline at end of file
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index db4c6dc6..ae42ba6 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -305,6 +305,12 @@
return defValue;
}
+ @Override
+ public ComplexColor getComplexColor(int index) {
+ // TODO: Support GradientColor
+ return getColorStateList(index);
+ }
+
/**
* Retrieve the ColorStateList for the attribute at <var>index</var>.
* The value may be either a single solid color or a reference to
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index c4fbd56..fa880f0 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -142,7 +142,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_setBitmap(long canvas, Bitmap bitmap) {
+ public static void native_setBitmap(long canvas, Bitmap bitmap) {
Canvas_Delegate canvasDelegate = sManager.getDelegate(canvas);
Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
if (canvasDelegate == null || bitmapDelegate==null) {
@@ -153,7 +153,7 @@
}
@LayoutlibDelegate
- /*package*/ static boolean native_isOpaque(long nativeCanvas) {
+ public static boolean native_isOpaque(long nativeCanvas) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -164,10 +164,10 @@
}
@LayoutlibDelegate
- /*package*/ static void native_setHighContrastText(long nativeCanvas, boolean highContrastText){}
+ public static void native_setHighContrastText(long nativeCanvas, boolean highContrastText){}
@LayoutlibDelegate
- /*package*/ static int native_getWidth(long nativeCanvas) {
+ public static int native_getWidth(long nativeCanvas) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -178,7 +178,7 @@
}
@LayoutlibDelegate
- /*package*/ static int native_getHeight(long nativeCanvas) {
+ public static int native_getHeight(long nativeCanvas) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -189,7 +189,7 @@
}
@LayoutlibDelegate
- /*package*/ static int native_save(long nativeCanvas, int saveFlags) {
+ public static int native_save(long nativeCanvas, int saveFlags) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -200,7 +200,7 @@
}
@LayoutlibDelegate
- /*package*/ static int native_saveLayer(long nativeCanvas, float l,
+ public static int native_saveLayer(long nativeCanvas, float l,
float t, float r, float b,
long paint, int layerFlags) {
// get the delegate from the native int.
@@ -219,7 +219,7 @@
}
@LayoutlibDelegate
- /*package*/ static int native_saveLayerAlpha(long nativeCanvas, float l,
+ public static int native_saveLayerAlpha(long nativeCanvas, float l,
float t, float r, float b,
int alpha, int layerFlags) {
// get the delegate from the native int.
@@ -232,7 +232,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_restore(long nativeCanvas, boolean throwOnUnderflow) {
+ public static void native_restore(long nativeCanvas, boolean throwOnUnderflow) {
// FIXME: implement throwOnUnderflow.
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
@@ -244,7 +244,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_restoreToCount(long nativeCanvas, int saveCount,
+ public static void native_restoreToCount(long nativeCanvas, int saveCount,
boolean throwOnUnderflow) {
// FIXME: implement throwOnUnderflow.
// get the delegate from the native int.
@@ -257,7 +257,7 @@
}
@LayoutlibDelegate
- /*package*/ static int native_getSaveCount(long nativeCanvas) {
+ public static int native_getSaveCount(long nativeCanvas) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -268,7 +268,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_translate(long nativeCanvas, float dx, float dy) {
+ public static void native_translate(long nativeCanvas, float dx, float dy) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -279,7 +279,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_scale(long nativeCanvas, float sx, float sy) {
+ public static void native_scale(long nativeCanvas, float sx, float sy) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -290,7 +290,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_rotate(long nativeCanvas, float degrees) {
+ public static void native_rotate(long nativeCanvas, float degrees) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -301,7 +301,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_skew(long nativeCanvas, float kx, float ky) {
+ public static void native_skew(long nativeCanvas, float kx, float ky) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -325,7 +325,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_concat(long nCanvas, long nMatrix) {
+ public static void native_concat(long nCanvas, long nMatrix) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
if (canvasDelegate == null) {
@@ -353,7 +353,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_setMatrix(long nCanvas, long nMatrix) {
+ public static void native_setMatrix(long nCanvas, long nMatrix) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
if (canvasDelegate == null) {
@@ -383,7 +383,7 @@
}
@LayoutlibDelegate
- /*package*/ static boolean native_clipRect(long nCanvas,
+ public static boolean native_clipRect(long nCanvas,
float left, float top,
float right, float bottom,
int regionOp) {
@@ -397,7 +397,7 @@
}
@LayoutlibDelegate
- /*package*/ static boolean native_clipPath(long nativeCanvas,
+ public static boolean native_clipPath(long nativeCanvas,
long nativePath,
int regionOp) {
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
@@ -414,7 +414,7 @@
}
@LayoutlibDelegate
- /*package*/ static boolean native_clipRegion(long nativeCanvas,
+ public static boolean native_clipRegion(long nativeCanvas,
long nativeRegion,
int regionOp) {
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
@@ -431,7 +431,7 @@
}
@LayoutlibDelegate
- /*package*/ static void nativeSetDrawFilter(long nativeCanvas, long nativeFilter) {
+ public static void nativeSetDrawFilter(long nativeCanvas, long nativeFilter) {
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return;
@@ -446,7 +446,7 @@
}
@LayoutlibDelegate
- /*package*/ static boolean native_getClipBounds(long nativeCanvas,
+ public static boolean native_getClipBounds(long nativeCanvas,
Rect bounds) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
@@ -467,7 +467,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_getCTM(long canvas, long matrix) {
+ public static void native_getCTM(long canvas, long matrix) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(canvas);
if (canvasDelegate == null) {
@@ -484,13 +484,13 @@
}
@LayoutlibDelegate
- /*package*/ static boolean native_quickReject(long nativeCanvas, long path) {
+ public static boolean native_quickReject(long nativeCanvas, long path) {
// FIXME properly implement quickReject
return false;
}
@LayoutlibDelegate
- /*package*/ static boolean native_quickReject(long nativeCanvas,
+ public static boolean native_quickReject(long nativeCanvas,
float left, float top,
float right, float bottom) {
// FIXME properly implement quickReject
@@ -498,7 +498,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawColor(long nativeCanvas, final int color, final int mode) {
+ public static void native_drawColor(long nativeCanvas, final int color, final int mode) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -529,14 +529,14 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawPaint(long nativeCanvas, long paint) {
+ public static void native_drawPaint(long nativeCanvas, long paint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Canvas.drawPaint is not supported.", null, null /*data*/);
}
@LayoutlibDelegate
- /*package*/ static void native_drawPoint(long nativeCanvas, float x, float y,
+ public static void native_drawPoint(long nativeCanvas, float x, float y,
long nativePaint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -544,7 +544,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawPoints(long nativeCanvas, float[] pts, int offset, int count,
+ public static void native_drawPoints(long nativeCanvas, float[] pts, int offset, int count,
long nativePaint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -552,7 +552,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawLine(long nativeCanvas,
+ public static void native_drawLine(long nativeCanvas,
final float startX, final float startY, final float stopX, final float stopY,
long paint) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
@@ -565,7 +565,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawLines(long nativeCanvas,
+ public static void native_drawLines(long nativeCanvas,
final float[] pts, final int offset, final int count,
long nativePaint) {
draw(nativeCanvas, nativePaint, false /*compositeOnly*/,
@@ -581,7 +581,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawRect(long nativeCanvas,
+ public static void native_drawRect(long nativeCanvas,
final float left, final float top, final float right, final float bottom, long paint) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
@@ -607,7 +607,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawOval(long nativeCanvas, final float left,
+ public static void native_drawOval(long nativeCanvas, final float left,
final float top, final float right, final float bottom, long paint) {
if (right > left && bottom > top) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
@@ -634,7 +634,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawCircle(long nativeCanvas,
+ public static void native_drawCircle(long nativeCanvas,
float cx, float cy, float radius, long paint) {
native_drawOval(nativeCanvas,
cx - radius, cy - radius, cx + radius, cy + radius,
@@ -642,7 +642,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawArc(long nativeCanvas,
+ public static void native_drawArc(long nativeCanvas,
final float left, final float top, final float right, final float bottom,
final float startAngle, final float sweep,
final boolean useCenter, long paint) {
@@ -674,7 +674,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawRoundRect(long nativeCanvas,
+ public static void native_drawRoundRect(long nativeCanvas,
final float left, final float top, final float right, final float bottom,
final float rx, final float ry, long paint) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
@@ -704,7 +704,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawPath(long nativeCanvas, long path, long paint) {
+ public static void native_drawPath(long nativeCanvas, long path, long paint) {
final Path_Delegate pathDelegate = Path_Delegate.getDelegate(path);
if (pathDelegate == null) {
return;
@@ -756,7 +756,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawRegion(long nativeCanvas, long nativeRegion,
+ public static void native_drawRegion(long nativeCanvas, long nativeRegion,
long nativePaint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -764,7 +764,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawNinePatch(Canvas thisCanvas, long nativeCanvas,
+ public static void native_drawNinePatch(Canvas thisCanvas, long nativeCanvas,
long nativeBitmap, long ninePatch, final float dstLeft, final float dstTop,
final float dstRight, final float dstBottom, long nativePaintOrZero,
final int screenDensity, final int bitmapDensity) {
@@ -811,7 +811,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
+ public static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
float left, float top,
long nativePaintOrZero,
int canvasDensity,
@@ -833,7 +833,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
+ public static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
float srcLeft, float srcTop, float srcRight, float srcBottom,
float dstLeft, float dstTop, float dstRight, float dstBottom,
long nativePaintOrZero, int screenDensity, int bitmapDensity) {
@@ -849,7 +849,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawBitmap(long nativeCanvas, int[] colors,
+ public static void native_drawBitmap(long nativeCanvas, int[] colors,
int offset, int stride, final float x,
final float y, int width, int height,
boolean hasAlpha,
@@ -874,7 +874,7 @@
}
@LayoutlibDelegate
- /*package*/ static void nativeDrawBitmapMatrix(long nCanvas, Bitmap bitmap,
+ public static void nativeDrawBitmapMatrix(long nCanvas, Bitmap bitmap,
long nMatrix, long nPaint) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
@@ -915,7 +915,7 @@
}
@LayoutlibDelegate
- /*package*/ static void nativeDrawBitmapMesh(long nCanvas, Bitmap bitmap,
+ public static void nativeDrawBitmapMesh(long nCanvas, Bitmap bitmap,
int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors,
int colorOffset, long nPaint) {
// FIXME
@@ -924,7 +924,7 @@
}
@LayoutlibDelegate
- /*package*/ static void nativeDrawVertices(long nCanvas, int mode, int n,
+ public static void nativeDrawVertices(long nCanvas, int mode, int n,
float[] verts, int vertOffset,
float[] texs, int texOffset,
int[] colors, int colorOffset,
@@ -936,14 +936,14 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawText(long nativeCanvas, char[] text, int index, int count,
+ public static void native_drawText(long nativeCanvas, char[] text, int index, int count,
float startX, float startY, int flags, long paint, long typeface) {
drawText(nativeCanvas, text, index, count, startX, startY, (flags & 1) != 0,
paint, typeface);
}
@LayoutlibDelegate
- /*package*/ static void native_drawText(long nativeCanvas, String text,
+ public static void native_drawText(long nativeCanvas, String text,
int start, int end, float x, float y, final int flags, long paint,
long typeface) {
int count = end - start;
@@ -954,7 +954,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawTextRun(long nativeCanvas, String text,
+ public static void native_drawTextRun(long nativeCanvas, String text,
int start, int end, int contextStart, int contextEnd,
float x, float y, boolean isRtl, long paint, long typeface) {
int count = end - start;
@@ -965,14 +965,14 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawTextRun(long nativeCanvas, char[] text,
+ public static void native_drawTextRun(long nativeCanvas, char[] text,
int start, int count, int contextStart, int contextCount,
float x, float y, boolean isRtl, long paint, long typeface) {
drawText(nativeCanvas, text, start, count, x, y, isRtl, paint, typeface);
}
@LayoutlibDelegate
- /*package*/ static void native_drawTextOnPath(long nativeCanvas,
+ public static void native_drawTextOnPath(long nativeCanvas,
char[] text, int index,
int count, long path,
float hOffset,
@@ -984,7 +984,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawTextOnPath(long nativeCanvas,
+ public static void native_drawTextOnPath(long nativeCanvas,
String text, long path,
float hOffset,
float vOffset,
diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
index 746ef36..7412bc2 100644
--- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
@@ -284,9 +284,9 @@
}
@LayoutlibDelegate
- /*package*/ static boolean nAddFontWeightStyle(long nativeFamily,
- ByteBuffer buffer, final List<FontListParser.Axis> axes,
- final int weight, final boolean isItalic) {
+ /*package*/ static boolean nAddFontWeightStyle(long nativeFamily, ByteBuffer font,
+ int ttcIndex, List<FontListParser.Axis> listOfAxis,
+ int weight, boolean isItalic) {
assert false : "The only client of this method has been overriden.";
return false;
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
index 514d785..839c182 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
@@ -223,6 +223,10 @@
return mColorFilter;
}
+ public void setColorFilter(long colorFilterPtr) {
+ mColorFilter = ColorFilter_Delegate.getDelegate(colorFilterPtr);
+ }
+
/**
* Returns the {@link Shader} delegate or null if none have been set
*
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
index e1da27b..08f0cb4 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
@@ -572,7 +572,7 @@
return null;
}
- private static void addPath(long destPath, long srcPath, AffineTransform transform) {
+ public static void addPath(long destPath, long srcPath, AffineTransform transform) {
Path_Delegate destPathDelegate = sManager.getDelegate(destPath);
if (destPathDelegate == null) {
return;
@@ -630,7 +630,7 @@
* Fills the given {@link RectF} with the path bounds.
* @param bounds the RectF to be filled.
*/
- private void fillBounds(RectF bounds) {
+ public void fillBounds(RectF bounds) {
Rectangle2D rect = mPath.getBounds2D();
bounds.left = (float)rect.getMinX();
bounds.right = (float)rect.getMaxX();
@@ -644,7 +644,7 @@
* @param x The x-coordinate of the start of a new contour
* @param y The y-coordinate of the start of a new contour
*/
- private void moveTo(float x, float y) {
+ public void moveTo(float x, float y) {
mPath.moveTo(mLastX = x, mLastY = y);
}
@@ -658,7 +658,7 @@
* @param dy The amount to add to the y-coordinate of the end of the
* previous contour, to specify the start of a new contour
*/
- private void rMoveTo(float dx, float dy) {
+ public void rMoveTo(float dx, float dy) {
dx += mLastX;
dy += mLastY;
mPath.moveTo(mLastX = dx, mLastY = dy);
@@ -672,7 +672,7 @@
* @param x The x-coordinate of the end of a line
* @param y The y-coordinate of the end of a line
*/
- private void lineTo(float x, float y) {
+ public void lineTo(float x, float y) {
if (!hasPoints()) {
mPath.moveTo(mLastX = 0, mLastY = 0);
}
@@ -689,7 +689,7 @@
* @param dy The amount to add to the y-coordinate of the previous point on
* this contour, to specify a line
*/
- private void rLineTo(float dx, float dy) {
+ public void rLineTo(float dx, float dy) {
if (!hasPoints()) {
mPath.moveTo(mLastX = 0, mLastY = 0);
}
@@ -714,7 +714,7 @@
* @param x2 The x-coordinate of the end point on a quadratic curve
* @param y2 The y-coordinate of the end point on a quadratic curve
*/
- private void quadTo(float x1, float y1, float x2, float y2) {
+ public void quadTo(float x1, float y1, float x2, float y2) {
mPath.quadTo(x1, y1, mLastX = x2, mLastY = y2);
}
@@ -732,7 +732,7 @@
* @param dy2 The amount to add to the y-coordinate of the last point on
* this contour, for the end point of a quadratic curve
*/
- private void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
+ public void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
if (!hasPoints()) {
mPath.moveTo(mLastX = 0, mLastY = 0);
}
@@ -755,7 +755,7 @@
* @param x3 The x-coordinate of the end point on a cubic curve
* @param y3 The y-coordinate of the end point on a cubic curve
*/
- private void cubicTo(float x1, float y1, float x2, float y2,
+ public void cubicTo(float x1, float y1, float x2, float y2,
float x3, float y3) {
if (!hasPoints()) {
mPath.moveTo(0, 0);
@@ -768,7 +768,7 @@
* current point on this contour. If there is no previous point, then a
* moveTo(0,0) is inserted automatically.
*/
- private void rCubicTo(float dx1, float dy1, float dx2, float dy2,
+ public void rCubicTo(float dx1, float dy1, float dx2, float dy2,
float dx3, float dy3) {
if (!hasPoints()) {
mPath.moveTo(mLastX = 0, mLastY = 0);
@@ -798,7 +798,7 @@
* mod 360.
* @param forceMoveTo If true, always begin a new contour with the arc
*/
- private void arcTo(float left, float top, float right, float bottom, float startAngle,
+ public void arcTo(float left, float top, float right, float bottom, float startAngle,
float sweepAngle,
boolean forceMoveTo) {
Arc2D arc = new Arc2D.Float(left, top, right - left, bottom - top, -startAngle,
@@ -812,7 +812,7 @@
* Close the current contour. If the current point is not equal to the
* first point of the contour, a line segment is automatically added.
*/
- private void close() {
+ public void close() {
mPath.closePath();
}
@@ -831,7 +831,7 @@
* @param bottom The bottom of a rectangle to add to the path
* @param dir The direction to wind the rectangle's contour
*/
- private void addRect(float left, float top, float right, float bottom,
+ public void addRect(float left, float top, float right, float bottom,
int dir) {
moveTo(left, top);
diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
new file mode 100644
index 0000000..eef8235
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
@@ -0,0 +1,1122 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.drawable;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
+import android.graphics.Canvas_Delegate;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Paint.Cap;
+import android.graphics.Paint.Join;
+import android.graphics.Paint_Delegate;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
+import android.graphics.Path_Delegate;
+import android.graphics.Rect;
+import android.graphics.Region.Op;
+import android.util.ArrayMap;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.MathUtils;
+import android.util.PathParser_Delegate;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.util.ArrayList;
+
+import static android.graphics.Canvas.CLIP_SAVE_FLAG;
+import static android.graphics.Canvas.MATRIX_SAVE_FLAG;
+import static android.graphics.Paint.Cap.BUTT;
+import static android.graphics.Paint.Cap.ROUND;
+import static android.graphics.Paint.Cap.SQUARE;
+import static android.graphics.Paint.Join.BEVEL;
+import static android.graphics.Paint.Join.MITER;
+import static android.graphics.Paint.Style;
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link VectorDrawable}
+ * <p>
+ * Through the layoutlib_create tool, the original methods of VectorDrawable have been replaced by
+ * calls to methods of the same name in this delegate class.
+ */
+@SuppressWarnings("unused")
+public class VectorDrawable_Delegate {
+ private static final String LOGTAG = VectorDrawable_Delegate.class.getSimpleName();
+ private static final boolean DBG_VECTOR_DRAWABLE = false;
+
+ private static final DelegateManager<VNativeObject> sPathManager =
+ new DelegateManager<>(VNativeObject.class);
+
+ private static <T> T getDelegate(long nativePtr) {
+ //noinspection unchecked
+ T object = (T) sPathManager.getDelegate(nativePtr);
+ assert object != null;
+
+ return object;
+ }
+
+ /**
+ * Obtains styled attributes from the theme, if available, or unstyled resources if the theme is
+ * null.
+ */
+ private static TypedArray obtainAttributes(
+ Resources res, Theme theme, AttributeSet set, int[] attrs) {
+ if (theme == null) {
+ return res.obtainAttributes(set, attrs);
+ }
+ return theme.obtainStyledAttributes(set, attrs, 0, 0);
+ }
+
+ private static int applyAlpha(int color, float alpha) {
+ int alphaBytes = Color.alpha(color);
+ color &= 0x00FFFFFF;
+ color |= ((int) (alphaBytes * alpha)) << 24;
+ return color;
+ }
+
+ @LayoutlibDelegate
+ static long nCreateRenderer(long rootGroupPtr) {
+ VGroup_Delegate rootGroup = getDelegate(rootGroupPtr);
+ return sPathManager.addNewDelegate(new VPathRenderer_Delegate(rootGroup));
+ }
+
+ @LayoutlibDelegate
+ static void nSetRendererViewportSize(long rendererPtr, float viewportWidth,
+ float viewportHeight) {
+ VPathRenderer_Delegate nativePathRenderer = getDelegate(rendererPtr);
+ nativePathRenderer.mViewportWidth = viewportWidth;
+ nativePathRenderer.mViewportHeight = viewportHeight;
+ }
+
+ @LayoutlibDelegate
+ static boolean nSetRootAlpha(long rendererPtr, float alpha) {
+ VPathRenderer_Delegate nativePathRenderer = getDelegate(rendererPtr);
+ nativePathRenderer.setRootAlpha(alpha);
+
+ return true;
+ }
+
+ @LayoutlibDelegate
+ static float nGetRootAlpha(long rendererPtr) {
+ VPathRenderer_Delegate nativePathRenderer = getDelegate(rendererPtr);
+
+ return nativePathRenderer.getRootAlpha();
+ }
+
+ @LayoutlibDelegate
+ static void nSetAllowCaching(long rendererPtr, boolean allowCaching) {
+ // ignored
+ }
+
+ @LayoutlibDelegate
+ static void nDraw(long rendererPtr, long canvasWrapperPtr,
+ long colorFilterPtr, Rect bounds, boolean needsMirroring, boolean canReuseCache) {
+ VPathRenderer_Delegate nativePathRenderer =
+ getDelegate(rendererPtr);
+
+ Canvas_Delegate.native_save(canvasWrapperPtr, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG);
+ Canvas_Delegate.native_translate(canvasWrapperPtr, bounds.left, bounds.top);
+
+ if (needsMirroring) {
+ Canvas_Delegate.native_translate(canvasWrapperPtr, bounds.width(), 0);
+ Canvas_Delegate.native_scale(canvasWrapperPtr, -1.0f, 1.0f);
+ }
+
+ // At this point, canvas has been translated to the right position.
+ // And we use this bound for the destination rect for the drawBitmap, so
+ // we offset to (0, 0);
+ bounds.offsetTo(0, 0);
+ nativePathRenderer.draw(canvasWrapperPtr, colorFilterPtr, bounds.width(), bounds.height());
+
+ Canvas_Delegate.native_restore(canvasWrapperPtr, true);
+ }
+
+ @LayoutlibDelegate
+ static long nCreateFullPath() {
+ return sPathManager.addNewDelegate(new VFullPath_Delegate());
+ }
+
+ @LayoutlibDelegate
+ static long nCreateFullPath(long nativeFullPathPtr) {
+ VFullPath_Delegate original = getDelegate(nativeFullPathPtr);
+
+ return sPathManager.addNewDelegate(new VFullPath_Delegate(original));
+ }
+
+ @LayoutlibDelegate
+ static boolean nGetFullPathProperties(long pathPtr, byte[] propertiesData,
+ int length) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+
+ ByteBuffer properties = ByteBuffer.wrap(propertiesData);
+ properties.order(ByteOrder.nativeOrder());
+
+ properties.putFloat(VFullPath_Delegate.STROKE_WIDTH_INDEX * 4, path.getStrokeWidth());
+ properties.putInt(VFullPath_Delegate.STROKE_COLOR_INDEX * 4, path.getStrokeColor());
+ properties.putFloat(VFullPath_Delegate.STROKE_ALPHA_INDEX * 4, path.getStrokeAlpha());
+ properties.putInt(VFullPath_Delegate.FILL_COLOR_INDEX * 4, path.getFillColor());
+ properties.putFloat(VFullPath_Delegate.FILL_ALPHA_INDEX * 4, path.getStrokeAlpha());
+ properties.putFloat(VFullPath_Delegate.TRIM_PATH_START_INDEX * 4, path.getTrimPathStart());
+ properties.putFloat(VFullPath_Delegate.TRIM_PATH_END_INDEX * 4, path.getTrimPathEnd());
+ properties.putFloat(VFullPath_Delegate.TRIM_PATH_OFFSET_INDEX * 4,
+ path.getTrimPathOffset());
+ properties.putInt(VFullPath_Delegate.STROKE_LINE_CAP_INDEX * 4, path.getStrokeLineCap());
+ properties.putInt(VFullPath_Delegate.STROKE_LINE_JOIN_INDEX * 4, path.getStrokeLineJoin());
+ properties.putFloat(VFullPath_Delegate.STROKE_MITER_LIMIT_INDEX * 4,
+ path.getStrokeMiterlimit());
+
+ return true;
+ }
+
+ @LayoutlibDelegate
+ static void nUpdateFullPathProperties(long pathPtr, float strokeWidth,
+ int strokeColor, float strokeAlpha, int fillColor, float fillAlpha, float trimPathStart,
+ float trimPathEnd, float trimPathOffset, float strokeMiterLimit, int strokeLineCap,
+ int strokeLineJoin) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+
+ path.setStrokeWidth(strokeWidth);
+ path.setStrokeColor(strokeColor);
+ path.setStrokeAlpha(strokeAlpha);
+ path.setFillColor(fillColor);
+ path.setFillAlpha(fillAlpha);
+ path.setTrimPathStart(trimPathStart);
+ path.setTrimPathEnd(trimPathEnd);
+ path.setTrimPathOffset(trimPathOffset);
+ path.setStrokeMiterlimit(strokeMiterLimit);
+ path.setStrokeLineCap(strokeLineCap);
+ path.setStrokeLineJoin(strokeLineJoin);
+ }
+
+ @LayoutlibDelegate
+ static void nUpdateFullPathFillGradient(long pathPtr, long fillGradientPtr) {
+
+ }
+
+ @LayoutlibDelegate
+ static void nUpdateFullPathStrokeGradient(long pathPtr, long strokeGradientPtr) {
+
+ }
+
+ @LayoutlibDelegate
+ static long nCreateClipPath() {
+ return sPathManager.addNewDelegate(new VClipPath_Delegate());
+ }
+
+ @LayoutlibDelegate
+ static long nCreateClipPath(long clipPathPtr) {
+ VClipPath_Delegate original = getDelegate(clipPathPtr);
+ return sPathManager.addNewDelegate(new VClipPath_Delegate(original));
+ }
+
+ @LayoutlibDelegate
+ static long nCreateGroup() {
+ return sPathManager.addNewDelegate(new VGroup_Delegate());
+ }
+
+ @LayoutlibDelegate
+ static long nCreateGroup(long groupPtr) {
+ VGroup_Delegate original = getDelegate(groupPtr);
+ return sPathManager.addNewDelegate(
+ new VGroup_Delegate(original, new ArrayMap<String, Object>()));
+ }
+
+ @LayoutlibDelegate
+ static void nSetName(long nodePtr, String name) {
+ VNativeObject group = getDelegate(nodePtr);
+ group.setName(name);
+ }
+
+ @LayoutlibDelegate
+ static boolean nGetGroupProperties(long groupPtr, float[] propertiesData,
+ int length) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+
+ FloatBuffer properties = FloatBuffer.wrap(propertiesData);
+
+ properties.put(VGroup_Delegate.ROTATE_INDEX, group.getRotation());
+ properties.put(VGroup_Delegate.PIVOT_X_INDEX, group.getPivotX());
+ properties.put(VGroup_Delegate.PIVOT_Y_INDEX, group.getPivotY());
+ properties.put(VGroup_Delegate.SCALE_X_INDEX, group.getScaleX());
+ properties.put(VGroup_Delegate.SCALE_Y_INDEX, group.getScaleY());
+ properties.put(VGroup_Delegate.TRANSLATE_X_INDEX, group.getTranslateX());
+ properties.put(VGroup_Delegate.TRANSLATE_Y_INDEX, group.getTranslateY());
+
+ return true;
+ }
+ @LayoutlibDelegate
+ static void nUpdateGroupProperties(long groupPtr, float rotate, float pivotX,
+ float pivotY, float scaleX, float scaleY, float translateX, float translateY) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+
+ group.setRotation(rotate);
+ group.setPivotX(pivotX);
+ group.setPivotY(pivotY);
+ group.setScaleX(scaleX);
+ group.setScaleY(scaleY);
+ group.setTranslateX(translateX);
+ group.setTranslateY(translateY);
+ }
+
+ @LayoutlibDelegate
+ static void nAddChild(long groupPtr, long nodePtr) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ group.mChildren.add(getDelegate(nodePtr));
+ }
+
+ @LayoutlibDelegate
+ static void nSetPathString(long pathPtr, String pathString, int length) {
+ VPath_Delegate path = getDelegate(pathPtr);
+ path.setPathData(PathParser_Delegate.createNodesFromPathData(pathString));
+ }
+
+ /**
+ * The setters and getters below for paths and groups are here temporarily, and will be removed
+ * once the animation in AVD is replaced with RenderNodeAnimator, in which case the animation
+ * will modify these properties in native. By then no JNI hopping would be necessary for VD
+ * during animation, and these setters and getters will be obsolete.
+ */
+ // Setters and getters during animation.
+ @LayoutlibDelegate
+ static float nGetRotation(long groupPtr) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ return group.getRotation();
+ }
+
+ @LayoutlibDelegate
+ static void nSetRotation(long groupPtr, float rotation) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ group.setRotation(rotation);
+ }
+
+ @LayoutlibDelegate
+ static float nGetPivotX(long groupPtr) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ return group.getPivotX();
+ }
+
+ @LayoutlibDelegate
+ static void nSetPivotX(long groupPtr, float pivotX) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ group.setPivotX(pivotX);
+ }
+
+ @LayoutlibDelegate
+ static float nGetPivotY(long groupPtr) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ return group.getPivotY();
+ }
+
+ @LayoutlibDelegate
+ static void nSetPivotY(long groupPtr, float pivotY) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ group.setPivotY(pivotY);
+ }
+
+ @LayoutlibDelegate
+ static float nGetScaleX(long groupPtr) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ return group.getScaleX();
+ }
+
+ @LayoutlibDelegate
+ static void nSetScaleX(long groupPtr, float scaleX) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ group.setScaleX(scaleX);
+ }
+
+ @LayoutlibDelegate
+ static float nGetScaleY(long groupPtr) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ return group.getScaleY();
+ }
+
+ @LayoutlibDelegate
+ static void nSetScaleY(long groupPtr, float scaleY) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ group.setScaleY(scaleY);
+ }
+
+ @LayoutlibDelegate
+ static float nGetTranslateX(long groupPtr) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ return group.getTranslateX();
+ }
+
+ @LayoutlibDelegate
+ static void nSetTranslateX(long groupPtr, float translateX) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ group.setTranslateX(translateX);
+ }
+
+ @LayoutlibDelegate
+ static float nGetTranslateY(long groupPtr) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ return group.getTranslateY();
+ }
+
+ @LayoutlibDelegate
+ static void nSetTranslateY(long groupPtr, float translateY) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ group.setTranslateY(translateY);
+ }
+
+ @LayoutlibDelegate
+ static void nSetPathData(long pathPtr, long pathDataPtr) {
+ VPath_Delegate path = getDelegate(pathPtr);
+ path.setPathData(PathParser_Delegate.getDelegate(pathDataPtr).getPathDataNodes());
+ }
+
+ @LayoutlibDelegate
+ static float nGetStrokeWidth(long pathPtr) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ return path.getStrokeWidth();
+ }
+
+ @LayoutlibDelegate
+ static void nSetStrokeWidth(long pathPtr, float width) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ path.setStrokeWidth(width);
+ }
+
+ @LayoutlibDelegate
+ static int nGetStrokeColor(long pathPtr) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ return path.getStrokeColor();
+ }
+
+ @LayoutlibDelegate
+ static void nSetStrokeColor(long pathPtr, int strokeColor) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ path.setStrokeColor(strokeColor);
+ }
+
+ @LayoutlibDelegate
+ static float nGetStrokeAlpha(long pathPtr) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ return path.getStrokeAlpha();
+ }
+
+ @LayoutlibDelegate
+ static void nSetStrokeAlpha(long pathPtr, float alpha) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ path.setStrokeAlpha(alpha);
+ }
+
+ @LayoutlibDelegate
+ static int nGetFillColor(long pathPtr) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ return path.getFillColor();
+ }
+
+ @LayoutlibDelegate
+ static void nSetFillColor(long pathPtr, int fillColor) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ path.setFillColor(fillColor);
+ }
+
+ @LayoutlibDelegate
+ static float nGetFillAlpha(long pathPtr) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ return path.getFillAlpha();
+ }
+
+ @LayoutlibDelegate
+ static void nSetFillAlpha(long pathPtr, float fillAlpha) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ path.setFillAlpha(fillAlpha);
+ }
+
+ @LayoutlibDelegate
+ static float nGetTrimPathStart(long pathPtr) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ return path.getTrimPathStart();
+ }
+
+ @LayoutlibDelegate
+ static void nSetTrimPathStart(long pathPtr, float trimPathStart) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ path.setTrimPathStart(trimPathStart);
+ }
+
+ @LayoutlibDelegate
+ static float nGetTrimPathEnd(long pathPtr) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ return path.getTrimPathEnd();
+ }
+
+ @LayoutlibDelegate
+ static void nSetTrimPathEnd(long pathPtr, float trimPathEnd) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ path.setTrimPathEnd(trimPathEnd);
+ }
+
+ @LayoutlibDelegate
+ static float nGetTrimPathOffset(long pathPtr) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ return path.getTrimPathOffset();
+ }
+
+ @LayoutlibDelegate
+ static void nSetTrimPathOffset(long pathPtr, float trimPathOffset) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ path.setTrimPathOffset(trimPathOffset);
+ }
+
+ /**
+ * Base class for all the internal Delegates that does two functions:
+ * <ol>
+ * <li>Serves as base class to store all the delegates in one {@link DelegateManager}
+ * <li>Provides setName for all the classes. {@link VPathRenderer_Delegate} does actually
+ * not need it
+ * </ol>
+ */
+ private interface VNativeObject {
+ void setName(String name);
+ }
+
+ private static class VClipPath_Delegate extends VPath_Delegate {
+ private VClipPath_Delegate() {
+ // Empty constructor.
+ }
+
+ private VClipPath_Delegate(VClipPath_Delegate copy) {
+ super(copy);
+ }
+
+ @Override
+ public boolean isClipPath() {
+ return true;
+ }
+ }
+
+ private static class VFullPath_Delegate extends VPath_Delegate {
+ // These constants need to be kept in sync with their values in VectorDrawable.VFullPath
+ private static final int STROKE_WIDTH_INDEX = 0;
+ private static final int STROKE_COLOR_INDEX = 1;
+ private static final int STROKE_ALPHA_INDEX = 2;
+ private static final int FILL_COLOR_INDEX = 3;
+ private static final int FILL_ALPHA_INDEX = 4;
+ private static final int TRIM_PATH_START_INDEX = 5;
+ private static final int TRIM_PATH_END_INDEX = 6;
+ private static final int TRIM_PATH_OFFSET_INDEX = 7;
+ private static final int STROKE_LINE_CAP_INDEX = 8;
+ private static final int STROKE_LINE_JOIN_INDEX = 9;
+ private static final int STROKE_MITER_LIMIT_INDEX = 10;
+
+ private static final int LINECAP_BUTT = 0;
+ private static final int LINECAP_ROUND = 1;
+ private static final int LINECAP_SQUARE = 2;
+
+ private static final int LINEJOIN_MITER = 0;
+ private static final int LINEJOIN_ROUND = 1;
+ private static final int LINEJOIN_BEVEL = 2;
+
+ /////////////////////////////////////////////////////
+ // Variables below need to be copied (deep copy if applicable) for mutation.
+
+ int mStrokeColor = Color.TRANSPARENT;
+ float mStrokeWidth = 0;
+
+ int mFillColor = Color.TRANSPARENT;
+ float mStrokeAlpha = 1.0f;
+ float mFillAlpha = 1.0f;
+ float mTrimPathStart = 0;
+ float mTrimPathEnd = 1;
+ float mTrimPathOffset = 0;
+
+ Cap mStrokeLineCap = BUTT;
+ Join mStrokeLineJoin = MITER;
+ float mStrokeMiterlimit = 4;
+
+ private VFullPath_Delegate() {
+ // Empty constructor.
+ }
+
+ private VFullPath_Delegate(VFullPath_Delegate copy) {
+ super(copy);
+
+ mStrokeColor = copy.mStrokeColor;
+ mStrokeWidth = copy.mStrokeWidth;
+ mStrokeAlpha = copy.mStrokeAlpha;
+ mFillColor = copy.mFillColor;
+ mFillAlpha = copy.mFillAlpha;
+ mTrimPathStart = copy.mTrimPathStart;
+ mTrimPathEnd = copy.mTrimPathEnd;
+ mTrimPathOffset = copy.mTrimPathOffset;
+
+ mStrokeLineCap = copy.mStrokeLineCap;
+ mStrokeLineJoin = copy.mStrokeLineJoin;
+ mStrokeMiterlimit = copy.mStrokeMiterlimit;
+ }
+
+ private int getStrokeLineCap() {
+ switch (mStrokeLineCap) {
+ case BUTT:
+ return LINECAP_BUTT;
+ case ROUND:
+ return LINECAP_ROUND;
+ case SQUARE:
+ return LINECAP_SQUARE;
+ default:
+ assert false;
+ }
+
+ return -1;
+ }
+
+ private void setStrokeLineCap(int cap) {
+ switch (cap) {
+ case LINECAP_BUTT:
+ mStrokeLineCap = BUTT;
+ break;
+ case LINECAP_ROUND:
+ mStrokeLineCap = ROUND;
+ break;
+ case LINECAP_SQUARE:
+ mStrokeLineCap = SQUARE;
+ break;
+ default:
+ assert false;
+ }
+ }
+
+ private int getStrokeLineJoin() {
+ switch (mStrokeLineJoin) {
+ case MITER:
+ return LINEJOIN_MITER;
+ case ROUND:
+ return LINEJOIN_ROUND;
+ case BEVEL:
+ return LINEJOIN_BEVEL;
+ default:
+ assert false;
+ }
+
+ return -1;
+ }
+
+ private void setStrokeLineJoin(int join) {
+ switch (join) {
+ case LINEJOIN_BEVEL:
+ mStrokeLineJoin = BEVEL;
+ break;
+ case LINEJOIN_MITER:
+ mStrokeLineJoin = MITER;
+ break;
+ case LINEJOIN_ROUND:
+ mStrokeLineJoin = Join.ROUND;
+ break;
+ default:
+ assert false;
+ }
+ }
+
+ private int getStrokeColor() {
+ return mStrokeColor;
+ }
+
+ private void setStrokeColor(int strokeColor) {
+ mStrokeColor = strokeColor;
+ }
+
+ private float getStrokeWidth() {
+ return mStrokeWidth;
+ }
+
+ private void setStrokeWidth(float strokeWidth) {
+ mStrokeWidth = strokeWidth;
+ }
+
+ private float getStrokeAlpha() {
+ return mStrokeAlpha;
+ }
+
+ private void setStrokeAlpha(float strokeAlpha) {
+ mStrokeAlpha = strokeAlpha;
+ }
+
+ private int getFillColor() {
+ return mFillColor;
+ }
+
+ private void setFillColor(int fillColor) {
+ mFillColor = fillColor;
+ }
+
+ private float getFillAlpha() {
+ return mFillAlpha;
+ }
+
+ private void setFillAlpha(float fillAlpha) {
+ mFillAlpha = fillAlpha;
+ }
+
+ private float getTrimPathStart() {
+ return mTrimPathStart;
+ }
+
+ private void setTrimPathStart(float trimPathStart) {
+ mTrimPathStart = trimPathStart;
+ }
+
+ private float getTrimPathEnd() {
+ return mTrimPathEnd;
+ }
+
+ private void setTrimPathEnd(float trimPathEnd) {
+ mTrimPathEnd = trimPathEnd;
+ }
+
+ private float getTrimPathOffset() {
+ return mTrimPathOffset;
+ }
+
+ private void setTrimPathOffset(float trimPathOffset) {
+ mTrimPathOffset = trimPathOffset;
+ }
+
+ private void setStrokeMiterlimit(float limit) {
+ mStrokeMiterlimit = limit;
+ }
+
+ private float getStrokeMiterlimit() {
+ return mStrokeMiterlimit;
+ }
+ }
+
+ private static class VGroup_Delegate implements VNativeObject {
+ // This constants need to be kept in sync with their definitions in VectorDrawable.Group
+ private static final int ROTATE_INDEX = 0;
+ private static final int PIVOT_X_INDEX = 1;
+ private static final int PIVOT_Y_INDEX = 2;
+ private static final int SCALE_X_INDEX = 3;
+ private static final int SCALE_Y_INDEX = 4;
+ private static final int TRANSLATE_X_INDEX = 5;
+ private static final int TRANSLATE_Y_INDEX = 6;
+
+ /////////////////////////////////////////////////////
+ // Variables below need to be copied (deep copy if applicable) for mutation.
+ final ArrayList<Object> mChildren = new ArrayList<>();
+ // mStackedMatrix is only used temporarily when drawing, it combines all
+ // the parents' local matrices with the current one.
+ private final Matrix mStackedMatrix = new Matrix();
+ // mLocalMatrix is updated based on the update of transformation information,
+ // either parsed from the XML or by animation.
+ private final Matrix mLocalMatrix = new Matrix();
+ private float mRotate = 0;
+ private float mPivotX = 0;
+ private float mPivotY = 0;
+ private float mScaleX = 1;
+ private float mScaleY = 1;
+ private float mTranslateX = 0;
+ private float mTranslateY = 0;
+ private int mChangingConfigurations;
+ private String mGroupName = null;
+
+ private VGroup_Delegate(VGroup_Delegate copy, ArrayMap<String, Object> targetsMap) {
+ mRotate = copy.mRotate;
+ mPivotX = copy.mPivotX;
+ mPivotY = copy.mPivotY;
+ mScaleX = copy.mScaleX;
+ mScaleY = copy.mScaleY;
+ mTranslateX = copy.mTranslateX;
+ mTranslateY = copy.mTranslateY;
+ mGroupName = copy.mGroupName;
+ mChangingConfigurations = copy.mChangingConfigurations;
+ if (mGroupName != null) {
+ targetsMap.put(mGroupName, this);
+ }
+
+ mLocalMatrix.set(copy.mLocalMatrix);
+
+ final ArrayList<Object> children = copy.mChildren;
+ //noinspection ForLoopReplaceableByForEach
+ for (int i = 0; i < children.size(); i++) {
+ Object copyChild = children.get(i);
+ if (copyChild instanceof VGroup_Delegate) {
+ VGroup_Delegate copyGroup = (VGroup_Delegate) copyChild;
+ mChildren.add(new VGroup_Delegate(copyGroup, targetsMap));
+ } else {
+ VPath_Delegate newPath;
+ if (copyChild instanceof VFullPath_Delegate) {
+ newPath = new VFullPath_Delegate((VFullPath_Delegate) copyChild);
+ } else if (copyChild instanceof VClipPath_Delegate) {
+ newPath = new VClipPath_Delegate((VClipPath_Delegate) copyChild);
+ } else {
+ throw new IllegalStateException("Unknown object in the tree!");
+ }
+ mChildren.add(newPath);
+ if (newPath.mPathName != null) {
+ targetsMap.put(newPath.mPathName, newPath);
+ }
+ }
+ }
+ }
+
+ private VGroup_Delegate() {
+ }
+
+ private void updateLocalMatrix() {
+ // The order we apply is the same as the
+ // RenderNode.cpp::applyViewPropertyTransforms().
+ mLocalMatrix.reset();
+ mLocalMatrix.postTranslate(-mPivotX, -mPivotY);
+ mLocalMatrix.postScale(mScaleX, mScaleY);
+ mLocalMatrix.postRotate(mRotate, 0, 0);
+ mLocalMatrix.postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY);
+ }
+
+ /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
+ private float getRotation() {
+ return mRotate;
+ }
+
+ private void setRotation(float rotation) {
+ if (rotation != mRotate) {
+ mRotate = rotation;
+ updateLocalMatrix();
+ }
+ }
+
+ private float getPivotX() {
+ return mPivotX;
+ }
+
+ private void setPivotX(float pivotX) {
+ if (pivotX != mPivotX) {
+ mPivotX = pivotX;
+ updateLocalMatrix();
+ }
+ }
+
+ private float getPivotY() {
+ return mPivotY;
+ }
+
+ private void setPivotY(float pivotY) {
+ if (pivotY != mPivotY) {
+ mPivotY = pivotY;
+ updateLocalMatrix();
+ }
+ }
+
+ private float getScaleX() {
+ return mScaleX;
+ }
+
+ private void setScaleX(float scaleX) {
+ if (scaleX != mScaleX) {
+ mScaleX = scaleX;
+ updateLocalMatrix();
+ }
+ }
+
+ private float getScaleY() {
+ return mScaleY;
+ }
+
+ private void setScaleY(float scaleY) {
+ if (scaleY != mScaleY) {
+ mScaleY = scaleY;
+ updateLocalMatrix();
+ }
+ }
+
+ private float getTranslateX() {
+ return mTranslateX;
+ }
+
+ private void setTranslateX(float translateX) {
+ if (translateX != mTranslateX) {
+ mTranslateX = translateX;
+ updateLocalMatrix();
+ }
+ }
+
+ private float getTranslateY() {
+ return mTranslateY;
+ }
+
+ private void setTranslateY(float translateY) {
+ if (translateY != mTranslateY) {
+ mTranslateY = translateY;
+ updateLocalMatrix();
+ }
+ }
+
+ @Override
+ public void setName(String name) {
+ mGroupName = name;
+ }
+ }
+
+ public static class VPath_Delegate implements VNativeObject {
+ protected PathParser_Delegate.PathDataNode[] mNodes = null;
+ String mPathName;
+ int mChangingConfigurations;
+
+ public VPath_Delegate() {
+ // Empty constructor.
+ }
+
+ public VPath_Delegate(VPath_Delegate copy) {
+ mPathName = copy.mPathName;
+ mChangingConfigurations = copy.mChangingConfigurations;
+ mNodes = PathParser_Delegate.deepCopyNodes(copy.mNodes);
+ }
+
+ public void toPath(Path path) {
+ path.reset();
+ if (mNodes != null) {
+ PathParser_Delegate.PathDataNode.nodesToPath(mNodes,
+ Path_Delegate.getDelegate(path.mNativePath));
+ }
+ }
+
+ @Override
+ public void setName(String name) {
+ mPathName = name;
+ }
+
+ public boolean isClipPath() {
+ return false;
+ }
+
+ private void setPathData(PathParser_Delegate.PathDataNode[] nodes) {
+ if (!PathParser_Delegate.canMorph(mNodes, nodes)) {
+ // This should not happen in the middle of animation.
+ mNodes = PathParser_Delegate.deepCopyNodes(nodes);
+ } else {
+ PathParser_Delegate.updateNodes(mNodes, nodes);
+ }
+ }
+ }
+
+ private static class VPathRenderer_Delegate implements VNativeObject {
+ /* Right now the internal data structure is organized as a tree.
+ * Each node can be a group node, or a path.
+ * A group node can have groups or paths as children, but a path node has
+ * no children.
+ * One example can be:
+ * Root Group
+ * / | \
+ * Group Path Group
+ * / \ |
+ * Path Path Path
+ *
+ */
+ // Variables that only used temporarily inside the draw() call, so there
+ // is no need for deep copying.
+ private final Path mPath;
+ private final Path mRenderPath;
+ private final Matrix mFinalPathMatrix = new Matrix();
+ private final VGroup_Delegate mRootGroup;
+ private float mViewportWidth = 0;
+ private float mViewportHeight = 0;
+ private float mRootAlpha = 1.0f;
+ private Paint mStrokePaint;
+ private Paint mFillPaint;
+ private PathMeasure mPathMeasure;
+
+ private VPathRenderer_Delegate(VGroup_Delegate rootGroup) {
+ mRootGroup = rootGroup;
+ mPath = new Path();
+ mRenderPath = new Path();
+ }
+
+ private float getRootAlpha() {
+ return mRootAlpha;
+ }
+
+ private void setRootAlpha(float alpha) {
+ mRootAlpha = alpha;
+ }
+
+ private void drawGroupTree(VGroup_Delegate currentGroup, Matrix currentMatrix,
+ long canvasPtr, int w, int h, long filterPtr) {
+ // Calculate current group's matrix by preConcat the parent's and
+ // and the current one on the top of the stack.
+ // Basically the Mfinal = Mviewport * M0 * M1 * M2;
+ // Mi the local matrix at level i of the group tree.
+ currentGroup.mStackedMatrix.set(currentMatrix);
+ currentGroup.mStackedMatrix.preConcat(currentGroup.mLocalMatrix);
+
+ // Save the current clip information, which is local to this group.
+ Canvas_Delegate.native_save(canvasPtr, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG);
+ // Draw the group tree in the same order as the XML file.
+ for (int i = 0; i < currentGroup.mChildren.size(); i++) {
+ Object child = currentGroup.mChildren.get(i);
+ if (child instanceof VGroup_Delegate) {
+ VGroup_Delegate childGroup = (VGroup_Delegate) child;
+ drawGroupTree(childGroup, currentGroup.mStackedMatrix,
+ canvasPtr, w, h, filterPtr);
+ } else if (child instanceof VPath_Delegate) {
+ VPath_Delegate childPath = (VPath_Delegate) child;
+ drawPath(currentGroup, childPath, canvasPtr, w, h, filterPtr);
+ }
+ }
+ Canvas_Delegate.native_restore(canvasPtr, true);
+ }
+
+ public void draw(long canvasPtr, long filterPtr, int w, int h) {
+ // Traverse the tree in pre-order to draw.
+ drawGroupTree(mRootGroup, Matrix.IDENTITY_MATRIX, canvasPtr, w, h, filterPtr);
+ }
+
+ private void drawPath(VGroup_Delegate VGroup, VPath_Delegate VPath, long canvasPtr,
+ int w,
+ int h,
+ long filterPtr) {
+ final float scaleX = w / mViewportWidth;
+ final float scaleY = h / mViewportHeight;
+ final float minScale = Math.min(scaleX, scaleY);
+ final Matrix groupStackedMatrix = VGroup.mStackedMatrix;
+
+ mFinalPathMatrix.set(groupStackedMatrix);
+ mFinalPathMatrix.postScale(scaleX, scaleY);
+
+ final float matrixScale = getMatrixScale(groupStackedMatrix);
+ if (matrixScale == 0) {
+ // When either x or y is scaled to 0, we don't need to draw anything.
+ return;
+ }
+ VPath.toPath(mPath);
+ final Path path = mPath;
+
+ mRenderPath.reset();
+
+ if (VPath.isClipPath()) {
+ mRenderPath.addPath(path, mFinalPathMatrix);
+ Canvas_Delegate.native_clipPath(canvasPtr, mRenderPath.mNativePath, Op
+ .INTERSECT.nativeInt);
+ } else {
+ VFullPath_Delegate fullPath = (VFullPath_Delegate) VPath;
+ if (fullPath.mTrimPathStart != 0.0f || fullPath.mTrimPathEnd != 1.0f) {
+ float start = (fullPath.mTrimPathStart + fullPath.mTrimPathOffset) % 1.0f;
+ float end = (fullPath.mTrimPathEnd + fullPath.mTrimPathOffset) % 1.0f;
+
+ if (mPathMeasure == null) {
+ mPathMeasure = new PathMeasure();
+ }
+ mPathMeasure.setPath(mPath, false);
+
+ float len = mPathMeasure.getLength();
+ start = start * len;
+ end = end * len;
+ path.reset();
+ if (start > end) {
+ mPathMeasure.getSegment(start, len, path, true);
+ mPathMeasure.getSegment(0f, end, path, true);
+ } else {
+ mPathMeasure.getSegment(start, end, path, true);
+ }
+ path.rLineTo(0, 0); // fix bug in measure
+ }
+ mRenderPath.addPath(path, mFinalPathMatrix);
+
+ if (fullPath.mFillColor != Color.TRANSPARENT) {
+ if (mFillPaint == null) {
+ mFillPaint = new Paint();
+ mFillPaint.setStyle(Style.FILL);
+ mFillPaint.setAntiAlias(true);
+ }
+
+ final Paint fillPaint = mFillPaint;
+ fillPaint.setColor(applyAlpha(fullPath.mFillColor, fullPath.mFillAlpha));
+ Paint_Delegate fillPaintDelegate = Paint_Delegate.getDelegate(fillPaint
+ .getNativeInstance
+ ());
+ // mFillPaint can not be null at this point so we will have a delegate
+ assert fillPaintDelegate != null;
+ fillPaintDelegate.setColorFilter(filterPtr);
+ Canvas_Delegate.native_drawPath(canvasPtr, mRenderPath.mNativePath, fillPaint
+ .getNativeInstance());
+ }
+
+ if (fullPath.mStrokeColor != Color.TRANSPARENT) {
+ if (mStrokePaint == null) {
+ mStrokePaint = new Paint();
+ mStrokePaint.setStyle(Style.STROKE);
+ mStrokePaint.setAntiAlias(true);
+ }
+
+ final Paint strokePaint = mStrokePaint;
+ if (fullPath.mStrokeLineJoin != null) {
+ strokePaint.setStrokeJoin(fullPath.mStrokeLineJoin);
+ }
+
+ if (fullPath.mStrokeLineCap != null) {
+ strokePaint.setStrokeCap(fullPath.mStrokeLineCap);
+ }
+
+ strokePaint.setStrokeMiter(fullPath.mStrokeMiterlimit);
+ strokePaint.setColor(applyAlpha(fullPath.mStrokeColor, fullPath.mStrokeAlpha));
+ Paint_Delegate strokePaintDelegate = Paint_Delegate.getDelegate(strokePaint
+ .getNativeInstance());
+ // mStrokePaint can not be null at this point so we will have a delegate
+ assert strokePaintDelegate != null;
+ strokePaintDelegate.setColorFilter(filterPtr);
+ final float finalStrokeScale = minScale * matrixScale;
+ strokePaint.setStrokeWidth(fullPath.mStrokeWidth * finalStrokeScale);
+ Canvas_Delegate.native_drawPath(canvasPtr, mRenderPath.mNativePath, strokePaint
+ .getNativeInstance());
+ }
+ }
+ }
+
+ private float getMatrixScale(Matrix groupStackedMatrix) {
+ // Given unit vectors A = (0, 1) and B = (1, 0).
+ // After matrix mapping, we got A' and B'. Let theta = the angel b/t A' and B'.
+ // Therefore, the final scale we want is min(|A'| * sin(theta), |B'| * sin(theta)),
+ // which is (|A'| * |B'| * sin(theta)) / max (|A'|, |B'|);
+ // If max (|A'|, |B'|) = 0, that means either x or y has a scale of 0.
+ //
+ // For non-skew case, which is most of the cases, matrix scale is computing exactly the
+ // scale on x and y axis, and take the minimal of these two.
+ // For skew case, an unit square will mapped to a parallelogram. And this function will
+ // return the minimal height of the 2 bases.
+ float[] unitVectors = new float[]{0, 1, 1, 0};
+ groupStackedMatrix.mapVectors(unitVectors);
+ float scaleX = MathUtils.mag(unitVectors[0], unitVectors[1]);
+ float scaleY = MathUtils.mag(unitVectors[2], unitVectors[3]);
+ float crossProduct = MathUtils.cross(unitVectors[0], unitVectors[1],
+ unitVectors[2], unitVectors[3]);
+ float maxScale = MathUtils.max(scaleX, scaleY);
+
+ float matrixScale = 0;
+ if (maxScale > 0) {
+ matrixScale = MathUtils.abs(crossProduct) / maxScale;
+ }
+ if (DBG_VECTOR_DRAWABLE) {
+ Log.d(LOGTAG, "Scale x " + scaleX + " y " + scaleY + " final " + matrixScale);
+ }
+ return matrixScale;
+ }
+
+ @Override
+ public void setName(String name) {
+ }
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java b/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java
index d3af837..6c34c70 100644
--- a/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java
@@ -24,7 +24,6 @@
import android.annotation.NonNull;
import android.graphics.Path_Delegate;
-import java.awt.geom.Path2D;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.logging.Level;
@@ -52,10 +51,18 @@
@NonNull
private PathDataNode[] mPathDataNodes;
+ public static PathParser_Delegate getDelegate(long nativePtr) {
+ return sManager.getDelegate(nativePtr);
+ }
+
private PathParser_Delegate(@NonNull PathDataNode[] nodes) {
mPathDataNodes = nodes;
}
+ public PathDataNode[] getPathDataNodes() {
+ return mPathDataNodes;
+ }
+
@LayoutlibDelegate
/*package*/ static boolean nParseStringForPath(long pathPtr, @NonNull String pathString, int
stringLength) {
@@ -64,7 +71,7 @@
return false;
}
assert pathString.length() == stringLength;
- PathDataNode.nodesToPath(createNodesFromPathData(pathString), path_delegate.getJavaShape());
+ PathDataNode.nodesToPath(createNodesFromPathData(pathString), path_delegate);
return true;
}
@@ -75,7 +82,7 @@
if (source == null || path_delegate == null) {
return;
}
- PathDataNode.nodesToPath(source.mPathDataNodes, path_delegate.getJavaShape());
+ PathDataNode.nodesToPath(source.mPathDataNodes, path_delegate);
}
@LayoutlibDelegate
@@ -124,8 +131,11 @@
out.mPathDataNodes = new PathDataNode[length];
}
for (int i = 0; i < length; i++) {
+ if (out.mPathDataNodes[i] == null) {
+ out.mPathDataNodes[i] = new PathDataNode(from.mPathDataNodes[i]);
+ }
out.mPathDataNodes[i].interpolatePathDataNode(from.mPathDataNodes[i],
- to.mPathDataNodes[i], fraction);
+ to.mPathDataNodes[i], fraction);
}
return true;
}
@@ -137,9 +147,13 @@
@LayoutlibDelegate
/*package*/ static boolean nCanMorph(long fromDataPtr, long toDataPtr) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, "morphing path data isn't " +
- "supported", null, null);
- return false;
+ PathParser_Delegate fromPath = PathParser_Delegate.getDelegate(fromDataPtr);
+ PathParser_Delegate toPath = PathParser_Delegate.getDelegate(toDataPtr);
+ if (fromPath == null || toPath == null || fromPath.getPathDataNodes() == null || toPath
+ .getPathDataNodes() == null) {
+ return true;
+ }
+ return PathParser_Delegate.canMorph(fromPath.getPathDataNodes(), toPath.getPathDataNodes());
}
@LayoutlibDelegate
@@ -158,7 +172,7 @@
* @return an array of the PathDataNode.
*/
@NonNull
- private static PathDataNode[] createNodesFromPathData(@NonNull String pathData) {
+ public static PathDataNode[] createNodesFromPathData(@NonNull String pathData) {
int start = 0;
int end = 1;
@@ -186,7 +200,7 @@
* @return a deep copy of the <code>source</code>.
*/
@NonNull
- private static PathDataNode[] deepCopyNodes(@NonNull PathDataNode[] source) {
+ public static PathDataNode[] deepCopyNodes(@NonNull PathDataNode[] source) {
PathDataNode[] copy = new PathDataNode[source.length];
for (int i = 0; i < source.length; i++) {
copy[i] = new PathDataNode(source[i]);
@@ -194,6 +208,45 @@
return copy;
}
+ /**
+ * @param nodesFrom The source path represented in an array of PathDataNode
+ * @param nodesTo The target path represented in an array of PathDataNode
+ * @return whether the <code>nodesFrom</code> can morph into <code>nodesTo</code>
+ */
+ public static boolean canMorph(PathDataNode[] nodesFrom, PathDataNode[] nodesTo) {
+ if (nodesFrom == null || nodesTo == null) {
+ return false;
+ }
+
+ if (nodesFrom.length != nodesTo.length) {
+ return false;
+ }
+
+ for (int i = 0; i < nodesFrom.length; i ++) {
+ if (nodesFrom[i].mType != nodesTo[i].mType
+ || nodesFrom[i].mParams.length != nodesTo[i].mParams.length) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Update the target's data to match the source.
+ * Before calling this, make sure canMorph(target, source) is true.
+ *
+ * @param target The target path represented in an array of PathDataNode
+ * @param source The source path represented in an array of PathDataNode
+ */
+ public static void updateNodes(PathDataNode[] target, PathDataNode[] source) {
+ for (int i = 0; i < source.length; i ++) {
+ target[i].mType = source[i].mType;
+ for (int j = 0; j < source[i].mParams.length; j ++) {
+ target[i].mParams[j] = source[i].mParams[j];
+ }
+ }
+ }
+
private static int nextStart(@NonNull String s, int end) {
char c;
@@ -330,7 +383,7 @@
* Each PathDataNode represents one command in the "d" attribute of the svg file. An array of
* PathDataNode can represent the whole "d" attribute.
*/
- private static class PathDataNode {
+ public static class PathDataNode {
private char mType;
@NonNull
private float[] mParams;
@@ -355,12 +408,13 @@
}
/**
- * Convert an array of PathDataNode to Path.
+ * Convert an array of PathDataNode to Path. Reset the passed path as needed before
+ * calling this method.
*
* @param node The source array of PathDataNode.
* @param path The target Path object.
*/
- private static void nodesToPath(@NonNull PathDataNode[] node, @NonNull Path2D path) {
+ public static void nodesToPath(@NonNull PathDataNode[] node, @NonNull Path_Delegate path) {
float[] current = new float[6];
char previousCommand = 'm';
//noinspection ForLoopReplaceableByForEach
@@ -387,24 +441,32 @@
}
@SuppressWarnings("PointlessArithmeticExpression")
- private static void addCommand(@NonNull Path2D path, float[] current, char cmd,
- char lastCmd, @NonNull float[] val) {
+ private static void addCommand(@NonNull Path_Delegate path, float[] current,
+ char previousCmd, char cmd, @NonNull float[] val) {
int incr = 2;
-
- float cx = current[0];
- float cy = current[1];
- float cpx = current[2];
- float cpy = current[3];
- float loopX = current[4];
- float loopY = current[5];
+ float currentX = current[0];
+ float currentY = current[1];
+ float ctrlPointX = current[2];
+ float ctrlPointY = current[3];
+ float currentSegmentStartX = current[4];
+ float currentSegmentStartY = current[5];
+ float reflectiveCtrlPointX;
+ float reflectiveCtrlPointY;
switch (cmd) {
case 'z':
case 'Z':
- path.closePath();
- cx = loopX;
- cy = loopY;
+ path.close();
+ // Path is closed here, but we need to move the pen to the
+ // closed position. So we cache the segment's starting position,
+ // and restore it here.
+ currentX = currentSegmentStartX;
+ currentY = currentSegmentStartY;
+ ctrlPointX = currentSegmentStartX;
+ ctrlPointY = currentSegmentStartY;
+ path.moveTo(currentX, currentY);
+ break;
case 'm':
case 'M':
case 'l':
@@ -432,185 +494,206 @@
case 'a':
case 'A':
incr = 7;
+ break;
}
for (int k = 0; k < val.length; k += incr) {
- boolean reflectCtrl;
- float tempReflectedX, tempReflectedY;
-
switch (cmd) {
- case 'm':
- cx += val[k + 0];
- cy += val[k + 1];
+ case 'm': // moveto - Start a new sub-path (relative)
+ currentX += val[k + 0];
+ currentY += val[k + 1];
+
if (k > 0) {
// According to the spec, if a moveto is followed by multiple
// pairs of coordinates, the subsequent pairs are treated as
// implicit lineto commands.
- path.lineTo(cx, cy);
+ path.rLineTo(val[k + 0], val[k + 1]);
} else {
- path.moveTo(cx, cy);
- loopX = cx;
- loopY = cy;
+ path.rMoveTo(val[k + 0], val[k + 1]);
+ currentSegmentStartX = currentX;
+ currentSegmentStartY = currentY;
}
break;
- case 'M':
- cx = val[k + 0];
- cy = val[k + 1];
+ case 'M': // moveto - Start a new sub-path
+ currentX = val[k + 0];
+ currentY = val[k + 1];
+
if (k > 0) {
// According to the spec, if a moveto is followed by multiple
// pairs of coordinates, the subsequent pairs are treated as
// implicit lineto commands.
- path.lineTo(cx, cy);
+ path.lineTo(val[k + 0], val[k + 1]);
} else {
- path.moveTo(cx, cy);
- loopX = cx;
- loopY = cy;
+ path.moveTo(val[k + 0], val[k + 1]);
+ currentSegmentStartX = currentX;
+ currentSegmentStartY = currentY;
}
break;
- case 'l':
- cx += val[k + 0];
- cy += val[k + 1];
- path.lineTo(cx, cy);
+ case 'l': // lineto - Draw a line from the current point (relative)
+ path.rLineTo(val[k + 0], val[k + 1]);
+ currentX += val[k + 0];
+ currentY += val[k + 1];
break;
- case 'L':
- cx = val[k + 0];
- cy = val[k + 1];
- path.lineTo(cx, cy);
+ case 'L': // lineto - Draw a line from the current point
+ path.lineTo(val[k + 0], val[k + 1]);
+ currentX = val[k + 0];
+ currentY = val[k + 1];
break;
- case 'z':
- case 'Z':
- path.closePath();
- cx = loopX;
- cy = loopY;
+ case 'h': // horizontal lineto - Draws a horizontal line (relative)
+ path.rLineTo(val[k + 0], 0);
+ currentX += val[k + 0];
break;
- case 'h':
- cx += val[k + 0];
- path.lineTo(cx, cy);
+ case 'H': // horizontal lineto - Draws a horizontal line
+ path.lineTo(val[k + 0], currentY);
+ currentX = val[k + 0];
break;
- case 'H':
- path.lineTo(val[k + 0], cy);
- cx = val[k + 0];
+ case 'v': // vertical lineto - Draws a vertical line from the current point (r)
+ path.rLineTo(0, val[k + 0]);
+ currentY += val[k + 0];
break;
- case 'v':
- cy += val[k + 0];
- path.lineTo(cx, cy);
+ case 'V': // vertical lineto - Draws a vertical line from the current point
+ path.lineTo(currentX, val[k + 0]);
+ currentY = val[k + 0];
break;
- case 'V':
- path.lineTo(cx, val[k + 0]);
- cy = val[k + 0];
- break;
- case 'c':
- path.curveTo(cx + val[k + 0], cy + val[k + 1], cx + val[k + 2],
- cy + val[k + 3], cx + val[k + 4], cy + val[k + 5]);
- cpx = cx + val[k + 2];
- cpy = cy + val[k + 3];
- cx += val[k + 4];
- cy += val[k + 5];
- break;
- case 'C':
- path.curveTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3],
+ case 'c': // curveto - Draws a cubic Bézier curve (relative)
+ path.rCubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3],
val[k + 4], val[k + 5]);
- cx = val[k + 4];
- cy = val[k + 5];
- cpx = val[k + 2];
- cpy = val[k + 3];
- break;
- case 's':
- reflectCtrl = (lastCmd == 'c' || lastCmd == 's' || lastCmd == 'C' ||
- lastCmd == 'S');
- path.curveTo(reflectCtrl ? 2 * cx - cpx : cx, reflectCtrl ? 2
- * cy - cpy : cy, cx + val[k + 0], cy + val[k + 1], cx
- + val[k + 2], cy + val[k + 3]);
- cpx = cx + val[k + 0];
- cpy = cy + val[k + 1];
- cx += val[k + 2];
- cy += val[k + 3];
+ ctrlPointX = currentX + val[k + 2];
+ ctrlPointY = currentY + val[k + 3];
+ currentX += val[k + 4];
+ currentY += val[k + 5];
+
break;
- case 'S':
- reflectCtrl = (lastCmd == 'c' || lastCmd == 's' || lastCmd == 'C' ||
- lastCmd == 'S');
- path.curveTo(reflectCtrl ? 2 * cx - cpx : cx, reflectCtrl ? 2
- * cy - cpy : cy, val[k + 0], val[k + 1], val[k + 2],
- val[k + 3]);
- cpx = (val[k + 0]);
- cpy = (val[k + 1]);
- cx = val[k + 2];
- cy = val[k + 3];
+ case 'C': // curveto - Draws a cubic Bézier curve
+ path.cubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3],
+ val[k + 4], val[k + 5]);
+ currentX = val[k + 4];
+ currentY = val[k + 5];
+ ctrlPointX = val[k + 2];
+ ctrlPointY = val[k + 3];
break;
- case 'q':
- path.quadTo(cx + val[k + 0], cy + val[k + 1], cx + val[k + 2],
- cy + val[k + 3]);
- cpx = cx + val[k + 0];
- cpy = cy + val[k + 1];
- // Note that we have to update cpx first, since cx will be updated here.
- cx += val[k + 2];
- cy += val[k + 3];
+ case 's': // smooth curveto - Draws a cubic Bézier curve (reflective cp)
+ reflectiveCtrlPointX = 0;
+ reflectiveCtrlPointY = 0;
+ if (previousCmd == 'c' || previousCmd == 's'
+ || previousCmd == 'C' || previousCmd == 'S') {
+ reflectiveCtrlPointX = currentX - ctrlPointX;
+ reflectiveCtrlPointY = currentY - ctrlPointY;
+ }
+ path.rCubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+ val[k + 0], val[k + 1],
+ val[k + 2], val[k + 3]);
+
+ ctrlPointX = currentX + val[k + 0];
+ ctrlPointY = currentY + val[k + 1];
+ currentX += val[k + 2];
+ currentY += val[k + 3];
break;
- case 'Q':
+ case 'S': // shorthand/smooth curveto Draws a cubic Bézier curve(reflective cp)
+ reflectiveCtrlPointX = currentX;
+ reflectiveCtrlPointY = currentY;
+ if (previousCmd == 'c' || previousCmd == 's'
+ || previousCmd == 'C' || previousCmd == 'S') {
+ reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
+ reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
+ }
+ path.cubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+ val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+ ctrlPointX = val[k + 0];
+ ctrlPointY = val[k + 1];
+ currentX = val[k + 2];
+ currentY = val[k + 3];
+ break;
+ case 'q': // Draws a quadratic Bézier (relative)
+ path.rQuadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+ ctrlPointX = currentX + val[k + 0];
+ ctrlPointY = currentY + val[k + 1];
+ currentX += val[k + 2];
+ currentY += val[k + 3];
+ break;
+ case 'Q': // Draws a quadratic Bézier
path.quadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
- cx = val[k + 2];
- cy = val[k + 3];
- cpx = val[k + 0];
- cpy = val[k + 1];
+ ctrlPointX = val[k + 0];
+ ctrlPointY = val[k + 1];
+ currentX = val[k + 2];
+ currentY = val[k + 3];
break;
- case 't':
- reflectCtrl = (lastCmd == 'q' || lastCmd == 't' || lastCmd == 'Q' ||
- lastCmd == 'T');
- tempReflectedX = reflectCtrl ? 2 * cx - cpx : cx;
- tempReflectedY = reflectCtrl ? 2 * cy - cpy : cy;
- path.quadTo(tempReflectedX, tempReflectedY, cx + val[k + 0],
- cy + val[k + 1]);
- cpx = tempReflectedX;
- cpy = tempReflectedY;
- cx += val[k + 0];
- cy += val[k + 1];
+ case 't': // Draws a quadratic Bézier curve(reflective control point)(relative)
+ reflectiveCtrlPointX = 0;
+ reflectiveCtrlPointY = 0;
+ if (previousCmd == 'q' || previousCmd == 't'
+ || previousCmd == 'Q' || previousCmd == 'T') {
+ reflectiveCtrlPointX = currentX - ctrlPointX;
+ reflectiveCtrlPointY = currentY - ctrlPointY;
+ }
+ path.rQuadTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+ val[k + 0], val[k + 1]);
+ ctrlPointX = currentX + reflectiveCtrlPointX;
+ ctrlPointY = currentY + reflectiveCtrlPointY;
+ currentX += val[k + 0];
+ currentY += val[k + 1];
break;
- case 'T':
- reflectCtrl = (lastCmd == 'q' || lastCmd == 't' || lastCmd == 'Q' ||
- lastCmd == 'T');
- tempReflectedX = reflectCtrl ? 2 * cx - cpx : cx;
- tempReflectedY = reflectCtrl ? 2 * cy - cpy : cy;
- path.quadTo(tempReflectedX, tempReflectedY, val[k + 0], val[k + 1]);
- cx = val[k + 0];
- cy = val[k + 1];
- cpx = tempReflectedX;
- cpy = tempReflectedY;
+ case 'T': // Draws a quadratic Bézier curve (reflective control point)
+ reflectiveCtrlPointX = currentX;
+ reflectiveCtrlPointY = currentY;
+ if (previousCmd == 'q' || previousCmd == 't'
+ || previousCmd == 'Q' || previousCmd == 'T') {
+ reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
+ reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
+ }
+ path.quadTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+ val[k + 0], val[k + 1]);
+ ctrlPointX = reflectiveCtrlPointX;
+ ctrlPointY = reflectiveCtrlPointY;
+ currentX = val[k + 0];
+ currentY = val[k + 1];
break;
- case 'a':
+ case 'a': // Draws an elliptical arc
// (rx ry x-axis-rotation large-arc-flag sweep-flag x y)
- drawArc(path, cx, cy, val[k + 5] + cx, val[k + 6] + cy,
- val[k + 0], val[k + 1], val[k + 2], val[k + 3] != 0,
+ drawArc(path,
+ currentX,
+ currentY,
+ val[k + 5] + currentX,
+ val[k + 6] + currentY,
+ val[k + 0],
+ val[k + 1],
+ val[k + 2],
+ val[k + 3] != 0,
val[k + 4] != 0);
- cx += val[k + 5];
- cy += val[k + 6];
- cpx = cx;
- cpy = cy;
-
+ currentX += val[k + 5];
+ currentY += val[k + 6];
+ ctrlPointX = currentX;
+ ctrlPointY = currentY;
break;
- case 'A':
- drawArc(path, cx, cy, val[k + 5], val[k + 6], val[k + 0],
- val[k + 1], val[k + 2], val[k + 3] != 0,
+ case 'A': // Draws an elliptical arc
+ drawArc(path,
+ currentX,
+ currentY,
+ val[k + 5],
+ val[k + 6],
+ val[k + 0],
+ val[k + 1],
+ val[k + 2],
+ val[k + 3] != 0,
val[k + 4] != 0);
- cx = val[k + 5];
- cy = val[k + 6];
- cpx = cx;
- cpy = cy;
+ currentX = val[k + 5];
+ currentY = val[k + 6];
+ ctrlPointX = currentX;
+ ctrlPointY = currentY;
break;
-
}
- lastCmd = cmd;
+ previousCmd = cmd;
}
- current[0] = cx;
- current[1] = cy;
- current[2] = cpx;
- current[3] = cpy;
- current[4] = loopX;
- current[5] = loopY;
-
+ current[0] = currentX;
+ current[1] = currentY;
+ current[2] = ctrlPointX;
+ current[3] = ctrlPointY;
+ current[4] = currentSegmentStartX;
+ current[5] = currentSegmentStartY;
}
- private static void drawArc(@NonNull Path2D p, float x0, float y0, float x1,
+ private static void drawArc(@NonNull Path_Delegate p, float x0, float y0, float x1,
float y1, float a, float b, float theta, boolean isMoreThanHalf,
boolean isPositiveArc) {
@@ -707,7 +790,7 @@
* @param start The start angle of the arc on the ellipse
* @param sweep The angle (positive or negative) of the sweep of the arc on the ellipse
*/
- private static void arcToBezier(@NonNull Path2D p, double cx, double cy, double a,
+ private static void arcToBezier(@NonNull Path_Delegate p, double cx, double cy, double a,
double b, double e1x, double e1y, double theta, double start,
double sweep) {
// Taken from equations at:
@@ -744,8 +827,12 @@
double q2x = e2x - alpha * ep2x;
double q2y = e2y - alpha * ep2y;
- p.curveTo((float) q1x, (float) q1y, (float) q2x, (float) q2y,
- (float) e2x, (float) e2y);
+ p.cubicTo((float) q1x,
+ (float) q1y,
+ (float) q2x,
+ (float) q2y,
+ (float) e2x,
+ (float) e2y);
eta1 = eta2;
e1x = e2x;
e1y = e2y;
diff --git a/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java b/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
index 4901f72..94f3f54 100644
--- a/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
+++ b/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
@@ -45,4 +45,10 @@
public static void dispatchOnPreDraw(View view) {
view.mAttachInfo.mTreeObserver.dispatchOnPreDraw();
}
+
+ public static void detachFromWindow(View view) {
+ if (view != null) {
+ view.dispatchDetachedFromWindow();
+ }
+ }
}
diff --git a/tools/layoutlib/bridge/src/android/view/HandlerActionQueue_Delegate.java b/tools/layoutlib/bridge/src/android/view/HandlerActionQueue_Delegate.java
new file mode 100644
index 0000000..e580ed0
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/view/HandlerActionQueue_Delegate.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+/**
+ * Delegate used to provide new implementation of a select few methods of
+ * {@link HandlerActionQueue}
+ *
+ * Through the layoutlib_create tool, the original methods of ViewRootImpl.RunQueue have been
+ * replaced by calls to methods of the same name in this delegate class.
+ *
+ */
+public class HandlerActionQueue_Delegate {
+
+ @LayoutlibDelegate
+ /*package*/ static void postDelayed(HandlerActionQueue thisQueue, Runnable action, long
+ delayMillis) {
+ // The actual HandlerActionQueue is never run and therefore never cleared. This method
+ // avoids runnables to be added to the RunQueue so they do not leak resources.
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 8d1b124..97195e4 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -20,6 +20,7 @@
import android.graphics.Rect;
import com.android.internal.app.IAssistScreenshotReceiver;
import com.android.internal.os.IResultReceiver;
+import com.android.internal.policy.IShortcutService;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
@@ -348,7 +349,7 @@
}
@Override
- public void notifyAppStopped(IBinder token) throws RemoteException {
+ public void notifyAppStopped(IBinder token, boolean stopped) throws RemoteException {
// TODO Auto-generated method stub
}
@@ -566,4 +567,8 @@
@Override
public void getStableInsets(Rect outInsets) throws RemoteException {
}
+
+ @Override
+ public void registerShortcutKey(long shortcutCode, IShortcutService service)
+ throws RemoteException {}
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
index 2ac212c..fea633e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
@@ -208,6 +208,9 @@
@Override
public void dispose() {
+ if (mSession != null) {
+ mSession.dispose();
+ }
}
/*package*/ BridgeRenderSession(RenderSessionImpl scene, Result lastResult) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
index 01c3c50..5c74caf 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
@@ -184,15 +184,6 @@
}
@Override
- public InputBindResult startInput(
- /* @InputMethodClient.StartInputReason */ int startInputReason,
- IInputMethodClient client, IInputContext inputContext, EditorInfo attribute,
- int controlFlags) throws RemoteException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
public boolean switchToLastInputMethod(IBinder arg0) throws RemoteException {
// TODO Auto-generated method stub
return false;
@@ -228,7 +219,7 @@
}
@Override
- public InputBindResult windowGainedFocus(
+ public InputBindResult startInputOrWindowGainedFocus(
/* @InputMethodClient.StartInputReason */ int startInputReason,
IInputMethodClient client, IBinder windowToken, int controlFlags, int softInputMode,
int windowFlags, EditorInfo attribute, IInputContext inputContext)
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
index fcfbad2..4039cdf 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
@@ -24,7 +24,6 @@
import android.content.IntentSender;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
-import android.content.pm.ContainerEncryptionParams;
import android.content.pm.EphemeralApplicationInfo;
import android.content.pm.FeatureInfo;
import android.content.pm.IPackageDataObserver;
@@ -43,7 +42,6 @@
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
-import android.content.pm.VerificationParams;
import android.content.pm.VerifierDeviceIdentity;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
@@ -486,6 +484,12 @@
}
@Override
+ public Drawable getManagedUserBadgedDrawable(Drawable drawable, Rect badgeLocation,
+ int badgeDensity) {
+ return null;
+ }
+
+ @Override
public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
return null;
}
@@ -555,40 +559,11 @@
}
@Override
- public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
- int flags, String installerPackageName, Uri verificationURI,
- ContainerEncryptionParams encryptionParams) {
- }
-
- @Override
- public void installPackageWithVerificationAndEncryption(Uri packageURI,
- IPackageInstallObserver observer, int flags, String installerPackageName,
- VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
- }
-
- @Override
public void installPackage(Uri packageURI, PackageInstallObserver observer, int flags,
String installerPackageName) {
}
@Override
- public void installPackageAsUser(Uri packageURI, PackageInstallObserver observer,int flags,
- String installerPackageName, int userId) {
- }
-
- @Override
- public void installPackageWithVerification(Uri packageURI, PackageInstallObserver observer,
- int flags, String installerPackageName, Uri verificationURI,
- ContainerEncryptionParams encryptionParams) {
- }
-
- @Override
- public void installPackageWithVerificationAndEncryption(Uri packageURI,
- PackageInstallObserver observer, int flags, String installerPackageName,
- VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
- }
-
- @Override
public int installExistingPackage(String packageName) throws NameNotFoundException {
return 0;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
index 2000fbc..533a10a 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
@@ -50,7 +50,8 @@
@Override
public void resized(Rect rect, Rect rect2, Rect rect3, Rect rect4, Rect rect5, Rect rect6,
- boolean b, Configuration configuration, Rect rect7, boolean b2) throws RemoteException {
+ boolean b, Configuration configuration, Rect rect7, boolean b2, boolean b3)
+ throws RemoteException {
// pass for now.
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index ec50cfe..53f1912 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -60,6 +60,7 @@
import android.graphics.Bitmap;
import android.graphics.Bitmap_Delegate;
import android.graphics.Canvas;
+import android.os.Looper;
import android.preference.Preference_Delegate;
import android.view.AttachInfo_Accessor;
import android.view.BridgeInflater;
@@ -1396,4 +1397,33 @@
public RenderSession getSession() {
return mScene;
}
+
+ public void dispose() {
+ boolean createdLooper = false;
+ if (Looper.myLooper() == null) {
+ // Detaching the root view from the window will try to stop any running animations.
+ // The stop method checks that it can run in the looper so, if there is no current
+ // looper, we create a temporary one to complete the shutdown.
+ Bridge.prepareThread();
+ createdLooper = true;
+ }
+ AttachInfo_Accessor.detachFromWindow(mViewRoot);
+ if (mCanvas != null) {
+ mCanvas.release();
+ mCanvas = null;
+ }
+ if (mViewInfoList != null) {
+ mViewInfoList.clear();
+ }
+ if (mSystemViewInfoList != null) {
+ mSystemViewInfoList.clear();
+ }
+ mImage = null;
+ mViewRoot = null;
+ mContentRoot = null;
+
+ if (createdLooper) {
+ Bridge.cleanupThread();
+ }
+ }
}
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
index fe16a3e..2726042 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
@@ -291,7 +291,6 @@
@Test
public void testActivity() throws ClassNotFoundException {
renderAndVerify("activity.xml", "activity.png");
-
}
/** Test allwidgets.xml */
@@ -336,7 +335,7 @@
.setNavigation(Navigation.NONAV);
SessionParams params = getSessionParams(parser, customConfigGenerator,
- layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false,
+ layoutLibCallback, "Theme.Material.Light.NoActionBar.Fullscreen", false,
RenderingMode.V_SCROLL, 22);
renderAndVerify(params, "expand_vert_layout.png");
@@ -349,7 +348,7 @@
parser = new LayoutPullParser(APP_TEST_RES + "/layout/" +
"expand_horz_layout.xml");
params = getSessionParams(parser, customConfigGenerator,
- layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false,
+ layoutLibCallback, "Theme.Material.Light.NoActionBar.Fullscreen", false,
RenderingMode.H_SCROLL, 22);
renderAndVerify(params, "expand_horz_layout.png");
@@ -431,6 +430,8 @@
ImageUtils.requireSimilar(goldenImagePath, session.getImage());
} catch (IOException e) {
getLogger().error(e, e.getMessage());
+ } finally {
+ session.dispose();
}
}
diff --git a/tools/layoutlib/create/create.iml b/tools/layoutlib/create/create.iml
index b2b14b4..368b46b 100644
--- a/tools/layoutlib/create/create.iml
+++ b/tools/layoutlib/create/create.iml
@@ -22,6 +22,6 @@
</SOURCES>
</library>
</orderEntry>
- <orderEntry type="library" scope="TEST" name="JUnit4" level="application" />
+ <orderEntry type="library" scope="TEST" name="junit" level="project" />
</component>
</module>
\ No newline at end of file
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 9e390f6..8c3bd2f 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -178,6 +178,7 @@
"android.view.Choreographer#scheduleVsyncLocked",
"android.view.Display#updateDisplayInfoLocked",
"android.view.Display#getWindowManager",
+ "android.view.HandlerActionQueue#postDelayed",
"android.view.LayoutInflater#rInflate",
"android.view.LayoutInflater#parseInclude",
"android.view.View#getWindowToken",
@@ -268,6 +269,7 @@
"android.graphics.SweepGradient",
"android.graphics.Typeface",
"android.graphics.Xfermode",
+ "android.graphics.drawable.VectorDrawable",
"android.os.SystemClock",
"android.os.SystemProperties",
"android.text.AndroidBidi",
@@ -320,7 +322,12 @@
"org.kxml2.io.KXmlParser"
};
+ /**
+ * List of fields for which we will update the visibility to be public. This is sometimes
+ * needed when access from the delegate classes is needed.
+ */
private final static String[] PROMOTED_FIELDS = new String[] {
+ "android.graphics.drawable.VectorDrawable#mVectorState",
"android.view.Choreographer#mLastFrameTimeNanos"
};
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/RefactorClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/RefactorClassAdapter.java
index 91161f5..024e32f 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/RefactorClassAdapter.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/RefactorClassAdapter.java
@@ -16,9 +16,11 @@
package com.android.tools.layoutlib.create;
+import java.util.Arrays;
import java.util.HashMap;
import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.MethodVisitor;
public class RefactorClassAdapter extends AbstractClassAdapter {
@@ -30,6 +32,14 @@
}
@Override
+ public MethodVisitor visitMethod(int access, String name, String desc, String signature,
+ String[] exceptions) {
+ MethodVisitor mw = super.visitMethod(access, name, desc, signature, exceptions);
+
+ return new RefactorStackMapAdapter(mw);
+ }
+
+ @Override
protected String renameInternalType(String oldClassName) {
if (oldClassName != null) {
String newName = mRefactorClasses.get(oldClassName);
@@ -46,4 +56,49 @@
}
return oldClassName;
}
+
+ /**
+ * A method visitor that renames all references from an old class name to a new class name in
+ * the stackmap of the method.
+ */
+ private class RefactorStackMapAdapter extends MethodVisitor {
+
+ private RefactorStackMapAdapter(MethodVisitor mv) {
+ super(Main.ASM_VERSION, mv);
+ }
+
+
+ private Object[] renameFrame(Object[] elements) {
+ if (elements == null) {
+ return null;
+ }
+
+ // The input array cannot be modified. We only copy the source array on write
+ boolean copied = false;
+ for (int i = 0; i < elements.length; i++) {
+ if (!(elements[i] instanceof String)) {
+ continue;
+ }
+
+ if (!copied) {
+ elements = Arrays.copyOf(elements, elements.length);
+ copied = true;
+ }
+
+ String type = (String)elements[i];
+ if (type.indexOf(';') > 0) {
+ elements[i] = renameTypeDesc(type);
+ } else {
+ elements[i] = renameInternalType(type);
+ }
+ }
+
+ return elements;
+ }
+
+ @Override
+ public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
+ super.visitFrame(type, nLocal, renameFrame(local), nStack, renameFrame(stack));
+ }
+ }
}
diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java
index 0912fb1..afaa399 100644
--- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java
@@ -53,12 +53,10 @@
private MockLog mLog;
- private static final String NATIVE_CLASS_NAME = ClassWithNative.class.getCanonicalName();
- private static final String OUTER_CLASS_NAME = OuterClass.class.getCanonicalName();
- private static final String INNER_CLASS_NAME = OuterClass.class.getCanonicalName() + "$" +
- InnerClass.class.getSimpleName();
- private static final String STATIC_INNER_CLASS_NAME =
- OuterClass.class.getCanonicalName() + "$" + StaticInnerClass.class.getSimpleName();
+ private static final String NATIVE_CLASS_NAME = ClassWithNative.class.getName();
+ private static final String OUTER_CLASS_NAME = OuterClass.class.getName();
+ private static final String INNER_CLASS_NAME = InnerClass.class.getName();
+ private static final String STATIC_INNER_CLASS_NAME = StaticInnerClass.class.getName();
@Before
public void setUp() throws Exception {
@@ -69,12 +67,12 @@
/**
* Tests that a class not being modified still works.
*/
- @SuppressWarnings("unchecked")
@Test
public void testNoOp() throws Throwable {
// create an instance of the class that will be modified
// (load the class in a distinct class loader so that we can trash its definition later)
ClassLoader cl1 = new ClassLoader(this.getClass().getClassLoader()) { };
+ @SuppressWarnings("unchecked")
Class<ClassWithNative> clazz1 = (Class<ClassWithNative>) cl1.loadClass(NATIVE_CLASS_NAME);
ClassWithNative instance1 = clazz1.newInstance();
assertEquals(42, instance1.add(20, 22));
diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/StubMethodAdapterTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/StubMethodAdapterTest.java
new file mode 100644
index 0000000..3db3e23
--- /dev/null
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/StubMethodAdapterTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.layoutlib.create;
+
+import com.android.tools.layoutlib.create.dataclass.StubClass;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+import java.lang.reflect.Method;
+import java.util.function.BiPredicate;
+import java.util.function.Consumer;
+
+import static org.junit.Assert.*;
+
+public class StubMethodAdapterTest {
+
+ private static final String STUB_CLASS_NAME = StubClass.class.getName();
+
+ /**
+ * Load a dummy class, stub one of its method and ensure that the modified class works as
+ * intended.
+ */
+ @Test
+ public void testBoolean() throws Exception {
+ final String methodName = "returnTrue";
+ // First don't change the method and assert that it returns true
+ testBoolean((name, type) -> false, Assert::assertTrue, methodName);
+ // Change the method now and assert that it returns false.
+ testBoolean((name, type) -> methodName.equals(name) &&
+ Type.BOOLEAN_TYPE.equals(type.getReturnType()), Assert::assertFalse, methodName);
+ }
+
+ /**
+ * @param methodPredicate tests if the method should be replaced
+ */
+ private void testBoolean(BiPredicate<String, Type> methodPredicate, Consumer<Boolean> assertion,
+ String methodName) throws Exception {
+ ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+ // Always rename the class to avoid conflict with the original class.
+ String newClassName = STUB_CLASS_NAME + '_';
+ new ClassReader(STUB_CLASS_NAME).accept(
+ new ClassAdapter(newClassName, writer, methodPredicate), 0);
+ MyClassLoader myClassLoader = new MyClassLoader(newClassName, writer.toByteArray());
+ Class<?> aClass = myClassLoader.loadClass(newClassName);
+ assertTrue("StubClass not loaded by the classloader. Likely a bug in the test.",
+ myClassLoader.findClassCalled);
+ Method method = aClass.getMethod(methodName);
+ Object o = aClass.newInstance();
+ assertion.accept((Boolean) method.invoke(o));
+ }
+
+ private static class ClassAdapter extends ClassVisitor {
+
+ private final String mClassName;
+ private final BiPredicate<String, Type> mMethodPredicate;
+
+ private ClassAdapter(String className, ClassVisitor cv,
+ BiPredicate<String, Type> methodPredicate) {
+ super(Main.ASM_VERSION, cv);
+ mClassName = className.replace('.', '/');
+ mMethodPredicate = methodPredicate;
+ }
+
+ @Override
+ public void visit(int version, int access, String name, String signature, String superName,
+ String[] interfaces) {
+ super.visit(version, access, mClassName, signature, superName,
+ interfaces);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(int access, String name, String desc, String signature,
+ String[] exceptions) {
+ // Copied partly from
+ // com.android.tools.layoutlib.create.DelegateClassAdapter.visitMethod()
+ // but not generating the _Original method.
+ boolean isStatic = (access & Opcodes.ACC_STATIC) != 0;
+ boolean isNative = (access & Opcodes.ACC_NATIVE) != 0;
+ MethodVisitor originalMethod =
+ super.visitMethod(access, name, desc, signature, exceptions);
+ Type descriptor = Type.getMethodType(desc);
+ if (mMethodPredicate.test(name, descriptor)) {
+ String methodSignature = mClassName + "#" + name;
+ String invokeSignature = methodSignature + desc;
+ return new StubMethodAdapter(originalMethod, name, descriptor.getReturnType(),
+ invokeSignature, isStatic, isNative);
+ }
+ return originalMethod;
+ }
+ }
+
+ private static class MyClassLoader extends ClassLoader {
+ private final String mName;
+ private final byte[] mBytes;
+ private boolean findClassCalled;
+
+ private MyClassLoader(String name, byte[] bytes) {
+ mName = name;
+ mBytes = bytes;
+ }
+
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ if (name.equals(mName)) {
+ findClassCalled = true;
+ return defineClass(name, mBytes, 0, mBytes.length);
+ }
+ return super.findClass(name);
+ }
+ }
+}
diff --git a/media/mca/effect/java/android/media/effect/package-info.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/StubClass.java
similarity index 63%
copy from media/mca/effect/java/android/media/effect/package-info.java
copy to tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/StubClass.java
index b2c14ff..3ae8e47 100644
--- a/media/mca/effect/java/android/media/effect/package-info.java
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/StubClass.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,15 +14,17 @@
* limitations under the License.
*/
+package com.android.tools.layoutlib.create.dataclass;
-package android.media.effect;
+import com.android.tools.layoutlib.create.StubMethodAdapterTest;
/**
- * <h1>Effect Framework</h1>
- *
- * This package includes a collection of high-performance visual effects that make use of the
- * mobile filter framework subsystem.
- *
- * TODO: More Documentation
- *
+ * Used by {@link StubMethodAdapterTest}
*/
+@SuppressWarnings("unused")
+public class StubClass {
+
+ public boolean returnTrue() {
+ return true;
+ }
+}
diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java
index 7f1ae24..13abaff 100644
--- a/wifi/java/android/net/wifi/RttManager.java
+++ b/wifi/java/android/net/wifi/RttManager.java
@@ -300,7 +300,7 @@
try {
mRttCapabilities = mService.getRttCapabilities();
} catch (RemoteException e) {
- Log.e(TAG, "Can not get RTT Capabilities");
+ throw e.rethrowFromSystemServer();
}
}
return mRttCapabilities;
@@ -324,6 +324,11 @@
public int requestType;
/**
+ * Whether the secure RTT protocol needs to be used for ranging this peer device.
+ */
+ public boolean secure;
+
+ /**
* mac address of the device being ranged
* Default value: null
*/
@@ -478,6 +483,7 @@
for (RttParams params : mParams) {
dest.writeInt(params.deviceType);
dest.writeInt(params.requestType);
+ dest.writeByte(params.secure ? (byte) 1 : 0);
dest.writeString(params.bssid);
dest.writeInt(params.channelWidth);
dest.writeInt(params.frequency);
@@ -515,6 +521,7 @@
params[i] = new RttParams();
params[i].deviceType = in.readInt();
params[i].requestType = in.readInt();
+ params[i].secure = (in.readByte() != 0);
params[i].bssid = in.readString();
params[i].channelWidth = in.readInt();
params[i].frequency = in.readInt();
@@ -690,6 +697,11 @@
/** LCR information Element, only available to double side RTT. */
public WifiInformationElement LCR;
+
+ /**
+ * Whether the secure RTT protocol was used for ranging.
+ */
+ public boolean secure;
}
@@ -742,6 +754,7 @@
dest.writeInt((byte) result.LCR.data.length);
dest.writeByte(result.LCR.id);
}
+ dest.writeByte(result.secure ? (byte) 1 : 0);
}
} else {
dest.writeInt(0);
@@ -796,6 +809,7 @@
results[i].LCR.data = new byte[length];
in.readByteArray(results[i].LCR.data);
}
+ results[i].secure = (in.readByte() != 0);
}
ParcelableRttResults parcelableResults = new ParcelableRttResults(results);
@@ -1118,7 +1132,7 @@
Log.d(TAG, "Get the messenger from " + mService);
messenger = mService.getMessenger();
} catch (RemoteException e) {
- /* do nothing */
+ throw e.rethrowFromSystemServer();
} catch (SecurityException e) {
/* do nothing */
}
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 31da670..a46aaec 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -160,21 +160,6 @@
}
}
- /** @hide */
- public static final int ENABLED = 0;
- /** @hide */
- public static final int AUTO_ROAM_DISABLED = 16;
- /** @hide */
- public static final int AUTO_JOIN_DISABLED = 32;
- /** @hide */
- public static final int AUTHENTICATION_ERROR = 128;
-
- /**
- * Status: indicating join status
- * @hide
- */
- public int autoJoinStatus;
-
/**
* num IP configuration failures
* @hide
@@ -187,17 +172,6 @@
*/
public long blackListTimestamp;
- /** @hide **/
- public void setAutoJoinStatus(int status) {
- if (status < 0) status = 0;
- if (status == 0) {
- blackListTimestamp = 0;
- } else if (status > autoJoinStatus) {
- blackListTimestamp = System.currentTimeMillis();
- }
- autoJoinStatus = status;
- }
-
/**
* Status: indicating the scan result is not a result
* that is part of user's saved configurations
@@ -331,6 +305,7 @@
*/
public static class InformationElement {
public static final int EID_SSID = 0;
+ public static final int EID_TIM = 5;
public static final int EID_BSS_LOAD = 11;
public static final int EID_RSN = 48;
public static final int EID_HT_OPERATION = 61;
@@ -461,7 +436,6 @@
distanceCm = source.distanceCm;
distanceSdCm = source.distanceSdCm;
seen = source.seen;
- autoJoinStatus = source.autoJoinStatus;
untrusted = source.untrusted;
numConnection = source.numConnection;
numUsage = source.numUsage;
@@ -505,9 +479,6 @@
sb.append(", passpoint: ");
sb.append(((flags & FLAG_PASSPOINT_NETWORK) != 0) ? "yes" : "no");
- if (autoJoinStatus != 0) {
- sb.append(", status: ").append(autoJoinStatus);
- }
sb.append(", ChannelBandwidth: ").append(channelWidth);
sb.append(", centerFreq0: ").append(centerFreq0);
sb.append(", centerFreq1: ").append(centerFreq1);
@@ -543,7 +514,6 @@
dest.writeInt(centerFreq0);
dest.writeInt(centerFreq1);
dest.writeLong(seen);
- dest.writeInt(autoJoinStatus);
dest.writeInt(untrusted ? 1 : 0);
dest.writeInt(numConnection);
dest.writeInt(numUsage);
@@ -614,7 +584,6 @@
);
sr.seen = in.readLong();
- sr.autoJoinStatus = in.readInt();
sr.untrusted = in.readInt() != 0;
sr.numConnection = in.readInt();
sr.numUsage = in.readInt();
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index cce8386..7dc8049 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -403,6 +403,15 @@
/**
* @hide
+ * The number of beacon intervals between Delivery Traffic Indication Maps (DTIM)
+ * This value is populated from scan results that contain Beacon Frames, which are infrequent.
+ * The value is not guaranteed to be set or current (Although it SHOULDNT change once set)
+ * Valid values are from 1 - 255. Initialized here as 0, use this to check if set.
+ */
+ public int dtimInterval = 0;
+
+ /**
+ * @hide
* Uid of app creating the configuration
*/
@SystemApi
@@ -1298,6 +1307,7 @@
lastUpdateUid = -1;
creatorUid = -1;
shared = true;
+ dtimInterval = 0;
}
/**
@@ -1347,6 +1357,7 @@
append(" PROVIDER-NAME: ").append(this.providerFriendlyName).
append(" BSSID: ").append(this.BSSID).append(" FQDN: ").append(this.FQDN)
.append(" PRIO: ").append(this.priority)
+ .append(" HIDDEN: ").append(this.hiddenSSID)
.append('\n');
@@ -2044,4 +2055,4 @@
config.allowedKeyManagement.set(in.readInt());
return config;
}
-}
\ No newline at end of file
+}
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 362738e..58e8761 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -20,6 +20,7 @@
import android.os.Parcelable;
import android.security.Credentials;
import android.text.TextUtils;
+import android.util.Log;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
@@ -116,10 +117,30 @@
public static final String CA_CERT_ALIAS_DELIMITER = " ";
+ // Fields to copy verbatim from wpa_supplicant.
+ private static final String[] SUPPLICANT_CONFIG_KEYS = new String[] {
+ IDENTITY_KEY,
+ ANON_IDENTITY_KEY,
+ PASSWORD_KEY,
+ CLIENT_CERT_KEY,
+ CA_CERT_KEY,
+ SUBJECT_MATCH_KEY,
+ ENGINE_KEY,
+ ENGINE_ID_KEY,
+ PRIVATE_KEY_ID_KEY,
+ ALTSUBJECT_MATCH_KEY,
+ DOM_SUFFIX_MATCH_KEY,
+ CA_PATH_KEY
+ };
+
private HashMap<String, String> mFields = new HashMap<String, String>();
private X509Certificate[] mCaCerts;
private PrivateKey mClientPrivateKey;
private X509Certificate mClientCertificate;
+ private int mEapMethod = Eap.NONE;
+ private int mPhase2Method = Phase2.NONE;
+
+ private static final String TAG = "WifiEnterpriseConfig";
public WifiEnterpriseConfig() {
// Do not set defaults so that the enterprise fields that are not changed
@@ -134,6 +155,8 @@
for (String key : source.mFields.keySet()) {
mFields.put(key, source.mFields.get(key));
}
+ mEapMethod = source.mEapMethod;
+ mPhase2Method = source.mPhase2Method;
}
@Override
@@ -149,6 +172,8 @@
dest.writeString(entry.getValue());
}
+ dest.writeInt(mEapMethod);
+ dest.writeInt(mPhase2Method);
writeCertificates(dest, mCaCerts);
if (mClientPrivateKey != null) {
@@ -200,6 +225,8 @@
enterpriseConfig.mFields.put(key, value);
}
+ enterpriseConfig.mEapMethod = in.readInt();
+ enterpriseConfig.mPhase2Method = in.readInt();
enterpriseConfig.mCaCerts = readCertificates(in);
PrivateKey userKey = null;
@@ -296,7 +323,8 @@
public static final int MSCHAPV2 = 3;
/** Generic Token Card */
public static final int GTC = 4;
- private static final String PREFIX = "auth=";
+ private static final String AUTH_PREFIX = "auth=";
+ private static final String AUTHEAP_PREFIX = "autheap=";
/** @hide */
public static final String[] strings = {EMPTY_VALUE, "PAP", "MSCHAP",
"MSCHAPV2", "GTC" };
@@ -305,11 +333,98 @@
private Phase2() {}
}
- /** Internal use only
+ // Loader and saver interfaces for exchanging data with wpa_supplicant.
+ // TODO: Decouple this object (which is just a placeholder of the configuration)
+ // from the implementation that knows what wpa_supplicant wants.
+ /**
+ * Interface used for retrieving supplicant configuration from WifiEnterpriseConfig
* @hide
*/
- public HashMap<String, String> getFields() {
- return mFields;
+ public interface SupplicantSaver {
+ /**
+ * Set a value within wpa_supplicant configuration
+ * @param key index to set within wpa_supplciant
+ * @param value the value for the key
+ * @return true if successful; false otherwise
+ */
+ boolean saveValue(String key, String value);
+ }
+
+ /**
+ * Interface used for populating a WifiEnterpriseConfig from supplicant configuration
+ * @hide
+ */
+ public interface SupplicantLoader {
+ /**
+ * Returns a value within wpa_supplicant configuration
+ * @param key index to set within wpa_supplciant
+ * @return string value if successful; null otherwise
+ */
+ String loadValue(String key);
+ }
+
+ /**
+ * Internal use only; supply field values to wpa_supplicant config. The configuration
+ * process aborts on the first failed call on {@code saver}.
+ * @param saver proxy for setting configuration in wpa_supplciant
+ * @return whether the save succeeded on all attempts
+ * @hide
+ */
+ public boolean saveToSupplicant(SupplicantSaver saver) {
+ if (!isEapMethodValid()) {
+ return false;
+ }
+
+ for (String key : mFields.keySet()) {
+ if (!saver.saveValue(key, mFields.get(key))) {
+ return false;
+ }
+ }
+
+ if (!saver.saveValue(EAP_KEY, Eap.strings[mEapMethod])) {
+ return false;
+ }
+
+ if (mEapMethod != Eap.TLS && mPhase2Method != Phase2.NONE) {
+ boolean is_autheap = mEapMethod == Eap.TTLS && mPhase2Method == Phase2.GTC;
+ String prefix = is_autheap ? Phase2.AUTHEAP_PREFIX : Phase2.AUTH_PREFIX;
+ String value = convertToQuotedString(prefix + Phase2.strings[mPhase2Method]);
+ return saver.saveValue(PHASE2_KEY, value);
+ } else if (mPhase2Method == Phase2.NONE) {
+ // By default, send a null phase 2 to clear old configuration values.
+ return saver.saveValue(PHASE2_KEY, null);
+ } else {
+ Log.e(TAG, "WiFi enterprise configuration is invalid as it supplies a "
+ + "phase 2 method but the phase1 method does not support it.");
+ return false;
+ }
+ }
+
+ /**
+ * Internal use only; retrieve configuration from wpa_supplicant config.
+ * @param loader proxy for retrieving configuration keys from wpa_supplicant
+ * @hide
+ */
+ public void loadFromSupplicant(SupplicantLoader loader) {
+ for (String key : SUPPLICANT_CONFIG_KEYS) {
+ String value = loader.loadValue(key);
+ if (value == null) {
+ mFields.put(key, EMPTY_VALUE);
+ } else {
+ mFields.put(key, value);
+ }
+ }
+ String eapMethod = loader.loadValue(EAP_KEY);
+ mEapMethod = getStringIndex(Eap.strings, eapMethod, Eap.NONE);
+
+ String phase2Method = removeDoubleQuotes(loader.loadValue(PHASE2_KEY));
+ // Remove "auth=" or "autheap=" prefix.
+ if (phase2Method.startsWith(Phase2.AUTH_PREFIX)) {
+ phase2Method = phase2Method.substring(Phase2.AUTH_PREFIX.length());
+ } else if (phase2Method.startsWith(Phase2.AUTHEAP_PREFIX)) {
+ phase2Method = phase2Method.substring(Phase2.AUTHEAP_PREFIX.length());
+ }
+ mPhase2Method = getStringIndex(Phase2.strings, phase2Method, Phase2.NONE);
}
/**
@@ -330,7 +445,7 @@
case Eap.SIM:
case Eap.AKA:
case Eap.AKA_PRIME:
- mFields.put(EAP_KEY, Eap.strings[eapMethod]);
+ mEapMethod = eapMethod;
mFields.put(OPP_KEY_CACHING, "1");
break;
default:
@@ -343,8 +458,7 @@
* @return eap method configured
*/
public int getEapMethod() {
- String eapMethod = mFields.get(EAP_KEY);
- return getStringIndex(Eap.strings, eapMethod, Eap.NONE);
+ return mEapMethod;
}
/**
@@ -359,15 +473,11 @@
public void setPhase2Method(int phase2Method) {
switch (phase2Method) {
case Phase2.NONE:
- mFields.put(PHASE2_KEY, EMPTY_VALUE);
- break;
- /** Valid methods */
case Phase2.PAP:
case Phase2.MSCHAP:
case Phase2.MSCHAPV2:
case Phase2.GTC:
- mFields.put(PHASE2_KEY, convertToQuotedString(
- Phase2.PREFIX + Phase2.strings[phase2Method]));
+ mPhase2Method = phase2Method;
break;
default:
throw new IllegalArgumentException("Unknown Phase 2 method");
@@ -379,12 +489,7 @@
* @return a phase 2 method defined at {@link Phase2}
* */
public int getPhase2Method() {
- String phase2Method = removeDoubleQuotes(mFields.get(PHASE2_KEY));
- // Remove auth= prefix
- if (phase2Method.startsWith(Phase2.PREFIX)) {
- phase2Method = phase2Method.substring(Phase2.PREFIX.length());
- }
- return getStringIndex(Phase2.strings, phase2Method, Phase2.NONE);
+ return mPhase2Method;
}
/**
@@ -412,7 +517,8 @@
setFieldValue(ANON_IDENTITY_KEY, anonymousIdentity, "");
}
- /** Get the anonymous identity
+ /**
+ * Get the anonymous identity
* @return anonymous identity
*/
public String getAnonymousIdentity() {
@@ -839,18 +945,15 @@
}
/** See {@link WifiConfiguration#getKeyIdForCredentials} @hide */
- String getKeyId(WifiEnterpriseConfig current) {
- String eap = mFields.get(EAP_KEY);
- String phase2 = mFields.get(PHASE2_KEY);
-
- // If either eap or phase2 are not initialized, use current config details
- if (TextUtils.isEmpty((eap))) {
- eap = current.mFields.get(EAP_KEY);
+ public String getKeyId(WifiEnterpriseConfig current) {
+ // If EAP method is not initialized, use current config details
+ if (mEapMethod == Eap.NONE) {
+ return (current != null) ? current.getKeyId(null) : EMPTY_VALUE;
}
- if (TextUtils.isEmpty(phase2)) {
- phase2 = current.mFields.get(PHASE2_KEY);
+ if (!isEapMethodValid()) {
+ return EMPTY_VALUE;
}
- return eap + "_" + phase2;
+ return Eap.strings[mEapMethod] + "_" + Phase2.strings[mPhase2Method];
}
private String removeDoubleQuotes(String string) {
@@ -867,7 +970,8 @@
return "\"" + string + "\"";
}
- /** Returns the index at which the toBeFound string is found in the array.
+ /**
+ * Returns the index at which the toBeFound string is found in the array.
* @param arr array of strings
* @param toBeFound string to be found
* @param defaultIndex default index to be returned when string is not found
@@ -881,13 +985,16 @@
return defaultIndex;
}
- /** Returns the field value for the key.
+ /**
+ * Returns the field value for the key.
* @param key into the hash
* @param prefix is the prefix that the value may have
* @return value
* @hide
*/
public String getFieldValue(String key, String prefix) {
+ // TODO: Should raise an exception if |key| is EAP_KEY or PHASE2_KEY since
+ // neither of these keys should be retrieved in this manner.
String value = mFields.get(key);
// Uninitialized or known to be empty after reading from supplicant
if (TextUtils.isEmpty(value) || EMPTY_VALUE.equals(value)) return "";
@@ -900,13 +1007,16 @@
}
}
- /** Set a value with an optional prefix at key
+ /**
+ * Set a value with an optional prefix at key
* @param key into the hash
* @param value to be set
* @param prefix an optional value to be prefixed to actual value
* @hide
*/
public void setFieldValue(String key, String value, String prefix) {
+ // TODO: Should raise an exception if |key| is EAP_KEY or PHASE2_KEY since
+ // neither of these keys should be set in this manner.
if (TextUtils.isEmpty(value)) {
mFields.put(key, EMPTY_VALUE);
} else {
@@ -915,13 +1025,16 @@
}
- /** Set a value with an optional prefix at key
+ /**
+ * Set a value with an optional prefix at key
* @param key into the hash
* @param value to be set
* @param prefix an optional value to be prefixed to actual value
* @hide
*/
public void setFieldValue(String key, String value) {
+ // TODO: Should raise an exception if |key| is EAP_KEY or PHASE2_KEY since
+ // neither of these keys should be set in this manner.
if (TextUtils.isEmpty(value)) {
mFields.put(key, EMPTY_VALUE);
} else {
@@ -939,4 +1052,25 @@
}
return sb.toString();
}
+
+ /**
+ * Returns whether the EAP method data is valid, i.e., whether mEapMethod and mPhase2Method
+ * are valid indices into {@code Eap.strings[]} and {@code Phase2.strings[]} respectively.
+ */
+ private boolean isEapMethodValid() {
+ if (mEapMethod == Eap.NONE) {
+ Log.e(TAG, "WiFi enterprise configuration is invalid as it supplies no EAP method.");
+ return false;
+ }
+ if (mEapMethod < 0 || mEapMethod >= Eap.strings.length) {
+ Log.e(TAG, "mEapMethod is invald for WiFi enterprise configuration: " + mEapMethod);
+ return false;
+ }
+ if (mPhase2Method < 0 || mPhase2Method >= Phase2.strings.length) {
+ Log.e(TAG, "mPhase2Method is invald for WiFi enterprise configuration: "
+ + mPhase2Method);
+ return false;
+ }
+ return true;
+ }
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 4921073..a5bfd3c 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -39,9 +39,9 @@
import android.util.Log;
import android.util.SparseArray;
-import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.Protocol;
+import com.android.server.net.NetworkPinner;
import java.net.InetAddress;
import java.util.ArrayList;
@@ -678,11 +678,6 @@
private static int sThreadRefCount;
private static HandlerThread sHandlerThread;
- @GuardedBy("sCM")
- // TODO: Introduce refcounting and make this a per-process static callback, instead of a
- // per-WifiManager callback.
- private PinningNetworkCallback mNetworkCallback;
-
/**
* Create a new WifiManager instance.
* Applications will almost always want to use
@@ -723,8 +718,7 @@
try {
return mService.getConfiguredNetworks();
} catch (RemoteException e) {
- Log.w(TAG, "Caught RemoteException trying to get configured networks: " + e);
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -734,7 +728,7 @@
try {
return mService.getPrivilegedConfiguredNetworks();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -744,7 +738,7 @@
try {
return mService.getConnectionStatistics();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -758,7 +752,7 @@
try {
return mService.getMatchingWifiConfig(scanResult);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -818,7 +812,7 @@
try {
return mService.addOrUpdateNetwork(config);
} catch (RemoteException e) {
- return -1;
+ throw e.rethrowFromSystemServer();
}
}
@@ -832,7 +826,7 @@
try {
return mService.addPasspointManagementObject(mo);
} catch (RemoteException e) {
- return -1;
+ throw e.rethrowFromSystemServer();
}
}
@@ -848,7 +842,7 @@
try {
return mService.modifyPasspointManagementObject(fqdn, mos);
} catch (RemoteException e) {
- return -1;
+ throw e.rethrowFromSystemServer();
}
}
@@ -862,6 +856,7 @@
try {
mService.queryPasspointIcon(bssid, fileName);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -875,7 +870,7 @@
try {
return mService.matchProviderWithCurrentNetwork(fqdn);
} catch (RemoteException e) {
- return -1;
+ throw e.rethrowFromSystemServer();
}
}
@@ -889,28 +884,11 @@
try {
mService.deauthenticateNetwork(holdoff, ess);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
/**
- * Sets whether or not the given network is metered from a network policy
- * point of view. A network should be classified as metered when the user is
- * sensitive to heavy data usage on that connection due to monetary costs,
- * data limitations or battery/performance issues. A typical example would
- * be a wifi connection where the user was being charged for usage.
- * @param netId the integer that identifies the network configuration
- * to the supplicant.
- * @param isMetered True to mark the network as metered.
- * @return {@code true} if the operation succeeded.
- * @hide
- */
- @SystemApi
- public boolean setMetered(int netId, boolean isMetered) {
- // TODO(jjoslin): Implement
- return false;
- }
-
- /**
* Remove the specified network from the list of configured networks.
* This may result in the asynchronous delivery of state change
* events.
@@ -922,7 +900,7 @@
try {
return mService.removeNetwork(netId);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -955,18 +933,22 @@
public boolean enableNetwork(int netId, boolean disableOthers) {
final boolean pin = disableOthers && mTargetSdkVersion < Build.VERSION_CODES.LOLLIPOP;
if (pin) {
- registerPinningNetworkCallback();
+ NetworkRequest request = new NetworkRequest.Builder()
+ .clearCapabilities()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .build();
+ NetworkPinner.pin(mContext, request);
}
boolean success;
try {
success = mService.enableNetwork(netId, disableOthers);
} catch (RemoteException e) {
- success = false;
+ throw e.rethrowFromSystemServer();
}
if (pin && !success) {
- unregisterPinningNetworkCallback();
+ NetworkPinner.unpin();
}
return success;
@@ -983,7 +965,7 @@
try {
return mService.disableNetwork(netId);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -997,7 +979,7 @@
mService.disconnect();
return true;
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1012,7 +994,7 @@
mService.reconnect();
return true;
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1027,7 +1009,7 @@
mService.reassociate();
return true;
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1042,7 +1024,7 @@
try {
return mService.pingSupplicant();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1090,7 +1072,7 @@
try {
return mService.getSupportedFeatures();
} catch (RemoteException e) {
- return 0;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1216,9 +1198,8 @@
return mService.reportActivityInfo();
}
} catch (RemoteException e) {
- Log.e(TAG, "getControllerActivityEnergyInfo: " + e);
+ throw e.rethrowFromSystemServer();
}
- return null;
}
/**
@@ -1232,7 +1213,7 @@
mService.startScan(null, null);
return true;
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1243,7 +1224,7 @@
mService.startScan(null, workSource);
return true;
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1299,7 +1280,7 @@
try {
return mService.getWpsNfcConfigurationToken(netId);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1311,7 +1292,7 @@
try {
return mService.getConnectionInfo();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1328,7 +1309,7 @@
try {
return mService.getScanResults(mContext.getOpPackageName());
} catch (RemoteException e) {
- return new ArrayList<ScanResult>();
+ throw e.rethrowFromSystemServer();
}
}
@@ -1344,7 +1325,7 @@
try {
return mService.isScanAlwaysAvailable();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1361,7 +1342,7 @@
try {
return mService.saveConfiguration();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1375,7 +1356,9 @@
public void setCountryCode(String country, boolean persist) {
try {
mService.setCountryCode(country, persist);
- } catch (RemoteException e) { }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -1387,9 +1370,9 @@
public String getCountryCode() {
try {
String country = mService.getCountryCode();
- return(country);
+ return country;
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1405,7 +1388,9 @@
public void setFrequencyBand(int band, boolean persist) {
try {
mService.setFrequencyBand(band, persist);
- } catch (RemoteException e) { }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -1421,7 +1406,7 @@
try {
return mService.getFrequencyBand();
} catch (RemoteException e) {
- return -1;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1434,7 +1419,7 @@
try {
return mService.isDualBandSupported();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1447,7 +1432,7 @@
try {
return mService.getDhcpInfo();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1461,7 +1446,7 @@
try {
return mService.setWifiEnabled(enabled);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1476,7 +1461,7 @@
try {
return mService.getWifiEnabledState();
} catch (RemoteException e) {
- return WIFI_STATE_UNKNOWN;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1553,7 +1538,7 @@
mService.setWifiApEnabled(wifiConfig, enabled);
return true;
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1571,7 +1556,7 @@
try {
return mService.getWifiApEnabledState();
} catch (RemoteException e) {
- return WIFI_AP_STATE_FAILED;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1598,7 +1583,7 @@
try {
return mService.getWifiApConfiguration();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1612,8 +1597,7 @@
try {
return mService.buildWifiConfig(uriString, mimeType, data);
} catch (RemoteException e) {
- Log.w(TAG, "Caught RemoteException trying to build wifi config: " + e);
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1629,7 +1613,7 @@
mService.setWifiApConfiguration(wifiConfig);
return true;
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1646,7 +1630,7 @@
mService.addToBlacklist(bssid);
return true;
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1663,7 +1647,7 @@
mService.clearBlacklist();
return true;
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1692,7 +1676,7 @@
try {
mService.enableTdls(remoteIPAddress.getHostAddress(), enable);
} catch (RemoteException e) {
- // Just ignore the exception
+ throw e.rethrowFromSystemServer();
}
}
@@ -1706,7 +1690,7 @@
try {
mService.enableTdlsWithMacAddress(remoteMacAddress, enable);
} catch (RemoteException e) {
- // Just ignore the exception
+ throw e.rethrowFromSystemServer();
}
}
@@ -2012,100 +1996,6 @@
"No permission to access and change wifi or a bad initialization");
}
- private void initConnectivityManager() {
- // TODO: what happens if an app calls a WifiManager API before ConnectivityManager is
- // registered? Can we fix this by starting ConnectivityService before WifiService?
- if (sCM == null) {
- sCM = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
- if (sCM == null) {
- throw new IllegalStateException("Bad luck, ConnectivityService not started.");
- }
- }
- }
-
- /**
- * A NetworkCallback that pins the process to the first wifi network to connect.
- *
- * We use this to maintain compatibility with pre-M apps that call WifiManager.enableNetwork()
- * to connect to a Wi-Fi network that has no Internet access, and then assume that they will be
- * able to use that network because it's the system default.
- *
- * In order to maintain compatibility with apps that call setProcessDefaultNetwork themselves,
- * we try not to set the default network unless they have already done so, and we try not to
- * clear the default network unless we set it ourselves.
- *
- * This should maintain behaviour that's compatible with L, which would pin the whole system to
- * any wifi network that was created via enableNetwork(..., true) until that network
- * disconnected.
- *
- * Note that while this hack allows network traffic to flow, it is quite limited. For example:
- *
- * 1. setProcessDefaultNetwork only affects this process, so:
- * - Any subprocesses spawned by this process will not be pinned to Wi-Fi.
- * - If this app relies on any other apps on the device also being on Wi-Fi, that won't work
- * either, because other apps on the device will not be pinned.
- * 2. The behaviour of other APIs is not modified. For example:
- * - getActiveNetworkInfo will return the system default network, not Wi-Fi.
- * - There will be no CONNECTIVITY_ACTION broadcasts about TYPE_WIFI.
- * - getProcessDefaultNetwork will not return null, so if any apps are relying on that, they
- * will be surprised as well.
- */
- private class PinningNetworkCallback extends NetworkCallback {
- private Network mPinnedNetwork;
-
- @Override
- public void onPreCheck(Network network) {
- if (sCM.getProcessDefaultNetwork() == null && mPinnedNetwork == null) {
- sCM.setProcessDefaultNetwork(network);
- mPinnedNetwork = network;
- Log.d(TAG, "Wifi alternate reality enabled on network " + network);
- }
- }
-
- @Override
- public void onLost(Network network) {
- if (network.equals(mPinnedNetwork) && network.equals(sCM.getProcessDefaultNetwork())) {
- sCM.setProcessDefaultNetwork(null);
- Log.d(TAG, "Wifi alternate reality disabled on network " + network);
- mPinnedNetwork = null;
- unregisterPinningNetworkCallback();
- }
- }
- }
-
- private void registerPinningNetworkCallback() {
- initConnectivityManager();
- synchronized (sCM) {
- if (mNetworkCallback == null) {
- // TODO: clear all capabilities.
- NetworkRequest request = new NetworkRequest.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
- .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build();
- mNetworkCallback = new PinningNetworkCallback();
- try {
- sCM.registerNetworkCallback(request, mNetworkCallback);
- } catch (SecurityException e) {
- Log.d(TAG, "Failed to register network callback", e);
- }
- }
- }
- }
-
- private void unregisterPinningNetworkCallback() {
- initConnectivityManager();
- synchronized (sCM) {
- if (mNetworkCallback != null) {
- try {
- sCM.unregisterNetworkCallback(mNetworkCallback);
- } catch (SecurityException e) {
- Log.d(TAG, "Failed to unregister network callback", e);
- }
- mNetworkCallback = null;
- }
- }
- }
-
/**
* Connect to a network with the given configuration. The network also
* gets added to the supplicant configuration.
@@ -2219,6 +2109,7 @@
try {
mService.disableEphemeralNetwork(SSID);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2259,7 +2150,7 @@
try {
return mService.getWifiServiceMessenger();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
} catch (SecurityException e) {
return null;
}
@@ -2274,7 +2165,7 @@
try {
return mService.getConfigFile();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2340,7 +2231,8 @@
}
mActiveLockCount++;
}
- } catch (RemoteException ignore) {
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
mHeld = true;
}
@@ -2367,7 +2259,8 @@
synchronized (WifiManager.this) {
mActiveLockCount--;
}
- } catch (RemoteException ignore) {
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
mHeld = false;
}
@@ -2427,6 +2320,7 @@
try {
mService.updateWifiLockWorkSource(mBinder, mWorkSource);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2456,7 +2350,8 @@
synchronized (WifiManager.this) {
mActiveLockCount--;
}
- } catch (RemoteException ignore) {
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2572,7 +2467,8 @@
}
mActiveLockCount++;
}
- } catch (RemoteException ignore) {
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
mHeld = true;
}
@@ -2611,7 +2507,8 @@
synchronized (WifiManager.this) {
mActiveLockCount--;
}
- } catch (RemoteException ignore) {
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
mHeld = false;
}
@@ -2685,7 +2582,7 @@
try {
return mService.isMulticastEnabled();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2698,7 +2595,7 @@
mService.initializeMulticastFiltering();
return true;
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2736,7 +2633,7 @@
try {
return mService.getVerboseLoggingLevel();
} catch (RemoteException e) {
- return 0;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2748,7 +2645,7 @@
try {
mService.enableAggressiveHandover(enabled);
} catch (RemoteException e) {
-
+ throw e.rethrowFromSystemServer();
}
}
@@ -2761,7 +2658,7 @@
try {
return mService.getAggressiveHandover();
} catch (RemoteException e) {
- return 0;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2773,7 +2670,7 @@
try {
mService.setAllowScansWithTraffic(enabled);
} catch (RemoteException e) {
-
+ throw e.rethrowFromSystemServer();
}
}
@@ -2785,7 +2682,7 @@
try {
return mService.getAllowScansWithTraffic();
} catch (RemoteException e) {
- return 0;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2798,6 +2695,7 @@
try {
mService.factoryReset();
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2810,7 +2708,7 @@
try {
return mService.getCurrentNetwork();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2824,7 +2722,7 @@
try {
return mService.enableAutoJoinWhenAssociated(enabled);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2836,7 +2734,7 @@
try {
return mService.getEnableAutoJoinWhenAssociated();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
/**
@@ -2847,7 +2745,7 @@
try {
mService.setHalBasedAutojoinOffload(enabled);
} catch (RemoteException e) {
-
+ throw e.rethrowFromSystemServer();
}
}
@@ -2859,7 +2757,7 @@
try {
return mService.getHalBasedAutojoinOffload();
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return 0;
}
}
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 2373754..97dd985 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -30,7 +30,9 @@
import android.util.Log;
import android.util.SparseArray;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.Preconditions;
import com.android.internal.util.Protocol;
import java.util.List;
@@ -78,6 +80,8 @@
public static final int REASON_INVALID_REQUEST = -3;
/** Invalid request */
public static final int REASON_NOT_AUTHORIZED = -4;
+ /** An outstanding request with the same listener hasn't finished yet. */
+ public static final int REASON_DUPLICATE_REQEUST = -5;
/** @hide */
public static final String GET_AVAILABLE_CHANNELS_EXTRA = "Channels";
@@ -188,6 +192,11 @@
* for a given period
*/
public int stepCount;
+ /**
+ * Flag to indicate if the scan settings are targeted for PNO scan.
+ * {@hide}
+ */
+ public boolean isPnoScan;
/** Implement the Parcelable interface {@hide} */
public int describeContents() {
@@ -203,6 +212,7 @@
dest.writeInt(maxScansToCache);
dest.writeInt(maxPeriodInMs);
dest.writeInt(stepCount);
+ dest.writeInt(isPnoScan ? 1 : 0);
if (channels != null) {
dest.writeInt(channels.length);
@@ -230,6 +240,7 @@
settings.maxScansToCache = in.readInt();
settings.maxPeriodInMs = in.readInt();
settings.stepCount = in.readInt();
+ settings.isPnoScan = in.readInt() == 1;
int num_channels = in.readInt();
settings.channels = new ChannelSpec[num_channels];
for (int i = 0; i < num_channels; i++) {
@@ -432,6 +443,158 @@
};
}
+ /** {@hide} */
+ public static final String PNO_PARAMS_PNO_SETTINGS_KEY = "PnoSettings";
+ /** {@hide} */
+ public static final String PNO_PARAMS_SCAN_SETTINGS_KEY = "ScanSettings";
+ /**
+ * PNO scan configuration parameters to be sent to {@link #startPnoScan}.
+ * Note: This structure needs to be in sync with |wifi_epno_params| struct in gscan HAL API.
+ * {@hide}
+ */
+ public static class PnoSettings implements Parcelable {
+ /**
+ * Pno network to be added to the PNO scan filtering.
+ * {@hide}
+ */
+ public static class PnoNetwork {
+ /*
+ * Pno flags bitmask to be set in {@link #PnoNetwork.flags}
+ */
+ /** Whether directed scan needs to be performed (for hidden SSIDs) */
+ public static final byte FLAG_DIRECTED_SCAN = (1 << 0);
+ /** Whether PNO event shall be triggered if the network is found on A band */
+ public static final byte FLAG_A_BAND = (1 << 1);
+ /** Whether PNO event shall be triggered if the network is found on G band */
+ public static final byte FLAG_G_BAND = (1 << 2);
+ /**
+ * Whether strict matching is required
+ * If required then the firmware must store the network's SSID and not just a hash
+ */
+ public static final byte FLAG_STRICT_MATCH = (1 << 3);
+ /**
+ * If this SSID should be considered the same network as the currently connected
+ * one for scoring.
+ */
+ public static final byte FLAG_SAME_NETWORK = (1 << 4);
+
+ /*
+ * Code for matching the beacon AUTH IE - additional codes. Bitmask to be set in
+ * {@link #PnoNetwork.authBitField}
+ */
+ /** Open Network */
+ public static final byte AUTH_CODE_OPEN = (1 << 0);
+ /** WPA_PSK or WPA2PSK */
+ public static final byte AUTH_CODE_PSK = (1 << 1);
+ /** any EAPOL */
+ public static final byte AUTH_CODE_EAPOL = (1 << 2);
+
+ /** SSID of the network */
+ public String ssid;
+ /** Network ID in wpa_supplicant */
+ public int networkId;
+ /** Assigned priority for the network */
+ public int priority;
+ /** Bitmask of the FLAG_XXX */
+ public byte flags;
+ /** Bitmask of the ATUH_XXX */
+ public byte authBitField;
+
+ /**
+ * default constructor for PnoNetwork
+ */
+ public PnoNetwork(String ssid) {
+ this.ssid = ssid;
+ flags = 0;
+ authBitField = 0;
+ }
+ }
+
+ /** Connected vs Disconnected PNO flag {@hide} */
+ public boolean isConnected;
+ /** Minimum 5GHz RSSI for a BSSID to be considered */
+ public int min5GHzRssi;
+ /** Minimum 2.4GHz RSSI for a BSSID to be considered */
+ public int min24GHzRssi;
+ /** Maximum score that a network can have before bonuses */
+ public int initialScoreMax;
+ /**
+ * Only report when there is a network's score this much higher
+ * than the current connection.
+ */
+ public int currentConnectionBonus;
+ /** score bonus for all networks with the same network flag */
+ public int sameNetworkBonus;
+ /** score bonus for networks that are not open */
+ public int secureBonus;
+ /** 5GHz RSSI score bonus (applied to all 5GHz networks) */
+ public int band5GHzBonus;
+ /** Pno Network filter list */
+ public PnoNetwork[] networkList;
+
+ /** Implement the Parcelable interface {@hide} */
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(isConnected ? 1 : 0);
+ dest.writeInt(min5GHzRssi);
+ dest.writeInt(min24GHzRssi);
+ dest.writeInt(initialScoreMax);
+ dest.writeInt(currentConnectionBonus);
+ dest.writeInt(sameNetworkBonus);
+ dest.writeInt(secureBonus);
+ dest.writeInt(band5GHzBonus);
+ if (networkList != null) {
+ dest.writeInt(networkList.length);
+ for (int i = 0; i < networkList.length; i++) {
+ dest.writeString(networkList[i].ssid);
+ dest.writeInt(networkList[i].networkId);
+ dest.writeInt(networkList[i].priority);
+ dest.writeByte(networkList[i].flags);
+ dest.writeByte(networkList[i].authBitField);
+ }
+ } else {
+ dest.writeInt(0);
+ }
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public static final Creator<PnoSettings> CREATOR =
+ new Creator<PnoSettings>() {
+ public PnoSettings createFromParcel(Parcel in) {
+ PnoSettings settings = new PnoSettings();
+ settings.isConnected = in.readInt() == 1;
+ settings.min5GHzRssi = in.readInt();
+ settings.min24GHzRssi = in.readInt();
+ settings.initialScoreMax = in.readInt();
+ settings.currentConnectionBonus = in.readInt();
+ settings.sameNetworkBonus = in.readInt();
+ settings.secureBonus = in.readInt();
+ settings.band5GHzBonus = in.readInt();
+ int numNetworks = in.readInt();
+ settings.networkList = new PnoNetwork[numNetworks];
+ for (int i = 0; i < numNetworks; i++) {
+ String ssid = in.readString();
+ PnoNetwork network = new PnoNetwork(ssid);
+ network.networkId = in.readInt();
+ network.priority = in.readInt();
+ network.flags = in.readByte();
+ network.authBitField = in.readByte();
+ settings.networkList[i] = network;
+ }
+ return settings;
+ }
+
+ public PnoSettings[] newArray(int size) {
+ return new PnoSettings[size];
+ }
+ };
+
+ }
+
/**
* interface to get scan events on; specify this on {@link #startBackgroundScan} or
* {@link #startScan}
@@ -452,6 +615,18 @@
public void onFullResult(ScanResult fullScanResult);
}
+ /**
+ * interface to get PNO scan events on; specify this on {@link #startDisconnectedPnoScan} and
+ * {@link #startConnectedPnoScan}.
+ * {@hide}
+ */
+ public interface PnoScanListener extends ScanListener {
+ /**
+ * Invoked when one of the PNO networks are found in scan results.
+ */
+ void onPnoNetworkFound(ScanResult[] results);
+ }
+
/** start wifi scan in background
* @param settings specifies various parameters for the scan; for more information look at
* {@link ScanSettings}
@@ -460,8 +635,11 @@
* scans should also not share this object.
*/
public void startBackgroundScan(ScanSettings settings, ScanListener listener) {
+ Preconditions.checkNotNull(listener, "listener cannot be null");
+ int key = addListener(listener);
+ if (key == INVALID_KEY) return;
validateChannel();
- sAsyncChannel.sendMessage(CMD_START_BACKGROUND_SCAN, 0, putListener(listener), settings);
+ sAsyncChannel.sendMessage(CMD_START_BACKGROUND_SCAN, 0, key, settings);
}
/**
* stop an ongoing wifi scan
@@ -469,8 +647,11 @@
* #startBackgroundScan}
*/
public void stopBackgroundScan(ScanListener listener) {
+ Preconditions.checkNotNull(listener, "listener cannot be null");
+ int key = removeListener(listener);
+ if (key == INVALID_KEY) return;
validateChannel();
- sAsyncChannel.sendMessage(CMD_STOP_BACKGROUND_SCAN, 0, removeListener(listener));
+ sAsyncChannel.sendMessage(CMD_STOP_BACKGROUND_SCAN, 0, key);
}
/**
* reports currently available scan results on appropriate listeners
@@ -491,8 +672,11 @@
* scans should also not share this object.
*/
public void startScan(ScanSettings settings, ScanListener listener) {
+ Preconditions.checkNotNull(listener, "listener cannot be null");
+ int key = addListener(listener);
+ if (key == INVALID_KEY) return;
validateChannel();
- sAsyncChannel.sendMessage(CMD_START_SINGLE_SCAN, 0, putListener(listener), settings);
+ sAsyncChannel.sendMessage(CMD_START_SINGLE_SCAN, 0, key, settings);
}
/**
@@ -501,8 +685,80 @@
* @param listener
*/
public void stopScan(ScanListener listener) {
+ Preconditions.checkNotNull(listener, "listener cannot be null");
+ int key = removeListener(listener);
+ if (key == INVALID_KEY) return;
validateChannel();
- sAsyncChannel.sendMessage(CMD_STOP_SINGLE_SCAN, 0, removeListener(listener));
+ sAsyncChannel.sendMessage(CMD_STOP_SINGLE_SCAN, 0, key);
+ }
+
+ private void startPnoScan(ScanSettings scanSettings, PnoSettings pnoSettings, int key) {
+ // Bundle up both the settings and send it across.
+ Bundle pnoParams = new Bundle();
+ if (pnoParams == null) return;
+ // Set the PNO scan flag.
+ scanSettings.isPnoScan = true;
+ pnoParams.putParcelable(PNO_PARAMS_SCAN_SETTINGS_KEY, scanSettings);
+ pnoParams.putParcelable(PNO_PARAMS_PNO_SETTINGS_KEY, pnoSettings);
+ sAsyncChannel.sendMessage(CMD_START_PNO_SCAN, 0, key, pnoParams);
+ }
+ /**
+ * Start wifi connected PNO scan
+ * @param scanSettings specifies various parameters for the scan; for more information look at
+ * {@link ScanSettings}
+ * @param pnoSettings specifies various parameters for PNO; for more information look at
+ * {@link PnoSettings}
+ * @param listener specifies the object to report events to. This object is also treated as a
+ * key for this scan, and must also be specified to cancel the scan. Multiple
+ * scans should also not share this object.
+ * {@hide}
+ */
+ public void startConnectedPnoScan(ScanSettings scanSettings, PnoSettings pnoSettings,
+ PnoScanListener listener) {
+ Preconditions.checkNotNull(listener, "listener cannot be null");
+ Preconditions.checkNotNull(pnoSettings, "pnoSettings cannot be null");
+ int key = addListener(listener);
+ if (key == INVALID_KEY) return;
+ validateChannel();
+ pnoSettings.isConnected = true;
+ startPnoScan(scanSettings, pnoSettings, key);
+ }
+ /**
+ * Start wifi disconnected PNO scan
+ * @param scanSettings specifies various parameters for the scan; for more information look at
+ * {@link ScanSettings}
+ * @param pnoSettings specifies various parameters for PNO; for more information look at
+ * {@link PnoSettings}
+ * @param listener specifies the object to report events to. This object is also treated as a
+ * key for this scan, and must also be specified to cancel the scan. Multiple
+ * scans should also not share this object.
+ * {@hide}
+ */
+ public void startDisconnectedPnoScan(ScanSettings scanSettings, PnoSettings pnoSettings,
+ PnoScanListener listener) {
+ Preconditions.checkNotNull(listener, "listener cannot be null");
+ Preconditions.checkNotNull(pnoSettings, "pnoSettings cannot be null");
+ int key = addListener(listener);
+ if (key == INVALID_KEY) return;
+ validateChannel();
+ pnoSettings.isConnected = false;
+ startPnoScan(scanSettings, pnoSettings, key);
+ }
+ /**
+ * Stop an ongoing wifi PNO scan
+ * @param pnoSettings specifies various parameters for PNO; for more information look at
+ * {@link PnoSettings}
+ * @param listener specifies which scan to cancel; must be same object as passed in {@link
+ * #startPnoScan}
+ * TODO(rpius): Check if we can remove pnoSettings param in stop.
+ * {@hide}
+ */
+ public void stopPnoScan(PnoSettings pnoSettings, ScanListener listener) {
+ Preconditions.checkNotNull(listener, "listener cannot be null");
+ int key = removeListener(listener);
+ if (key == INVALID_KEY) return;
+ validateChannel();
+ sAsyncChannel.sendMessage(CMD_STOP_PNO_SCAN, 0, key, pnoSettings);
}
/** specifies information about an access point of interest */
@@ -634,8 +890,11 @@
* provided on {@link #stopTrackingWifiChange}
*/
public void startTrackingWifiChange(WifiChangeListener listener) {
+ Preconditions.checkNotNull(listener, "listener cannot be null");
+ int key = addListener(listener);
+ if (key == INVALID_KEY) return;
validateChannel();
- sAsyncChannel.sendMessage(CMD_START_TRACKING_CHANGE, 0, putListener(listener));
+ sAsyncChannel.sendMessage(CMD_START_TRACKING_CHANGE, 0, key);
}
/**
@@ -644,8 +903,10 @@
* #stopTrackingWifiChange}
*/
public void stopTrackingWifiChange(WifiChangeListener listener) {
+ int key = removeListener(listener);
+ if (key == INVALID_KEY) return;
validateChannel();
- sAsyncChannel.sendMessage(CMD_STOP_TRACKING_CHANGE, 0, removeListener(listener));
+ sAsyncChannel.sendMessage(CMD_STOP_TRACKING_CHANGE, 0, key);
}
/** @hide */
@@ -730,11 +991,14 @@
*/
public void startTrackingBssids(BssidInfo[] bssidInfos,
int apLostThreshold, BssidListener listener) {
+ Preconditions.checkNotNull(listener, "listener cannot be null");
+ int key = addListener(listener);
+ if (key == INVALID_KEY) return;
validateChannel();
HotlistSettings settings = new HotlistSettings();
settings.bssidInfos = bssidInfos;
settings.apLostThreshold = apLostThreshold;
- sAsyncChannel.sendMessage(CMD_SET_HOTLIST, 0, putListener(listener), settings);
+ sAsyncChannel.sendMessage(CMD_SET_HOTLIST, 0, key, settings);
}
/**
@@ -742,8 +1006,11 @@
* @param listener same object provided in {@link #startTrackingBssids}
*/
public void stopTrackingBssids(BssidListener listener) {
+ Preconditions.checkNotNull(listener, "listener cannot be null");
+ int key = removeListener(listener);
+ if (key == INVALID_KEY) return;
validateChannel();
- sAsyncChannel.sendMessage(CMD_RESET_HOTLIST, 0, removeListener(listener));
+ sAsyncChannel.sendMessage(CMD_RESET_HOTLIST, 0, key);
}
@@ -797,6 +1064,12 @@
public static final int CMD_STOP_SINGLE_SCAN = BASE + 22;
/** @hide */
public static final int CMD_SINGLE_SCAN_COMPLETED = BASE + 23;
+ /** @hide */
+ public static final int CMD_START_PNO_SCAN = BASE + 24;
+ /** @hide */
+ public static final int CMD_STOP_PNO_SCAN = BASE + 25;
+ /** @hide */
+ public static final int CMD_PNO_NETWORK_FOUND = BASE + 26;
private Context mContext;
private IWifiScanner mService;
@@ -812,7 +1085,7 @@
private static final Object sThreadRefLock = new Object();
private static int sThreadRefCount;
- private static HandlerThread sHandlerThread;
+ private static Handler sInternalHandler;
/**
* Create a new WifiScanner instance.
@@ -824,12 +1097,29 @@
* @hide
*/
public WifiScanner(Context context, IWifiScanner service) {
- mContext = context;
- mService = service;
- init();
+ this(context, service, null, true);
}
- private void init() {
+ /**
+ * Create a new WifiScanner instance.
+ *
+ * @param context The application context.
+ * @param service The IWifiScanner Binder interface
+ * @param looper Looper for running WifiScanner operations. If null, a handler thread will be
+ * created for running WifiScanner operations.
+ * @param waitForConnection If true, this will not return until a connection to Wifi Scanner
+ * service is established.
+ * @hide
+ */
+ @VisibleForTesting
+ public WifiScanner(Context context, IWifiScanner service, Looper looper,
+ boolean waitForConnection) {
+ mContext = context;
+ mService = service;
+ init(looper, waitForConnection);
+ }
+
+ private void init(Looper looper, boolean waitForConnection) {
synchronized (sThreadRefLock) {
if (++sThreadRefCount == 1) {
Messenger messenger = null;
@@ -846,17 +1136,23 @@
return;
}
- sHandlerThread = new HandlerThread("WifiScanner");
sAsyncChannel = new AsyncChannel();
sConnected = new CountDownLatch(1);
- sHandlerThread.start();
- Handler handler = new ServiceHandler(sHandlerThread.getLooper());
- sAsyncChannel.connect(mContext, handler, messenger);
- try {
- sConnected.await();
- } catch (InterruptedException e) {
- Log.e(TAG, "interrupted wait at init");
+ if (looper == null) {
+ HandlerThread thread = new HandlerThread("WifiScanner");
+ thread.start();
+ sInternalHandler = new ServiceHandler(thread.getLooper());
+ } else {
+ sInternalHandler = new ServiceHandler(looper);
+ }
+ sAsyncChannel.connect(mContext, sInternalHandler, messenger);
+ if (waitForConnection) {
+ try {
+ sConnected.await();
+ } catch (InterruptedException e) {
+ Log.e(TAG, "interrupted wait at init");
+ }
}
}
}
@@ -867,6 +1163,30 @@
"No permission to access and change wifi or a bad initialization");
}
+ // Add a listener into listener map. If the listener already exists, return INVALID_KEY and
+ // send an error message to internal handler; Otherwise add the listener to the listener map and
+ // return the key of the listener.
+ private int addListener(ActionListener listener) {
+ synchronized (sListenerMap) {
+ boolean keyExists = (getListenerKey(listener) != INVALID_KEY);
+ // Note we need to put the listener into listener map even if it's a duplicate as the
+ // internal handler will need the key to find the listener. In case of duplicates,
+ // removing duplicate key logic will be handled in internal handler.
+ int key = putListener(listener);
+ if (keyExists) {
+ if (DBG) Log.d(TAG, "listener key already exists");
+ OperationResult operationResult = new OperationResult(REASON_DUPLICATE_REQEUST,
+ "Outstanding request with same key not stopped yet");
+ Message message = Message.obtain(sInternalHandler, CMD_OP_FAILED, 0, key,
+ operationResult);
+ message.sendToTarget();
+ return INVALID_KEY;
+ } else {
+ return key;
+ }
+ }
+ }
+
private static int putListener(Object listener) {
if (listener == null) return INVALID_KEY;
int key;
@@ -910,7 +1230,10 @@
private static int removeListener(Object listener) {
int key = getListenerKey(listener);
- if (key == INVALID_KEY) return key;
+ if (key == INVALID_KEY) {
+ Log.e(TAG, "listener cannot be found");
+ return key;
+ }
synchronized (sListenerMapLock) {
sListenerMap.remove(key);
return key;
@@ -1033,6 +1356,10 @@
if (DBG) Log.d(TAG, "removing listener for single scan");
removeListener(msg.arg2);
break;
+ case CMD_PNO_NETWORK_FOUND:
+ ((PnoScanListener) listener).onPnoNetworkFound(
+ ((ParcelableScanResults) msg.obj).getResults());
+ return;
default:
if (DBG) Log.d(TAG, "Ignoring message " + msg.what);
return;
diff --git a/wifi/java/android/net/wifi/WifiWakeReasonAndCounts.java b/wifi/java/android/net/wifi/WifiWakeReasonAndCounts.java
index 17cc29f..f5cad13 100644
--- a/wifi/java/android/net/wifi/WifiWakeReasonAndCounts.java
+++ b/wifi/java/android/net/wifi/WifiWakeReasonAndCounts.java
@@ -16,8 +16,8 @@
package android.net.wifi;
-import android.os.Parcelable;
import android.os.Parcel;
+import android.os.Parcelable;
/**
* A class representing wifi wake reason accounting.
@@ -52,6 +52,8 @@
public int ipv4RxMulticast;
public int ipv6Multicast;
public int otherRxMulticast;
+ public int[] cmdEventWakeCntArray;
+ public int[] driverFWLocalWakeCntArray;
/* {@hide} */
public WifiWakeReasonAndCounts () {
@@ -78,6 +80,13 @@
sb.append(" ipv4RxMulticast ").append(ipv4RxMulticast);
sb.append(" ipv6Multicast ").append(ipv6Multicast);
sb.append(" otherRxMulticast ").append(otherRxMulticast);
+ for (int i = 0; i < cmdEventWakeCntArray.length; i++) {
+ sb.append(" cmdEventWakeCntArray[" + i + "] " + cmdEventWakeCntArray[i]);
+ }
+ for (int i = 0; i < driverFWLocalWakeCntArray.length; i++) {
+ sb.append(" driverFWLocalWakeCntArray[" + i + "] " + driverFWLocalWakeCntArray[i]);
+ }
+
return sb.toString();
}
@@ -111,6 +120,8 @@
dest.writeInt(ipv4RxMulticast);
dest.writeInt(ipv6Multicast);
dest.writeInt(otherRxMulticast);
+ dest.writeIntArray(cmdEventWakeCntArray);
+ dest.writeIntArray(driverFWLocalWakeCntArray);
}
/* Implement the Parcelable interface
@@ -137,6 +148,8 @@
counts.ipv4RxMulticast = in.readInt();
counts.ipv6Multicast = in.readInt();
counts.otherRxMulticast = in.readInt();
+ in.readIntArray(counts.cmdEventWakeCntArray);
+ in.readIntArray(counts.driverFWLocalWakeCntArray);
return counts;
}
/* Implement the Parcelable interface
diff --git a/wifi/java/android/net/wifi/nan/WifiNanManager.java b/wifi/java/android/net/wifi/nan/WifiNanManager.java
index 667c4b1..1b78beb 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanManager.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanManager.java
@@ -75,7 +75,7 @@
}
mService.connect(mBinder, listener.callback, events);
} catch (RemoteException e) {
- Log.w(TAG, "connect RemoteException (FYI - ignoring): " + e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -94,7 +94,7 @@
mService.disconnect(mBinder);
mBinder = null;
} catch (RemoteException e) {
- Log.w(TAG, "disconnect RemoteException (FYI - ignoring): " + e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -116,7 +116,7 @@
try {
mService.requestConfig(configRequest);
} catch (RemoteException e) {
- Log.w(TAG, "requestConfig RemoteException (FYI - ignoring): " + e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -173,8 +173,7 @@
if (DBG) Log.d(TAG, "publish: session created - sessionId=" + sessionId);
mService.publish(sessionId, publishData, publishSettings);
} catch (RemoteException e) {
- Log.w(TAG, "createSession/publish RemoteException: " + e);
- return null;
+ throw e.rethrowFromSystemServer();
}
return new WifiNanPublishSession(this, sessionId);
@@ -200,7 +199,7 @@
try {
mService.publish(sessionId, publishData, publishSettings);
} catch (RemoteException e) {
- Log.w(TAG, "publish RemoteException: " + e);
+ throw e.rethrowFromSystemServer();
}
}
/**
@@ -256,8 +255,7 @@
if (DBG) Log.d(TAG, "subscribe: session created - sessionId=" + sessionId);
mService.subscribe(sessionId, subscribeData, subscribeSettings);
} catch (RemoteException e) {
- Log.w(TAG, "createSession/subscribe RemoteException: " + e);
- return null;
+ throw e.rethrowFromSystemServer();
}
return new WifiNanSubscribeSession(this, sessionId);
@@ -286,7 +284,7 @@
try {
mService.subscribe(sessionId, subscribeData, subscribeSettings);
} catch (RemoteException e) {
- Log.w(TAG, "subscribe RemoteException: " + e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -299,7 +297,7 @@
try {
mService.stopSession(sessionId);
} catch (RemoteException e) {
- Log.w(TAG, "stopSession RemoteException (FYI - ignoring): " + e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -312,7 +310,7 @@
try {
mService.destroySession(sessionId);
} catch (RemoteException e) {
- Log.w(TAG, "destroySession RemoteException (FYI - ignoring): " + e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -328,7 +326,7 @@
}
mService.sendMessage(sessionId, peerId, message, messageLength, messageId);
} catch (RemoteException e) {
- Log.w(TAG, "subscribe RemoteException (FYI - ignoring): " + e);
+ throw e.rethrowFromSystemServer();
}
}
}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index 6409450..8d5cf63 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -1362,8 +1362,8 @@
public void setMiracastMode(int mode) {
try {
mService.setMiracastMode(mode);
- } catch(RemoteException e) {
- // ignore
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1378,7 +1378,7 @@
try {
return mService.getMessenger();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1393,7 +1393,7 @@
try {
return mService.getP2pStateMachineMessenger();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}